2006-03-16 19:18:18 +00:00
/*
* Copyright (C) 2004 Michael Niedermayer <michaelni@gmx.at>
* Copyright (C) 2006 Robert Edele <yartrebo@earthlink.net>
*
2011-03-18 17:35:10 +00:00
* This file is part of Libav.
2006-10-07 15:30:46 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is free software; you can redistribute it and/or
2006-03-16 19:18:18 +00:00
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
2006-10-07 15:30:46 +00:00
* version 2.1 of the License, or (at your option) any later version.
2006-03-16 19:18:18 +00:00
*
2011-03-18 17:35:10 +00:00
* Libav is distributed in the hope that it will be useful,
2006-03-16 19:18:18 +00:00
* 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
2011-03-18 17:35:10 +00:00
* License along with Libav; if not, write to the Free Software
2006-03-16 19:18:18 +00:00
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
2008-08-31 07:39:47 +00:00
#ifndef AVCODEC_SNOW_H
#define AVCODEC_SNOW_H
2006-03-16 19:18:18 +00:00
#include "dsputil.h"
2010-03-14 17:50:12 +00:00
#include "dwt.h"
2006-03-16 19:18:18 +00:00
2011-11-02 10:10:40 -07:00
#include "rangecoder.h"
#include "mathops.h"
#include "mpegvideo.h"
2006-03-16 19:18:18 +00:00
#define MID_STATE 128
#define MAX_PLANES 4
#define QSHIFT 5
#define QROOT (1<<QSHIFT)
#define LOSSLESS_QLOG -128
2007-08-25 03:00:51 +00:00
#define FRAC_BITS 4
2006-05-28 21:44:47 +00:00
#define MAX_REF_FRAMES 8
2006-03-16 19:18:18 +00:00
2006-03-20 05:52:23 +00:00
#define LOG2_OBMC_MAX 8
2006-03-16 19:18:18 +00:00
#define OBMC_MAX (1<<(LOG2_OBMC_MAX))
2011-11-02 10:10:40 -07:00
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 {
AVClass * class ;
AVCodecContext * avctx ;
RangeCoder c ;
DSPContext dsp ;
DWTContext dwt ;
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
2011-11-26 20:59:17 +00:00
unsigned me_cache [ ME_CACHE_SIZE ];
unsigned me_cache_generation ;
2011-11-02 10:10:40 -07:00
slice_buffer sb ;
int memc_only ;
MpegEncContext m ; // needed for motion estimation, should not be used for anything else, the idea is to eventually make the motion estimation independent of MpegEncContext, so this will be removed then (FIXME/XXX)
uint8_t * scratchbuf ;
} SnowContext ;
/* Tables */
2012-02-15 12:43:58 +02:00
extern const uint8_t * const ff_obmc_tab [ 4 ];
extern uint8_t ff_qexp [ QROOT ];
extern int ff_scale_mv_ref [ MAX_REF_FRAMES ][ MAX_REF_FRAMES ];
2006-03-16 19:18:18 +00:00
2006-03-27 12:51:19 +00:00
/* C bits used by mmx/sse2/altivec */
2007-08-25 03:00:51 +00:00
static av_always_inline void snow_interleave_line_header ( int * i , int width , IDWTELEM * low , IDWTELEM * high ){
2006-03-27 12:51:19 +00:00
( * i ) = ( width ) - 2 ;
if ( width & 1 ){
low [( * i ) + 1 ] = low [(( * i ) + 1 ) >> 1 ];
( * i ) -- ;
}
}
2007-08-25 03:00:51 +00:00
static av_always_inline void snow_interleave_line_footer ( int * i , IDWTELEM * low , IDWTELEM * high ){
2006-03-27 12:51:19 +00:00
for (; ( * i ) >= 0 ; ( * i ) -= 2 ){
low [( * i ) + 1 ] = high [( * i ) >> 1 ];
low [ * i ] = low [( * i ) >> 1 ];
}
}
2007-08-25 03:00:51 +00:00
static av_always_inline void snow_horizontal_compose_lift_lead_out ( int i , IDWTELEM * dst , IDWTELEM * src , IDWTELEM * ref , int width , int w , int lift_high , int mul , int add , int shift ){
2006-03-27 12:51:19 +00:00
for (; i < w ; i ++ ){
dst [ i ] = src [ i ] - (( mul * ( ref [ i ] + ref [ i + 1 ]) + add ) >> shift );
}
if (( width ^ lift_high ) & 1 ){
dst [ w ] = src [ w ] - (( mul * 2 * ref [ w ] + add ) >> shift );
}
}
2007-08-25 03:00:51 +00:00
static av_always_inline void snow_horizontal_compose_liftS_lead_out ( int i , IDWTELEM * dst , IDWTELEM * src , IDWTELEM * ref , int width , int w ){
2006-03-27 12:51:19 +00:00
for (; i < w ; i ++ ){
2007-08-21 16:29:40 +00:00
dst [ i ] = src [ i ] + (( ref [ i ] + ref [( i + 1 )] + W_BO + 4 * src [ i ]) >> W_BS );
2006-03-27 12:51:19 +00:00
}
if ( width & 1 ){
2007-08-21 16:29:40 +00:00
dst [ w ] = src [ w ] + (( 2 * ref [ w ] + W_BO + 4 * src [ w ]) >> W_BS );
2006-03-27 12:51:19 +00:00
}
}
2011-11-02 10:10:40 -07:00
/* common code */
int ff_snow_common_init ( AVCodecContext * avctx );
int ff_snow_common_init_after_header ( AVCodecContext * avctx );
void ff_snow_common_end ( SnowContext * s );
void ff_snow_release_buffer ( AVCodecContext * avctx );
void ff_snow_reset_contexts ( SnowContext * s );
int ff_snow_alloc_blocks ( SnowContext * s );
int ff_snow_frame_start ( SnowContext * s );
void ff_snow_pred_block ( SnowContext * s , uint8_t * dst , uint8_t * tmp , int stride ,
int sx , int sy , int b_w , int b_h , BlockNode * block ,
int plane_index , int w , int h );
/* common inline functions */
//XXX doublecheck all of them should stay inlined
static inline void snow_set_blocks ( SnowContext * s , int level , int x , int y , int l , int cb , int cr , int mx , int my , int ref , int type ){
const int w = s -> b_width << s -> block_max_depth ;
const int rem_depth = s -> block_max_depth - level ;
const int index = ( x + y * w ) << rem_depth ;
const int block_w = 1 << rem_depth ;
BlockNode block ;
int i , j ;
block . color [ 0 ] = l ;
block . color [ 1 ] = cb ;
block . color [ 2 ] = cr ;
block . mx = mx ;
block . my = my ;
block . ref = ref ;
block . type = type ;
block . level = level ;
for ( j = 0 ; j < block_w ; j ++ ){
for ( i = 0 ; i < block_w ; i ++ ){
s -> block [ index + i + j * w ] = block ;
}
}
}
static inline void pred_mv ( SnowContext * s , int * mx , int * my , int ref ,
const BlockNode * left , const BlockNode * top , const BlockNode * tr ){
if ( s -> ref_frames == 1 ){
* mx = mid_pred ( left -> mx , top -> mx , tr -> mx );
* my = mid_pred ( left -> my , top -> my , tr -> my );
} else {
2012-02-15 12:43:58 +02:00
const int * scale = ff_scale_mv_ref [ ref ];
2011-11-02 10:10:40 -07:00
* mx = mid_pred (( left -> mx * scale [ left -> ref ] + 128 ) >> 8 ,
( top -> mx * scale [ top -> ref ] + 128 ) >> 8 ,
( tr -> mx * scale [ tr -> ref ] + 128 ) >> 8 );
* my = mid_pred (( left -> my * scale [ left -> ref ] + 128 ) >> 8 ,
( top -> my * scale [ top -> ref ] + 128 ) >> 8 ,
( tr -> my * scale [ tr -> ref ] + 128 ) >> 8 );
}
}
static av_always_inline int same_block ( BlockNode * a , BlockNode * b ){
if (( a -> type & BLOCK_INTRA ) && ( b -> type & BLOCK_INTRA )){
return ! (( a -> color [ 0 ] - b -> color [ 0 ]) | ( a -> color [ 1 ] - b -> color [ 1 ]) | ( a -> color [ 2 ] - b -> color [ 2 ]));
} else {
return ! (( a -> mx - b -> mx ) | ( a -> my - b -> my ) | ( a -> ref - b -> ref ) | (( a -> type ^ b -> type ) & BLOCK_INTRA ));
}
}
//FIXME name cleanup (b_w, block_w, b_width stuff)
//XXX should we really inline it?
static av_always_inline void add_yblock ( SnowContext * s , int sliced , slice_buffer * sb , IDWTELEM * dst , uint8_t * dst8 , const uint8_t * obmc , int src_x , int src_y , int b_w , int b_h , int w , int h , int dst_stride , int src_stride , int obmc_stride , int b_x , int b_y , int add , int offset_dst , int plane_index ){
const int b_width = s -> b_width << s -> block_max_depth ;
const int b_height = s -> b_height << s -> block_max_depth ;
const int b_stride = b_width ;
BlockNode * lt = & s -> block [ b_x + b_y * b_stride ];
BlockNode * rt = lt + 1 ;
BlockNode * lb = lt + b_stride ;
BlockNode * rb = lb + 1 ;
uint8_t * block [ 4 ];
int tmp_step = src_stride >= 7 * MB_SIZE ? MB_SIZE : MB_SIZE * src_stride ;
uint8_t * tmp = s -> scratchbuf ;
uint8_t * ptmp ;
int x , y ;
if ( b_x < 0 ){
lt = rt ;
lb = rb ;
} else if ( b_x + 1 >= b_width ){
rt = lt ;
rb = lb ;
}
if ( b_y < 0 ){
lt = lb ;
rt = rb ;
} else if ( b_y + 1 >= b_height ){
lb = lt ;
rb = rt ;
}
if ( src_x < 0 ){ //FIXME merge with prev & always round internal width up to *16
obmc -= src_x ;
b_w += src_x ;
if ( ! sliced && ! offset_dst )
dst -= src_x ;
src_x = 0 ;
} else if ( src_x + b_w > w ){
b_w = w - src_x ;
}
if ( src_y < 0 ){
obmc -= src_y * obmc_stride ;
b_h += src_y ;
if ( ! sliced && ! offset_dst )
dst -= src_y * dst_stride ;
src_y = 0 ;
} else if ( src_y + b_h > h ){
b_h = h - src_y ;
}
if ( b_w <= 0 || b_h <= 0 ) return ;
assert ( src_stride > 2 * MB_SIZE + 5 );
if ( ! sliced && offset_dst )
dst += src_x + src_y * dst_stride ;
dst8 += src_x + src_y * src_stride ;
// src += src_x + src_y*src_stride;
ptmp = tmp + 3 * tmp_step ;
block [ 0 ] = ptmp ;
ptmp += tmp_step ;
ff_snow_pred_block ( s , block [ 0 ], tmp , src_stride , src_x , src_y , b_w , b_h , lt , plane_index , w , h );
if ( same_block ( lt , rt )){
block [ 1 ] = block [ 0 ];
} else {
block [ 1 ] = ptmp ;
ptmp += tmp_step ;
ff_snow_pred_block ( s , block [ 1 ], tmp , src_stride , src_x , src_y , b_w , b_h , rt , plane_index , w , h );
}
if ( same_block ( lt , lb )){
block [ 2 ] = block [ 0 ];
} else if ( same_block ( rt , lb )){
block [ 2 ] = block [ 1 ];
} else {
block [ 2 ] = ptmp ;
ptmp += tmp_step ;
ff_snow_pred_block ( s , block [ 2 ], tmp , src_stride , src_x , src_y , b_w , b_h , lb , plane_index , w , h );
}
if ( same_block ( lt , rb ) ){
block [ 3 ] = block [ 0 ];
} else if ( same_block ( rt , rb )){
block [ 3 ] = block [ 1 ];
} else if ( same_block ( lb , rb )){
block [ 3 ] = block [ 2 ];
} else {
block [ 3 ] = ptmp ;
ff_snow_pred_block ( s , block [ 3 ], tmp , src_stride , src_x , src_y , b_w , b_h , rb , plane_index , w , h );
}
if ( sliced ){
s -> dwt . inner_add_yblock ( obmc , obmc_stride , block , b_w , b_h , src_x , src_y , src_stride , sb , add , dst8 );
} else {
for ( y = 0 ; y < b_h ; y ++ ){
//FIXME ugly misuse of obmc_stride
const uint8_t * obmc1 = obmc + y * obmc_stride ;
const uint8_t * obmc2 = obmc1 + ( obmc_stride >> 1 );
const uint8_t * obmc3 = obmc1 + obmc_stride * ( obmc_stride >> 1 );
const uint8_t * obmc4 = obmc3 + ( obmc_stride >> 1 );
for ( x = 0 ; x < b_w ; x ++ ){
int v = obmc1 [ x ] * block [ 3 ][ x + y * src_stride ]
+ obmc2 [ x ] * block [ 2 ][ x + y * src_stride ]
+ obmc3 [ x ] * block [ 1 ][ x + y * src_stride ]
+ obmc4 [ x ] * block [ 0 ][ x + y * src_stride ];
v <<= 8 - LOG2_OBMC_MAX ;
if ( FRAC_BITS != 8 ){
v >>= 8 - FRAC_BITS ;
}
if ( add ){
v += dst [ x + y * dst_stride ];
v = ( v + ( 1 << ( FRAC_BITS - 1 ))) >> FRAC_BITS ;
if ( v & ( ~ 255 )) v = ~ ( v >> 31 );
dst8 [ x + y * src_stride ] = v ;
} else {
dst [ x + y * dst_stride ] -= v ;
}
}
}
}
}
static av_always_inline void predict_slice ( SnowContext * s , IDWTELEM * buf , int plane_index , int add , int mb_y ){
Plane * p = & s -> plane [ plane_index ];
const int mb_w = s -> b_width << s -> block_max_depth ;
const int mb_h = s -> b_height << s -> block_max_depth ;
int x , y , mb_x ;
int block_size = MB_SIZE >> s -> block_max_depth ;
int block_w = plane_index ? block_size / 2 : block_size ;
2012-02-15 12:43:58 +02:00
const uint8_t * obmc = plane_index ? ff_obmc_tab [ s -> block_max_depth + 1 ] : ff_obmc_tab [ s -> block_max_depth ];
2011-11-02 10:10:40 -07:00
const int obmc_stride = plane_index ? block_size : 2 * block_size ;
int ref_stride = s -> current_picture . linesize [ plane_index ];
uint8_t * dst8 = s -> current_picture . data [ plane_index ];
int w = p -> width ;
int h = p -> height ;
if ( s -> keyframe || ( s -> avctx -> debug & 512 )){
if ( mb_y == mb_h )
return ;
if ( add ){
for ( y = block_w * mb_y ; y < FFMIN ( h , block_w * ( mb_y + 1 )); y ++ ){
for ( x = 0 ; x < w ; x ++ ){
int v = buf [ x + y * w ] + ( 128 << FRAC_BITS ) + ( 1 << ( FRAC_BITS - 1 ));
v >>= FRAC_BITS ;
if ( v & ( ~ 255 )) v = ~ ( v >> 31 );
dst8 [ x + y * ref_stride ] = v ;
}
}
} else {
for ( y = block_w * mb_y ; y < FFMIN ( h , block_w * ( mb_y + 1 )); y ++ ){
for ( x = 0 ; x < w ; x ++ ){
buf [ x + y * w ] -= 128 << FRAC_BITS ;
}
}
}
return ;
}
for ( mb_x = 0 ; mb_x <= mb_w ; mb_x ++ ){
add_yblock ( s , 0 , NULL , buf , dst8 , obmc ,
block_w * mb_x - block_w / 2 ,
block_w * mb_y - block_w / 2 ,
block_w , block_w ,
w , h ,
w , ref_stride , obmc_stride ,
mb_x - 1 , mb_y - 1 ,
add , 1 , plane_index );
}
}
static av_always_inline void predict_plane ( SnowContext * s , IDWTELEM * buf , int plane_index , int add ){
const int mb_h = s -> b_height << s -> block_max_depth ;
int mb_y ;
for ( mb_y = 0 ; mb_y <= mb_h ; mb_y ++ )
predict_slice ( s , buf , plane_index , add , mb_y );
}
static inline void set_blocks ( SnowContext * s , int level , int x , int y , int l , int cb , int cr , int mx , int my , int ref , int type ){
const int w = s -> b_width << s -> block_max_depth ;
const int rem_depth = s -> block_max_depth - level ;
const int index = ( x + y * w ) << rem_depth ;
const int block_w = 1 << rem_depth ;
BlockNode block ;
int i , j ;
block . color [ 0 ] = l ;
block . color [ 1 ] = cb ;
block . color [ 2 ] = cr ;
block . mx = mx ;
block . my = my ;
block . ref = ref ;
block . type = type ;
block . level = level ;
for ( j = 0 ; j < block_w ; j ++ ){
for ( i = 0 ; i < block_w ; i ++ ){
s -> block [ index + i + j * w ] = block ;
}
}
}
static inline void init_ref ( MotionEstContext * c , uint8_t * src [ 3 ], uint8_t * ref [ 3 ], uint8_t * ref2 [ 3 ], int x , int y , int ref_index ){
const int offset [ 3 ] = {
y * c -> stride + x ,
(( y * c -> uvstride + x ) >> 1 ),
(( y * c -> uvstride + x ) >> 1 ),
};
int i ;
for ( i = 0 ; i < 3 ; i ++ ){
c -> src [ 0 ][ i ] = src [ i ];
c -> ref [ 0 ][ i ] = ref [ i ] + offset [ i ];
}
assert ( ! ref_index );
}
/* bitstream functions */
2012-02-15 12:43:58 +02:00
extern const int8_t ff_quant3bA [ 256 ];
2011-11-02 10:10:40 -07:00
#define QEXPSHIFT (7-FRAC_BITS+8) //FIXME try to change this to 0
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 );
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 , 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
e ++ ;
}
a = 1 ;
for ( i = e - 1 ; i >= 0 ; i -- ){
a += a + get_rac ( c , state + 22 + FFMIN ( i , 9 )); //22..31
}
e = - ( is_signed && get_rac ( c , state + 11 + FFMIN ( e , 10 ))); //11..21
return ( a ^ e ) - e ;
}
}
static inline void put_symbol2 ( RangeCoder * c , uint8_t * state , int v , int log2 ){
int i ;
int r = log2 >= 0 ? 1 << log2 : 1 ;
assert ( v >= 0 );
assert ( log2 >=- 4 );
while ( v >= r ){
put_rac ( c , state + 4 + log2 , 1 );
v -= r ;
log2 ++ ;
if ( log2 > 0 ) r += r ;
}
put_rac ( c , state + 4 + log2 , 0 );
for ( i = log2 - 1 ; i >= 0 ; i -- ){
put_rac ( c , state + 31 - i , ( v >> i ) & 1 );
}
}
static inline int get_symbol2 ( RangeCoder * c , uint8_t * state , int log2 ){
int i ;
int r = log2 >= 0 ? 1 << log2 : 1 ;
int v = 0 ;
assert ( log2 >=- 4 );
while ( get_rac ( c , state + 4 + log2 )){
v += r ;
log2 ++ ;
if ( log2 > 0 ) r += r ;
}
for ( i = log2 - 1 ; i >= 0 ; i -- ){
v += get_rac ( c , state + 31 - i ) << i ;
}
return v ;
}
static inline void unpack_coeffs ( SnowContext * s , SubBand * b , SubBand * parent , int orientation ){
const int w = b -> width ;
const int h = b -> height ;
int x , y ;
int run , runs ;
x_and_coeff * xc = b -> x_coeff ;
x_and_coeff * prev_xc = NULL ;
x_and_coeff * prev2_xc = xc ;
x_and_coeff * parent_xc = parent ? parent -> x_coeff : NULL ;
x_and_coeff * prev_parent_xc = parent_xc ;
runs = get_symbol2 ( & s -> c , b -> state [ 30 ], 0 );
if ( runs -- > 0 ) run = get_symbol2 ( & s -> c , b -> state [ 1 ], 3 );
else run = INT_MAX ;
for ( y = 0 ; y < h ; y ++ ){
int v = 0 ;
int lt = 0 , t = 0 , rt = 0 ;
if ( y && prev_xc -> x == 0 ){
rt = prev_xc -> coeff ;
}
for ( x = 0 ; x < w ; x ++ ){
int p = 0 ;
const int l = v ;
lt = t ; t = rt ;
if ( y ){
if ( prev_xc -> x <= x )
prev_xc ++ ;
if ( prev_xc -> x == x + 1 )
rt = prev_xc -> coeff ;
else
rt = 0 ;
}
if ( parent_xc ){
if ( x >> 1 > parent_xc -> x ){
parent_xc ++ ;
}
if ( x >> 1 == parent_xc -> x ){
p = parent_xc -> coeff ;
}
}
if ( /*ll|*/ l | lt | t | rt | p ){
int context = av_log2 ( /*FFABS(ll) + */ 3 * ( l >> 1 ) + ( lt >> 1 ) + ( t &~ 1 ) + ( rt >> 1 ) + ( p >> 1 ));
v = get_rac ( & s -> c , & b -> state [ 0 ][ context ]);
if ( v ){
v = 2 * ( get_symbol2 ( & s -> c , b -> state [ context + 2 ], context - 4 ) + 1 );
2012-02-15 12:43:58 +02:00
v += get_rac ( & s -> c , & b -> state [ 0 ][ 16 + 1 + 3 + ff_quant3bA [ l & 0xFF ] + 3 * ff_quant3bA [ t & 0xFF ]]);
2011-11-02 10:10:40 -07:00
xc -> x = x ;
( xc ++ ) -> coeff = v ;
}
} else {
if ( ! run ){
if ( runs -- > 0 ) run = get_symbol2 ( & s -> c , b -> state [ 1 ], 3 );
else run = INT_MAX ;
v = 2 * ( get_symbol2 ( & s -> c , b -> state [ 0 + 2 ], 0 - 4 ) + 1 );
v += get_rac ( & s -> c , & b -> state [ 0 ][ 16 + 1 + 3 ]);
xc -> x = x ;
( xc ++ ) -> coeff = v ;
} else {
int max_run ;
run -- ;
v = 0 ;
if ( y ) max_run = FFMIN ( run , prev_xc -> x - x - 2 );
else max_run = FFMIN ( run , w - x - 1 );
if ( parent_xc )
max_run = FFMIN ( max_run , 2 * parent_xc -> x - x - 1 );
x += max_run ;
run -= max_run ;
}
}
}
( xc ++ ) -> x = w + 1 ; //end marker
prev_xc = prev2_xc ;
prev2_xc = xc ;
if ( parent_xc ){
if ( y & 1 ){
while ( parent_xc -> x != parent -> width + 1 )
parent_xc ++ ;
parent_xc ++ ;
prev_parent_xc = parent_xc ;
} else {
parent_xc = prev_parent_xc ;
}
}
}
( xc ++ ) -> x = w + 1 ; //end marker
}
2008-08-31 07:39:47 +00:00
#endif /* AVCODEC_SNOW_H */