From 240ae356e9c12c9b56e58e9245a58f3716815d13 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 23 Sep 2011 12:46:05 +0200 Subject: [PATCH 1/8] avconv: remove fake coded_frame on streamcopy hack Back in 2002 when it was added, some muxers used information from coded_frame. It's not true anymore, so this hack is useless and can be removed. --- avconv.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/avconv.c b/avconv.c index fb744bd537..43792e119b 100644 --- a/avconv.c +++ b/avconv.c @@ -1755,7 +1755,6 @@ static int output_packet(InputStream *ist, int ist_index, abort(); } } else { - AVFrame avframe; //FIXME/XXX remove this AVPacket opkt; int64_t ost_tb_start_time= av_rescale_q(of->start_time, AV_TIME_BASE_Q, ost->st->time_base); @@ -1771,10 +1770,6 @@ static int output_packet(InputStream *ist, int ist_index, /* no reencoding needed : output the packet directly */ /* force the input stream PTS */ - avcodec_get_frame_defaults(&avframe); - ost->st->codec->coded_frame= &avframe; - avframe.key_frame = pkt->flags & AV_PKT_FLAG_KEY; - if(ost->st->codec->codec_type == AVMEDIA_TYPE_AUDIO) audio_size += data_size; else if (ost->st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { From 9b921a8272cfcf5168a03042a6d84091cd33ee7b Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 23 Sep 2011 14:40:29 +0200 Subject: [PATCH 2/8] avconv: use correct output stream index when checking max_frames --- avconv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/avconv.c b/avconv.c index 43792e119b..9e2fac7f3b 100644 --- a/avconv.c +++ b/avconv.c @@ -2333,8 +2333,8 @@ static int transcode(OutputFile *output_files, } if (ost->frame_number >= ost->max_frames) { int j; - for (j = of->ost_index; j < of->ctx->nb_streams; j++) - output_streams[j].is_past_recording_time = 1; + for (j = 0; j < of->ctx->nb_streams; j++) + output_streams[of->ost_index + j].is_past_recording_time = 1; continue; } } From a246cefa75aed2ade315d6d09068aacb6b0fe76b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 24 Sep 2011 18:57:31 +0300 Subject: [PATCH 3/8] flvdec: Check for overflow before allocating arrays MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On allocation, the array length is multiplied by sizeof(int64_t), this prevents the multiplication from overflowing. Signed-off-by: Martin Storsjö --- libavformat/flvdec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c index 474c4d8658..ad00c65e25 100644 --- a/libavformat/flvdec.c +++ b/libavformat/flvdec.c @@ -161,6 +161,9 @@ static int parse_keyframes_index(AVFormatContext *s, AVIOContext *ioc, AVStream break; arraylen = avio_rb32(ioc); + if (arraylen >> 28) + break; + /* * Expect only 'times' or 'filepositions' sub-arrays in other case refuse to use such metadata * for indexing From d1186ff72d75b6067770890758c4feb92abd84f7 Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sat, 24 Sep 2011 16:16:39 +0200 Subject: [PATCH 4/8] h264: check for out of bounds reads in ff_h264_decode_extradata(). Signed-off-by: Anton Khirnov --- libavcodec/h264.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index 9889224abd..e5d0ed8660 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1005,6 +1005,8 @@ int ff_h264_decode_extradata(H264Context *h) p += 6; for (i = 0; i < cnt; i++) { nalsize = AV_RB16(p) + 2; + if (p - avctx->extradata + nalsize > avctx->extradata_size) + return -1; if(decode_nal_units(h, p, nalsize) < 0) { av_log(avctx, AV_LOG_ERROR, "Decoding sps %d from avcC failed\n", i); return -1; @@ -1015,6 +1017,8 @@ int ff_h264_decode_extradata(H264Context *h) cnt = *(p++); // Number of pps for (i = 0; i < cnt; i++) { nalsize = AV_RB16(p) + 2; + if (p - avctx->extradata + nalsize > avctx->extradata_size) + return -1; if (decode_nal_units(h, p, nalsize) < 0) { av_log(avctx, AV_LOG_ERROR, "Decoding pps %d from avcC failed\n", i); return -1; From bb416bd68ca46b4a3f1901533064d56a6b8ac95e Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 17 Jul 2011 16:02:33 +0100 Subject: [PATCH 5/8] lavf: do not set codec_tag for rawvideo If the demuxer did not set a codec_tag, there is none and inventing one makes no sense. This change stops the rawvideo "decoder" over-writing user-supplied pixfmt with one derived from the codec_tag. The pixfmt-codec_tag-pixfmt round-trip is lossy since several pixfmts map to the same codec_tag. This fixes fate-lavf-pixfmt with avfilter disabled. Signed-off-by: Mans Rullgard --- libavformat/utils.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index 17b342e8ad..b59cde0a2f 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -2418,9 +2418,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options) (st->codec_info_nb_frames-2)*(int64_t)st->time_base.den, st->info->codec_info_duration*(int64_t)st->time_base.num, 60000); if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { - if(st->codec->codec_id == CODEC_ID_RAWVIDEO && !st->codec->codec_tag && !st->codec->bits_per_coded_sample) - st->codec->codec_tag= avcodec_pix_fmt_to_codec_tag(st->codec->pix_fmt); - // the check for tb_unreliable() is not completely correct, since this is not about handling // a unreliable/inexact time base, but a time base that is finer than necessary, as e.g. // ipmovie.c produces. From 4568c2bf975e51d843bf1ff6ac06060a8a6291b3 Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Sun, 11 Sep 2011 20:17:54 -0400 Subject: [PATCH 6/8] vmdaudio: fix decoding of 16-bit audio format. The initial sample of each block is raw 16-bit PCM, not DPCM. Fixes decoding of all samples in: http://streams.videolan.org/samples/game-formats/sierra-vmd/Lighthouse/ --- libavcodec/vmdav.c | 120 ++++++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 40 deletions(-) diff --git a/libavcodec/vmdav.c b/libavcodec/vmdav.c index 110d19cd9a..45289966b7 100644 --- a/libavcodec/vmdav.c +++ b/libavcodec/vmdav.c @@ -417,9 +417,8 @@ static av_cold int vmdvideo_decode_end(AVCodecContext *avctx) #define BLOCK_TYPE_SILENCE 3 typedef struct VmdAudioContext { - AVCodecContext *avctx; int out_bps; - int predictors[2]; + int chunk_size; } VmdAudioContext; static const uint16_t vmdaudio_table[128] = { @@ -442,13 +441,23 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) { VmdAudioContext *s = avctx->priv_data; - s->avctx = avctx; + if (avctx->channels < 1 || avctx->channels > 2) { + av_log(avctx, AV_LOG_ERROR, "invalid number of channels\n"); + return AVERROR(EINVAL); + } + if (avctx->block_align < 1) { + av_log(avctx, AV_LOG_ERROR, "invalid block align\n"); + return AVERROR(EINVAL); + } + if (avctx->bits_per_coded_sample == 16) avctx->sample_fmt = AV_SAMPLE_FMT_S16; else avctx->sample_fmt = AV_SAMPLE_FMT_U8; s->out_bps = av_get_bytes_per_sample(avctx->sample_fmt); + s->chunk_size = avctx->block_align + avctx->channels * (s->out_bps == 2); + av_log(avctx, AV_LOG_DEBUG, "%d channels, %d bits/sample, " "block align = %d, sample rate = %d\n", avctx->channels, avctx->bits_per_coded_sample, avctx->block_align, @@ -457,41 +466,33 @@ static av_cold int vmdaudio_decode_init(AVCodecContext *avctx) return 0; } -static void vmdaudio_decode_audio(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int buf_size, int stereo) +static void decode_audio_s16(int16_t *out, const uint8_t *buf, int buf_size, + int channels) { - int i; - int chan = 0; - int16_t *out = (int16_t*)data; - - for(i = 0; i < buf_size; i++) { - if(buf[i] & 0x80) - s->predictors[chan] -= vmdaudio_table[buf[i] & 0x7F]; - else - s->predictors[chan] += vmdaudio_table[buf[i]]; - s->predictors[chan] = av_clip_int16(s->predictors[chan]); - out[i] = s->predictors[chan]; - chan ^= stereo; + int ch; + const uint8_t *buf_end = buf + buf_size; + int predictor[2]; + int st = channels - 1; + + /* decode initial raw sample */ + for (ch = 0; ch < channels; ch++) { + predictor[ch] = (int16_t)AV_RL16(buf); + buf += 2; + *out++ = predictor[ch]; } -} -static int vmdaudio_loadsound(VmdAudioContext *s, unsigned char *data, - const uint8_t *buf, int silent_chunks, int data_size) -{ - int silent_size = s->avctx->block_align * silent_chunks * s->out_bps; - - if (silent_chunks) { - memset(data, s->out_bps == 2 ? 0x00 : 0x80, silent_size); - data += silent_size; - } - if (s->avctx->bits_per_coded_sample == 16) - vmdaudio_decode_audio(s, data, buf, data_size, s->avctx->channels == 2); - else { - /* just copy the data */ - memcpy(data, buf, data_size); + /* decode DPCM samples */ + ch = 0; + while (buf < buf_end) { + uint8_t b = *buf++; + if (b & 0x80) + predictor[ch] -= vmdaudio_table[b & 0x7F]; + else + predictor[ch] += vmdaudio_table[b]; + predictor[ch] = av_clip_int16(predictor[ch]); + *out++ = predictor[ch]; + ch ^= st; } - - return silent_size + data_size * s->out_bps; } static int vmdaudio_decode_frame(AVCodecContext *avctx, @@ -499,10 +500,13 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, AVPacket *avpkt) { const uint8_t *buf = avpkt->data; + const uint8_t *buf_end; int buf_size = avpkt->size; VmdAudioContext *s = avctx->priv_data; - int block_type, silent_chunks; - unsigned char *output_samples = (unsigned char *)data; + int block_type, silent_chunks, audio_chunks; + int nb_samples, out_size; + uint8_t *output_samples_u8 = data; + int16_t *output_samples_s16 = data; if (buf_size < 16) { av_log(avctx, AV_LOG_WARNING, "skipping small junk packet\n"); @@ -518,10 +522,16 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, buf += 16; buf_size -= 16; + /* get number of silent chunks */ silent_chunks = 0; if (block_type == BLOCK_TYPE_INITIAL) { - uint32_t flags = AV_RB32(buf); - silent_chunks = av_popcount(flags); + uint32_t flags; + if (buf_size < 4) { + av_log(avctx, AV_LOG_ERROR, "packet is too small\n"); + return AVERROR(EINVAL); + } + flags = AV_RB32(buf); + silent_chunks = av_popcount(flags); buf += 4; buf_size -= 4; } else if (block_type == BLOCK_TYPE_SILENCE) { @@ -530,11 +540,41 @@ static int vmdaudio_decode_frame(AVCodecContext *avctx, } /* ensure output buffer is large enough */ - if (*data_size < (avctx->block_align*silent_chunks + buf_size) * s->out_bps) + audio_chunks = buf_size / s->chunk_size; + nb_samples = ((silent_chunks + audio_chunks) * avctx->block_align) / avctx->channels; + out_size = nb_samples * avctx->channels * s->out_bps; + if (*data_size < out_size) return -1; - *data_size = vmdaudio_loadsound(s, output_samples, buf, silent_chunks, buf_size); + /* decode silent chunks */ + if (silent_chunks > 0) { + int silent_size = avctx->block_align * silent_chunks; + if (s->out_bps == 2) { + memset(output_samples_s16, 0x00, silent_size * 2); + output_samples_s16 += silent_size; + } else { + memset(output_samples_u8, 0x80, silent_size); + output_samples_u8 += silent_size; + } + } + + /* decode audio chunks */ + if (audio_chunks > 0) { + buf_end = buf + buf_size; + while (buf < buf_end) { + if (s->out_bps == 2) { + decode_audio_s16(output_samples_s16, buf, s->chunk_size, + avctx->channels); + output_samples_s16 += avctx->block_align; + } else { + memcpy(output_samples_u8, buf, s->chunk_size); + output_samples_u8 += avctx->block_align; + } + buf += s->chunk_size; + } + } + *data_size = out_size; return avpkt->size; } From 6e4a35ced96cdf31a9d3bd82fd147554750af839 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 25 Sep 2011 12:53:44 +0100 Subject: [PATCH 7/8] ppc: fix 32-bit PIC build On 32-bit ppc, the GOT pointer must be loaded manually. This adds a "get_got" assembler macro to compute the GOT address. The "movrel" macro is updated to take an additional parameter containing the GOT address since no register is reserved for this purpose on ppc32. These changes have no effect on ppc64 builds. Signed-off-by: Mans Rullgard --- libavcodec/ppc/asm.S | 19 ++++++++++++++++--- libavcodec/ppc/fft_altivec_s.S | 7 ++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/libavcodec/ppc/asm.S b/libavcodec/ppc/asm.S index 5cbbf97b64..4d4285b6d3 100644 --- a/libavcodec/ppc/asm.S +++ b/libavcodec/ppc/asm.S @@ -44,10 +44,13 @@ X(\name): L(\name): .endm -.macro movrel rd, sym +.macro movrel rd, sym, gp ld \rd, \sym@got(r2) .endm +.macro get_got rd +.endm + #else /* ARCH_PPC64 */ #define PTR .int @@ -65,15 +68,25 @@ X(\name): \name: .endm -.macro movrel rd, sym +.macro movrel rd, sym, gp #if CONFIG_PIC - lwz \rd, \sym@got(r2) + lwz \rd, \sym@got(\gp) #else lis \rd, \sym@ha la \rd, \sym@l(\rd) #endif .endm +.macro get_got rd +#if CONFIG_PIC + bcl 20, 31, .Lgot\@ +.Lgot\@: + mflr \rd + addis \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@ha + addi \rd, \rd, _GLOBAL_OFFSET_TABLE_ - .Lgot\@@l +#endif +.endm + #endif /* ARCH_PPC64 */ #if HAVE_IBM_ASM diff --git a/libavcodec/ppc/fft_altivec_s.S b/libavcodec/ppc/fft_altivec_s.S index ab33900582..958d7df0ee 100644 --- a/libavcodec/ppc/fft_altivec_s.S +++ b/libavcodec/ppc/fft_altivec_s.S @@ -353,6 +353,7 @@ extfunc ff_fft_calc\interleave\()_altivec mflr r0 stp r0, 2*PS(r1) stpu r1, -(160+16*PS)(r1) + get_got r11 addi r6, r1, 16*PS stvm r6, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29 mfvrsave r0 @@ -360,14 +361,14 @@ extfunc ff_fft_calc\interleave\()_altivec li r6, 0xfffffffc mtvrsave r6 - movrel r6, fft_data + movrel r6, fft_data, r11 lvm r6, v14, v15, v16, v17, v18, v19, v20, v21 lvm r6, v22, v23, v24, v25, v26, v27, v28, v29 li r9, 16 - movrel r12, X(ff_cos_tabs) + movrel r12, X(ff_cos_tabs), r11 - movrel r6, fft_dispatch_tab\interleave\()_altivec + movrel r6, fft_dispatch_tab\interleave\()_altivec, r11 lwz r3, 0(r3) subi r3, r3, 2 slwi r3, r3, 2+ARCH_PPC64 From d853e571ad5e7e12c6a68cfde390daced7d85fbb Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sun, 25 Sep 2011 18:27:47 +0100 Subject: [PATCH 8/8] ppc: fix some pointer to integer casts Use uintptr_t instead of plain int. Without this change, the comparisons will come out wrong for pointers in certain ranges. Fixes random failures on ppc64. Also fixes some compiler warnings. Signed-off-by: Mans Rullgard --- libswscale/ppc/swscale_altivec.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libswscale/ppc/swscale_altivec.c b/libswscale/ppc/swscale_altivec.c index 67db2de687..e73750f396 100644 --- a/libswscale/ppc/swscale_altivec.c +++ b/libswscale/ppc/swscale_altivec.c @@ -36,13 +36,13 @@ altivec_packIntArrayToCharArray(int *val, uint8_t* dest, int dstW) register int i; vector unsigned int altivec_vectorShiftInt19 = vec_add(vec_splat_u32(10), vec_splat_u32(9)); - if ((unsigned int)dest % 16) { + if ((uintptr_t)dest % 16) { /* badly aligned store, we force store alignment */ /* and will handle load misalignment on val w/ vec_perm */ vector unsigned char perm1; vector signed int v1; for (i = 0 ; (i < dstW) && - (((unsigned int)dest + i) % 16) ; i++) { + (((uintptr_t)dest + i) % 16) ; i++) { int t = val[i] >> 19; dest[i] = (t < 0) ? 0 : ((t > 255) ? 255 : t); } @@ -242,7 +242,7 @@ static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW, vector unsigned char src_v1, src_vF; vector signed short src_v, filter_v; vector signed int val_vEven, val_s; - if ((((int)src + srcPos)% 16) > 12) { + if ((((uintptr_t)src + srcPos) % 16) > 12) { src_v1 = vec_ld(srcPos + 16, src); } src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src)); @@ -281,7 +281,7 @@ static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW, vector unsigned char src_v1, src_vF; vector signed short src_v, filter_v; vector signed int val_v, val_s; - if ((((int)src + srcPos)% 16) > 8) { + if ((((uintptr_t)src + srcPos) % 16) > 8) { src_v1 = vec_ld(srcPos + 16, src); } src_vF = vec_perm(src_v0, src_v1, vec_lvsl(srcPos, src)); @@ -367,7 +367,7 @@ static void hScale_altivec_real(SwsContext *c, int16_t *dst, int dstW, //vector unsigned char src_v0 = vec_ld(srcPos + j, src); vector unsigned char src_v1, src_vF; vector signed short src_v, filter_v1R, filter_v; - if ((((int)src + srcPos)% 16) > 8) { + if ((((uintptr_t)src + srcPos) % 16) > 8) { src_v1 = vec_ld(srcPos + j + 16, src); } src_vF = vec_perm(src_v0, src_v1, permS);