From 42feaf40700246d9afb9c27ef09a0022ddfdb998 Mon Sep 17 00:00:00 2001 From: Kostya Shishkov Date: Thu, 13 Oct 2011 10:12:42 +0200 Subject: [PATCH 01/22] vc1: explicitly zero interlaced mode coding variables for progressive mode Both v->fcm and v->field_mode are used in common code, now they won't be reset for progressive frame after interlaced one causing writing past the frame end for example. Signed-off-by: Ronald S. Bultje --- libavcodec/vc1.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/vc1.c b/libavcodec/vc1.c index 9d36811c2c..cb228e6107 100644 --- a/libavcodec/vc1.c +++ b/libavcodec/vc1.c @@ -832,17 +832,18 @@ int vc1_parse_frame_header_adv(VC1Context *v, GetBitContext* gb) goto parse_common_info; } + v->field_mode = 0; if (v->interlace) { v->fcm = decode012(gb); if (v->fcm) { if (v->fcm == 2) v->field_mode = 1; - else - v->field_mode = 0; if (!v->warn_interlaced++) av_log(v->s.avctx, AV_LOG_ERROR, "Interlaced frames/fields support is incomplete\n"); } + } else { + v->fcm = 0; } if (v->field_mode) { From f59bb3d8f3eb50aa182b0d7ae209848b94a507cc Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 9 Oct 2011 12:57:08 +0100 Subject: [PATCH 02/22] mathops: remove undefined behaviour from sign_extend() This function intentionally overflows the signed range on the left shift. Using this type-punning avoids errors from the overflow checker without disabling this test globally. Signed-off-by: Mans Rullgard --- libavcodec/mathops.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavcodec/mathops.h b/libavcodec/mathops.h index ec76eaae29..45b1ecf1ae 100644 --- a/libavcodec/mathops.h +++ b/libavcodec/mathops.h @@ -116,7 +116,9 @@ static inline av_const int mid_pred(int a, int b, int c) #ifndef sign_extend static inline av_const int sign_extend(int val, unsigned bits) { - return (val << ((8 * sizeof(int)) - bits)) >> ((8 * sizeof(int)) - bits); + unsigned shift = 8 * sizeof(int) - bits; + union { unsigned u; int s; } v = { (unsigned) val << shift }; + return v.s >> shift; } #endif From b45eb9d619d4a039a44bcd1dd82ec70ad29819f0 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 8 Oct 2011 12:47:53 +0100 Subject: [PATCH 03/22] pcm: reduce pointer type casting Making 'samples' a pointer to uint8_t simplifies the DECODE macro and reduces the amount of type casting overall. This also fixes some signed overflows on left shift. Signed-off-by: Mans Rullgard --- libavcodec/pcm.c | 77 +++++++++++++++++++++++------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c index 2ad395dd0e..66edfba0f2 100644 --- a/libavcodec/pcm.c +++ b/libavcodec/pcm.c @@ -236,7 +236,7 @@ static av_cold int pcm_decode_init(AVCodecContext * avctx) /** * Read PCM samples macro - * @param type Datatype of native machine format + * @param size Data size of native machine format * @param endian bytestream_get_xxx() endian suffix * @param src Source pointer (variable name) * @param dst Destination pointer (variable name) @@ -244,13 +244,12 @@ static av_cold int pcm_decode_init(AVCodecContext * avctx) * @param shift Bitshift (bits) * @param offset Sample value offset */ -#define DECODE(type, endian, src, dst, n, shift, offset) \ - dst_##type = (type*)dst; \ +#define DECODE(size, endian, src, dst, n, shift, offset) \ for(;n>0;n--) { \ - register type v = bytestream_get_##endian(&src); \ - *dst_##type++ = (v - offset) << shift; \ - } \ - dst = (short*)dst_##type; + uint##size##_t v = bytestream_get_##endian(&src); \ + AV_WN##size##A(dst, (v - offset) << shift); \ + dst += size / 8; \ + } static int pcm_decode_frame(AVCodecContext *avctx, void *data, int *data_size, @@ -260,14 +259,9 @@ static int pcm_decode_frame(AVCodecContext *avctx, int buf_size = avpkt->size; PCMDecode *s = avctx->priv_data; int sample_size, c, n, i; - short *samples; + uint8_t *samples; const uint8_t *src, *src8, *src2[MAX_CHANNELS]; - uint8_t *dstu8; - int16_t *dst_int16_t; int32_t *dst_int32_t; - int64_t *dst_int64_t; - uint16_t *dst_uint16_t; - uint32_t *dst_uint32_t; samples = data; src = buf; @@ -314,29 +308,30 @@ static int pcm_decode_frame(AVCodecContext *avctx, switch(avctx->codec->id) { case CODEC_ID_PCM_U32LE: - DECODE(uint32_t, le32, src, samples, n, 0, 0x80000000) + DECODE(32, le32, src, samples, n, 0, 0x80000000) break; case CODEC_ID_PCM_U32BE: - DECODE(uint32_t, be32, src, samples, n, 0, 0x80000000) + DECODE(32, be32, src, samples, n, 0, 0x80000000) break; case CODEC_ID_PCM_S24LE: - DECODE(int32_t, le24, src, samples, n, 8, 0) + DECODE(32, le24, src, samples, n, 8, 0) break; case CODEC_ID_PCM_S24BE: - DECODE(int32_t, be24, src, samples, n, 8, 0) + DECODE(32, be24, src, samples, n, 8, 0) break; case CODEC_ID_PCM_U24LE: - DECODE(uint32_t, le24, src, samples, n, 8, 0x800000) + DECODE(32, le24, src, samples, n, 8, 0x800000) break; case CODEC_ID_PCM_U24BE: - DECODE(uint32_t, be24, src, samples, n, 8, 0x800000) + DECODE(32, be24, src, samples, n, 8, 0x800000) break; case CODEC_ID_PCM_S24DAUD: for(;n>0;n--) { uint32_t v = bytestream_get_be24(&src); v >>= 4; // sync flags are here - *samples++ = av_reverse[(v >> 8) & 0xff] + - (av_reverse[v & 0xff] << 8); + AV_WN16A(samples, av_reverse[(v >> 8) & 0xff] + + (av_reverse[v & 0xff] << 8)); + samples += 2; } break; case CODEC_ID_PCM_S16LE_PLANAR: @@ -344,33 +339,33 @@ static int pcm_decode_frame(AVCodecContext *avctx, for(c=0;cchannels;c++) src2[c] = &src[c*n*2]; for(;n>0;n--) - for(c=0;cchannels;c++) - *samples++ = bytestream_get_le16(&src2[c]); + for(c=0;cchannels;c++) { + AV_WN16A(samples, bytestream_get_le16(&src2[c])); + samples += 2; + } src = src2[avctx->channels-1]; break; case CODEC_ID_PCM_U16LE: - DECODE(uint16_t, le16, src, samples, n, 0, 0x8000) + DECODE(16, le16, src, samples, n, 0, 0x8000) break; case CODEC_ID_PCM_U16BE: - DECODE(uint16_t, be16, src, samples, n, 0, 0x8000) + DECODE(16, be16, src, samples, n, 0, 0x8000) break; case CODEC_ID_PCM_S8: - dstu8= (uint8_t*)samples; for(;n>0;n--) { - *dstu8++ = *src++ + 128; + *samples++ = *src++ + 128; } - samples= (short*)dstu8; break; #if HAVE_BIGENDIAN case CODEC_ID_PCM_F64LE: - DECODE(int64_t, le64, src, samples, n, 0, 0) + DECODE(64, le64, src, samples, n, 0, 0) break; case CODEC_ID_PCM_S32LE: case CODEC_ID_PCM_F32LE: - DECODE(int32_t, le32, src, samples, n, 0, 0) + DECODE(32, le32, src, samples, n, 0, 0) break; case CODEC_ID_PCM_S16LE: - DECODE(int16_t, le16, src, samples, n, 0, 0) + DECODE(16, le16, src, samples, n, 0, 0) break; case CODEC_ID_PCM_F64BE: case CODEC_ID_PCM_F32BE: @@ -378,14 +373,14 @@ static int pcm_decode_frame(AVCodecContext *avctx, case CODEC_ID_PCM_S16BE: #else case CODEC_ID_PCM_F64BE: - DECODE(int64_t, be64, src, samples, n, 0, 0) + DECODE(64, be64, src, samples, n, 0, 0) break; case CODEC_ID_PCM_F32BE: case CODEC_ID_PCM_S32BE: - DECODE(int32_t, be32, src, samples, n, 0, 0) + DECODE(32, be32, src, samples, n, 0, 0) break; case CODEC_ID_PCM_S16BE: - DECODE(int16_t, be16, src, samples, n, 0, 0) + DECODE(16, be16, src, samples, n, 0, 0) break; case CODEC_ID_PCM_F64LE: case CODEC_ID_PCM_F32LE: @@ -395,20 +390,22 @@ static int pcm_decode_frame(AVCodecContext *avctx, case CODEC_ID_PCM_U8: memcpy(samples, src, n*sample_size); src += n*sample_size; - samples = (short*)((uint8_t*)data + n*sample_size); + samples += n * sample_size; break; case CODEC_ID_PCM_ZORK: for(;n>0;n--) { int x= *src++; if(x&128) x-= 128; else x = -x; - *samples++ = x << 8; + AV_WN16A(samples, x << 8); + samples += 2; } break; case CODEC_ID_PCM_ALAW: case CODEC_ID_PCM_MULAW: for(;n>0;n--) { - *samples++ = s->table[*src++]; + AV_WN16A(samples, s->table[*src++]); + samples += 2; } break; case CODEC_ID_PCM_DVD: @@ -441,7 +438,7 @@ static int pcm_decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_ERROR, "PCM DVD unsupported sample depth\n"); return -1; } - samples = (short *) dst_int32_t; + samples = (uint8_t *) dst_int32_t; break; case CODEC_ID_PCM_LXF: dst_int32_t = data; @@ -461,12 +458,12 @@ static int pcm_decode_frame(AVCodecContext *avctx, } } src += n * avctx->channels * 5; - samples = (short *) dst_int32_t; + samples = (uint8_t *) dst_int32_t; break; default: return -1; } - *data_size = (uint8_t *)samples - (uint8_t *)data; + *data_size = samples - (uint8_t *)data; return src - buf; } From caa845851d790f894a2ccbe12580934f75545f92 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 22:30:44 -0400 Subject: [PATCH 04/22] mlpdec: validate that the reported channel count matches the actual output channel count --- libavcodec/mlpdec.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index c90285af8e..15b8de4e04 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -909,7 +909,12 @@ static int output_data_internal(MLPDecodeContext *m, unsigned int substr, int32_t *data_32 = (int32_t*) data; int16_t *data_16 = (int16_t*) data; - if (*data_size < (s->max_channel + 1) * s->blockpos * (is32 ? 4 : 2)) + if (m->avctx->channels != s->max_matrix_channel + 1) { + av_log(m->avctx, AV_LOG_ERROR, "channel count mismatch\n"); + return AVERROR_INVALIDDATA; + } + + if (*data_size < m->avctx->channels * s->blockpos * (is32 ? 4 : 2)) return -1; for (i = 0; i < s->blockpos; i++) { From 37b67f1bff8662219a9a837e8bdba072f14ec990 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 21 Sep 2011 12:14:28 -0400 Subject: [PATCH 05/22] mlpdec: only calculate output size once --- libavcodec/mlpdec.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 15b8de4e04..f39e963edf 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -906,6 +906,7 @@ static int output_data_internal(MLPDecodeContext *m, unsigned int substr, { SubStream *s = &m->substream[substr]; unsigned int i, out_ch = 0; + int out_size; int32_t *data_32 = (int32_t*) data; int16_t *data_16 = (int16_t*) data; @@ -914,8 +915,11 @@ static int output_data_internal(MLPDecodeContext *m, unsigned int substr, return AVERROR_INVALIDDATA; } - if (*data_size < m->avctx->channels * s->blockpos * (is32 ? 4 : 2)) - return -1; + out_size = s->blockpos * m->avctx->channels * + av_get_bytes_per_sample(m->avctx->sample_fmt); + + if (*data_size < out_size) + return AVERROR(EINVAL); for (i = 0; i < s->blockpos; i++) { for (out_ch = 0; out_ch <= s->max_matrix_channel; out_ch++) { @@ -928,7 +932,7 @@ static int output_data_internal(MLPDecodeContext *m, unsigned int substr, } } - *data_size = i * out_ch * (is32 ? 4 : 2); + *data_size = out_size; return 0; } From e1b8d88d52028a1c064dc1c2c96c1e0b200c73a1 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 22:37:12 -0400 Subject: [PATCH 06/22] mlpdec: remove unnecessary wrapper function --- libavcodec/mlpdec.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index f39e963edf..794f8964d0 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -901,14 +901,15 @@ static void rematrix_channels(MLPDecodeContext *m, unsigned int substr) /** Write the audio data into the output buffer. */ -static int output_data_internal(MLPDecodeContext *m, unsigned int substr, - uint8_t *data, unsigned int *data_size, int is32) +static int output_data(MLPDecodeContext *m, unsigned int substr, + uint8_t *data, unsigned int *data_size) { SubStream *s = &m->substream[substr]; unsigned int i, out_ch = 0; int out_size; int32_t *data_32 = (int32_t*) data; int16_t *data_16 = (int16_t*) data; + int is32 = (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32); if (m->avctx->channels != s->max_matrix_channel + 1) { av_log(m->avctx, AV_LOG_ERROR, "channel count mismatch\n"); @@ -937,16 +938,6 @@ static int output_data_internal(MLPDecodeContext *m, unsigned int substr, return 0; } -static int output_data(MLPDecodeContext *m, unsigned int substr, - uint8_t *data, unsigned int *data_size) -{ - if (m->avctx->sample_fmt == AV_SAMPLE_FMT_S32) - return output_data_internal(m, substr, data, data_size, 1); - else - return output_data_internal(m, substr, data, data_size, 0); -} - - /** Read an access unit from the stream. * @return negative on error, 0 if not enough data is present in the input stream, * otherwise the number of bytes consumed. */ From 82be06bbb348bde16ed6e13ccbafac5f9264c478 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 22:47:50 -0400 Subject: [PATCH 07/22] mlpdec: return meaningful error codes instead of -1 --- libavcodec/mlp_parser.c | 6 +-- libavcodec/mlpdec.c | 112 +++++++++++++++++++++------------------- 2 files changed, 61 insertions(+), 57 deletions(-) diff --git a/libavcodec/mlp_parser.c b/libavcodec/mlp_parser.c index e85eb72c38..e1f4c5610e 100644 --- a/libavcodec/mlp_parser.c +++ b/libavcodec/mlp_parser.c @@ -138,11 +138,11 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) checksum = ff_mlp_checksum16(gb->buffer, 26); if (checksum != AV_RL16(gb->buffer+26)) { av_log(log, AV_LOG_ERROR, "major sync info header checksum error\n"); - return -1; + return AVERROR_INVALIDDATA; } if (get_bits_long(gb, 24) != 0xf8726f) /* Sync words */ - return -1; + return AVERROR_INVALIDDATA; mh->stream_type = get_bits(gb, 8); @@ -173,7 +173,7 @@ int ff_mlp_read_major_sync(void *log, MLPHeaderInfo *mh, GetBitContext *gb) mh->channels_thd_stream2 = get_bits(gb, 13); } else - return -1; + return AVERROR_INVALIDDATA; mh->access_unit_size = 40 << (ratebits & 7); mh->access_unit_size_pow2 = 64 << (ratebits & 7); diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 794f8964d0..cefd0b5614 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -214,7 +214,7 @@ static inline int read_huff_channels(MLPDecodeContext *m, GetBitContext *gbp, VLC_BITS, (9 + VLC_BITS - 1) / VLC_BITS); if (result < 0) - return -1; + return AVERROR_INVALIDDATA; if (lsb_bits > 0) result = (result << lsb_bits) + get_bits(gbp, lsb_bits); @@ -250,61 +250,61 @@ static av_cold int mlp_decode_init(AVCodecContext *avctx) static int read_major_sync(MLPDecodeContext *m, GetBitContext *gb) { MLPHeaderInfo mh; - int substr; + int substr, ret; - if (ff_mlp_read_major_sync(m->avctx, &mh, gb) != 0) - return -1; + if ((ret = ff_mlp_read_major_sync(m->avctx, &mh, gb)) != 0) + return ret; if (mh.group1_bits == 0) { av_log(m->avctx, AV_LOG_ERROR, "invalid/unknown bits per sample\n"); - return -1; + return AVERROR_INVALIDDATA; } if (mh.group2_bits > mh.group1_bits) { av_log(m->avctx, AV_LOG_ERROR, "Channel group 2 cannot have more bits per sample than group 1.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (mh.group2_samplerate && mh.group2_samplerate != mh.group1_samplerate) { av_log(m->avctx, AV_LOG_ERROR, "Channel groups with differing sample rates are not currently supported.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (mh.group1_samplerate == 0) { av_log(m->avctx, AV_LOG_ERROR, "invalid/unknown sampling rate\n"); - return -1; + return AVERROR_INVALIDDATA; } if (mh.group1_samplerate > MAX_SAMPLERATE) { av_log(m->avctx, AV_LOG_ERROR, "Sampling rate %d is greater than the supported maximum (%d).\n", mh.group1_samplerate, MAX_SAMPLERATE); - return -1; + return AVERROR_INVALIDDATA; } if (mh.access_unit_size > MAX_BLOCKSIZE) { av_log(m->avctx, AV_LOG_ERROR, "Block size %d is greater than the supported maximum (%d).\n", mh.access_unit_size, MAX_BLOCKSIZE); - return -1; + return AVERROR_INVALIDDATA; } if (mh.access_unit_size_pow2 > MAX_BLOCKSIZE_POW2) { av_log(m->avctx, AV_LOG_ERROR, "Block size pow2 %d is greater than the supported maximum (%d).\n", mh.access_unit_size_pow2, MAX_BLOCKSIZE_POW2); - return -1; + return AVERROR_INVALIDDATA; } if (mh.num_substreams == 0) - return -1; + return AVERROR_INVALIDDATA; if (m->avctx->codec_id == CODEC_ID_MLP && mh.num_substreams > 2) { av_log(m->avctx, AV_LOG_ERROR, "MLP only supports up to 2 substreams.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (mh.num_substreams > MAX_SUBSTREAMS) { av_log(m->avctx, AV_LOG_ERROR, "Number of substreams %d is larger than the maximum supported " "by the decoder. %s\n", mh.num_substreams, sample_message); - return -1; + return AVERROR_INVALIDDATA; } m->access_unit_size = mh.access_unit_size; @@ -351,14 +351,14 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, if (sync_word != 0x31ea >> 1) { av_log(m->avctx, AV_LOG_ERROR, "restart header sync incorrect (got 0x%04x)\n", sync_word); - return -1; + return AVERROR_INVALIDDATA; } s->noise_type = get_bits1(gbp); if (m->avctx->codec_id == CODEC_ID_MLP && s->noise_type) { av_log(m->avctx, AV_LOG_ERROR, "MLP must have 0x31ea sync word.\n"); - return -1; + return AVERROR_INVALIDDATA; } skip_bits(gbp, 16); /* Output timestamp */ @@ -371,13 +371,13 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, av_log(m->avctx, AV_LOG_ERROR, "Max matrix channel cannot be greater than %d.\n", max_matrix_channel); - return -1; + return AVERROR_INVALIDDATA; } if (s->max_channel != s->max_matrix_channel) { av_log(m->avctx, AV_LOG_ERROR, "Max channel must be equal max matrix channel.\n"); - return -1; + return AVERROR_INVALIDDATA; } /* This should happen for TrueHD streams with >6 channels and MLP's noise @@ -386,13 +386,13 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, av_log(m->avctx, AV_LOG_ERROR, "Number of channels %d is larger than the maximum supported " "by the decoder. %s\n", s->max_channel+2, sample_message); - return -1; + return AVERROR_INVALIDDATA; } if (s->min_channel > s->max_channel) { av_log(m->avctx, AV_LOG_ERROR, "Substream min channel cannot be greater than max channel.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (m->avctx->request_channels > 0 @@ -431,7 +431,7 @@ static int read_restart_header(MLPDecodeContext *m, GetBitContext *gbp, av_log(m->avctx, AV_LOG_ERROR, "Assignment of matrix channel %d to invalid output channel %d. %s\n", ch, ch_assign, sample_message); - return -1; + return AVERROR_INVALIDDATA; } s->ch_assign[ch_assign] = ch; } @@ -487,7 +487,7 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, if (m->filter_changed[channel][filter]++ > 1) { av_log(m->avctx, AV_LOG_ERROR, "Filters may change only once per access unit.\n"); - return -1; + return AVERROR_INVALIDDATA; } order = get_bits(gbp, 4); @@ -495,7 +495,7 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, av_log(m->avctx, AV_LOG_ERROR, "%cIR filter order %d is greater than maximum %d.\n", fchar, order, max_order); - return -1; + return AVERROR_INVALIDDATA; } fp->order = order; @@ -511,13 +511,13 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, av_log(m->avctx, AV_LOG_ERROR, "%cIR filter coeff_bits must be between 1 and 16.\n", fchar); - return -1; + return AVERROR_INVALIDDATA; } if (coeff_bits + coeff_shift > 16) { av_log(m->avctx, AV_LOG_ERROR, "Sum of coeff_bits and coeff_shift for %cIR filter must be 16 or less.\n", fchar); - return -1; + return AVERROR_INVALIDDATA; } for (i = 0; i < order; i++) @@ -529,7 +529,7 @@ static int read_filter_params(MLPDecodeContext *m, GetBitContext *gbp, if (filter == FIR) { av_log(m->avctx, AV_LOG_ERROR, "FIR filter has state data specified.\n"); - return -1; + return AVERROR_INVALIDDATA; } state_bits = get_bits(gbp, 4); @@ -557,7 +557,7 @@ static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitCo if (m->matrix_changed++ > 1) { av_log(m->avctx, AV_LOG_ERROR, "Matrices may change only once per access unit.\n"); - return -1; + return AVERROR_INVALIDDATA; } s->num_primitive_matrices = get_bits(gbp, 4); @@ -566,7 +566,7 @@ static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitCo av_log(m->avctx, AV_LOG_ERROR, "Number of primitive matrices cannot be greater than %d.\n", max_primitive_matrices); - return -1; + return AVERROR_INVALIDDATA; } for (mat = 0; mat < s->num_primitive_matrices; mat++) { @@ -579,12 +579,12 @@ static int read_matrix_params(MLPDecodeContext *m, unsigned int substr, GetBitCo av_log(m->avctx, AV_LOG_ERROR, "Invalid channel %d specified as output from matrix.\n", s->matrix_out_ch[mat]); - return -1; + return AVERROR_INVALIDDATA; } if (frac_bits > 14) { av_log(m->avctx, AV_LOG_ERROR, "Too many fractional bits specified.\n"); - return -1; + return AVERROR_INVALIDDATA; } max_chan = s->max_matrix_channel; @@ -617,27 +617,28 @@ static int read_channel_params(MLPDecodeContext *m, unsigned int substr, ChannelParams *cp = &s->channel_params[ch]; FilterParams *fir = &cp->filter_params[FIR]; FilterParams *iir = &cp->filter_params[IIR]; + int ret; if (s->param_presence_flags & PARAM_FIR) if (get_bits1(gbp)) - if (read_filter_params(m, gbp, substr, ch, FIR) < 0) - return -1; + if ((ret = read_filter_params(m, gbp, substr, ch, FIR)) < 0) + return ret; if (s->param_presence_flags & PARAM_IIR) if (get_bits1(gbp)) - if (read_filter_params(m, gbp, substr, ch, IIR) < 0) - return -1; + if ((ret = read_filter_params(m, gbp, substr, ch, IIR)) < 0) + return ret; if (fir->order + iir->order > 8) { av_log(m->avctx, AV_LOG_ERROR, "Total filter orders too high.\n"); - return -1; + return AVERROR_INVALIDDATA; } if (fir->order && iir->order && fir->shift != iir->shift) { av_log(m->avctx, AV_LOG_ERROR, "FIR and IIR filters must use the same precision.\n"); - return -1; + return AVERROR_INVALIDDATA; } /* The FIR and IIR filters must have the same precision. * To simplify the filtering code, only the precision of the @@ -656,7 +657,7 @@ static int read_channel_params(MLPDecodeContext *m, unsigned int substr, if (cp->huff_lsbs > 24) { av_log(m->avctx, AV_LOG_ERROR, "Invalid huff_lsbs.\n"); - return -1; + return AVERROR_INVALIDDATA; } cp->sign_huff_offset = calculate_sign_huff(m, substr, ch); @@ -672,6 +673,7 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, { SubStream *s = &m->substream[substr]; unsigned int ch; + int ret; if (s->param_presence_flags & PARAM_PRESENCE) if (get_bits1(gbp)) @@ -683,14 +685,14 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, if (s->blocksize < 8 || s->blocksize > m->access_unit_size) { av_log(m->avctx, AV_LOG_ERROR, "Invalid blocksize."); s->blocksize = 0; - return -1; + return AVERROR_INVALIDDATA; } } if (s->param_presence_flags & PARAM_MATRIX) if (get_bits1(gbp)) - if (read_matrix_params(m, substr, gbp) < 0) - return -1; + if ((ret = read_matrix_params(m, substr, gbp)) < 0) + return ret; if (s->param_presence_flags & PARAM_OUTSHIFT) if (get_bits1(gbp)) @@ -709,8 +711,8 @@ static int read_decoding_params(MLPDecodeContext *m, GetBitContext *gbp, for (ch = s->min_channel; ch <= s->max_channel; ch++) if (get_bits1(gbp)) - if (read_channel_params(m, substr, gbp, ch) < 0) - return -1; + if ((ret = read_channel_params(m, substr, gbp, ch)) < 0) + return ret; return 0; } @@ -752,6 +754,7 @@ static int read_block_data(MLPDecodeContext *m, GetBitContext *gbp, { SubStream *s = &m->substream[substr]; unsigned int i, ch, expected_stream_pos = 0; + int ret; if (s->data_check_present) { expected_stream_pos = get_bits_count(gbp); @@ -762,15 +765,15 @@ static int read_block_data(MLPDecodeContext *m, GetBitContext *gbp, if (s->blockpos + s->blocksize > m->access_unit_size) { av_log(m->avctx, AV_LOG_ERROR, "too many audio samples in frame\n"); - return -1; + return AVERROR_INVALIDDATA; } memset(&m->bypassed_lsbs[s->blockpos][0], 0, s->blocksize * sizeof(m->bypassed_lsbs[0])); for (i = 0; i < s->blocksize; i++) - if (read_huff_channels(m, gbp, substr, i) < 0) - return -1; + if ((ret = read_huff_channels(m, gbp, substr, i)) < 0) + return ret; for (ch = s->min_channel; ch <= s->max_channel; ch++) filter_channel(m, substr, ch); @@ -956,6 +959,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, uint8_t substream_parity_present[MAX_SUBSTREAMS]; uint16_t substream_data_len[MAX_SUBSTREAMS]; uint8_t parity_bits; + int ret; if (buf_size < 4) return 0; @@ -963,7 +967,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, length = (AV_RB16(buf) & 0xfff) * 2; if (length < 4 || length > buf_size) - return -1; + return AVERROR_INVALIDDATA; init_get_bits(&gb, (buf + 4), (length - 4) * 8); @@ -1069,8 +1073,8 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, if (!s->restart_seen) goto next_substr; - if (read_block_data(m, &gb, substr) < 0) - return -1; + if ((ret = read_block_data(m, &gb, substr)) < 0) + return ret; if (get_bits_count(&gb) >= substream_data_len[substr] * 8) goto substream_length_mismatch; @@ -1083,13 +1087,13 @@ static int read_access_unit(AVCodecContext *avctx, void* data, int *data_size, int shorten_by; if (get_bits(&gb, 16) != 0xD234) - return -1; + return AVERROR_INVALIDDATA; shorten_by = get_bits(&gb, 16); if (m->avctx->codec_id == CODEC_ID_TRUEHD && shorten_by & 0x2000) s->blockpos -= FFMIN(shorten_by & 0x1FFF, s->blockpos); else if (m->avctx->codec_id == CODEC_ID_MLP && shorten_by != 0xD234) - return -1; + return AVERROR_INVALIDDATA; if (substr == m->max_decoded_substream) av_log(m->avctx, AV_LOG_INFO, "End of stream indicated.\n"); @@ -1123,18 +1127,18 @@ next_substr: rematrix_channels(m, m->max_decoded_substream); - if (output_data(m, m->max_decoded_substream, data, data_size) < 0) - return -1; + if ((ret = output_data(m, m->max_decoded_substream, data, data_size)) < 0) + return ret; return length; substream_length_mismatch: av_log(m->avctx, AV_LOG_ERROR, "substream %d length mismatch\n", substr); - return -1; + return AVERROR_INVALIDDATA; error: m->params_valid = 0; - return -1; + return AVERROR_INVALIDDATA; } AVCodec ff_mlp_decoder = { From 595cf1a1aa09f6214eed57bd9eb6493456918efe Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 23:10:41 -0400 Subject: [PATCH 08/22] truespeech: remove unneeded zero-size packet check. This is already checked in avcodec_decode_audio3() --- libavcodec/truespeech.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 6b6d13142f..0ab2cab03c 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -344,9 +344,6 @@ static int truespeech_decode_frame(AVCodecContext *avctx, int16_t out_buf[240]; int iterations; - if (!buf_size) - return 0; - if (buf_size < 32) { av_log(avctx, AV_LOG_ERROR, "Too small input buffer (%d bytes), need at least 32 bytes\n", buf_size); From a8f8db2636cf9f605fbe842d1136a3e1acc3c9b2 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 23:15:00 -0400 Subject: [PATCH 09/22] truespeech: check for large enough output buffer rather than truncating output --- libavcodec/truespeech.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 0ab2cab03c..6f663f30c5 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -342,14 +342,22 @@ static int truespeech_decode_frame(AVCodecContext *avctx, short *samples = data; int consumed = 0; int16_t out_buf[240]; - int iterations; + int iterations, out_size; - if (buf_size < 32) { + iterations = buf_size / 32; + + if (!iterations) { av_log(avctx, AV_LOG_ERROR, "Too small input buffer (%d bytes), need at least 32 bytes\n", buf_size); return -1; } - iterations = FFMIN(buf_size / 32, *data_size / 480); + + out_size = iterations * 240 * av_get_bytes_per_sample(avctx->sample_fmt); + if (*data_size < out_size) { + av_log(avctx, AV_LOG_ERROR, "Output buffer is too small\n"); + return AVERROR(EINVAL); + } + for(j = 0; j < iterations; j++) { truespeech_read_frame(c, buf + consumed); consumed += 32; @@ -373,7 +381,7 @@ static int truespeech_decode_frame(AVCodecContext *avctx, } - *data_size = consumed * 15; + *data_size = out_size; return consumed; } From 3e7a176759e8a8e66d65c779b47b5bba793dfd4e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 23:23:18 -0400 Subject: [PATCH 10/22] truespeech: check to make sure channels == 1 --- libavcodec/truespeech.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 6f663f30c5..555ec87f00 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -56,6 +56,11 @@ static av_cold int truespeech_decode_init(AVCodecContext * avctx) { // TSContext *c = avctx->priv_data; + if (avctx->channels != 1) { + av_log_ask_for_sample(avctx, "Unsupported channel count: %d\n", avctx->channels); + return AVERROR(EINVAL); + } + avctx->sample_fmt = AV_SAMPLE_FMT_S16; return 0; } From 5e5ce70f192274ab8d1564170f7f9dc12d503311 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 12 Oct 2011 23:27:32 -0400 Subject: [PATCH 11/22] truespeech: decode directly to output buffer instead of a temp buffer --- libavcodec/truespeech.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 555ec87f00..eec77eac9f 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -346,7 +346,6 @@ static int truespeech_decode_frame(AVCodecContext *avctx, int i, j; short *samples = data; int consumed = 0; - int16_t out_buf[240]; int iterations, out_size; iterations = buf_size / 32; @@ -363,6 +362,8 @@ static int truespeech_decode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); } + memset(samples, 0, out_size); + for(j = 0; j < iterations; j++) { truespeech_read_frame(c, buf + consumed); consumed += 32; @@ -370,20 +371,15 @@ static int truespeech_decode_frame(AVCodecContext *avctx, truespeech_correlate_filter(c); truespeech_filters_merge(c); - memset(out_buf, 0, 240 * 2); for(i = 0; i < 4; i++) { truespeech_apply_twopoint_filter(c, i); - truespeech_place_pulses(c, out_buf + i * 60, i); - truespeech_update_filters(c, out_buf + i * 60, i); - truespeech_synth(c, out_buf + i * 60, i); + truespeech_place_pulses (c, samples, i); + truespeech_update_filters(c, samples, i); + truespeech_synth (c, samples, i); + samples += 60; } truespeech_save_prevvec(c); - - /* finally output decoded frame */ - for(i = 0; i < 240; i++) - *samples++ = out_buf[i]; - } *data_size = out_size; From b84048935ec423a0c2063ffaed69b44059d0ca98 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 13 Oct 2011 00:17:05 -0400 Subject: [PATCH 12/22] truespeech: simplify truespeech_read_frame() by using get_bits() --- libavcodec/truespeech.c | 121 ++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 78 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index eec77eac9f..c48a9c1769 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -21,6 +21,8 @@ #include "libavutil/intreadwrite.h" #include "avcodec.h" +#include "dsputil.h" +#include "get_bits.h" #include "truespeech_data.h" /** @@ -32,7 +34,9 @@ * TrueSpeech decoder context */ typedef struct { + DSPContext dsp; /* input data */ + uint8_t buffer[32]; int16_t vector[8]; ///< input vector: 5/5/4/4/4/3/3/3 int offset1[2]; ///< 8-bit value, used in one copying offset int offset2[4]; ///< 7-bit value, encodes offsets for copying and for two-point filter @@ -54,7 +58,7 @@ typedef struct { static av_cold int truespeech_decode_init(AVCodecContext * avctx) { -// TSContext *c = avctx->priv_data; + TSContext *c = avctx->priv_data; if (avctx->channels != 1) { av_log_ask_for_sample(avctx, "Unsupported channel count: %d\n", avctx->channels); @@ -62,97 +66,58 @@ static av_cold int truespeech_decode_init(AVCodecContext * avctx) } avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + dsputil_init(&c->dsp, avctx); + return 0; } static void truespeech_read_frame(TSContext *dec, const uint8_t *input) { - uint32_t t; + GetBitContext gb; - /* first dword */ - t = AV_RL32(input); - input += 4; + dec->dsp.bswap_buf((uint32_t *)dec->buffer, (const uint32_t *)input, 8); + init_get_bits(&gb, dec->buffer, 32 * 8); - dec->flag = t & 1; + dec->vector[7] = ts_codebook[7][get_bits(&gb, 3)]; + dec->vector[6] = ts_codebook[6][get_bits(&gb, 3)]; + dec->vector[5] = ts_codebook[5][get_bits(&gb, 3)]; + dec->vector[4] = ts_codebook[4][get_bits(&gb, 4)]; + dec->vector[3] = ts_codebook[3][get_bits(&gb, 4)]; + dec->vector[2] = ts_codebook[2][get_bits(&gb, 4)]; + dec->vector[1] = ts_codebook[1][get_bits(&gb, 5)]; + dec->vector[0] = ts_codebook[0][get_bits(&gb, 5)]; + dec->flag = get_bits1(&gb); - dec->vector[0] = ts_codebook[0][(t >> 1) & 0x1F]; - dec->vector[1] = ts_codebook[1][(t >> 6) & 0x1F]; - dec->vector[2] = ts_codebook[2][(t >> 11) & 0xF]; - dec->vector[3] = ts_codebook[3][(t >> 15) & 0xF]; - dec->vector[4] = ts_codebook[4][(t >> 19) & 0xF]; - dec->vector[5] = ts_codebook[5][(t >> 23) & 0x7]; - dec->vector[6] = ts_codebook[6][(t >> 26) & 0x7]; - dec->vector[7] = ts_codebook[7][(t >> 29) & 0x7]; + dec->offset1[0] = get_bits(&gb, 4) << 4; + dec->offset2[3] = get_bits(&gb, 7); + dec->offset2[2] = get_bits(&gb, 7); + dec->offset2[1] = get_bits(&gb, 7); + dec->offset2[0] = get_bits(&gb, 7); - /* second dword */ - t = AV_RL32(input); - input += 4; + dec->offset1[1] = get_bits(&gb, 4); + dec->pulseval[1] = get_bits(&gb, 14); + dec->pulseval[0] = get_bits(&gb, 14); - dec->offset2[0] = (t >> 0) & 0x7F; - dec->offset2[1] = (t >> 7) & 0x7F; - dec->offset2[2] = (t >> 14) & 0x7F; - dec->offset2[3] = (t >> 21) & 0x7F; + dec->offset1[1] |= get_bits(&gb, 4) << 4; + dec->pulseval[3] = get_bits(&gb, 14); + dec->pulseval[2] = get_bits(&gb, 14); - dec->offset1[0] = ((t >> 28) & 0xF) << 4; + dec->offset1[0] |= get_bits1(&gb); + dec->pulsepos[0] = get_bits_long(&gb, 27); + dec->pulseoff[0] = get_bits(&gb, 4); - /* third dword */ - t = AV_RL32(input); - input += 4; + dec->offset1[0] |= get_bits1(&gb) << 1; + dec->pulsepos[1] = get_bits_long(&gb, 27); + dec->pulseoff[1] = get_bits(&gb, 4); - dec->pulseval[0] = (t >> 0) & 0x3FFF; - dec->pulseval[1] = (t >> 14) & 0x3FFF; - - dec->offset1[1] = (t >> 28) & 0x0F; - - /* fourth dword */ - t = AV_RL32(input); - input += 4; - - dec->pulseval[2] = (t >> 0) & 0x3FFF; - dec->pulseval[3] = (t >> 14) & 0x3FFF; - - dec->offset1[1] |= ((t >> 28) & 0x0F) << 4; - - /* fifth dword */ - t = AV_RL32(input); - input += 4; - - dec->pulsepos[0] = (t >> 4) & 0x7FFFFFF; - - dec->pulseoff[0] = (t >> 0) & 0xF; - - dec->offset1[0] |= (t >> 31) & 1; - - /* sixth dword */ - t = AV_RL32(input); - input += 4; - - dec->pulsepos[1] = (t >> 4) & 0x7FFFFFF; - - dec->pulseoff[1] = (t >> 0) & 0xF; - - dec->offset1[0] |= ((t >> 31) & 1) << 1; - - /* seventh dword */ - t = AV_RL32(input); - input += 4; - - dec->pulsepos[2] = (t >> 4) & 0x7FFFFFF; - - dec->pulseoff[2] = (t >> 0) & 0xF; - - dec->offset1[0] |= ((t >> 31) & 1) << 2; - - /* eighth dword */ - t = AV_RL32(input); - input += 4; - - dec->pulsepos[3] = (t >> 4) & 0x7FFFFFF; - - dec->pulseoff[3] = (t >> 0) & 0xF; - - dec->offset1[0] |= ((t >> 31) & 1) << 3; + dec->offset1[0] |= get_bits1(&gb) << 2; + dec->pulsepos[2] = get_bits_long(&gb, 27); + dec->pulseoff[2] = get_bits(&gb, 4); + dec->offset1[0] |= get_bits1(&gb) << 3; + dec->pulsepos[3] = get_bits_long(&gb, 27); + dec->pulseoff[3] = get_bits(&gb, 4); } static void truespeech_correlate_filter(TSContext *dec) From 6d55506c8bbe9f7b4dba244d40519832eff66c9b Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 13 Oct 2011 00:21:17 -0400 Subject: [PATCH 13/22] truespeech: remove unneeded variable, 'consumed' increment the 'buf' pointer instead, and consume the whole packet. --- libavcodec/truespeech.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index c48a9c1769..72d828a9cb 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -310,7 +310,6 @@ static int truespeech_decode_frame(AVCodecContext *avctx, int i, j; short *samples = data; - int consumed = 0; int iterations, out_size; iterations = buf_size / 32; @@ -330,8 +329,8 @@ static int truespeech_decode_frame(AVCodecContext *avctx, memset(samples, 0, out_size); for(j = 0; j < iterations; j++) { - truespeech_read_frame(c, buf + consumed); - consumed += 32; + truespeech_read_frame(c, buf); + buf += 32; truespeech_correlate_filter(c); truespeech_filters_merge(c); @@ -349,7 +348,7 @@ static int truespeech_decode_frame(AVCodecContext *avctx, *data_size = out_size; - return consumed; + return buf_size; } AVCodec ff_truespeech_decoder = { From c6ac30c84b1d6a21af49b72f13ba2248e6b2844d Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Thu, 13 Oct 2011 14:03:17 -0400 Subject: [PATCH 14/22] truespeech: use sizeof() instead of hardcoded sizes --- libavcodec/truespeech.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/truespeech.c b/libavcodec/truespeech.c index 72d828a9cb..7747fca6b2 100644 --- a/libavcodec/truespeech.c +++ b/libavcodec/truespeech.c @@ -127,7 +127,7 @@ static void truespeech_correlate_filter(TSContext *dec) for(i = 0; i < 8; i++){ if(i > 0){ - memcpy(tmp, dec->cvector, i * 2); + memcpy(tmp, dec->cvector, i * sizeof(*tmp)); for(j = 0; j < i; j++) dec->cvector[j] = ((tmp[i - j - 1] * dec->vector[i]) + (dec->cvector[j] << 15) + 0x4000) >> 15; @@ -169,7 +169,7 @@ static void truespeech_apply_twopoint_filter(TSContext *dec, int quart) t = dec->offset2[quart]; if(t == 127){ - memset(dec->newvec, 0, 60 * 2); + memset(dec->newvec, 0, 60 * sizeof(*dec->newvec)); return; } for(i = 0; i < 146; i++) @@ -194,7 +194,7 @@ static void truespeech_place_pulses(TSContext *dec, int16_t *out, int quart) int16_t *ptr2; int coef; - memset(out, 0, 60 * 2); + memset(out, 0, 60 * sizeof(*out)); for(i = 0; i < 7; i++) { t = dec->pulseval[quart] & 3; dec->pulseval[quart] >>= 2; From 0041cdba98d5b636a8d912352dd3d8ca72bba4ce Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 16 Sep 2011 19:02:23 -0400 Subject: [PATCH 15/22] avformat: don't unconditionally call ff_read_frame_flush() when trying to seek. This prevents flushing the packet buffer when the input format does not support seeking. --- libavformat/utils.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index e4e6d24e53..fc17f18464 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1749,10 +1749,10 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f int ret; AVStream *st; - ff_read_frame_flush(s); - - if(flags & AVSEEK_FLAG_BYTE) + if (flags & AVSEEK_FLAG_BYTE) { + ff_read_frame_flush(s); return seek_frame_byte(s, stream_index, timestamp, flags); + } if(stream_index < 0){ stream_index= av_find_default_stream_index(s); @@ -1765,18 +1765,22 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f } /* first, we try the format specific seek */ - if (s->iformat->read_seek) + if (s->iformat->read_seek) { + ff_read_frame_flush(s); ret = s->iformat->read_seek(s, stream_index, timestamp, flags); - else + } else ret = -1; if (ret >= 0) { return 0; } - if(s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) + if (s->iformat->read_timestamp && !(s->iformat->flags & AVFMT_NOBINSEARCH)) { + ff_read_frame_flush(s); return av_seek_frame_binary(s, stream_index, timestamp, flags); - else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) + } else if (!(s->iformat->flags & AVFMT_NOGENSEARCH)) { + ff_read_frame_flush(s); return seek_frame_generic(s, stream_index, timestamp, flags); + } else return -1; } @@ -1786,10 +1790,10 @@ int avformat_seek_file(AVFormatContext *s, int stream_index, int64_t min_ts, int if(min_ts > ts || max_ts < ts) return -1; - ff_read_frame_flush(s); - - if (s->iformat->read_seek2) + if (s->iformat->read_seek2) { + ff_read_frame_flush(s); return s->iformat->read_seek2(s, stream_index, min_ts, ts, max_ts, flags); + } if(s->iformat->read_timestamp){ //try to seek via read_timestamp() From 050e20aee653bf17c0e8d0317b50cfe0a7142366 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 2 Oct 2011 11:29:20 -0400 Subject: [PATCH 16/22] avformat: update AVInputFormat allowed flags --- libavformat/avformat.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index cc5457e8a2..7b350f15cd 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -406,7 +406,9 @@ typedef struct AVInputFormat { int64_t *pos, int64_t pos_limit); /** - * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER. + * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, + * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, + * AVFMT_NOGENSEARCH. */ int flags; From b631fba936d2b353f3c2a76f746bc40a1a193b75 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 2 Oct 2011 11:57:53 -0400 Subject: [PATCH 17/22] avformat: add AVInputFormat flag AVFMT_NO_BYTE_SEEK. This will prevent seeking by bytes for formats that cannot handle this. --- doc/APIchanges | 3 +++ libavformat/avformat.h | 3 ++- libavformat/utils.c | 2 ++ libavformat/version.h | 2 +- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index e48173c516..c4557f06a0 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -13,6 +13,9 @@ libavutil: 2011-04-18 API changes, most recent first: +2011-xx-xx - xxxxxxx - lavf 53.9.0 + Add AVFMT_NO_BYTE_SEEK AVInputFormat flag. + 2011-10-12 - lavu 51.12.0 AVOptions API rewrite. diff --git a/libavformat/avformat.h b/libavformat/avformat.h index 7b350f15cd..70d466e0d1 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -274,6 +274,7 @@ typedef struct AVFormatParameters { #define AVFMT_NOSTREAMS 0x1000 /**< Format does not require any streams */ #define AVFMT_NOBINSEARCH 0x2000 /**< Format does not allow to fallback to binary search via read_timestamp */ #define AVFMT_NOGENSEARCH 0x4000 /**< Format does not allow to fallback to generic search */ +#define AVFMT_NO_BYTE_SEEK 0x8000 /**< Format does not allow seeking by bytes */ typedef struct AVOutputFormat { const char *name; @@ -408,7 +409,7 @@ typedef struct AVInputFormat { /** * Can use flags: AVFMT_NOFILE, AVFMT_NEEDNUMBER, AVFMT_SHOW_IDS, * AVFMT_GENERIC_INDEX, AVFMT_TS_DISCONT, AVFMT_NOBINSEARCH, - * AVFMT_NOGENSEARCH. + * AVFMT_NOGENSEARCH, AVFMT_NO_BYTE_SEEK. */ int flags; diff --git a/libavformat/utils.c b/libavformat/utils.c index fc17f18464..3115723668 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -1750,6 +1750,8 @@ int av_seek_frame(AVFormatContext *s, int stream_index, int64_t timestamp, int f AVStream *st; if (flags & AVSEEK_FLAG_BYTE) { + if (s->iformat->flags & AVFMT_NO_BYTE_SEEK) + return -1; ff_read_frame_flush(s); return seek_frame_byte(s, stream_index, timestamp, flags); } diff --git a/libavformat/version.h b/libavformat/version.h index 82a07dbc32..53c585a06b 100644 --- a/libavformat/version.h +++ b/libavformat/version.h @@ -24,7 +24,7 @@ #include "libavutil/avutil.h" #define LIBAVFORMAT_VERSION_MAJOR 53 -#define LIBAVFORMAT_VERSION_MINOR 8 +#define LIBAVFORMAT_VERSION_MINOR 9 #define LIBAVFORMAT_VERSION_MICRO 0 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \ From e32dfdaa8dbe77ffd47e8a66261584ad4ed5931c Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 2 Oct 2011 12:03:22 -0400 Subject: [PATCH 18/22] shn: do not allow seeking in the raw shn demuxer. The demuxer does not read the seektable, a parser is not possible without a full decode, and no shorten decoder can handle random seeking because it needs side info from the seektable. --- libavformat/rawdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/rawdec.c b/libavformat/rawdec.c index ab0e98c94a..c4c027ab06 100644 --- a/libavformat/rawdec.c +++ b/libavformat/rawdec.c @@ -244,7 +244,7 @@ AVInputFormat ff_shorten_demuxer = { .long_name = NULL_IF_CONFIG_SMALL("raw Shorten"), .read_header = ff_raw_audio_read_header, .read_packet = ff_raw_read_partial_packet, - .flags= AVFMT_GENERIC_INDEX, + .flags = AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK, .extensions = "shn", .value = CODEC_ID_SHORTEN, }; From 617a51f9b7a5be6b660bfd45bcd84f8ac3510c4e Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Fri, 16 Sep 2011 22:21:47 -0400 Subject: [PATCH 19/22] shorten: remove the flush function. The shorten decoder does not support seeking. --- libavcodec/shorten.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 22c5c0a152..dd1bef8a18 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -534,13 +534,6 @@ static av_cold int shorten_decode_close(AVCodecContext *avctx) return 0; } -static void shorten_flush(AVCodecContext *avctx){ - ShortenContext *s = avctx->priv_data; - - s->bitstream_size= - s->bitstream_index= 0; -} - AVCodec ff_shorten_decoder = { .name = "shorten", .type = AVMEDIA_TYPE_AUDIO, @@ -549,6 +542,5 @@ AVCodec ff_shorten_decoder = { .init = shorten_decode_init, .close = shorten_decode_close, .decode = shorten_decode_frame, - .flush= shorten_flush, .long_name= NULL_IF_CONFIG_SMALL("Shorten"), }; From 3b78c180e44a0fe82c38dc8fb1af66d7fde20ab8 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 10 Oct 2011 15:48:59 +0200 Subject: [PATCH 20/22] id3v2: cosmetics: move some declarations before the places they are used --- libavformat/id3v2.c | 130 ++++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index cea0ee04f1..9c715eeefa 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -26,6 +26,66 @@ #include "libavutil/dict.h" #include "avio_internal.h" +const AVMetadataConv ff_id3v2_34_metadata_conv[] = { + { "TALB", "album"}, + { "TCOM", "composer"}, + { "TCON", "genre"}, + { "TCOP", "copyright"}, + { "TENC", "encoded_by"}, + { "TIT2", "title"}, + { "TLAN", "language"}, + { "TPE1", "artist"}, + { "TPE2", "album_artist"}, + { "TPE3", "performer"}, + { "TPOS", "disc"}, + { "TPUB", "publisher"}, + { "TRCK", "track"}, + { "TSSE", "encoder"}, + { 0 } +}; + +const AVMetadataConv ff_id3v2_4_metadata_conv[] = { + { "TDRL", "date"}, + { "TDRC", "date"}, + { "TDEN", "creation_time"}, + { "TSOA", "album-sort"}, + { "TSOP", "artist-sort"}, + { "TSOT", "title-sort"}, + { 0 } +}; + +const AVMetadataConv ff_id3v2_2_metadata_conv[] = { + { "TAL", "album"}, + { "TCO", "genre"}, + { "TT2", "title"}, + { "TEN", "encoded_by"}, + { "TP1", "artist"}, + { "TP2", "album_artist"}, + { "TP3", "performer"}, + { "TRK", "track"}, + { 0 } +}; + + +const char ff_id3v2_tags[][4] = { + "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT", + "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", + "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", + "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE", + { 0 }, +}; + +const char ff_id3v2_4_tags[][4] = { + "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO", + "TPRO", "TSOA", "TSOP", "TSOT", "TSST", + { 0 }, +}; + +const char ff_id3v2_3_tags[][4] = { + "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER", + { 0 }, +}; + int ff_id3v2_match(const uint8_t *buf, const char * magic) { return buf[0] == magic[0] && @@ -320,6 +380,11 @@ finish: av_dict_set(m, "date", date, 0); } +const ID3v2EMFunc ff_id3v2_extra_meta_funcs[] = { + { "GEO", "GEOB", read_geobtag, free_geobtag }, + { NULL } +}; + /** * Get the corresponding ID3v2EMFunc struct for a tag. * @param isv34 Determines if v2.2 or v2.3/4 strings are used @@ -518,68 +583,3 @@ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta) current = next; } } - -const ID3v2EMFunc ff_id3v2_extra_meta_funcs[] = { - { "GEO", "GEOB", read_geobtag, free_geobtag }, - { NULL } -}; - -const AVMetadataConv ff_id3v2_34_metadata_conv[] = { - { "TALB", "album"}, - { "TCOM", "composer"}, - { "TCON", "genre"}, - { "TCOP", "copyright"}, - { "TENC", "encoded_by"}, - { "TIT2", "title"}, - { "TLAN", "language"}, - { "TPE1", "artist"}, - { "TPE2", "album_artist"}, - { "TPE3", "performer"}, - { "TPOS", "disc"}, - { "TPUB", "publisher"}, - { "TRCK", "track"}, - { "TSSE", "encoder"}, - { 0 } -}; - -const AVMetadataConv ff_id3v2_4_metadata_conv[] = { - { "TDRL", "date"}, - { "TDRC", "date"}, - { "TDEN", "creation_time"}, - { "TSOA", "album-sort"}, - { "TSOP", "artist-sort"}, - { "TSOT", "title-sort"}, - { 0 } -}; - -const AVMetadataConv ff_id3v2_2_metadata_conv[] = { - { "TAL", "album"}, - { "TCO", "genre"}, - { "TT2", "title"}, - { "TEN", "encoded_by"}, - { "TP1", "artist"}, - { "TP2", "album_artist"}, - { "TP3", "performer"}, - { "TRK", "track"}, - { 0 } -}; - - -const char ff_id3v2_tags[][4] = { - "TALB", "TBPM", "TCOM", "TCON", "TCOP", "TDLY", "TENC", "TEXT", - "TFLT", "TIT1", "TIT2", "TIT3", "TKEY", "TLAN", "TLEN", "TMED", - "TOAL", "TOFN", "TOLY", "TOPE", "TOWN", "TPE1", "TPE2", "TPE3", - "TPE4", "TPOS", "TPUB", "TRCK", "TRSN", "TRSO", "TSRC", "TSSE", - { 0 }, -}; - -const char ff_id3v2_4_tags[][4] = { - "TDEN", "TDOR", "TDRC", "TDRL", "TDTG", "TIPL", "TMCL", "TMOO", - "TPRO", "TSOA", "TSOP", "TSOT", "TSST", - { 0 }, -}; - -const char ff_id3v2_3_tags[][4] = { - "TDAT", "TIME", "TORY", "TRDA", "TSIZ", "TYER", - { 0 }, -}; From c4a378855e7a37605af3f9120537ed9bbc5d3996 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Mon, 10 Oct 2011 15:51:02 +0200 Subject: [PATCH 21/22] id3v2: reduce the scope of some non-globally-used symbols/structures --- libavformat/id3v2.c | 22 ++++++++++++++-------- libavformat/id3v2.h | 10 ---------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index 9c715eeefa..c593007e87 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -54,7 +54,7 @@ const AVMetadataConv ff_id3v2_4_metadata_conv[] = { { 0 } }; -const AVMetadataConv ff_id3v2_2_metadata_conv[] = { +static const AVMetadataConv id3v2_2_metadata_conv[] = { { "TAL", "album"}, { "TCO", "genre"}, { "TT2", "title"}, @@ -380,7 +380,14 @@ finish: av_dict_set(m, "date", date, 0); } -const ID3v2EMFunc ff_id3v2_extra_meta_funcs[] = { +typedef struct ID3v2EMFunc { + const char *tag3; + const char *tag4; + void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **); + void (*free)(); +} ID3v2EMFunc; + +static const ID3v2EMFunc id3v2_extra_meta_funcs[] = { { "GEO", "GEOB", read_geobtag, free_geobtag }, { NULL } }; @@ -393,13 +400,12 @@ const ID3v2EMFunc ff_id3v2_extra_meta_funcs[] = { static const ID3v2EMFunc *get_extra_meta_func(const char *tag, int isv34) { int i = 0; - while (ff_id3v2_extra_meta_funcs[i].tag3) { + while (id3v2_extra_meta_funcs[i].tag3) { if (!memcmp(tag, - (isv34 ? - ff_id3v2_extra_meta_funcs[i].tag4 : - ff_id3v2_extra_meta_funcs[i].tag3), + (isv34 ? id3v2_extra_meta_funcs[i].tag4 : + id3v2_extra_meta_funcs[i].tag3), (isv34 ? 4 : 3))) - return &ff_id3v2_extra_meta_funcs[i]; + return &id3v2_extra_meta_funcs[i]; i++; } return NULL; @@ -560,7 +566,7 @@ void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **e } } while (found_header); ff_metadata_conv(&s->metadata, NULL, ff_id3v2_34_metadata_conv); - ff_metadata_conv(&s->metadata, NULL, ff_id3v2_2_metadata_conv); + ff_metadata_conv(&s->metadata, NULL, id3v2_2_metadata_conv); ff_metadata_conv(&s->metadata, NULL, ff_id3v2_4_metadata_conv); merge_date(&s->metadata); } diff --git a/libavformat/id3v2.h b/libavformat/id3v2.h index 13dec399d1..4fb738a764 100644 --- a/libavformat/id3v2.h +++ b/libavformat/id3v2.h @@ -59,13 +59,6 @@ typedef struct ID3v2ExtraMetaGEOB { uint8_t *data; } ID3v2ExtraMetaGEOB; -typedef struct ID3v2EMFunc { - const char *tag3; - const char *tag4; - void (*read)(AVFormatContext*, AVIOContext*, int, char*, ID3v2ExtraMeta **); - void (*free)(); -} ID3v2EMFunc; - /** * Detect ID3v2 Header. * @param buf must be ID3v2_HEADER_SIZE byte long @@ -99,11 +92,8 @@ void ff_id3v2_read_all(AVFormatContext *s, const char *magic, ID3v2ExtraMeta **e */ void ff_id3v2_free_extra_meta(ID3v2ExtraMeta **extra_meta); -extern const ID3v2EMFunc ff_id3v2_extra_meta_funcs[]; - extern const AVMetadataConv ff_id3v2_34_metadata_conv[]; extern const AVMetadataConv ff_id3v2_4_metadata_conv[]; -extern const AVMetadataConv ff_id3v2_2_metadata_conv[]; /** * A list of text information frames allowed in both ID3 v2.3 and v2.4 From a62d36697d3cefc705736d21fcaede425147b5f0 Mon Sep 17 00:00:00 2001 From: Diego Biurrun Date: Fri, 23 Sep 2011 02:06:23 +0200 Subject: [PATCH 22/22] prores: add FATE tests --- tests/Makefile | 1 + tests/fate/prores.mak | 15 +++++++++++++++ tests/ref/fate/prores-422 | 2 ++ tests/ref/fate/prores-422_hq | 2 ++ tests/ref/fate/prores-422_lt | 2 ++ tests/ref/fate/prores-422_proxy | 2 ++ tests/ref/fate/prores-alpha | 2 ++ 7 files changed, 26 insertions(+) create mode 100644 tests/fate/prores.mak create mode 100644 tests/ref/fate/prores-422 create mode 100644 tests/ref/fate/prores-422_hq create mode 100644 tests/ref/fate/prores-422_lt create mode 100644 tests/ref/fate/prores-422_proxy create mode 100644 tests/ref/fate/prores-alpha diff --git a/tests/Makefile b/tests/Makefile index c0afffddb3..1ec9dc342c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -31,6 +31,7 @@ include $(SRC_PATH)/tests/fate/fft.mak include $(SRC_PATH)/tests/fate/h264.mak include $(SRC_PATH)/tests/fate/libavutil.mak include $(SRC_PATH)/tests/fate/mp3.mak +include $(SRC_PATH)/tests/fate/prores.mak include $(SRC_PATH)/tests/fate/vorbis.mak include $(SRC_PATH)/tests/fate/vp8.mak diff --git a/tests/fate/prores.mak b/tests/fate/prores.mak new file mode 100644 index 0000000000..7be756da9e --- /dev/null +++ b/tests/fate/prores.mak @@ -0,0 +1,15 @@ +FATE_PRORES = fate-prores-422 \ + fate-prores-422_hq \ + fate-prores-422_lt \ + fate-prores-422_proxy \ + fate-prores-alpha \ + +FATE_TESTS += $(FATE_PRORES) +fate-prores: $(FATE_PRORES) + +fate-prores-422: CMD = framecrc -vsync 0 -i $(SAMPLES)/prores/Sequence_1-Apple_ProRes_422.mov +fate-prores-422_hq: CMD = framecrc -vsync 0 -i $(SAMPLES)/prores/Sequence_1-Apple_ProRes_422_HQ.mov +fate-prores-422_lt: CMD = framecrc -vsync 0 -i $(SAMPLES)/prores/Sequence_1-Apple_ProRes_422_LT.mov +fate-prores-422_proxy: CMD = framecrc -vsync 0 -i $(SAMPLES)/prores/Sequence_1-Apple_ProRes_422_Proxy.mov +fate-prores-alpha: CMD = framecrc -vsync 0 -i $(SAMPLES)/prores/Sequence_1-Apple_ProRes_with_Alpha.mov + diff --git a/tests/ref/fate/prores-422 b/tests/ref/fate/prores-422 new file mode 100644 index 0000000000..8d6f3ab517 --- /dev/null +++ b/tests/ref/fate/prores-422 @@ -0,0 +1,2 @@ +0, 0, 8294400, 0xe8e9d448 +0, 3003, 8294400, 0xe8e9d448 diff --git a/tests/ref/fate/prores-422_hq b/tests/ref/fate/prores-422_hq new file mode 100644 index 0000000000..8ce6937cf5 --- /dev/null +++ b/tests/ref/fate/prores-422_hq @@ -0,0 +1,2 @@ +0, 0, 8294400, 0x817063b0 +0, 3003, 8294400, 0x817063b0 diff --git a/tests/ref/fate/prores-422_lt b/tests/ref/fate/prores-422_lt new file mode 100644 index 0000000000..e9d0437568 --- /dev/null +++ b/tests/ref/fate/prores-422_lt @@ -0,0 +1,2 @@ +0, 0, 8294400, 0xcd4ccde1 +0, 3003, 8294400, 0xcd4ccde1 diff --git a/tests/ref/fate/prores-422_proxy b/tests/ref/fate/prores-422_proxy new file mode 100644 index 0000000000..c9e454fd61 --- /dev/null +++ b/tests/ref/fate/prores-422_proxy @@ -0,0 +1,2 @@ +0, 0, 8294400, 0x51d29320 +0, 3003, 8294400, 0x51d29320 diff --git a/tests/ref/fate/prores-alpha b/tests/ref/fate/prores-alpha new file mode 100644 index 0000000000..2e17020548 --- /dev/null +++ b/tests/ref/fate/prores-alpha @@ -0,0 +1,2 @@ +0, 0, 8294400, 0xee48d74b +0, 3003, 8294400, 0x2a0c7eb1