mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-02-04 06:08:26 +02:00
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 <lionaneesh@gmail.com>, and inspired by patch in Chromium by Chris Evans <cevans@chromium.org>.
This commit is contained in:
parent
a1e98f198e
commit
8cfbbd928c
5
configure
vendored
5
configure
vendored
@ -113,6 +113,9 @@ Configuration options:
|
|||||||
--disable-dxva2 disable DXVA2 code
|
--disable-dxva2 disable DXVA2 code
|
||||||
--enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
|
--enable-runtime-cpudetect detect cpu capabilities at runtime (bigger binary)
|
||||||
--enable-hardcoded-tables use hardcoded tables instead of runtime generation
|
--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
|
--enable-memalign-hack emulate memalign, interferes with memory debuggers
|
||||||
--disable-everything disable all components listed below
|
--disable-everything disable all components listed below
|
||||||
--disable-encoder=NAME disable encoder NAME
|
--disable-encoder=NAME disable encoder NAME
|
||||||
@ -976,6 +979,7 @@ CONFIG_LIST="
|
|||||||
rdft
|
rdft
|
||||||
rtpdec
|
rtpdec
|
||||||
runtime_cpudetect
|
runtime_cpudetect
|
||||||
|
safe_bitstream_reader
|
||||||
shared
|
shared
|
||||||
sinewin
|
sinewin
|
||||||
small
|
small
|
||||||
@ -1679,6 +1683,7 @@ enable doc
|
|||||||
enable fastdiv
|
enable fastdiv
|
||||||
enable network
|
enable network
|
||||||
enable optimizations
|
enable optimizations
|
||||||
|
enable safe_bitstream_reader
|
||||||
enable static
|
enable static
|
||||||
enable swscale_alpha
|
enable swscale_alpha
|
||||||
|
|
||||||
|
@ -35,12 +35,32 @@
|
|||||||
#include "libavutil/log.h"
|
#include "libavutil/log.h"
|
||||||
#include "mathops.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 */
|
/* bit input */
|
||||||
/* buffer, buffer_end and size_in_bits must be present and used by every reader */
|
/* buffer, buffer_end and size_in_bits must be present and used by every reader */
|
||||||
typedef struct GetBitContext {
|
typedef struct GetBitContext {
|
||||||
const uint8_t *buffer, *buffer_end;
|
const uint8_t *buffer, *buffer_end;
|
||||||
int index;
|
int index;
|
||||||
int size_in_bits;
|
int size_in_bits;
|
||||||
|
#if !UNCHECKED_BITSTREAM_READER
|
||||||
|
int size_in_bits_plus8;
|
||||||
|
#endif
|
||||||
} GetBitContext;
|
} GetBitContext;
|
||||||
|
|
||||||
#define VLC_TYPE int16_t
|
#define VLC_TYPE int16_t
|
||||||
@ -137,7 +157,12 @@ for examples see get_bits, show_bits, skip_bits, get_vlc
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
// FIXME name?
|
// FIXME name?
|
||||||
|
#if UNCHECKED_BITSTREAM_READER
|
||||||
# define SKIP_COUNTER(name, gb, num) name##_index += (num)
|
# 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 { \
|
# define SKIP_BITS(name, gb, num) do { \
|
||||||
SKIP_CACHE(name, gb, num); \
|
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){
|
static inline void skip_bits_long(GetBitContext *s, int n){
|
||||||
|
#if UNCHECKED_BITSTREAM_READER
|
||||||
s->index += n;
|
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 <<= index & 7;
|
||||||
result >>= 8 - 1;
|
result >>= 8 - 1;
|
||||||
#endif
|
#endif
|
||||||
index++;
|
#if !UNCHECKED_BITSTREAM_READER
|
||||||
|
if (s->index < s->size_in_bits_plus8)
|
||||||
|
#endif
|
||||||
|
index++;
|
||||||
s->index = index;
|
s->index = index;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -314,6 +346,9 @@ static inline void init_get_bits(GetBitContext *s,
|
|||||||
|
|
||||||
s->buffer = buffer;
|
s->buffer = buffer;
|
||||||
s->size_in_bits = bit_size;
|
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->buffer_end = buffer + buffer_size;
|
||||||
s->index = 0;
|
s->index = 0;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
* @author Ronald S. Bultje <rsbultje@gmail.com>
|
* @author Ronald S. Bultje <rsbultje@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define UNCHECKED_BITSTREAM_READER 1
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
#include "get_bits.h"
|
#include "get_bits.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user