📄 snow.c
字号:
0, 4, 12, 24, 32, 44, 52, 56, 56, 52, 44, 32, 24, 12, 4, 0,
0, 0, 4, 8, 12, 16, 20, 20, 20, 20, 16, 12, 8, 4, 0, 0,
0, 0, 0, 0, 0, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0,
//error:0.000022
};
#endif
//linear *64
static const uint8_t obmc8[64]={
4, 12, 20, 28, 28, 20, 12, 4,
12, 36, 60, 84, 84, 60, 36, 12,
20, 60,100,140,140,100, 60, 20,
28, 84,140,196,196,140, 84, 28,
28, 84,140,196,196,140, 84, 28,
20, 60,100,140,140,100, 60, 20,
12, 36, 60, 84, 84, 60, 36, 12,
4, 12, 20, 28, 28, 20, 12, 4,
//error:0.000000
};
//linear *64
static const uint8_t obmc4[16]={
16, 48, 48, 16,
48,144,144, 48,
48,144,144, 48,
16, 48, 48, 16,
//error:0.000000
};
static const uint8_t *obmc_tab[4]={
obmc32, obmc16, obmc8, obmc4
};
static int scale_mv_ref[MAX_REF_FRAMES][MAX_REF_FRAMES];
typedef struct BlockNode{
int16_t mx;
int16_t my;
uint8_t ref;
uint8_t color[3];
uint8_t type;
//#define TYPE_SPLIT 1
#define BLOCK_INTRA 1
#define BLOCK_OPT 2
//#define TYPE_NOCOLOR 4
uint8_t level; //FIXME merge into type?
}BlockNode;
static const BlockNode null_block= { //FIXME add border maybe
.color= {128,128,128},
.mx= 0,
.my= 0,
.ref= 0,
.type= 0,
.level= 0,
};
#define LOG2_MB_SIZE 4
#define MB_SIZE (1<<LOG2_MB_SIZE)
#define ENCODER_EXTRA_BITS 4
#define HTAPS_MAX 8
typedef struct x_and_coeff{
int16_t x;
uint16_t coeff;
} x_and_coeff;
typedef struct SubBand{
int level;
int stride;
int width;
int height;
int qlog; ///< log(qscale)/log[2^(1/6)]
DWTELEM *buf;
IDWTELEM *ibuf;
int buf_x_offset;
int buf_y_offset;
int stride_line; ///< Stride measured in lines, not pixels.
x_and_coeff * x_coeff;
struct SubBand *parent;
uint8_t state[/*7*2*/ 7 + 512][32];
}SubBand;
typedef struct Plane{
int width;
int height;
SubBand band[MAX_DECOMPOSITIONS][4];
int htaps;
int8_t hcoeff[HTAPS_MAX/2];
int diag_mc;
int fast_mc;
int last_htaps;
int8_t last_hcoeff[HTAPS_MAX/2];
int last_diag_mc;
}Plane;
typedef struct SnowContext{
// MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independent of MpegEncContext, so this will be removed then (FIXME/XXX)
AVCodecContext *avctx;
RangeCoder c;
DSPContext dsp;
AVFrame new_picture;
AVFrame input_picture; ///< new_picture with the internal linesizes
AVFrame current_picture;
AVFrame last_picture[MAX_REF_FRAMES];
uint8_t *halfpel_plane[MAX_REF_FRAMES][4][4];
AVFrame mconly_picture;
// uint8_t q_context[16];
uint8_t header_state[32];
uint8_t block_state[128 + 32*128];
int keyframe;
int always_reset;
int version;
int spatial_decomposition_type;
int last_spatial_decomposition_type;
int temporal_decomposition_type;
int spatial_decomposition_count;
int last_spatial_decomposition_count;
int temporal_decomposition_count;
int max_ref_frames;
int ref_frames;
int16_t (*ref_mvs[MAX_REF_FRAMES])[2];
uint32_t *ref_scores[MAX_REF_FRAMES];
DWTELEM *spatial_dwt_buffer;
IDWTELEM *spatial_idwt_buffer;
int colorspace_type;
int chroma_h_shift;
int chroma_v_shift;
int spatial_scalability;
int qlog;
int last_qlog;
int lambda;
int lambda2;
int pass1_rc;
int mv_scale;
int last_mv_scale;
int qbias;
int last_qbias;
#define QBIAS_SHIFT 3
int b_width;
int b_height;
int block_max_depth;
int last_block_max_depth;
Plane plane[MAX_PLANES];
BlockNode *block;
#define ME_CACHE_SIZE 1024
int me_cache[ME_CACHE_SIZE];
int me_cache_generation;
slice_buffer sb;
MpegEncContext m; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independent of MpegEncContext, so this will be removed then (FIXME/XXX)
}SnowContext;
typedef struct {
IDWTELEM *b0;
IDWTELEM *b1;
IDWTELEM *b2;
IDWTELEM *b3;
int y;
} dwt_compose_t;
#define slice_buffer_get_line(slice_buf, line_num) ((slice_buf)->line[line_num] ? (slice_buf)->line[line_num] : slice_buffer_load_line((slice_buf), (line_num)))
//#define slice_buffer_get_line(slice_buf, line_num) (slice_buffer_load_line((slice_buf), (line_num)))
static void iterative_me(SnowContext *s);
static void slice_buffer_init(slice_buffer * buf, int line_count, int max_allocated_lines, int line_width, IDWTELEM * base_buffer)
{
int i;
buf->base_buffer = base_buffer;
buf->line_count = line_count;
buf->line_width = line_width;
buf->data_count = max_allocated_lines;
buf->line = av_mallocz (sizeof(IDWTELEM *) * line_count);
buf->data_stack = av_malloc (sizeof(IDWTELEM *) * max_allocated_lines);
for (i = 0; i < max_allocated_lines; i++)
{
buf->data_stack[i] = av_malloc (sizeof(IDWTELEM) * line_width);
}
buf->data_stack_top = max_allocated_lines - 1;
}
static IDWTELEM * slice_buffer_load_line(slice_buffer * buf, int line)
{
int offset;
IDWTELEM * buffer;
// av_log(NULL, AV_LOG_DEBUG, "Cache hit: %d\n", line);
assert(buf->data_stack_top >= 0);
// assert(!buf->line[line]);
if (buf->line[line])
return buf->line[line];
offset = buf->line_width * line;
buffer = buf->data_stack[buf->data_stack_top];
buf->data_stack_top--;
buf->line[line] = buffer;
// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_load_line: line: %d remaining: %d\n", line, buf->data_stack_top + 1);
return buffer;
}
static void slice_buffer_release(slice_buffer * buf, int line)
{
int offset;
IDWTELEM * buffer;
assert(line >= 0 && line < buf->line_count);
assert(buf->line[line]);
offset = buf->line_width * line;
buffer = buf->line[line];
buf->data_stack_top++;
buf->data_stack[buf->data_stack_top] = buffer;
buf->line[line] = NULL;
// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_release: line: %d remaining: %d\n", line, buf->data_stack_top + 1);
}
static void slice_buffer_flush(slice_buffer * buf)
{
int i;
for (i = 0; i < buf->line_count; i++)
{
if (buf->line[i])
{
// av_log(NULL, AV_LOG_DEBUG, "slice_buffer_flush: line: %d \n", i);
slice_buffer_release(buf, i);
}
}
}
static void slice_buffer_destroy(slice_buffer * buf)
{
int i;
slice_buffer_flush(buf);
for (i = buf->data_count - 1; i >= 0; i--)
{
av_freep(&buf->data_stack[i]);
}
av_freep(&buf->data_stack);
av_freep(&buf->line);
}
#ifdef __sgi
// Avoid a name clash on SGI IRIX
#undef qexp
#endif
#define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
static uint8_t qexp[QROOT];
static inline int mirror(int v, int m){
while((unsigned)v > (unsigned)m){
v=-v;
if(v<0) v+= 2*m;
}
return v;
}
static inline void put_symbol(RangeCoder *c, uint8_t *state, int v, int is_signed){
int i;
if(v){
const int a= FFABS(v);
const int e= av_log2(a);
#if 1
const int el= FFMIN(e, 10);
put_rac(c, state+0, 0);
for(i=0; i<el; i++){
put_rac(c, state+1+i, 1); //1..10
}
for(; i<e; i++){
put_rac(c, state+1+9, 1); //1..10
}
put_rac(c, state+1+FFMIN(i,9), 0);
for(i=e-1; i>=el; i--){
put_rac(c, state+22+9, (a>>i)&1); //22..31
}
for(; i>=0; i--){
put_rac(c, state+22+i, (a>>i)&1); //22..31
}
if(is_signed)
put_rac(c, state+11 + el, v < 0); //11..21
#else
put_rac(c, state+0, 0);
if(e<=9){
for(i=0; i<e; i++){
put_rac(c, state+1+i, 1); //1..10
}
put_rac(c, state+1+i, 0);
for(i=e-1; i>=0; i--){
put_rac(c, state+22+i, (a>>i)&1); //22..31
}
if(is_signed)
put_rac(c, state+11 + e, v < 0); //11..21
}else{
for(i=0; i<e; i++){
put_rac(c, state+1+FFMIN(i,9), 1); //1..10
}
put_rac(c, state+1+FFMIN(i,9), 0);
for(i=e-1; i>=0; i--){
put_rac(c, state+22+FFMIN(i,9), (a>>i)&1); //22..31
}
if(is_signed)
put_rac(c, state+11 + FFMIN(e,10), v < 0); //11..21
}
#endif
}else{
put_rac(c, state+0, 1);
}
}
static inline int get_symbol(RangeCoder *c, uint8_t *state, int is_signed){
if(get_rac(c, state+0))
return 0;
else{
int i, e, a;
e= 0;
while(get_rac(c, state+1 + FFMIN(e,9))){ //1..10
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -