From 8cfbbd928cc94b4de6ad0a937cb818e999c7d75d Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 16 Dec 2011 21:42:04 +0000 Subject: [PATCH 01/16] get_bits: introduce safe bitreading to prevent overreads. When turned on, H264/CAVLC gets ~15% (CVPCMNL1_SVA_C.264) slower for ultra-high-bitrate files, or ~2.5% (CVFI1_SVA_C.264) for lower-bitrate files. Other codecs are affected to a lesser extent because they are less optimized; e.g., VC-1 slows down by less than 1% (all on x86). The patch generated 3 extra instructions (cmp, cmovae and mov) per call to get_bits(). The performance penalty on ARM is within the error margin for most files, up to 4% in extreme cases such as CVPCMNL1_SVA_C.264. Based on work (for GCI) by Aneesh Dogra , and inspired by patch in Chromium by Chris Evans . --- configure | 5 +++++ libavcodec/get_bits.h | 37 ++++++++++++++++++++++++++++++++++++- libavcodec/wmavoice.c | 2 ++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 974e75f91b..22542afbe7 100755 --- a/configure +++ b/configure @@ -113,6 +113,9 @@ Configuration options: --disable-dxva2 disable DXVA2 code --enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary) --enable-hardcoded-tables use hardcoded tables instead of runtime generation + --disable-safe-bitstream-reader + disable buffer boundary checking in bitreaders + (faster, but may crash) --enable-memalign-hack emulate memalign, interferes with memory debuggers --disable-everything disable all components listed below --disable-encoder=NAME disable encoder NAME @@ -976,6 +979,7 @@ CONFIG_LIST=" rdft rtpdec runtime_cpudetect + safe_bitstream_reader shared sinewin small @@ -1679,6 +1683,7 @@ enable doc enable fastdiv enable network enable optimizations +enable safe_bitstream_reader enable static enable swscale_alpha diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 684cc992fe..33ddb4b89f 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -35,12 +35,32 @@ #include "libavutil/log.h" #include "mathops.h" +/* + * Safe bitstream reading: + * optionally, the get_bits API can check to ensure that we + * don't read past input buffer boundaries. This is protected + * with CONFIG_SAFE_BITSTREAM_READER at the global level, and + * then below that with UNCHECKED_BITSTREAM_READER at the per- + * decoder level. This means that decoders that check internally + * can "#define UNCHECKED_BITSTREAM_READER 1" to disable + * overread checks. + * Boundary checking causes a minor performance penalty so for + * applications that won't want/need this, it can be disabled + * globally using "#define CONFIG_SAFE_BITSTREAM_READER 0". + */ +#ifndef UNCHECKED_BITSTREAM_READER +#define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER +#endif + /* bit input */ /* buffer, buffer_end and size_in_bits must be present and used by every reader */ typedef struct GetBitContext { const uint8_t *buffer, *buffer_end; int index; int size_in_bits; +#if !UNCHECKED_BITSTREAM_READER + int size_in_bits_plus8; +#endif } GetBitContext; #define VLC_TYPE int16_t @@ -137,7 +157,12 @@ for examples see get_bits, show_bits, skip_bits, get_vlc # endif // FIXME name? +#if UNCHECKED_BITSTREAM_READER # 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)) +#endif # define SKIP_BITS(name, gb, num) do { \ SKIP_CACHE(name, gb, num); \ @@ -164,7 +189,11 @@ static inline int get_bits_count(const GetBitContext *s){ } static inline void skip_bits_long(GetBitContext *s, int n){ +#if UNCHECKED_BITSTREAM_READER s->index += n; +#else + s->index += av_clip(n, -s->index, s->size_in_bits_plus8 - s->index); +#endif } /** @@ -237,7 +266,10 @@ static inline unsigned int get_bits1(GetBitContext *s){ result <<= index & 7; result >>= 8 - 1; #endif - index++; +#if !UNCHECKED_BITSTREAM_READER + if (s->index < s->size_in_bits_plus8) +#endif + index++; s->index = index; return result; @@ -314,6 +346,9 @@ static inline void init_get_bits(GetBitContext *s, s->buffer = buffer; s->size_in_bits = bit_size; +#if !UNCHECKED_BITSTREAM_READER + s->size_in_bits_plus8 = bit_size + 8; +#endif s->buffer_end = buffer + buffer_size; s->index = 0; } diff --git a/libavcodec/wmavoice.c b/libavcodec/wmavoice.c index 00e985d230..8854e35d93 100644 --- a/libavcodec/wmavoice.c +++ b/libavcodec/wmavoice.c @@ -25,6 +25,8 @@ * @author Ronald S. Bultje */ +#define UNCHECKED_BITSTREAM_READER 1 + #include #include "avcodec.h" #include "get_bits.h" From 4391805916a1557278351f25428d0145b1073520 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 16 Dec 2011 00:03:57 +0000 Subject: [PATCH 02/16] swscale: fix overflows in RGB rounding constants. Signed-off-by: Mans Rullgard --- libswscale/swscale.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 116f780efa..f072378001 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1456,8 +1456,8 @@ rgb16_32ToY_c_template(uint8_t *dst, const uint8_t *src, int maskr, int maskg, int maskb, int rsh, int gsh, int bsh, int S) { - const int ry = RY << rsh, gy = GY << gsh, by = BY << bsh, - rnd = 33 << (S - 1); + const int ry = RY << rsh, gy = GY << gsh, by = BY << bsh; + const unsigned rnd = 33u << (S - 1); int i; for (i = 0; i < width; i++) { @@ -1479,8 +1479,8 @@ rgb16_32ToUV_c_template(uint8_t *dstU, uint8_t *dstV, int rsh, int gsh, int bsh, int S) { const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh, - rv = RV << rsh, gv = GV << gsh, bv = BV << bsh, - rnd = 257 << (S - 1); + rv = RV << rsh, gv = GV << gsh, bv = BV << bsh; + const unsigned rnd = 257u << (S - 1); int i; for (i = 0; i < width; i++) { @@ -1504,7 +1504,8 @@ rgb16_32ToUV_half_c_template(uint8_t *dstU, uint8_t *dstV, { const int ru = RU << rsh, gu = GU << gsh, bu = BU << bsh, rv = RV << rsh, gv = GV << gsh, bv = BV << bsh, - rnd = 257 << S, maskgx = ~(maskr | maskb); + maskgx = ~(maskr | maskb); + const unsigned rnd = 257u << S; int i; maskr |= maskr << 1; maskb |= maskb << 1; maskg |= maskg << 1; From e614fac2e6e185a247d722d4e92368b3c3bc4bdb Mon Sep 17 00:00:00 2001 From: Shitiz Garg Date: Sat, 17 Dec 2011 19:35:59 +0530 Subject: [PATCH 03/16] adpcm: Check for channels to be a non-zero integer channels would be 0 sometimes and would cause floating point exception Fixes bugzilla #124 Signed-off-by: Justin Ruggles --- libavcodec/adpcm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/adpcm.c b/libavcodec/adpcm.c index 3ada328df3..48f44fe8dc 100644 --- a/libavcodec/adpcm.c +++ b/libavcodec/adpcm.c @@ -101,8 +101,9 @@ static av_cold int adpcm_decode_init(AVCodecContext * avctx) max_channels = 6; break; } - if(avctx->channels > max_channels){ - return -1; + if (avctx->channels <= 0 || avctx->channels > max_channels) { + av_log(avctx, AV_LOG_ERROR, "Invalid number of channels\n"); + return AVERROR(EINVAL); } switch(avctx->codec->id) { From 583d3b7f97be065165ed742e108423704279516b Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 15:48:19 +0000 Subject: [PATCH 04/16] fate: fix eatqi test The sample has an incomplete last frame. Decoding it is pointless. The garbage produced was changed by the bitstream reader now protecting against over-reads. Signed-off-by: Mans Rullgard --- tests/fate.mak | 2 +- tests/ref/fate/ea-tqi-adpcm | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/fate.mak b/tests/fate.mak index c31b30414a..cd976badb8 100644 --- a/tests/fate.mak +++ b/tests/fate.mak @@ -89,7 +89,7 @@ fate-ea-tgv-ima-ea-eacs: CMD = framecrc -i $(SAMPLES)/ea-tgv/INTRO8K-partial.TG FATE_TESTS += fate-ea-tgv-ima-ea-sead fate-ea-tgv-ima-ea-sead: CMD = framecrc -i $(SAMPLES)/ea-tgv/INTEL_S.TGV -pix_fmt rgb24 FATE_TESTS += fate-ea-tqi-adpcm -fate-ea-tqi-adpcm: CMD = framecrc -i $(SAMPLES)/ea-wve/networkBackbone-partial.wve +fate-ea-tqi-adpcm: CMD = framecrc -i $(SAMPLES)/ea-wve/networkBackbone-partial.wve -frames:v 26 FATE_TESTS += fate-ea-vp60 fate-ea-vp60: CMD = framecrc -i $(SAMPLES)/ea-vp6/g36.vp6 FATE_TESTS += fate-ea-vp61 diff --git a/tests/ref/fate/ea-tqi-adpcm b/tests/ref/fate/ea-tqi-adpcm index c79eed52bd..4fbc117070 100644 --- a/tests/ref/fate/ea-tqi-adpcm +++ b/tests/ref/fate/ea-tqi-adpcm @@ -49,4 +49,3 @@ 0, 144000, 115200, 0x65fd5e60 1, 144000, 5936, 0x2174304d 0, 150000, 115200, 0x0c256424 -0, 156000, 115200, 0xa9cdd8d2 From ac08f798bbfe6b3a631964a26da961e692b1c9af Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 16:19:24 +0000 Subject: [PATCH 05/16] mp3dec: hack: fix decoding with safe bitstream reader The buffer splicing relies on the bitstream reader over-reading the end of the buffer as declared in init_get_bits(), although more data is actually present. Manually moving the bitstream boundary after init_get_bits() allows this to work as expected. Signed-off-by: Mans Rullgard --- libavcodec/mpegaudiodec.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/mpegaudiodec.c b/libavcodec/mpegaudiodec.c index eeef470a57..0c8f9c787b 100644 --- a/libavcodec/mpegaudiodec.c +++ b/libavcodec/mpegaudiodec.c @@ -1548,6 +1548,9 @@ static int mp_decode_layer3(MPADecodeContext *s) memcpy(s->last_buf + s->last_buf_size, ptr, EXTRABYTES); s->in_gb = s->gb; init_get_bits(&s->gb, s->last_buf, s->last_buf_size*8); +#if CONFIG_SAFE_BITSTREAM_READER + s->gb.size_in_bits_plus8 += EXTRABYTES * 8; +#endif skip_bits_long(&s->gb, 8*(s->last_buf_size - main_data_begin)); } From adb28c49bdf02dd0e45b904c6b36d2696430f41e Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 00:30:59 +0000 Subject: [PATCH 06/16] get_bits: remove unnecessary #includes Signed-off-by: Mans Rullgard --- libavcodec/get_bits.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 33ddb4b89f..38a7463cfc 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -27,9 +27,6 @@ #define AVCODEC_GET_BITS_H #include -#include -#include -#include "libavutil/bswap.h" #include "libavutil/common.h" #include "libavutil/intreadwrite.h" #include "libavutil/log.h" From ed46a3d8423b8697773bdd9f22125bc19c9f72b1 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 16 Dec 2011 19:38:53 +0100 Subject: [PATCH 07/16] swscale: add rgb565 endianess conversion --- libswscale/swscale_unscaled.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index ec8f1bb552..b42854ad9f 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -718,15 +718,6 @@ void ff_get_unscaled_swscale(SwsContext *c) if (srcFormat==PIX_FMT_BGR24 && (dstFormat==PIX_FMT_YUV420P || dstFormat==PIX_FMT_YUVA420P) && !(flags & SWS_ACCURATE_RND)) c->swScale= bgr24ToYv12Wrapper; - /* bswap 16 bits per component packed formats */ - if ((srcFormat == PIX_FMT_RGB48LE && dstFormat == PIX_FMT_RGB48BE) || - (srcFormat == PIX_FMT_RGB48BE && dstFormat == PIX_FMT_RGB48LE) || - (srcFormat == PIX_FMT_BGR48LE && dstFormat == PIX_FMT_BGR48BE) || - (srcFormat == PIX_FMT_BGR48BE && dstFormat == PIX_FMT_BGR48LE) || - (srcFormat == PIX_FMT_GRAY16LE && dstFormat == PIX_FMT_GRAY16BE) || - (srcFormat == PIX_FMT_GRAY16BE && dstFormat == PIX_FMT_GRAY16LE)) - c->swScale = packed_16bpc_bswap; - /* RGB/BGR -> RGB/BGR (no dither needed forms) */ if ( isAnyRGB(srcFormat) && isAnyRGB(dstFormat) @@ -745,6 +736,19 @@ void ff_get_unscaled_swscale(SwsContext *c) && (!needsDither || (c->flags&(SWS_FAST_BILINEAR|SWS_POINT)))) c->swScale= rgbToRgbWrapper; + /* bswap 16 bits per pixel/component packed formats */ + if ((srcFormat == PIX_FMT_RGB48LE && dstFormat == PIX_FMT_RGB48BE) || + (srcFormat == PIX_FMT_RGB48BE && dstFormat == PIX_FMT_RGB48LE) || + (srcFormat == PIX_FMT_BGR48LE && dstFormat == PIX_FMT_BGR48BE) || + (srcFormat == PIX_FMT_BGR48BE && dstFormat == PIX_FMT_BGR48LE) || + (srcFormat == PIX_FMT_GRAY16LE && dstFormat == PIX_FMT_GRAY16BE) || + (srcFormat == PIX_FMT_GRAY16BE && dstFormat == PIX_FMT_GRAY16LE) || + (srcFormat == PIX_FMT_RGB565LE && dstFormat == PIX_FMT_RGB565BE) || + (srcFormat == PIX_FMT_RGB565BE && dstFormat == PIX_FMT_RGB565LE) || + (srcFormat == PIX_FMT_BGR565BE && dstFormat == PIX_FMT_BGR565LE) || + (srcFormat == PIX_FMT_BGR565LE && dstFormat == PIX_FMT_BGR565BE)) + c->swScale = packed_16bpc_bswap; + if ((usePal(srcFormat) && ( dstFormat == PIX_FMT_RGB32 || dstFormat == PIX_FMT_RGB32_1 || From e42bb0ee01706702b1d0f9a483dbc3013030c62d Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 01:05:35 +0000 Subject: [PATCH 08/16] get_bits: whitespace (mostly) cosmetics Signed-off-by: Mans Rullgard --- libavcodec/get_bits.h | 122 +++++++++++++++++++++++++----------------- 1 file changed, 73 insertions(+), 49 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 38a7463cfc..4aa5da86bb 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -125,33 +125,37 @@ for examples see get_bits, show_bits, skip_bits, get_vlc # define MIN_CACHE_BITS 25 #endif -# define OPEN_READER(name, gb) \ +#define OPEN_READER(name, gb) \ unsigned int name##_index = (gb)->index; \ unsigned int av_unused name##_cache = 0 -# define CLOSE_READER(name, gb) (gb)->index = name##_index +#define CLOSE_READER(name, gb) (gb)->index = name##_index + +#ifdef ALT_BITSTREAM_READER_LE -# ifdef ALT_BITSTREAM_READER_LE # ifdef LONG_BITSTREAM_READER -# define UPDATE_CACHE(name, gb) \ - name##_cache = AV_RL64((gb)->buffer+(name##_index>>3)) >> (name##_index&0x07) +# define UPDATE_CACHE(name, gb) name##_cache = \ + AV_RL64((gb)->buffer + (name##_index >> 3)) >> (name##_index & 7) # else -# define UPDATE_CACHE(name, gb) \ - name##_cache = AV_RL32((gb)->buffer+(name##_index>>3)) >> (name##_index&0x07) +# define UPDATE_CACHE(name, gb) name##_cache = \ + AV_RL32((gb)->buffer + (name##_index >> 3)) >> (name##_index & 7) # endif -# define SKIP_CACHE(name, gb, num) name##_cache >>= (num) -# else +# define SKIP_CACHE(name, gb, num) name##_cache >>= (num) + +#else + # ifdef LONG_BITSTREAM_READER -# define UPDATE_CACHE(name, gb) \ - name##_cache = AV_RB64((gb)->buffer+(name##_index >> 3)) >> (32 - (name##_index & 0x07)) +# define UPDATE_CACHE(name, gb) name##_cache = \ + AV_RB64((gb)->buffer + (name##_index >> 3)) >> (32 - (name##_index & 7)) # else -# define UPDATE_CACHE(name, gb) \ - name##_cache = AV_RB32((gb)->buffer+(name##_index>>3)) << (name##_index&0x07) +# define UPDATE_CACHE(name, gb) name##_cache = \ + AV_RB32((gb)->buffer + (name##_index >> 3)) << (name##_index & 7) # endif -# define SKIP_CACHE(name, gb, num) name##_cache <<= (num) -# endif +# define SKIP_CACHE(name, gb, num) name##_cache <<= (num) + +#endif // FIXME name? #if UNCHECKED_BITSTREAM_READER @@ -161,27 +165,26 @@ for examples see get_bits, show_bits, skip_bits, get_vlc name##_index = FFMIN((gb)->size_in_bits_plus8, name##_index + (num)) #endif -# define SKIP_BITS(name, gb, num) do { \ +#define SKIP_BITS(name, gb, num) do { \ SKIP_CACHE(name, gb, num); \ SKIP_COUNTER(name, gb, num); \ } while (0) -# define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) -# define LAST_SKIP_CACHE(name, gb, num) +#define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) +#define LAST_SKIP_CACHE(name, gb, num) -# ifdef ALT_BITSTREAM_READER_LE +#ifdef ALT_BITSTREAM_READER_LE # define SHOW_UBITS(name, gb, num) zero_extend(name##_cache, num) - # define SHOW_SBITS(name, gb, num) sign_extend(name##_cache, num) -# else +#else # define SHOW_UBITS(name, gb, num) NEG_USR32(name##_cache, num) - # define SHOW_SBITS(name, gb, num) NEG_SSR32(name##_cache, num) -# endif +#endif -# define GET_CACHE(name, gb) ((uint32_t)name##_cache) +#define GET_CACHE(name, gb) ((uint32_t)name##_cache) -static inline int get_bits_count(const GetBitContext *s){ +static inline int get_bits_count(const GetBitContext *s) +{ return s->index; } @@ -199,7 +202,8 @@ static inline void skip_bits_long(GetBitContext *s, int n){ * @param n length in bits * @author BERO */ -static inline int get_xbits(GetBitContext *s, int n){ +static inline int get_xbits(GetBitContext *s, int n) +{ register int sign; register int32_t cache; OPEN_READER(re, s); @@ -211,7 +215,8 @@ static inline int get_xbits(GetBitContext *s, int n){ return (NEG_USR32(sign ^ cache, n) ^ sign) - sign; } -static inline int get_sbits(GetBitContext *s, int n){ +static inline int get_sbits(GetBitContext *s, int n) +{ register int tmp; OPEN_READER(re, s); UPDATE_CACHE(re, s); @@ -224,7 +229,8 @@ static inline int get_sbits(GetBitContext *s, int n){ /** * Read 1-25 bits. */ -static inline unsigned int get_bits(GetBitContext *s, int n){ +static inline unsigned int get_bits(GetBitContext *s, int n) +{ register int tmp; OPEN_READER(re, s); UPDATE_CACHE(re, s); @@ -237,7 +243,8 @@ static inline unsigned int get_bits(GetBitContext *s, int n){ /** * Show 1-25 bits. */ -static inline unsigned int show_bits(GetBitContext *s, int n){ +static inline unsigned int show_bits(GetBitContext *s, int n) +{ register int tmp; OPEN_READER(re, s); UPDATE_CACHE(re, s); @@ -245,7 +252,8 @@ static inline unsigned int show_bits(GetBitContext *s, int n){ return tmp; } -static inline void skip_bits(GetBitContext *s, int n){ +static inline void skip_bits(GetBitContext *s, int n) +{ //Note gcc seems to optimize this to s->index+=n for the ALT_READER :)) OPEN_READER(re, s); UPDATE_CACHE(re, s); @@ -253,7 +261,8 @@ static inline void skip_bits(GetBitContext *s, int n){ CLOSE_READER(re, s); } -static inline unsigned int get_bits1(GetBitContext *s){ +static inline unsigned int get_bits1(GetBitContext *s) +{ unsigned int index = s->index; uint8_t result = s->buffer[index>>3]; #ifdef ALT_BITSTREAM_READER_LE @@ -272,19 +281,23 @@ static inline unsigned int get_bits1(GetBitContext *s){ return result; } -static inline unsigned int show_bits1(GetBitContext *s){ +static inline unsigned int show_bits1(GetBitContext *s) +{ return show_bits(s, 1); } -static inline void skip_bits1(GetBitContext *s){ +static inline void skip_bits1(GetBitContext *s) +{ skip_bits(s, 1); } /** * Read 0-32 bits. */ -static inline unsigned int get_bits_long(GetBitContext *s, int n){ - if (n <= MIN_CACHE_BITS) return get_bits(s, n); +static inline unsigned int get_bits_long(GetBitContext *s, int n) +{ + if (n <= MIN_CACHE_BITS) + return get_bits(s, n); else { #ifdef ALT_BITSTREAM_READER_LE int ret = get_bits(s, 16); @@ -299,15 +312,18 @@ static inline unsigned int get_bits_long(GetBitContext *s, int n){ /** * Read 0-32 bits as a signed integer. */ -static inline int get_sbits_long(GetBitContext *s, int n) { +static inline int get_sbits_long(GetBitContext *s, int n) +{ return sign_extend(get_bits_long(s, n), n); } /** * Show 0-32 bits. */ -static inline unsigned int show_bits_long(GetBitContext *s, int n){ - if (n <= MIN_CACHE_BITS) return show_bits(s, n); +static inline unsigned int show_bits_long(GetBitContext *s, int n) +{ + if (n <= MIN_CACHE_BITS) + return show_bits(s, n); else { GetBitContext gb = *s; return get_bits_long(&gb, n); @@ -332,8 +348,8 @@ static inline int check_marker(GetBitContext *s, const char *msg) * While GetBitContext stores the buffer size, for performance reasons you are * responsible for checking for the buffer end yourself (take advantage of the padding)! */ -static inline void init_get_bits(GetBitContext *s, - const uint8_t *buffer, int bit_size) +static inline void init_get_bits(GetBitContext *s, const uint8_t *buffer, + int bit_size) { int buffer_size = (bit_size+7)>>3; if (buffer_size < 0 || bit_size < 0) { @@ -387,7 +403,8 @@ void free_vlc(VLC *vlc); * If the vlc code is invalid and max_depth>1, then the number of bits removed * is undefined. */ -#define GET_VLC(code, name, gb, table, bits, max_depth) do { \ +#define GET_VLC(code, name, gb, table, bits, max_depth) \ + do { \ int n, nb_bits; \ unsigned int index; \ \ @@ -418,7 +435,8 @@ void free_vlc(VLC *vlc); SKIP_BITS(name, gb, n); \ } while (0) -#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update) do { \ +#define GET_RL_VLC(level, run, name, gb, table, bits, max_depth, need_update) \ + do { \ int n, nb_bits; \ unsigned int index; \ \ @@ -452,7 +470,7 @@ void free_vlc(VLC *vlc); * = (max_vlc_length + bits - 1) / bits */ static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], - int bits, int max_depth) + int bits, int max_depth) { int code; @@ -465,7 +483,8 @@ static av_always_inline int get_vlc2(GetBitContext *s, VLC_TYPE (*table)[2], return code; } -static inline int decode012(GetBitContext *gb){ +static inline int decode012(GetBitContext *gb) +{ int n; n = get_bits1(gb); if (n == 0) @@ -474,7 +493,8 @@ static inline int decode012(GetBitContext *gb){ return get_bits1(gb) + 1; } -static inline int decode210(GetBitContext *gb){ +static inline int decode210(GetBitContext *gb) +{ if (get_bits1(gb)) return 0; else @@ -489,7 +509,8 @@ static inline int get_bits_left(GetBitContext *gb) //#define TRACE #ifdef TRACE -static inline void print_bin(int bits, int n){ +static inline void print_bin(int bits, int n) +{ int i; for (i = n-1; i >= 0; i--) { @@ -500,7 +521,8 @@ static inline void print_bin(int bits, int n){ } static inline int get_bits_trace(GetBitContext *s, int n, char *file, - const char *func, int line){ + const char *func, int line) +{ int r = get_bits(s, n); print_bin(r, n); @@ -510,7 +532,8 @@ static inline int get_bits_trace(GetBitContext *s, int n, char *file, } static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], int bits, int max_depth, char *file, - const char *func, int line){ + const char *func, int line) +{ int show = show_bits(s, 24); int pos = get_bits_count(s); int r = get_vlc2(s, table, bits, max_depth); @@ -524,7 +547,8 @@ static inline int get_vlc_trace(GetBitContext *s, VLC_TYPE (*table)[2], return r; } static inline int get_xbits_trace(GetBitContext *s, int n, char *file, - const char *func, int line){ + const char *func, int line) +{ int show = show_bits(s, n); int r = get_xbits(s, n); From 5d8122db5c0b537c4d2c3352b4c89cb92f865bc2 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 01:07:32 +0000 Subject: [PATCH 09/16] get_bits: remove strange/obsolete comments Signed-off-by: Mans Rullgard --- libavcodec/get_bits.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 4aa5da86bb..9376b117f2 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -49,8 +49,6 @@ #define UNCHECKED_BITSTREAM_READER !CONFIG_SAFE_BITSTREAM_READER #endif -/* bit input */ -/* buffer, buffer_end and size_in_bits must be present and used by every reader */ typedef struct GetBitContext { const uint8_t *buffer, *buffer_end; int index; @@ -157,7 +155,6 @@ for examples see get_bits, show_bits, skip_bits, get_vlc #endif -// FIXME name? #if UNCHECKED_BITSTREAM_READER # define SKIP_COUNTER(name, gb, num) name##_index += (num) #else @@ -200,7 +197,6 @@ static inline void skip_bits_long(GetBitContext *s, int n){ * read mpeg1 dc style vlc (sign bit + mantisse with no MSB). * if MSB not set it is negative * @param n length in bits - * @author BERO */ static inline int get_xbits(GetBitContext *s, int n) { @@ -254,7 +250,6 @@ static inline unsigned int show_bits(GetBitContext *s, int n) static inline void skip_bits(GetBitContext *s, int n) { - //Note gcc seems to optimize this to s->index+=n for the ALT_READER :)) OPEN_READER(re, s); UPDATE_CACHE(re, s); LAST_SKIP_BITS(re, s, n); @@ -344,9 +339,6 @@ static inline int check_marker(GetBitContext *s, const char *msg) * @param buffer bitstream buffer, must be FF_INPUT_BUFFER_PADDING_SIZE bytes larger than the actual read bits * because some optimized bitstream readers read 32 or 64 bit at once and could read over the end * @param bit_size the size of the buffer in bits - * - * While GetBitContext stores the buffer size, for performance reasons you are - * responsible for checking for the buffer end yourself (take advantage of the padding)! */ static inline void init_get_bits(GetBitContext *s, const uint8_t *buffer, int bit_size) @@ -462,7 +454,7 @@ void free_vlc(VLC *vlc); /** - * Parse a vlc code, faster than get_vlc(). + * Parse a vlc code. * @param bits is the number of bits which will be read at once, must be * identical to nb_bits in init_vlc() * @param max_depth is the number of times bits bits must be read to completely From be1bafc303a77fa9ca5a99e36a65d5765012d3f4 Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Fri, 16 Dec 2011 00:03:54 +0000 Subject: [PATCH 10/16] swscale: fix overflows in output of RGB48 pixels. For certain types of filters where the intermediate sum of coefficients can go above the fixed-point equivalent of 1.0 in the middle of a filter, the sum of a 31-bit calculation can overflow in both directions and can thus not be represented in a 32-bit signed or unsigned integer. To work around this, we subtract 0x40000000 from a signed integer base, so that we're halfway signed/unsigned, which makes it fit even if it overflows. After the filter finishes, we add the scaled bias back after a shift. We use the same trick for 16-bit bpc YUV output routines. Signed-off-by: Mans Rullgard --- libswscale/swscale.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index f072378001..818c049f35 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -754,8 +754,8 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, for (i = 0; i < (dstW >> 1); i++) { int j; - int Y1 = 0; - int Y2 = 0; + int Y1 = -0x40000000; + int Y2 = -0x40000000; int U = -128 << 23; // 19 int V = -128 << 23; int R, G, B; @@ -771,7 +771,9 @@ yuv2rgb48_X_c_template(SwsContext *c, const int16_t *lumFilter, // 8bit: 12+15=27; 16-bit: 12+19=31 Y1 >>= 14; // 10 + Y1 += 0x10000; Y2 >>= 14; + Y2 += 0x10000; U >>= 14; V >>= 14; From b4dc68803bd7fa73c2e37f55ae73b5fdb293c68d Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 16 Dec 2011 23:04:30 +0100 Subject: [PATCH 11/16] swscale: add endian conversion for RGB555 and RGB444 pixel formats Add a macro to shorten the if condition. --- libswscale/swscale_unscaled.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/libswscale/swscale_unscaled.c b/libswscale/swscale_unscaled.c index b42854ad9f..3dc2929a5a 100644 --- a/libswscale/swscale_unscaled.c +++ b/libswscale/swscale_unscaled.c @@ -688,6 +688,12 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[ return srcSliceH; } + +#define IS_DIFFERENT_ENDIANESS(src_fmt, dst_fmt, pix_fmt) \ + ((src_fmt == pix_fmt ## BE && dst_fmt == pix_fmt ## LE) || \ + (src_fmt == pix_fmt ## LE && dst_fmt == pix_fmt ## BE)) + + void ff_get_unscaled_swscale(SwsContext *c) { const enum PixelFormat srcFormat = c->srcFormat; @@ -737,16 +743,15 @@ void ff_get_unscaled_swscale(SwsContext *c) c->swScale= rgbToRgbWrapper; /* bswap 16 bits per pixel/component packed formats */ - if ((srcFormat == PIX_FMT_RGB48LE && dstFormat == PIX_FMT_RGB48BE) || - (srcFormat == PIX_FMT_RGB48BE && dstFormat == PIX_FMT_RGB48LE) || - (srcFormat == PIX_FMT_BGR48LE && dstFormat == PIX_FMT_BGR48BE) || - (srcFormat == PIX_FMT_BGR48BE && dstFormat == PIX_FMT_BGR48LE) || - (srcFormat == PIX_FMT_GRAY16LE && dstFormat == PIX_FMT_GRAY16BE) || - (srcFormat == PIX_FMT_GRAY16BE && dstFormat == PIX_FMT_GRAY16LE) || - (srcFormat == PIX_FMT_RGB565LE && dstFormat == PIX_FMT_RGB565BE) || - (srcFormat == PIX_FMT_RGB565BE && dstFormat == PIX_FMT_RGB565LE) || - (srcFormat == PIX_FMT_BGR565BE && dstFormat == PIX_FMT_BGR565LE) || - (srcFormat == PIX_FMT_BGR565LE && dstFormat == PIX_FMT_BGR565BE)) + if (IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR444) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR48) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR555) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_BGR565) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_GRAY16) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB444) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB48) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB555) || + IS_DIFFERENT_ENDIANESS(srcFormat, dstFormat, PIX_FMT_RGB565)) c->swScale = packed_16bpc_bswap; if ((usePal(srcFormat) && ( From 77d88b872d8cbb42738ede2d4fc098c16f204236 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 18:45:46 +0000 Subject: [PATCH 12/16] swscale: fix integer overflows in RGB pixel writing. We're shifting individual components (8-bit, unsigned) left by 24, so making them unsigned should give the same results without the overflow. Signed-off-by: Ronald S. Bultje --- libswscale/swscale.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 818c049f35..3ea37104e8 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -920,8 +920,8 @@ YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48be, PIX_FMT_BGR48BE) YUV2PACKED16WRAPPER(yuv2, rgb48, bgr48le, PIX_FMT_BGR48LE) static av_always_inline void -yuv2rgb_write(uint8_t *_dest, int i, int Y1, int Y2, - int U, int V, int A1, int A2, +yuv2rgb_write(uint8_t *_dest, int i, unsigned Y1, unsigned Y2, + unsigned U, unsigned V, unsigned A1, unsigned A2, const void *_r, const void *_g, const void *_b, int y, enum PixelFormat target, int hasAlpha) { From 86a10281c7f6204b3ac1253718971b1f8c106699 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 19:40:16 +0000 Subject: [PATCH 13/16] get_bits: remove LAST_SKIP_CACHE macro This macro is empty since the removal of the A32 bitstream reader. Signed-off-by: Mans Rullgard --- libavcodec/get_bits.h | 6 +----- libavcodec/mpeg4videodec.c | 8 ++++---- libavcodec/msmpeg4.c | 2 +- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/libavcodec/get_bits.h b/libavcodec/get_bits.h index 9376b117f2..8abfde1150 100644 --- a/libavcodec/get_bits.h +++ b/libavcodec/get_bits.h @@ -108,11 +108,8 @@ SKIP_CACHE(name, gb, num) SKIP_COUNTER(name, gb, num) will increment the internal bit counter (see SKIP_CACHE & SKIP_BITS) -LAST_SKIP_CACHE(name, gb, num) - will remove the next num bits from the cache if it is needed for UPDATE_CACHE otherwise it will do nothing - LAST_SKIP_BITS(name, gb, num) - is equivalent to LAST_SKIP_CACHE; SKIP_COUNTER + like SKIP_BITS, to be used if next call is UPDATE_CACHE or CLOSE_READER for examples see get_bits, show_bits, skip_bits, get_vlc */ @@ -168,7 +165,6 @@ for examples see get_bits, show_bits, skip_bits, get_vlc } while (0) #define LAST_SKIP_BITS(name, gb, num) SKIP_COUNTER(name, gb, num) -#define LAST_SKIP_CACHE(name, gb, num) #ifdef ALT_BITSTREAM_READER_LE # define SHOW_UBITS(name, gb, num) zero_extend(name##_cache, num) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index f5835f3f4d..e15c348454 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -934,7 +934,7 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, }; SKIP_CACHE(re, &s->gb, 1); last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); - run= SHOW_UBITS(re, &s->gb, 6); LAST_SKIP_CACHE(re, &s->gb, 6); + run= SHOW_UBITS(re, &s->gb, 6); SKIP_COUNTER(re, &s->gb, 1+1+6); UPDATE_CACHE(re, &s->gb); @@ -951,7 +951,7 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, }; SKIP_CACHE(re, &s->gb, 5); level= level * qmul + qadd; - level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); LAST_SKIP_CACHE(re, &s->gb, 1); + level = (level ^ SHOW_SBITS(re, &s->gb, 1)) - SHOW_SBITS(re, &s->gb, 1); SKIP_COUNTER(re, &s->gb, 1+11+5+1); i+= run + 1; @@ -968,7 +968,7 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, /* third escape */ SKIP_CACHE(re, &s->gb, 2); last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); - run= SHOW_UBITS(re, &s->gb, 6); LAST_SKIP_CACHE(re, &s->gb, 6); + run= SHOW_UBITS(re, &s->gb, 6); SKIP_COUNTER(re, &s->gb, 2+1+6); UPDATE_CACHE(re, &s->gb); @@ -985,7 +985,7 @@ static inline int mpeg4_decode_block(MpegEncContext * s, DCTELEM * block, if(SHOW_UBITS(re, &s->gb, 1)==0){ av_log(s->avctx, AV_LOG_ERROR, "2. marker bit missing in 3. esc\n"); return -1; - }; LAST_SKIP_CACHE(re, &s->gb, 1); + } SKIP_COUNTER(re, &s->gb, 1+12+1); } diff --git a/libavcodec/msmpeg4.c b/libavcodec/msmpeg4.c index ee2ae3d49d..11a191570e 100644 --- a/libavcodec/msmpeg4.c +++ b/libavcodec/msmpeg4.c @@ -1691,7 +1691,7 @@ int ff_msmpeg4_decode_block(MpegEncContext * s, DCTELEM * block, if(s->msmpeg4_version<=3){ last= SHOW_UBITS(re, &s->gb, 1); SKIP_CACHE(re, &s->gb, 1); run= SHOW_UBITS(re, &s->gb, 6); SKIP_CACHE(re, &s->gb, 6); - level= SHOW_SBITS(re, &s->gb, 8); LAST_SKIP_CACHE(re, &s->gb, 8); + level= SHOW_SBITS(re, &s->gb, 8); SKIP_COUNTER(re, &s->gb, 1+6+8); }else{ int sign; From 72dafea0fc0eb7230d7ebb0a7bc803e13b72aaad Mon Sep 17 00:00:00 2001 From: "Ronald S. Bultje" Date: Sat, 17 Dec 2011 19:56:40 +0000 Subject: [PATCH 14/16] swscale: fix overflow in gray16 vertical scaling. This fixes the same overflow as in the RGB48/16-bit YUV scaling; some filters can overflow both negatively and positively (e.g. spline/lanczos), so we bias a signed integer so it's "half signed" and "half unsigned", and can cover overflows in both directions while maintaining full 31-bit depth. Signed-off-by: Mans Rullgard --- libswscale/swscale.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index 3ea37104e8..c9dfc8df2f 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -386,8 +386,8 @@ yuv2gray16_X_c_template(SwsContext *c, const int16_t *lumFilter, for (i = 0; i < (dstW >> 1); i++) { int j; - int Y1 = 1 << 14; - int Y2 = 1 << 14; + int Y1 = (1 << 14) - 0x40000000; + int Y2 = (1 << 14) - 0x40000000; for (j = 0; j < lumFilterSize; j++) { Y1 += lumSrc[j][i * 2] * lumFilter[j]; @@ -395,12 +395,10 @@ yuv2gray16_X_c_template(SwsContext *c, const int16_t *lumFilter, } Y1 >>= 15; Y2 >>= 15; - if ((Y1 | Y2) & 0x10000) { - Y1 = av_clip_uint16(Y1); - Y2 = av_clip_uint16(Y2); - } - output_pixel(&dest[i * 2 + 0], Y1); - output_pixel(&dest[i * 2 + 1], Y2); + Y1 = av_clip_int16(Y1); + Y2 = av_clip_int16(Y2); + output_pixel(&dest[i * 2 + 0], 0x8000 + Y1); + output_pixel(&dest[i * 2 + 1], 0x8000 + Y2); } } From e064d46e61b85d27a4e61c37b4a50944db8b188d Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 21:35:50 +0000 Subject: [PATCH 15/16] dct-test: remove unused variable cropTbl Signed-off-by: Mans Rullgard --- libavcodec/dct-test.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/libavcodec/dct-test.c b/libavcodec/dct-test.c index 1665682698..daa95bd0df 100644 --- a/libavcodec/dct-test.c +++ b/libavcodec/dct-test.c @@ -151,8 +151,6 @@ static const struct algo idct_tab[] = { #define AANSCALE_BITS 12 -static uint8_t cropTbl[256 + 2 * MAX_NEG_CROP]; - static int64_t gettime(void) { struct timeval tv; @@ -512,13 +510,6 @@ int main(int argc, char **argv) ff_ref_dct_init(); idct_mmx_init(); - for (i = 0; i < 256; i++) - cropTbl[i + MAX_NEG_CROP] = i; - for (i = 0; i < MAX_NEG_CROP; i++) { - cropTbl[i] = 0; - cropTbl[i + MAX_NEG_CROP + 256] = 255; - } - for (;;) { c = getopt(argc, argv, "ih4t"); if (c == -1) From 0ea5b44275aa334528eb384a6548cc9f98c50a17 Mon Sep 17 00:00:00 2001 From: Mans Rullgard Date: Sat, 17 Dec 2011 15:05:24 +0000 Subject: [PATCH 16/16] build: link test programs with static libraries Many of the test programs directly access internal symbols not exported from the shared libraries. This allows tests to run when configured with shared libraries. Signed-off-by: Mans Rullgard --- library.mak | 1 + 1 file changed, 1 insertion(+) diff --git a/library.mak b/library.mak index e269b509ce..f50e8e59ee 100644 --- a/library.mak +++ b/library.mak @@ -92,6 +92,7 @@ endef $(eval $(RULES)) $(EXAMPLES) $(TESTPROGS) $(TOOLS): $(THIS_LIB) $(DEP_LIBS) +$(TESTPROGS): $(SUBDIR)$(LIBNAME) examples: $(EXAMPLES) testprogs: $(TESTPROGS)