summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2013-05-28 11:58:46 +0200
committerMichael Niedermayer <michaelni@gmx.at>2013-05-28 11:58:46 +0200
commit3ed3aaab32f58dab2a841a95e032e871d928fb7f (patch)
tree86cdfb67870860e42d568d965ca1cfff242cd586
parent8012f93ed8afbf0b45fa378085cd4b000e30057f (diff)
parent851bc1d6be0c7485609e0208d188f3edbc4ade13 (diff)
Merge remote-tracking branch 'qatar/master'
* qatar/master: smacker: assign video frame PTS matroskadec: export full wavpack blocks. Conflicts: libavcodec/wavpack.c Merged-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--libavcodec/wavpack.c52
-rw-r--r--libavformat/matroskadec.c98
-rw-r--r--libavformat/smacker.c1
3 files changed, 111 insertions, 40 deletions
diff --git a/libavcodec/wavpack.c b/libavcodec/wavpack.c
index 3be479c9b8..d579479621 100644
--- a/libavcodec/wavpack.c
+++ b/libavcodec/wavpack.c
@@ -137,7 +137,6 @@ typedef struct WavpackContext {
int fdec_num;
int multichannel;
- int mkv_mode;
int block;
int samples;
int ch_offset;
@@ -730,14 +729,6 @@ static av_cold int wavpack_decode_init(AVCodecContext *avctx)
: AV_CH_LAYOUT_MONO;
s->multichannel = avctx->channels > 2;
- /* lavf demuxer does not provide extradata, Matroska stores 0x403
- * there, use this to detect decoding mode for multichannel */
- s->mkv_mode = 0;
- if (s->multichannel && avctx->extradata && avctx->extradata_size == 2) {
- int ver = AV_RL16(avctx->extradata);
- if (ver >= 0x402 && ver <= 0x410)
- s->mkv_mode = 1;
- }
s->fdec_num = 0;
@@ -789,15 +780,11 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
bytestream2_init(&gb, buf, buf_size);
- if (!wc->mkv_mode) {
- s->samples = bytestream2_get_le32(&gb);
- if (s->samples != wc->samples) {
- av_log(avctx, AV_LOG_ERROR, "Mismatching number of samples in "
- "a sequence: %d and %d\n", wc->samples, s->samples);
- return AVERROR_INVALIDDATA;
- }
- } else {
- s->samples = wc->samples;
+ s->samples = bytestream2_get_le32(&gb);
+ if (s->samples != wc->samples) {
+ av_log(avctx, AV_LOG_ERROR, "Mismatching number of samples in "
+ "a sequence: %d and %d\n", wc->samples, s->samples);
+ return AVERROR_INVALIDDATA;
}
s->frame_flags = bytestream2_get_le32(&gb);
bpp = av_get_bytes_per_sample(avctx->sample_fmt);
@@ -822,9 +809,6 @@ static int wavpack_decode_block(AVCodecContext *avctx, int block_no,
if (s->stereo)
samples_r = data[wc->ch_offset + 1];
- if (wc->mkv_mode)
- bytestream2_skip(&gb, 4); // skip block size;
-
wc->ch_offset += 1 + s->stereo;
// parse metadata blocks
@@ -1165,14 +1149,8 @@ static int wavpack_decode_frame(AVCodecContext *avctx, void *data,
s->ch_offset = 0;
/* determine number of samples */
- if (s->mkv_mode) {
- s->samples = AV_RL32(buf);
- buf += 4;
- frame_flags = AV_RL32(buf);
- } else {
- s->samples = AV_RL32(buf + 20);
- frame_flags = AV_RL32(buf + 24);
- }
+ s->samples = AV_RL32(buf + 20);
+ frame_flags = AV_RL32(buf + 24);
if (s->samples <= 0 || s->samples > WV_MAX_SAMPLES) {
av_log(avctx, AV_LOG_ERROR, "Invalid number of samples: %d\n",
s->samples);
@@ -1195,17 +1173,11 @@ static int wavpack_decode_frame(AVCodecContext *avctx, void *data,
frame->nb_samples = s->samples;
while (buf_size > 0) {
- if (!s->mkv_mode) {
- if (buf_size <= WV_HEADER_SIZE)
- break;
- frame_size = AV_RL32(buf + 4) - 12;
- buf += 20;
- buf_size -= 20;
- } else {
- if (buf_size < 12) // MKV files can have zero flags after last block
- break;
- frame_size = AV_RL32(buf + 8) + 12;
- }
+ if (buf_size <= WV_HEADER_SIZE)
+ break;
+ frame_size = AV_RL32(buf + 4) - 12;
+ buf += 20;
+ buf_size -= 20;
if (frame_size <= 0 || frame_size > buf_size) {
av_log(avctx, AV_LOG_ERROR,
"Block %d has invalid size (size %d vs. %d bytes left)\n",
diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index b82f289e9f..60bb73b327 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -2144,6 +2144,88 @@ static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska,
return 0;
}
+
+/* reconstruct full wavpack blocks from mangled matroska ones */
+static int matroska_parse_wavpack(MatroskaTrack *track, uint8_t *src,
+ uint8_t **pdst, int *size)
+{
+ uint8_t *dst = NULL;
+ int dstlen = 0;
+ int srclen = *size;
+ uint32_t samples;
+ uint16_t ver;
+ int ret, offset = 0;
+
+ if (srclen < 12 || track->stream->codec->extradata_size < 2)
+ return AVERROR_INVALIDDATA;
+
+ ver = AV_RL16(track->stream->codec->extradata);
+
+ samples = AV_RL32(src);
+ src += 4;
+ srclen -= 4;
+
+ while (srclen >= 8) {
+ int multiblock;
+ uint32_t blocksize;
+ uint8_t *tmp;
+
+ uint32_t flags = AV_RL32(src);
+ uint32_t crc = AV_RL32(src + 4);
+ src += 8;
+ srclen -= 8;
+
+ multiblock = (flags & 0x1800) != 0x1800;
+ if (multiblock) {
+ if (srclen < 4) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+ blocksize = AV_RL32(src);
+ src += 4;
+ srclen -= 4;
+ } else
+ blocksize = srclen;
+
+ if (blocksize > srclen) {
+ ret = AVERROR_INVALIDDATA;
+ goto fail;
+ }
+
+ tmp = av_realloc(dst, dstlen + blocksize + 32);
+ if (!tmp) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ dst = tmp;
+ dstlen += blocksize + 32;
+
+ AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag
+ AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8
+ AV_WL16(dst + offset + 8, ver); // version
+ AV_WL16(dst + offset + 10, 0); // track/index_no
+ AV_WL32(dst + offset + 12, 0); // total samples
+ AV_WL32(dst + offset + 16, 0); // block index
+ AV_WL32(dst + offset + 20, samples); // number of samples
+ AV_WL32(dst + offset + 24, flags); // flags
+ AV_WL32(dst + offset + 28, crc); // crc
+ memcpy (dst + offset + 32, src, blocksize); // block data
+
+ src += blocksize;
+ srclen -= blocksize;
+ offset += blocksize + 32;
+ }
+
+ *pdst = dst;
+ *size = dstlen;
+
+ return 0;
+
+fail:
+ av_freep(&dst);
+ return ret;
+}
+
static int matroska_parse_frame(MatroskaDemuxContext *matroska,
MatroskaTrack *track,
AVStream *st,
@@ -2163,6 +2245,18 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
return res;
}
+ if (st->codec->codec_id == AV_CODEC_ID_WAVPACK) {
+ uint8_t *wv_data;
+ res = matroska_parse_wavpack(track, pkt_data, &wv_data, &pkt_size);
+ if (res < 0) {
+ av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing a wavpack block.\n");
+ goto fail;
+ }
+ if (pkt_data != data)
+ av_freep(&pkt_data);
+ pkt_data = wv_data;
+ }
+
if (st->codec->codec_id == AV_CODEC_ID_PRORES)
offset = 8;
@@ -2249,6 +2343,10 @@ static int matroska_parse_frame(MatroskaDemuxContext *matroska,
#endif
return 0;
+fail:
+ if (pkt_data != data)
+ av_freep(&pkt_data);
+ return res;
}
static int matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data,
diff --git a/libavformat/smacker.c b/libavformat/smacker.c
index 7f270b48b1..e04a214ff3 100644
--- a/libavformat/smacker.c
+++ b/libavformat/smacker.c
@@ -338,6 +338,7 @@ static int smacker_read_packet(AVFormatContext *s, AVPacket *pkt)
if(ret != frame_size)
return AVERROR(EIO);
pkt->stream_index = smk->videoindex;
+ pkt->pts = smk->cur_frame;
pkt->size = ret + 769;
smk->cur_frame++;
smk->nextpos = avio_tell(s->pb);