📄 common.h
字号:
/**
* @file common.h
* common internal api header.
*/
#ifndef COMMON_H
#define COMMON_H
#if defined(WIN32) && !defined(__MINGW32__) && !defined(__CYGWIN__)
# define CONFIG_WIN32
#endif
#define ALT_BITSTREAM_READER
#define LIBMPEG2_BITSTREAM_READER_HACK //add BERO
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifdef HAVE_AV_CONFIG_H
/* only include the following when compiling package */
# include "config.h"
# include <stdlib.h>
# include <stdio.h>
# include <string.h>
# include <ctype.h>
#ifdef WINCE //berrno.h
# include "berrno.h"
#else
# ifndef __BEOS__
# include <errno.h>
# else
# include "berrno.h"
# endif
#endif
# include <math.h>
#define tprintf() {}
# ifndef ENODATA
# define ENODATA 61
# endif
#include <stddef.h>
#ifndef offsetof
# define offsetof(T,F) ((unsigned int)((char *)&((T *)0)->F))
#endif
#endif /* HAVE_AV_CONFIG_H */
/* Suppress restrict if it was not defined in config.h. */
#ifndef restrict
# define restrict
#endif
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
# define always_inline __attribute__((always_inline)) inline
#else
# define always_inline inline
#endif
#if defined(__GNUC__) && (__GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ > 0)
# define attribute_used __attribute__((used))
#else
# define attribute_used
#endif
#ifndef EMULATE_INTTYPES
# include <inttypes.h>
#else
typedef signed char int8_t;
typedef signed short int16_t;
typedef signed int int32_t;
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
# ifdef CONFIG_WIN32
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
# else /* other OS */
typedef signed long long int64_t;
typedef unsigned long long uint64_t;
# endif /* other OS */
#endif /* HAVE_INTTYPES_H */
#ifndef INT64_MAX
#define INT64_MAX int64_t_C(9223372036854775807)
#endif
#ifdef CONFIG_WIN32
/* windows */
# ifndef __MINGW32__
# define int64_t_C(c) (c ## i64)
# define uint64_t_C(c) (c ## i64)
# ifdef HAVE_AV_CONFIG_H
# define inline __inline
# endif
# else
# define int64_t_C(c) (c ## LL)
# define uint64_t_C(c) (c ## ULL)
# endif /* __MINGW32__ */
# ifdef HAVE_AV_CONFIG_H
# ifdef _DEBUG
//# define DEBUG
# endif
# define snprintf _snprintf
# define vsnprintf _vsnprintf
# endif
/* CONFIG_WIN32 end */
#elif defined (CONFIG_OS2)
/* OS/2 EMX */
#ifndef int64_t_C
#define int64_t_C(c) (c ## LL)
#define uint64_t_C(c) (c ## ULL)
#endif
#ifdef HAVE_AV_CONFIG_H
#ifdef USE_FASTMEMCPY
#include "fastmemcpy.h"
#endif
#include <float.h>
#endif /* HAVE_AV_CONFIG_H */
/* CONFIG_OS2 end */
#else
/* unix */
#ifndef int64_t_C
#define int64_t_C(c) (c ## LL)
#define uint64_t_C(c) (c ## ULL)
#endif
#ifdef HAVE_AV_CONFIG_H
# ifdef USE_FASTMEMCPY
# include "fastmemcpy.h"
# endif
# endif /* HAVE_AV_CONFIG_H */
#endif /* !CONFIG_WIN32 && !CONFIG_OS2 */
#ifdef HAVE_AV_CONFIG_H
# include "bswap.h"
# if defined(__MINGW32__) || defined(__CYGWIN__) || \
defined(__OS2__) || (defined (__OpenBSD__) && !defined(__ELF__))
# define MANGLE(a) "_" #a
# else
# define MANGLE(a) #a
# endif
#ifndef WINCE
# include <assert.h>
#endif
/* dprintf macros */
# if defined(CONFIG_WIN32) && !defined(__MINGW32__)
inline void dprintf(const char* fmt,...) {}
# else
# ifdef DEBUG
# define dprintf(fmt,...) av_log(NULL, AV_LOG_DEBUG, fmt, __VA_ARGS__)
# else
# define dprintf(fmt,...)
# endif
# endif /* !CONFIG_WIN32 */
#ifdef WINCE
# define av_abort() do { exit(0); } while (0)
#else
# define av_abort() do { av_log(NULL, AV_LOG_ERROR, "Abort at %s:%d\n", __FILE__, __LINE__); abort(); } while (0)
#endif
//rounded divison & shift
#define RSHIFT(a,b) ((a) > 0 ? ((a) + (1<<((b)-1)))>>(b) : ((a) + (1<<((b)-1))-1)>>(b))
/* assume b>0 */
#define ROUNDED_DIV(a,b) (((a)>0 ? (a) + ((b)>>1) : (a) - ((b)>>1))/(b))
#define ABS(a) ((a) >= 0 ? (a) : (-(a)))
#define FFMAX(a,b) ((a) > (b) ? (a) : (b))
#define FFMIN(a,b) ((a) > (b) ? (b) : (a))
extern const uint32_t inverse[256];
#ifdef ARCH_X86
# define FASTDIV(a,b) \
({\
int ret,dmy;\
asm volatile(\
"mull %3"\
:"=d"(ret),"=a"(dmy)\
:"1"(a),"g"(inverse[b])\
);\
ret;\
})
#elif defined(CONFIG_FASTDIV)
# define FASTDIV(a,b) ((uint32_t)((((uint64_t)a)*inverse[b])>>32))
#else
# define FASTDIV(a,b) ((a)/(b))
#endif
#ifdef ARCH_X86
// avoid +32 for shift optimization (gcc should do that ...)
static inline 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 inline 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 */
struct PutBitContext;
typedef void (*WriteDataFunc)(void *, uint8_t *, int);
/* 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 inline void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
{
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 inline 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 inline 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 put_string(PutBitContext * pbc, char *s, int put_zero);
/* 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 VLC {
int bits;
VLC_TYPE (*table)[2]; ///< code, bits
int table_size, table_allocated;
} VLC;
typedef struct RL_VLC_ELEM {
int16_t level;
int8_t len;
uint8_t run;
} RL_VLC_ELEM;
#ifdef ARCH_SPARC64
#define UNALIGNED_STORES_ARE_BAD
#endif
/* used to avoid missaligned exceptions on some archs (alpha, ...) */
#ifdef ARCH_X86
# define unaligned32(a) (*(uint32_t*)(a))
#else
# ifdef __GNUC__
static inline uint32_t unaligned32(const void *v) {
struct Unaligned {
uint32_t i;
} __attribute__((packed));
return ((const struct Unaligned *) v)->i;
}
# elif defined(__DECC)
static inline uint32_t unaligned32(const void *v) {
return *(const __unaligned uint32_t *) v;
}
# else
static inline uint32_t unaligned32(const void *v) {
return *(const uint32_t *) v;
}
# endif
#endif //!ARCH_X86
#ifndef ALT_BITSTREAM_WRITER
static inline void put_bits(PutBitContext *s, int n, unsigned int value)
{
unsigned int bit_buf;
int bit_left;
#ifdef STATS
st_out_bit_counts[st_current_index] += n;
#endif
// printf("put_bits=%d %x\n", n, value);
#ifndef WINCE //assert
assert(n == 32 || value < (1U << n));
#endif
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 & (int) 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 inline void put_bits(PutBitContext *s, int n, unsigned int value)
{
# ifdef ALIGNED_BITSTREAM_WRITER
# ifdef 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
# ifdef 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 inline 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 inline void skip_put_bytes(PutBitContext *s, int n){
#ifndef WINCE //assert
assert((put_bits_count(s)&7)==0);
#endif
#ifdef ALT_BITSTREAM_WRITER
//FIXME may need some cleaning of the buffer
s->index += n<<3;
#else
#ifndef WINCE //assert
assert(s->bit_left==32);
#endif
s->buf_ptr += n;
#endif
}
/**
* Changes the end of the buffer.
*/
static inline 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 nest num bits
SHOW_SBITS(name, gb, num)
will return the nest num bits and do sign extension
SKIP_BITS(name, gb, num)
will skip over the next num bits
note, this is equinvalent 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 equinvalent to SKIP_LAST_CACHE; SKIP_COUNTER
for examples see get_bits, show_bits, skip_bits, get_vlc
*/
static inline int unaligned32_be(const void *v)
{
#ifdef CONFIG_ALIGN
const uint8_t *p=(uint8_t *)v;
return (((p[0]<<8) | p[1])<<16) | (p[2]<<8) | (p[3]);
#else
return be2me_32( unaligned32(v)); //original
#endif
}
#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;\
# define UPDATE_CACHE(name, gb)\
name##_cache= unaligned32_be( ((uint8_t *)(gb)->buffer)+(name##_index>>3) ) << (name##_index&0x07);\
# define SKIP_CACHE(name, gb, num)\
name##_cache <<= (num);\
// FIXME name?
# define SKIP_COUNTER(name, gb, num)\
name##_index += (num);\
# define SKIP_BITS(name, gb, num)\
{\
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -