From 2e74a5abc2fda6cfbc86589852d6194d502332cb Mon Sep 17 00:00:00 2001 From: Christophe GISQUET Date: Thu, 23 Feb 2012 22:25:48 +0100 Subject: [PATCH 01/17] SBR DSP: use intptr_t for the ixh parameter. Signed-off-by: Ronald S. Bultje --- libavcodec/arm/sbrdsp_init_arm.c | 2 +- libavcodec/sbrdsp.c | 2 +- libavcodec/sbrdsp.h | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libavcodec/arm/sbrdsp_init_arm.c b/libavcodec/arm/sbrdsp_init_arm.c index 2ab0df829d..04294cc401 100644 --- a/libavcodec/arm/sbrdsp_init_arm.c +++ b/libavcodec/arm/sbrdsp_init_arm.c @@ -30,7 +30,7 @@ void ff_sbr_qmf_post_shuffle_neon(float W[32][2], const float *z); void ff_sbr_qmf_deint_neg_neon(float *v, const float *src); void ff_sbr_qmf_deint_bfly_neon(float *v, const float *src0, const float *src1); void ff_sbr_hf_g_filt_neon(float (*Y)[2], const float (*X_high)[40][2], - const float *g_filt, int m_max, int ixh); + const float *g_filt, int m_max, intptr_t ixh); void ff_sbr_hf_gen_neon(float (*X_high)[2], const float (*X_low)[2], const float alpha0[2], const float alpha1[2], float bw, int start, int end); diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c index 2711e71338..aef894a51d 100644 --- a/libavcodec/sbrdsp.c +++ b/libavcodec/sbrdsp.c @@ -151,7 +151,7 @@ static void sbr_hf_gen_c(float (*X_high)[2], const float (*X_low)[2], } static void sbr_hf_g_filt_c(float (*Y)[2], const float (*X_high)[40][2], - const float *g_filt, int m_max, int ixh) + const float *g_filt, int m_max, intptr_t ixh) { int m; diff --git a/libavcodec/sbrdsp.h b/libavcodec/sbrdsp.h index 88285b07ec..ee5d5a0972 100644 --- a/libavcodec/sbrdsp.h +++ b/libavcodec/sbrdsp.h @@ -21,6 +21,8 @@ #ifndef LIBAVCODEC_SBRDSP_H #define LIBAVCODEC_SBRDSP_H +#include + typedef struct SBRDSPContext { void (*sum64x5)(float *z); float (*sum_square)(float (*x)[2], int n); @@ -34,7 +36,7 @@ typedef struct SBRDSPContext { const float alpha0[2], const float alpha1[2], float bw, int start, int end); void (*hf_g_filt)(float (*Y)[2], const float (*X_high)[40][2], - const float *g_filt, int m_max, int ixh); + const float *g_filt, int m_max, intptr_t ixh); void (*hf_apply_noise[4])(float (*Y)[2], const float *s_m, const float *q_filt, int noise, int kx, int m_max); From 34454c761f01275d4adaf40df6d70a59011c4a6c Mon Sep 17 00:00:00 2001 From: Christophe GISQUET Date: Thu, 23 Feb 2012 19:48:58 +0100 Subject: [PATCH 02/17] SBR DSP x86: implement SSE sbr_sum_square_sse The 32bits targets have been compiled with -mfpmath=sse for proper reference. sbr_sum_square C /32bits: 82c (unrolled)/102c C /64bits: 69c (unrolled)/82c SSE/32bits: 42c SSE/64bits: 31c Use of SSE4.1 dpps to perform the final sum is slower. Not unrolling to perform 8 operations in a loop yields 10 more cycles. Signed-off-by: Ronald S. Bultje --- libavcodec/sbrdsp.c | 2 + libavcodec/sbrdsp.h | 1 + libavcodec/x86/Makefile | 2 + libavcodec/x86/sbrdsp.asm | 74 ++++++++++++++++++++++++++++++++++++ libavcodec/x86/sbrdsp_init.c | 37 ++++++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 libavcodec/x86/sbrdsp.asm create mode 100644 libavcodec/x86/sbrdsp_init.c diff --git a/libavcodec/sbrdsp.c b/libavcodec/sbrdsp.c index aef894a51d..f942759aa7 100644 --- a/libavcodec/sbrdsp.c +++ b/libavcodec/sbrdsp.c @@ -238,4 +238,6 @@ av_cold void ff_sbrdsp_init(SBRDSPContext *s) if (ARCH_ARM) ff_sbrdsp_init_arm(s); + if (HAVE_MMX) + ff_sbrdsp_init_x86(s); } diff --git a/libavcodec/sbrdsp.h b/libavcodec/sbrdsp.h index ee5d5a0972..fe91957ce4 100644 --- a/libavcodec/sbrdsp.h +++ b/libavcodec/sbrdsp.h @@ -46,5 +46,6 @@ extern const float ff_sbr_noise_table[][2]; void ff_sbrdsp_init(SBRDSPContext *s); void ff_sbrdsp_init_arm(SBRDSPContext *s); +void ff_sbrdsp_init_x86(SBRDSPContext *s); #endif diff --git a/libavcodec/x86/Makefile b/libavcodec/x86/Makefile index fc88433783..e64697aa2b 100644 --- a/libavcodec/x86/Makefile +++ b/libavcodec/x86/Makefile @@ -47,6 +47,8 @@ YASM-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp.o MMX-OBJS-$(CONFIG_PNG_DECODER) += x86/pngdsp-init.o YASM-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp.o MMX-OBJS-$(CONFIG_PRORES_DECODER) += x86/proresdsp-init.o +MMX-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp_init.o +YASM-OBJS-$(CONFIG_AAC_DECODER) += x86/sbrdsp.o MMX-OBJS-$(CONFIG_DWT) += x86/snowdsp_mmx.o MMX-OBJS-$(CONFIG_VC1_DECODER) += x86/vc1dsp_mmx.o YASM-OBJS-$(CONFIG_VP3_DECODER) += x86/vp3dsp.o diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm new file mode 100644 index 0000000000..71471bd5ab --- /dev/null +++ b/libavcodec/x86/sbrdsp.asm @@ -0,0 +1,74 @@ +;****************************************************************************** +;* AAC Spectral Band Replication decoding functions +;* Copyright (C) 2012 Christophe Gisquet +;* +;* This file is part of Libav. +;* +;* Libav is free software; you can redistribute it and/or +;* modify it under the terms of the GNU Lesser General Public +;* License as published by the Free Software Foundation; either +;* version 2.1 of the License, or (at your option) any later version. +;* +;* Libav is distributed in the hope that it will be useful, +;* but WITHOUT ANY WARRANTY; without even the implied warranty of +;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;* Lesser General Public License for more details. +;* +;* You should have received a copy of the GNU Lesser General Public +;* License along with Libav; if not, write to the Free Software +;* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +;****************************************************************************** + +%include "x86inc.asm" +%include "x86util.asm" + +;SECTION_RODATA +SECTION .text + +INIT_XMM sse +cglobal sbr_sum_square, 2, 3, 6 + mov r2, r1 + xorps m0, m0 + xorps m1, m1 + sar r2, 3 + jz .prepare +.loop: + movu m2, [r0 + 0] + movu m3, [r0 + 16] + movu m4, [r0 + 32] + movu m5, [r0 + 48] + mulps m2, m2 + mulps m3, m3 + mulps m4, m4 + mulps m5, m5 + addps m0, m2 + addps m1, m3 + addps m0, m4 + addps m1, m5 + add r0, 64 + dec r2 + jnz .loop +.prepare: + and r1, 7 + sar r1, 1 + jz .end +; len is a multiple of 2, thus there are at least 4 elements to process +.endloop: + movu m2, [r0] + add r0, 16 + mulps m2, m2 + dec r1 + addps m0, m2 + jnz .endloop +.end: + addps m0, m1 + movhlps m2, m0 + addps m0, m2 + movss m1, m0 + shufps m0, m0, 1 + addss m0, m1 +%if ARCH_X86_64 == 0 + movd r0m, m0 + fld dword r0m +%endif + RET diff --git a/libavcodec/x86/sbrdsp_init.c b/libavcodec/x86/sbrdsp_init.c new file mode 100644 index 0000000000..313f492054 --- /dev/null +++ b/libavcodec/x86/sbrdsp_init.c @@ -0,0 +1,37 @@ +/* + * AAC Spectral Band Replication decoding functions + * Copyright (c) 2012 Christophe Gisquet + * + * This file is part of Libav. + * + * Libav is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Libav is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Libav; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "config.h" +#include "libavutil/cpu.h" +#include "libavcodec/sbrdsp.h" + +float ff_sbr_sum_square_sse(float (*x)[2], int n); + +void ff_sbrdsp_init_x86(SBRDSPContext *s) +{ + if (HAVE_YASM) { + int mm_flags = av_get_cpu_flags(); + + if (mm_flags & AV_CPU_FLAG_SSE) { + s->sum_square = ff_sbr_sum_square_sse; + } + } +} From 2784d187919b48022a89633fb3b5a99ca97cf869 Mon Sep 17 00:00:00 2001 From: Christophe GISQUET Date: Thu, 23 Feb 2012 20:12:39 +0100 Subject: [PATCH 03/17] SBR DSP x86: implement SSE sbr_hf_g_filt Unrolling the main loop to process, instead of 4 elements: - 8: minor gain of 2 cycles (not worth the extra object size) - 2: loss of 8 cycles. Assigning STEP to a register is a loss. Output address (Y) is almost always unaligned. Timings: - C (32/64 bits): 117/109 cycles - SSE: 57 cycles Signed-off-by: Ronald S. Bultje --- libavcodec/x86/sbrdsp.asm | 40 ++++++++++++++++++++++++++++++++++++ libavcodec/x86/sbrdsp_init.c | 3 +++ 2 files changed, 43 insertions(+) diff --git a/libavcodec/x86/sbrdsp.asm b/libavcodec/x86/sbrdsp.asm index 71471bd5ab..c165c52ca4 100644 --- a/libavcodec/x86/sbrdsp.asm +++ b/libavcodec/x86/sbrdsp.asm @@ -72,3 +72,43 @@ cglobal sbr_sum_square, 2, 3, 6 fld dword r0m %endif RET + +%define STEP 40*4*2 +cglobal sbr_hf_g_filt, 5, 6, 5 + lea r1, [r1 + 8*r4] ; offset by ixh elements into X_high + mov r5, r3 + and r3, 0xFC + lea r2, [r2 + r3*4] + lea r0, [r0 + r3*8] + neg r3 +.loop4: + movq m0, [r2 + 4*r3 + 0] + movq m1, [r2 + 4*r3 + 8] + movq m2, [r1 + 0*STEP] + movq m3, [r1 + 2*STEP] + movhps m2, [r1 + 1*STEP] + movhps m3, [r1 + 3*STEP] + punpckldq m0, m0 + punpckldq m1, m1 + mulps m0, m2 + mulps m1, m3 + movu [r0 + 8*r3 + 0], m0 + movu [r0 + 8*r3 + 16], m1 + add r1, 4*STEP + add r3, 4 + jnz .loop4 + and r5, 3 ; number of single element loops + jz .end +.loop1: ; element 0 and 1 can be computed at the same time + movss m0, [r2] + movq m2, [r1] + punpckldq m0, m0 + mulps m2, m0 + movq [r0], m2 + add r0, 8 + add r2, 4 + add r1, STEP + dec r5 + jnz .loop1 +.end: + RET diff --git a/libavcodec/x86/sbrdsp_init.c b/libavcodec/x86/sbrdsp_init.c index 313f492054..0ffe5b9e11 100644 --- a/libavcodec/x86/sbrdsp_init.c +++ b/libavcodec/x86/sbrdsp_init.c @@ -24,6 +24,8 @@ #include "libavcodec/sbrdsp.h" float ff_sbr_sum_square_sse(float (*x)[2], int n); +void ff_sbr_hf_g_filt_sse(float (*Y)[2], const float (*X_high)[40][2], + const float *g_filt, int m_max, intptr_t ixh); void ff_sbrdsp_init_x86(SBRDSPContext *s) { @@ -32,6 +34,7 @@ void ff_sbrdsp_init_x86(SBRDSPContext *s) if (mm_flags & AV_CPU_FLAG_SSE) { s->sum_square = ff_sbr_sum_square_sse; + s->hf_g_filt = ff_sbr_hf_g_filt_sse; } } } From 6d11057006b30ee6737a77f712cdd6a8f7e6c3df Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 23 Feb 2012 15:35:24 -0800 Subject: [PATCH 04/17] apetag: propagate errors. Fixes crashes if reading the tag value fails. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavformat/apetag.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavformat/apetag.c b/libavformat/apetag.c index 6c65a1c449..378ae10ad4 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -75,6 +75,8 @@ static int ape_tag_read_field(AVFormatContext *s) if (!value) return AVERROR(ENOMEM); c = avio_read(pb, value, size); + if (c < 0) + return c; value[c] = 0; av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); } From 14c98973f5822f5ada53c4cc40c0bcf71744d812 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Fri, 24 Feb 2012 00:15:36 +0000 Subject: [PATCH 05/17] apetag: do not leak memory if avio_read() fails Signed-off-by: Paul B Mahol Signed-off-by: Ronald S. Bultje --- libavformat/apetag.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/apetag.c b/libavformat/apetag.c index 378ae10ad4..68c987e7e6 100644 --- a/libavformat/apetag.c +++ b/libavformat/apetag.c @@ -75,8 +75,10 @@ static int ape_tag_read_field(AVFormatContext *s) if (!value) return AVERROR(ENOMEM); c = avio_read(pb, value, size); - if (c < 0) + if (c < 0) { + av_free(value); return c; + } value[c] = 0; av_dict_set(&s->metadata, key, value, AV_DICT_DONT_STRDUP_VAL); } From e32548d1331ce05a054f1028fcdda8823a4f215a Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Thu, 23 Feb 2012 10:22:51 -0800 Subject: [PATCH 06/17] tiff: Make the TIFF_LONG and TIFF_SHORT types unsigned. TIFF v6.0 (unimplemented) adds signed equivalents. --- libavcodec/tiff.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index a88d0f988b..51ebd69f66 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -59,24 +59,24 @@ typedef struct TiffContext { LZWState *lzw; } TiffContext; -static int tget_short(const uint8_t **p, int le){ - int v = le ? AV_RL16(*p) : AV_RB16(*p); +static unsigned tget_short(const uint8_t **p, int le) { + unsigned v = le ? AV_RL16(*p) : AV_RB16(*p); *p += 2; return v; } -static int tget_long(const uint8_t **p, int le){ - int v = le ? AV_RL32(*p) : AV_RB32(*p); +static unsigned tget_long(const uint8_t **p, int le) { + unsigned v = le ? AV_RL32(*p) : AV_RB32(*p); *p += 4; return v; } -static int tget(const uint8_t **p, int type, int le){ +static unsigned tget(const uint8_t **p, int type, int le) { switch(type){ case TIFF_BYTE : return *(*p)++; case TIFF_SHORT: return tget_short(p, le); case TIFF_LONG : return tget_long (p, le); - default : return -1; + default : return UINT_MAX; } } @@ -277,7 +277,7 @@ static int init_image(TiffContext *s) static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t *buf, const uint8_t *end_buf) { - int tag, type, count, off, value = 0; + unsigned tag, type, count, off, value = 0; int i, j; uint32_t *pal; const uint8_t *rp, *gp, *bp; @@ -307,7 +307,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * break; } default: - value = -1; + value = UINT_MAX; buf = start + off; } }else if(type_sizes[type] * count <= 4){ @@ -391,7 +391,7 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * } break; case TIFF_ROWSPERSTRIP: - if(type == TIFF_LONG && value == -1) + if (type == TIFF_LONG && value == UINT_MAX) value = s->avctx->height; if(value < 1){ av_log(s->avctx, AV_LOG_ERROR, "Incorrect value of rows per strip\n"); From 447363870f2f91e125e07ac2d0820359a5d86b06 Mon Sep 17 00:00:00 2001 From: Alex Converse Date: Thu, 23 Feb 2012 10:47:50 -0800 Subject: [PATCH 07/17] tiff: Prevent overreads in the type_sizes array. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/tiff.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index 51ebd69f66..d807149922 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -289,6 +289,11 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * count = tget_long(&buf, s->le); off = tget_long(&buf, s->le); + if (type == 0 || type >= FF_ARRAY_ELEMS(type_sizes)) { + av_log(s->avctx, AV_LOG_DEBUG, "Unknown tiff type (%u) encountered\n", type); + return 0; + } + if(count == 1){ switch(type){ case TIFF_BYTE: @@ -310,10 +315,12 @@ static int tiff_decode_tag(TiffContext *s, const uint8_t *start, const uint8_t * value = UINT_MAX; buf = start + off; } - }else if(type_sizes[type] * count <= 4){ - buf -= 4; - }else{ - buf = start + off; + } else { + if (count <= 4 && type_sizes[type] * count <= 4) { + buf -= 4; + } else { + buf = start + off; + } } if(buf && (buf < start || buf > end_buf)){ From 6e9ed7c7ae4699130a365da5d08b186ce605c068 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Sat, 28 Jan 2012 20:12:45 +0100 Subject: [PATCH 08/17] lavf/output-example: more proper usage of the new API. Passing the codec into avformat_new_stream() is preferred. --- libavformat/output-example.c | 44 ++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/libavformat/output-example.c b/libavformat/output-example.c index 50290aa264..38ce37715a 100644 --- a/libavformat/output-example.c +++ b/libavformat/output-example.c @@ -64,16 +64,22 @@ static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) { AVCodecContext *c; AVStream *st; + AVCodec *codec; - st = avformat_new_stream(oc, NULL); + /* find the audio encoder */ + codec = avcodec_find_encoder(codec_id); + if (!codec) { + fprintf(stderr, "codec not found\n"); + exit(1); + } + + st = avformat_new_stream(oc, codec); if (!st) { fprintf(stderr, "Could not alloc stream\n"); exit(1); } c = st->codec; - c->codec_id = codec_id; - c->codec_type = AVMEDIA_TYPE_AUDIO; /* put sample parameters */ c->sample_fmt = AV_SAMPLE_FMT_S16; @@ -91,19 +97,11 @@ static AVStream *add_audio_stream(AVFormatContext *oc, enum CodecID codec_id) static void open_audio(AVFormatContext *oc, AVStream *st) { AVCodecContext *c; - AVCodec *codec; c = st->codec; - /* find the audio encoder */ - codec = avcodec_find_encoder(c->codec_id); - if (!codec) { - fprintf(stderr, "codec not found\n"); - exit(1); - } - /* open it */ - if (avcodec_open2(c, codec, NULL) < 0) { + if (avcodec_open2(c, NULL, NULL) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } @@ -199,16 +197,22 @@ static AVStream *add_video_stream(AVFormatContext *oc, enum CodecID codec_id) { AVCodecContext *c; AVStream *st; + AVCodec *codec; - st = avformat_new_stream(oc, NULL); + /* find the video encoder */ + codec = avcodec_find_encoder(codec_id); + if (!codec) { + fprintf(stderr, "codec not found\n"); + exit(1); + } + + st = avformat_new_stream(oc, codec); if (!st) { fprintf(stderr, "Could not alloc stream\n"); exit(1); } c = st->codec; - c->codec_id = codec_id; - c->codec_type = AVMEDIA_TYPE_VIDEO; /* put sample parameters */ c->bit_rate = 400000; @@ -262,20 +266,12 @@ static AVFrame *alloc_picture(enum PixelFormat pix_fmt, int width, int height) static void open_video(AVFormatContext *oc, AVStream *st) { - AVCodec *codec; AVCodecContext *c; c = st->codec; - /* find the video encoder */ - codec = avcodec_find_encoder(c->codec_id); - if (!codec) { - fprintf(stderr, "codec not found\n"); - exit(1); - } - /* open the codec */ - if (avcodec_open2(c, codec, NULL) < 0) { + if (avcodec_open2(c, NULL, NULL) < 0) { fprintf(stderr, "could not open codec\n"); exit(1); } From 5ff42e3138998ef5207ca793735409105897c6f2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 24 Feb 2012 08:59:38 +0100 Subject: [PATCH 09/17] lavf/output-example: use new audio encoding API correctly. --- libavformat/output-example.c | 44 ++++++++++++------------------------ 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/libavformat/output-example.c b/libavformat/output-example.c index 38ce37715a..86324b4842 100644 --- a/libavformat/output-example.c +++ b/libavformat/output-example.c @@ -53,8 +53,6 @@ static int sws_flags = SWS_BICUBIC; static float t, tincr, tincr2; static int16_t *samples; -static uint8_t *audio_outbuf; -static int audio_outbuf_size; static int audio_input_frame_size; /* @@ -112,27 +110,12 @@ static void open_audio(AVFormatContext *oc, AVStream *st) /* increment frequency by 110 Hz per second */ tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - audio_outbuf_size = 10000; - audio_outbuf = av_malloc(audio_outbuf_size); - - /* ugly hack for PCM codecs (will be removed ASAP with new PCM - support to compute the input frame size in samples */ - if (c->frame_size <= 1) { - audio_input_frame_size = audio_outbuf_size / c->channels; - switch(st->codec->codec_id) { - case CODEC_ID_PCM_S16LE: - case CODEC_ID_PCM_S16BE: - case CODEC_ID_PCM_U16LE: - case CODEC_ID_PCM_U16BE: - audio_input_frame_size >>= 1; - break; - default: - break; - } - } else { + if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) + audio_input_frame_size = 10000; + else audio_input_frame_size = c->frame_size; - } - samples = av_malloc(audio_input_frame_size * 2 * c->channels); + samples = av_malloc(audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) + * c->channels); } /* prepare a 16 bit dummy audio frame of 'frame_size' samples and @@ -156,19 +139,23 @@ static void write_audio_frame(AVFormatContext *oc, AVStream *st) { AVCodecContext *c; AVPacket pkt; - av_init_packet(&pkt); + AVFrame *frame = avcodec_alloc_frame(); + int got_packet; + av_init_packet(&pkt); c = st->codec; get_audio_frame(samples, audio_input_frame_size, c->channels); + frame->nb_samples = audio_input_frame_size; + avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, (uint8_t *)samples, + audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) + * c->channels, 1); - pkt.size = avcodec_encode_audio2(c, audio_outbuf, audio_outbuf_size, samples); + avcodec_encode_audio2(c, &pkt, frame, &got_packet); + if (!got_packet) + return; - if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) - pkt.pts= av_rescale_q(c->coded_frame->pts, c->time_base, st->time_base); - pkt.flags |= AV_PKT_FLAG_KEY; pkt.stream_index= st->index; - pkt.data= audio_outbuf; /* write the compressed frame in the media file */ if (av_interleaved_write_frame(oc, &pkt) != 0) { @@ -182,7 +169,6 @@ static void close_audio(AVFormatContext *oc, AVStream *st) avcodec_close(st->codec); av_free(samples); - av_free(audio_outbuf); } /**************************************************************/ From b44b41633f110e9d938165e0f79c9d32191fc135 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Wed, 22 Feb 2012 12:09:33 -0800 Subject: [PATCH 10/17] get_bits: add HAVE_BITS_REMAINING macro. --- libavcodec/get_bits.h | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 158e6d2e69..64393bc9d9 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -120,10 +120,23 @@ for examples see get_bits, show_bits, skip_bits, get_vlc # define MIN_CACHE_BITS 25 #endif +#if UNCHECKED_BITSTREAM_READER #define OPEN_READER(name, gb) \ unsigned int name##_index = (gb)->index; \ unsigned int av_unused name##_cache = 0 +#define HAVE_BITS_REMAINING(name, gb) 1 +#else +#define OPEN_READER(name, gb) \ + unsigned int name##_index = (gb)->index; \ + unsigned int av_unused name##_cache = 0; \ + unsigned int av_unused name##_size_plus8 = \ + (gb)->size_in_bits_plus8 + +#define HAVE_BITS_REMAINING(name, gb) \ + name##_index < name##_size_plus8 +#endif + #define CLOSE_READER(name, gb) (gb)->index = name##_index #ifdef BITSTREAM_READER_LE @@ -156,7 +169,7 @@ for examples see get_bits, show_bits, skip_bits, get_vlc # define SKIP_COUNTER(name, gb, num) name##_index += (num) #else # define SKIP_COUNTER(name, gb, num) \ - name##_index = FFMIN((gb)->size_in_bits_plus8, name##_index + (num)) + name##_index = FFMIN(name##_size_plus8, name##_index + (num)) #endif #define SKIP_BITS(name, gb, num) do { \ From 46b3fbc30b7aaf7fdd52391734cfd6d93af8720a Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 17 Feb 2012 12:54:37 -0800 Subject: [PATCH 11/17] golomb: use HAVE_BITS_REMAINING() macro to prevent infloop on EOF. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/golomb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/golomb.h b/libavcodec/golomb.h index 5f720c03f3..1712540fd3 100644 --- a/libavcodec/golomb.h +++ b/libavcodec/golomb.h @@ -135,7 +135,7 @@ static inline int svq3_get_ue_golomb(GetBitContext *gb){ ret = (ret << 4) | ff_interleaved_dirac_golomb_vlc_code[buf]; UPDATE_CACHE(re, gb); buf = GET_CACHE(re, gb); - } while (ret); + } while (HAVE_BITS_REMAINING(re, gb)); CLOSE_READER(re, gb); return ret - 1; From ab492ca2ab105aeb24d955f3f03756bdb3139ee1 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 23 Feb 2012 12:22:40 -0800 Subject: [PATCH 12/17] mjpeg: abort decoding if packet is too large. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/mjpegdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index 27c47e9109..47a85cb598 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1458,6 +1458,10 @@ int ff_mjpeg_decode_frame(AVCodecContext *avctx, void *data, int *data_size, /* EOF */ if (start_code < 0) { goto the_end; + } else if (unescaped_buf_size > (1U<<29)) { + av_log(avctx, AV_LOG_ERROR, "MJPEG packet 0x%x too big (0x%x/0x%x), corrupt data?\n", + start_code, unescaped_buf_ptr, buf_size); + return AVERROR_INVALIDDATA; } else { av_log(avctx, AV_LOG_DEBUG, "marker=%x avail_size_in_buf=%td\n", start_code, buf_end - buf_ptr); From be129271eac04f91393bf42a490ec631e1a9abea Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Thu, 23 Feb 2012 16:09:36 -0800 Subject: [PATCH 13/17] lcl: error out if uncompressed input buffer is smaller than framesize. This prevents crashes when trying to read beyond the end of the buffer while decoding frame data. Found-by: Mateusz "j00ru" Jurczyk and Gynvael Coldwind CC: libav-stable@libav.org --- libavcodec/lcldec.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/libavcodec/lcldec.c b/libavcodec/lcldec.c index a7f0bde23e..d3a85f7863 100644 --- a/libavcodec/lcldec.c +++ b/libavcodec/lcldec.c @@ -223,8 +223,29 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPac len = mszh_dlen; } break; - case COMP_MSZH_NOCOMP: + case COMP_MSZH_NOCOMP: { + int bppx2; + switch (c->imgtype) { + case IMGTYPE_YUV111: + case IMGTYPE_RGB24: + bppx2 = 6; + break; + case IMGTYPE_YUV422: + case IMGTYPE_YUV211: + bppx2 = 4; + break; + case IMGTYPE_YUV411: + case IMGTYPE_YUV420: + bppx2 = 3; + break; + default: + bppx2 = 0; // will error out below + break; + } + if (len < ((width * height * bppx2) >> 1)) + return AVERROR_INVALIDDATA; break; + } default: av_log(avctx, AV_LOG_ERROR, "BUG! Unknown MSZH compression in frame decoder.\n"); return -1; From 9677247b0a6d86fa11e660e940d4836926b9bdaf Mon Sep 17 00:00:00 2001 From: Justin Ruggles Date: Wed, 22 Feb 2012 19:31:40 -0500 Subject: [PATCH 14/17] oggenc: free comment header for all codecs fixes a memleak for Vorbis and Theora, where the comment header from avpriv_split_xiph_headers() is replaced by a buffer that must be freed separately. --- libavformat/oggenc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/oggenc.c b/libavformat/oggenc.c index 33aba87039..f9472693f0 100644 --- a/libavformat/oggenc.c +++ b/libavformat/oggenc.c @@ -388,10 +388,10 @@ static int ogg_write_header(AVFormatContext *s) p = ogg_write_vorbiscomment(7, st->codec->flags & CODEC_FLAG_BITEXACT, &oggstream->header_len[1], &s->metadata, framing_bit); + oggstream->header[1] = p; if (!p) return AVERROR(ENOMEM); - oggstream->header[1] = p; bytestream_put_byte(&p, header_type); bytestream_put_buffer(&p, cstr, 6); @@ -497,8 +497,8 @@ static int ogg_write_trailer(AVFormatContext *s) if (st->codec->codec_id == CODEC_ID_FLAC || st->codec->codec_id == CODEC_ID_SPEEX) { av_free(oggstream->header[0]); - av_free(oggstream->header[1]); } + av_freep(&oggstream->header[1]); av_freep(&st->priv_data); } return 0; From 655b24c01cea2af7e56ac4ffe3d6fdc475223bcc Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Wed, 15 Feb 2012 08:38:51 +0100 Subject: [PATCH 15/17] lavf: move the packet keyframe setting code. compute_pkt_fields() is for unreliable estimates or guessing. The keyframe information from the parser is (at least in theory) reliable, so it should be used even when the other guessing is disabled with the AVFMT_FLAG_NOFILLIN flag. Therefore, move setting the packet keyframe flag based on parser information from compute_pkt_fields() to read_frame_internal(). --- libavformat/utils.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/libavformat/utils.c b/libavformat/utils.c index d6aab568b8..0515c45ce1 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -984,14 +984,6 @@ static void compute_pkt_fields(AVFormatContext *s, AVStream *st, /* update flags */ if(is_intra_only(st->codec)) pkt->flags |= AV_PKT_FLAG_KEY; - else if (pc) { - pkt->flags = 0; - /* keyframe computation */ - if (pc->key_frame == 1) - pkt->flags |= AV_PKT_FLAG_KEY; - else if (pc->key_frame == -1 && pc->pict_type == AV_PICTURE_TYPE_I) - pkt->flags |= AV_PKT_FLAG_KEY; - } if (pc) pkt->convergence_duration = pc->convergence_duration; } @@ -1053,6 +1045,10 @@ static int read_frame_internal(AVFormatContext *s, AVPacket *pkt) pkt->pts = st->parser->pts; pkt->dts = st->parser->dts; pkt->pos = st->parser->pos; + if (st->parser->key_frame == 1 || + (st->parser->key_frame == -1 && + st->parser->pict_type == AV_PICTURE_TYPE_I)) + pkt->flags |= AV_PKT_FLAG_KEY; if(pkt->data == st->cur_pkt.data && pkt->size == st->cur_pkt.size){ s->cur_st = NULL; pkt->destruct= st->cur_pkt.destruct; From b7165426917f91ebcad84bdff366824f03b32bfe Mon Sep 17 00:00:00 2001 From: Dale Curtis Date: Fri, 24 Feb 2012 13:17:39 -0500 Subject: [PATCH 16/17] mpegaudiodec: Prevent premature clipping of mp3 input buffer. Instead of clipping extrasize based on EXTRABYTES, clip based on the amount of buffer actually left. Without this fix, there are warbles and other distortions in the test case below. http://kevincennis.com/mix/assets/sounds/1901_voxfx.mp3 --- libavcodec/mpegaudiodec.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index 6c088626fc..d82432c775 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -40,6 +40,7 @@ #define BACKSTEP_SIZE 512 #define EXTRABYTES 24 +#define LAST_BUF_SIZE 2 * BACKSTEP_SIZE + EXTRABYTES /* layer 3 "granule" */ typedef struct GranuleDef { @@ -63,7 +64,7 @@ typedef struct GranuleDef { typedef struct MPADecodeContext { MPA_DECODE_HEADER - uint8_t last_buf[2 * BACKSTEP_SIZE + EXTRABYTES]; + uint8_t last_buf[LAST_BUF_SIZE]; int last_buf_size; /* next header (used in free format parsing) */ uint32_t free_format_next_header; @@ -1378,7 +1379,8 @@ static int mp_decode_layer3(MPADecodeContext *s) if (!s->adu_mode) { int skip; const uint8_t *ptr = s->gb.buffer + (get_bits_count(&s->gb)>>3); - int extrasize = av_clip(get_bits_left(&s->gb) >> 3, 0, EXTRABYTES); + int extrasize = av_clip(get_bits_left(&s->gb) >> 3, 0, + FFMAX(0, LAST_BUF_SIZE - s->last_buf_size)); assert((get_bits_count(&s->gb) & 7) == 0); /* now we get bits from the main_data_begin offset */ av_dlog(s->avctx, "seekback: %d\n", main_data_begin); From d6a77e2b97f3968b99798faeb70e873eb5910849 Mon Sep 17 00:00:00 2001 From: John Van Sickle Date: Fri, 24 Feb 2012 13:46:48 -0500 Subject: [PATCH 17/17] docs: use -bsf:[vas] instead of -[vas]bsf. The latter syntax is now invalid. Signed-off-by: Anton Khirnov --- doc/avconv.texi | 4 ++-- doc/bitstream_filters.texi | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/avconv.texi b/doc/avconv.texi index 6d96a2f0d3..008b421e9e 100644 --- a/doc/avconv.texi +++ b/doc/avconv.texi @@ -799,10 +799,10 @@ Set bitstream filters for matching streams. @var{bistream_filters} is a comma-separated list of bitstream filters. Use the @code{-bsfs} option to get the list of bitstream filters. @example -avconv -i h264.mp4 -c:v copy -vbsf h264_mp4toannexb -an out.h264 +avconv -i h264.mp4 -c:v copy -bsf:v h264_mp4toannexb -an out.h264 @end example @example -avconv -i file.mov -an -vn -sbsf mov2textsub -c:s copy -f rawvideo sub.txt +avconv -i file.mov -an -vn -bsf:s mov2textsub -c:s copy -f rawvideo sub.txt @end example @item -tag[:@var{stream_specifier}] @var{codec_tag} (@emph{output,per-stream}) diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 1fbd40a70c..a6fe2f2633 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -57,7 +57,7 @@ stream (carrying the AVI1 header ID and lacking a DHT segment) to produce fully qualified JPEG images. @example -avconv -i mjpeg-movie.avi -c:v copy -vbsf mjpeg2jpeg frame_%d.jpg +avconv -i mjpeg-movie.avi -c:v copy -bsf:v mjpeg2jpeg frame_%d.jpg exiftran -i -9 frame*.jpg avconv -i frame_%d.jpg -c:v copy rotated.avi @end example