* qatar/master: smacker: assign video frame PTS matroskadec: export full wavpack blocks. Conflicts: libavcodec/wavpack.c Merged-by: Michael Niedermayer <michaelni@gmx.at>tags/n2.0
| @@ -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", | |||
| @@ -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, | |||
| @@ -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); | |||