📄 bitstream.h
字号:
/*
* copyright (c) 2004 Michael Niedermayer <michaelni@gmx.at>
*
* This file is part of FFmpeg.
*
* FFmpeg 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.
*
* FFmpeg 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 FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @file bitstream.h
* bitstream api header.
*/
#ifndef FFMPEG_BITSTREAM_H
#define FFMPEG_BITSTREAM_H
#if defined(ALT_BITSTREAM_READER_LE) && !defined(ALT_BITSTREAM_READER)
# define ALT_BITSTREAM_READER
#endif
//#define ALT_BITSTREAM_WRITER
//#define ALIGNED_BITSTREAM_WRITER
#if !defined(LIBMPEG2_BITSTREAM_READER) && !defined(A32_BITSTREAM_READER) && !defined(ALT_BITSTREAM_READER)
# ifdef ARCH_ARMV4L
# define A32_BITSTREAM_READER
# else
# define ALT_BITSTREAM_READER
//#define LIBMPEG2_BITSTREAM_READER
//#define A32_BITSTREAM_READER
# endif
#endif
#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO
extern const uint8_t ff_reverse[256];
#if defined(ARCH_X86)
// avoid +32 for shift optimization (gcc should do that ...)
static int32_t NEG_SSR32( int32_t a, int8_t s){
asm ("sarl %1, %0\n\t"
: "+r" (a)
: "ic" ((uint8_t)(-s))
);
return a;
}
static uint32_t NEG_USR32(uint32_t a, int8_t s){
asm ("shrl %1, %0\n\t"
: "+r" (a)
: "ic" ((uint8_t)(-s))
);
return a;
}
#else
# define NEG_SSR32(a,s) ((( int32_t)(a))>>(32-(s)))
# define NEG_USR32(a,s) (((uint32_t)(a))>>(32-(s)))
#endif
/* bit output */
/* buf and buf_end must be present and used by every alternative writer. */
typedef struct PutBitContext {
#ifdef ALT_BITSTREAM_WRITER
uint8_t *buf, *buf_end;
int index;
#else
uint32_t bit_buf;
int bit_left;
uint8_t *buf, *buf_ptr, *buf_end;
#endif
} PutBitContext;
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
{
if(buffer_size < 0) {
buffer_size = 0;
buffer = NULL;
}
s->buf = buffer;
s->buf_end = s->buf + buffer_size;
#ifdef ALT_BITSTREAM_WRITER
s->index=0;
((uint32_t*)(s->buf))[0]=0;
// memset(buffer, 0, buffer_size);
#else
s->buf_ptr = s->buf;
s->bit_left=32;
s->bit_buf=0;
#endif
}
/* return the number of bits output */
static int put_bits_count(PutBitContext *s)
{
#ifdef ALT_BITSTREAM_WRITER
return s->index;
#else
return (s->buf_ptr - s->buf) * 8 + 32 - s->bit_left;
#endif
}
/* pad the end of the output stream with zeros */
static void flush_put_bits(PutBitContext *s)
{
#ifdef ALT_BITSTREAM_WRITER
align_put_bits(s);
#else
s->bit_buf<<= s->bit_left;
while (s->bit_left < 32) {
/* XXX: should test end of buffer */
*s->buf_ptr++=s->bit_buf >> 24;
s->bit_buf<<=8;
s->bit_left+=8;
}
s->bit_left=32;
s->bit_buf=0;
#endif
}
void align_put_bits(PutBitContext *s);
void ff_put_string(PutBitContext * pbc, const char *s, int put_zero);
void ff_copy_bits(PutBitContext *pb, const uint8_t *src, int length);
/* 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;
#ifdef ALT_BITSTREAM_READER
int index;
#elif defined LIBMPEG2_BITSTREAM_READER
uint8_t *buffer_ptr;
uint32_t cache;
int bit_count;
#elif defined A32_BITSTREAM_READER
uint32_t *buffer_ptr;
uint32_t cache0;
uint32_t cache1;
int bit_count;
#endif
int size_in_bits;
} GetBitContext;
#define VLC_TYPE int16_t
typedef struct H264VLC {
int bits;
VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated;
} H264VLC;
typedef struct RL_VLC_ELEM {
int16_t level;
int8_t len;
uint8_t run;
} RL_VLC_ELEM;
#if defined(ARCH_SPARC) || defined(ARCH_ARMV4L) || defined(ARCH_MIPS) || defined(ARCH_BFIN)
#define UNALIGNED_STORES_ARE_BAD
#endif
/* used to avoid misaligned exceptions on some archs (alpha, ...) */
#if defined(ARCH_X86)
# define unaligned16(a) (*(const uint16_t*)(a))
# define unaligned32(a) (*(const uint32_t*)(a))
# define unaligned64(a) (*(const uint64_t*)(a))
#else
# ifdef __GNUC__
# define unaligned(x) \
static uint##x##_t unaligned##x(const void *v) { \
struct Unaligned { \
uint##x##_t i; \
} __attribute__((packed)); \
\
return ((const struct Unaligned *) v)->i; \
}
# elif defined(__DECC)
# define unaligned(x) \
static uint##x##_t unaligned##x(const void *v) { \
return *(const __unaligned uint##x##_t *) v; \
}
# else
# define unaligned(x) \
static uint##x##_t unaligned##x(const void *v) { \
return *(const uint##x##_t *) v; \
}
# endif
//unaligned(16)
//unaligned(32)
//unaligned(64)
#undef unaligned
#endif /* defined(ARCH_X86) */
#ifndef ALT_BITSTREAM_WRITER
static void put_bits(PutBitContext *s, int n, unsigned int value)
{
unsigned int bit_buf;
int bit_left;
// printf("put_bits=%d %x\n", n, value);
assert(n == 32 || value < (1U << n));
bit_buf = s->bit_buf;
bit_left = s->bit_left;
// printf("n=%d value=%x cnt=%d buf=%x\n", n, value, bit_cnt, bit_buf);
/* XXX: optimize */
if (n < bit_left) {
bit_buf = (bit_buf<<n) | value;
bit_left-=n;
} else {
bit_buf<<=bit_left;
bit_buf |= value >> (n - bit_left);
#ifdef UNALIGNED_STORES_ARE_BAD
if (3 & (intptr_t) s->buf_ptr) {
s->buf_ptr[0] = bit_buf >> 24;
s->buf_ptr[1] = bit_buf >> 16;
s->buf_ptr[2] = bit_buf >> 8;
s->buf_ptr[3] = bit_buf ;
} else
#endif
*(uint32_t *)s->buf_ptr = be2me_32(bit_buf);
//printf("bitbuf = %08x\n", bit_buf);
s->buf_ptr+=4;
bit_left+=32 - n;
bit_buf = value;
}
s->bit_buf = bit_buf;
s->bit_left = bit_left;
}
#endif
#ifdef ALT_BITSTREAM_WRITER
static void put_bits(PutBitContext *s, int n, unsigned int value)
{
# ifdef ALIGNED_BITSTREAM_WRITER
# if defined(ARCH_X86)
asm volatile(
"movl %0, %%ecx \n\t"
"xorl %%eax, %%eax \n\t"
"shrdl %%cl, %1, %%eax \n\t"
"shrl %%cl, %1 \n\t"
"movl %0, %%ecx \n\t"
"shrl $3, %%ecx \n\t"
"andl $0xFFFFFFFC, %%ecx \n\t"
"bswapl %1 \n\t"
"orl %1, (%2, %%ecx) \n\t"
"bswapl %%eax \n\t"
"addl %3, %0 \n\t"
"movl %%eax, 4(%2, %%ecx) \n\t"
: "=&r" (s->index), "=&r" (value)
: "r" (s->buf), "r" (n), "0" (s->index), "1" (value<<(-n))
: "%eax", "%ecx"
);
# else
int index= s->index;
uint32_t *ptr= ((uint32_t *)s->buf)+(index>>5);
value<<= 32-n;
ptr[0] |= be2me_32(value>>(index&31));
ptr[1] = be2me_32(value<<(32-(index&31)));
//if(n>24) printf("%d %d\n", n, value);
index+= n;
s->index= index;
# endif
# else //ALIGNED_BITSTREAM_WRITER
# if defined(ARCH_X86)
asm volatile(
"movl $7, %%ecx \n\t"
"andl %0, %%ecx \n\t"
"addl %3, %%ecx \n\t"
"negl %%ecx \n\t"
"shll %%cl, %1 \n\t"
"bswapl %1 \n\t"
"movl %0, %%ecx \n\t"
"shrl $3, %%ecx \n\t"
"orl %1, (%%ecx, %2) \n\t"
"addl %3, %0 \n\t"
"movl $0, 4(%%ecx, %2) \n\t"
: "=&r" (s->index), "=&r" (value)
: "r" (s->buf), "r" (n), "0" (s->index), "1" (value)
: "%ecx"
);
# else
int index= s->index;
uint32_t *ptr= (uint32_t*)(((uint8_t *)s->buf)+(index>>3));
ptr[0] |= be2me_32(value<<(32-n-(index&7) ));
ptr[1] = 0;
//if(n>24) printf("%d %d\n", n, value);
index+= n;
s->index= index;
# endif
# endif //!ALIGNED_BITSTREAM_WRITER
}
#endif
static uint8_t* pbBufPtr(PutBitContext *s)
{
#ifdef ALT_BITSTREAM_WRITER
return s->buf + (s->index>>3);
#else
return s->buf_ptr;
#endif
}
/**
*
* PutBitContext must be flushed & aligned to a byte boundary before calling this.
*/
static void skip_put_bytes(PutBitContext *s, int n){
assert((put_bits_count(s)&7)==0);
#ifdef ALT_BITSTREAM_WRITER
FIXME may need some cleaning of the buffer
s->index += n<<3;
#else
assert(s->bit_left==32);
s->buf_ptr += n;
#endif
}
/**
* Skips the given number of bits.
* Must only be used if the actual values in the bitstream do not matter.
*/
/*static void skip_put_bits(PutBitContext *s, int n){
#ifdef ALT_BITSTREAM_WRITER
s->index += n;
#else
s->bit_left -= n;
s->buf_ptr-= s->bit_left>>5;
s->bit_left &= 31;
#endif
}*/
/**
* Changes the end of the buffer.
*/
/*static void set_put_bits_buffer_size(PutBitContext *s, int size){
s->buf_end= s->buf + size;
}*/
/* Bitstream reader API docs:
name
abritary name which is used as prefix for the internal variables
gb
getbitcontext
OPEN_READER(name, gb)
loads gb into local variables
CLOSE_READER(name, gb)
stores local vars in gb
UPDATE_CACHE(name, gb)
refills the internal cache from the bitstream
after this call at least MIN_CACHE_BITS will be available,
GET_CACHE(name, gb)
will output the contents of the internal cache, next bit is MSB of 32 or 64 bit (FIXME 64bit)
SHOW_UBITS(name, gb, num)
will return the next num bits
SHOW_SBITS(name, gb, num)
will return the next num bits and do sign extension
SKIP_BITS(name, gb, num)
will skip over the next num bits
note, this is equivalent to SKIP_CACHE; SKIP_COUNTER
SKIP_CACHE(name, gb, num)
will remove the next num bits from the cache (note SKIP_COUNTER MUST be called before UPDATE_CACHE / CLOSE_READER)
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 SKIP_LAST_CACHE; SKIP_COUNTER
for examples see get_bits, show_bits, skip_bits, get_vlc
*/
#ifdef ALT_BITSTREAM_READER
# define MIN_CACHE_BITS 25
# define OPEN_READER(name, gb)\
int name##_index= (gb)->index;\
int name##_cache= 0;\
# define CLOSE_READER(name, gb)\
(gb)->index= name##_index;\
# ifdef ALT_BITSTREAM_READER_LE
# define UPDATE_CACHE(name, gb)\
name##_cache= AV_RL32( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) >> (name##_index&0x07);\
# define SKIP_CACHE(name, gb, num)\
name##_cache >>= (num);
# else
# define UPDATE_CACHE(name, gb)\
name##_cache= AV_RB32( ((const uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\
# define SKIP_CACHE(name, gb, num)\
name##_cache <<= (num);
# endif
// FIXME name?
# define SKIP_COUNTER(name, gb, num)\
name##_index += (num);\
# define SKIP_BITS(name, gb, num)\
{\
SKIP_CACHE(name, gb, num)\
SKIP_COUNTER(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
# define SHOW_UBITS(name, gb, num)\
((name##_cache) & (NEG_USR32(0xffffffff,num)))
# define SHOW_SBITS(name, gb, num)\
NEG_SSR32((name##_cache)<<(32-(num)), num)
# else
# define SHOW_UBITS(name, gb, num)\
NEG_USR32(name##_cache, num)
# define SHOW_SBITS(name, gb, num)\
NEG_SSR32(name##_cache, num)
# endif
# define GET_CACHE(name, gb)\
((uint32_t)name##_cache)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -