@ -48,6 +48,8 @@
# undef NDEBUG
# include <assert.h>
extern const uint8_t mvtab [ 33 ] [ 2 ] ;
static VLC svq1_block_type ;
static VLC svq1_motion_component ;
static VLC svq1_intra_multistage [ 6 ] ;
@ -55,15 +57,13 @@ static VLC svq1_inter_multistage[6];
static VLC svq1_intra_mean ;
static VLC svq1_inter_mean ;
# define MEDIAN(a,b,c) (((a < b) != (b >= c)) ? b : (((a < c) != (c > b)) ? c : a))
# define SVQ1_BLOCK_SKIP 0
# define SVQ1_BLOCK_INTER 1
# define SVQ1_BLOCK_INTER_4V 2
# define SVQ1_BLOCK_INTRA 3
typedef struct SVQ1Context {
MpegEncContext m ; // needed for motion estimation, should not be used for anything else, the idea is to make the motion estimation eventually independant of MpegEncContext, so this will be removed then (FIXME/XXX)
AVCodecContext * avctx ;
DSPContext dsp ;
AVFrame picture ;
@ -86,6 +86,11 @@ typedef struct SVQ1Context {
int c_block_height ;
unsigned char * c_plane ;
uint16_t * mb_type ;
uint32_t * dummy ;
int16_t ( * motion_val8 [ 3 ] ) [ 2 ] ;
int16_t ( * motion_val16 [ 3 ] ) [ 2 ] ;
int64_t rd_total ;
} SVQ1Context ;
@ -349,13 +354,18 @@ static int svq1_decode_motion_vector (GetBitContext *bitbuf, svq1_pmv_t *mv, svq
for ( i = 0 ; i < 2 ; i + + ) {
/* get motion code */
diff = get_vlc2 ( bitbuf , svq1_motion_component . table , 7 , 2 ) - 32 ;
diff = get_vlc2 ( bitbuf , svq1_motion_component . table , 7 , 2 ) ;
if ( diff < 0 )
return - 1 ;
else if ( diff ) {
if ( get_bits1 ( bitbuf ) ) diff = - diff ;
}
/* add median of motion vector predictors and clip result */
if ( i = = 1 )
mv - > y = ( ( diff + MEDIAN ( pmv [ 0 ] - > y , pmv [ 1 ] - > y , pmv [ 2 ] - > y ) ) < < 26 ) > > 26 ;
mv - > y = ( ( diff + mid_pred ( pmv [ 0 ] - > y , pmv [ 1 ] - > y , pmv [ 2 ] - > y ) ) < < 26 ) > > 26 ;
else
mv - > x = ( ( diff + MEDIAN ( pmv [ 0 ] - > x , pmv [ 1 ] - > x , pmv [ 2 ] - > x ) ) < < 26 ) > > 26 ;
mv - > x = ( ( diff + mid_pred ( pmv [ 0 ] - > x , pmv [ 1 ] - > x , pmv [ 2 ] - > x ) ) < < 26 ) > > 26 ;
}
return 0 ;
@ -834,9 +844,9 @@ static int svq1_decode_init(AVCodecContext *avctx)
& svq1_block_type_vlc [ 0 ] [ 1 ] , 2 , 1 ,
& svq1_block_type_vlc [ 0 ] [ 0 ] , 2 , 1 ) ;
init_vlc ( & svq1_motion_component , 7 , 65 ,
& svq1_motion_component_vlc [ 0 ] [ 1 ] , 2 , 1 ,
& svq1_motion_component_vlc [ 0 ] [ 0 ] , 2 , 1 ) ;
init_vlc ( & svq1_motion_component , 7 , 33 ,
& mvtab [ 0 ] [ 1 ] , 2 , 1 ,
& mvtab [ 0 ] [ 0 ] , 2 , 1 ) ;
for ( i = 0 ; i < 6 ; i + + ) {
init_vlc ( & svq1_intra_multistage [ i ] , 3 , 8 ,
@ -1461,7 +1471,7 @@ static int encode_block(SVQ1Context *s, uint8_t *src, uint8_t *ref, uint8_t *dec
return best_score ;
}
static void svq1_encode_plane ( SVQ1Context * s , unsigned char * src_plane , unsigned char * ref_plane , unsigned char * decoded_plane ,
static void svq1_encode_plane ( SVQ1Context * s , int plane , unsigned char * src_plane , unsigned char * ref_plane , unsigned char * decoded_plane ,
int width , int height , int src_stride , int stride )
{
unsigned char buffer0 [ 256 ] ;
@ -1493,6 +1503,75 @@ av_log(s->avctx, AV_LOG_INFO, "********* frame #%d\n", frame++);
block_width = ( width + 15 ) / 16 ;
block_height = ( height + 15 ) / 16 ;
if ( s - > picture . pict_type = = P_TYPE ) {
s - > m . avctx = s - > avctx ;
s - > m . current_picture_ptr = & s - > m . current_picture ;
s - > m . last_picture_ptr = & s - > m . last_picture ;
s - > m . last_picture . data [ 0 ] = ref_plane ;
s - > m . linesize =
s - > m . last_picture . linesize [ 0 ] =
s - > m . new_picture . linesize [ 0 ] =
s - > m . current_picture . linesize [ 0 ] = stride ;
s - > m . width = width ;
s - > m . height = height ;
s - > m . mb_width = block_width ;
s - > m . mb_height = block_height ;
s - > m . mb_stride = s - > m . mb_width + 1 ;
s - > m . b8_stride = 2 * s - > m . mb_width + 1 ;
s - > m . f_code = 1 ;
s - > m . pict_type = s - > picture . pict_type ;
s - > m . qscale = s - > picture . quality / FF_QP2LAMBDA ;
s - > m . me_method = s - > avctx - > me_method ;
if ( ! s - > motion_val8 [ plane ] ) {
s - > motion_val8 [ plane ] = av_mallocz ( s - > m . b8_stride * block_height * 2 * 2 * sizeof ( int16_t ) ) ;
s - > motion_val16 [ plane ] = av_mallocz ( s - > m . mb_stride * block_height * 2 * sizeof ( int16_t ) ) ;
}
s - > m . mb_type = s - > mb_type ;
//dummies, to avoid segfaults
s - > m . current_picture . mb_mean = s - > dummy ;
s - > m . current_picture . mb_var = s - > dummy ;
s - > m . current_picture . mc_mb_var = s - > dummy ;
s - > m . current_picture . mb_type = s - > dummy ;
s - > m . current_picture . motion_val [ 0 ] = s - > motion_val8 [ plane ] ;
s - > m . p_mv_table = s - > motion_val16 [ plane ] ;
s - > m . dsp = s - > dsp ; //move
ff_init_me ( & s - > m ) ;
s - > m . me . dia_size = s - > avctx - > dia_size ;
s - > m . first_slice_line = 1 ;
for ( y = 0 ; y < block_height ; y + + ) {
uint8_t src [ stride * 16 ] ;
s - > m . new_picture . data [ 0 ] = src - y * 16 * stride ; //ugly
s - > m . mb_y = y ;
for ( i = 0 ; i < 16 & & i + 16 * y < height ; i + + ) {
memcpy ( & src [ i * stride ] , & src_plane [ ( i + 16 * y ) * src_stride ] , width ) ;
for ( x = width ; x < 16 * block_width ; x + + )
src [ i * stride + x ] = src [ i * stride + x - 1 ] ;
}
for ( ; i < 16 & & i + 16 * y < 16 * block_height ; i + + )
memcpy ( & src [ i * stride ] , & src [ ( i - 1 ) * stride ] , 16 * block_width ) ;
for ( x = 0 ; x < block_width ; x + + ) {
s - > m . mb_x = x ;
ff_init_block_index ( & s - > m ) ;
ff_update_block_index ( & s - > m ) ;
ff_estimate_p_frame_motion ( & s - > m , x , y ) ;
}
s - > m . first_slice_line = 0 ;
}
ff_fix_long_p_mvs ( & s - > m ) ;
ff_fix_long_mvs ( & s - > m , NULL , 0 , s - > m . p_mv_table , s - > m . f_code , CANDIDATE_MB_TYPE_INTER , 0 ) ;
}
s - > m . first_slice_line = 1 ;
for ( y = 0 ; y < block_height ; y + + ) {
uint8_t src [ stride * 16 ] ;
@ -1504,53 +1583,91 @@ av_log(s->avctx, AV_LOG_INFO, "********* frame #%d\n", frame++);
for ( ; i < 16 & & i + 16 * y < 16 * block_height ; i + + )
memcpy ( & src [ i * stride ] , & src [ ( i - 1 ) * stride ] , 16 * block_width ) ;
s - > m . mb_y = y ;
for ( x = 0 ; x < block_width ; x + + ) {
uint8_t reorder_buffer [ 2 ] [ 6 ] [ 7 * 32 ] ;
int count [ 2 ] [ 6 ] ;
uint8_t reorder_buffer [ 3 ] [ 6 ] [ 7 * 32 ] ;
int count [ 3 ] [ 6 ] ;
int offset = y * 16 * stride + x * 16 ;
uint8_t * decoded = decoded_plane + offset ;
uint8_t * ref = ref_plane + offset ;
int score [ 2 ] = { 0 , 0 } , best ;
int score [ 4 ] = { 0 , 0 , 0 , 0 } , best ;
uint8_t temp [ 16 * stride ] ;
s - > m . mb_x = x ;
ff_init_block_index ( & s - > m ) ;
ff_update_block_index ( & s - > m ) ;
# ifdef DEBUG_SVQ1
av_log ( s - > avctx , AV_LOG_INFO , " * level 5 vector @ %d, %d: \n " , x * 16 , y * 16 ) ;
# endif
for ( i = 0 ; i < 6 ; i + + ) {
init_put_bits ( & s - > reorder_pb [ i ] , reorder_buffer [ 0 ] [ i ] , 7 * 32 ) ;
}
if ( s - > picture . pict_type = = P_TYPE ) {
const uint8_t * vlc = svq1_block_type_vlc [ SVQ1_BLOCK_INTRA ] ;
put_bits ( & s - > reorder_pb [ 5 ] , vlc [ 1 ] , vlc [ 0 ] ) ;
score [ 0 ] = vlc [ 1 ] * lambda ;
}
score [ 0 ] + = encode_block ( s , src + 16 * x , ref , temp , stride , 5 , 64 , lambda , 1 ) ;
for ( i = 0 ; i < 6 ; i + + ) {
count [ 0 ] [ i ] = put_bits_count ( & s - > reorder_pb [ i ] ) ;
flush_put_bits ( & s - > reorder_pb [ i ] ) ;
init_put_bits ( & s - > reorder_pb [ i ] , reorder_buffer [ 1 ] [ i ] , 7 * 32 ) ;
}
if ( s - > picture . pict_type = = I_TYPE | | ( s - > m . mb_type [ x + y * s - > m . mb_stride ] & CANDIDATE_MB_TYPE_INTRA ) ) {
for ( i = 0 ; i < 6 ; i + + ) {
init_put_bits ( & s - > reorder_pb [ i ] , reorder_buffer [ 0 ] [ i ] , 7 * 32 ) ;
}
if ( s - > picture . pict_type = = P_TYPE ) {
const uint8_t * vlc = svq1_block_type_vlc [ SVQ1_BLOCK_INTRA ] ;
put_bits ( & s - > reorder_pb [ 5 ] , vlc [ 1 ] , vlc [ 0 ] ) ;
score [ 0 ] = vlc [ 1 ] * lambda ;
}
score [ 0 ] + = encode_block ( s , src + 16 * x , NULL , temp , stride , 5 , 64 , lambda , 1 ) ;
for ( i = 0 ; i < 6 ; i + + ) {
count [ 0 ] [ i ] = put_bits_count ( & s - > reorder_pb [ i ] ) ;
flush_put_bits ( & s - > reorder_pb [ i ] ) ;
}
} else
score [ 0 ] = INT_MAX ;
best = 0 ;
if ( s - > picture . pict_type = = P_TYPE ) {
const uint8_t * vlc = svq1_block_type_vlc [ SVQ1_BLOCK_INTER ] ;
put_bits ( & s - > reorder_pb [ 5 ] , vlc [ 1 ] , vlc [ 0 ] ) ;
score [ 1 ] = vlc [ 1 ] * lambda ;
for ( i = 0 ; i < 2 ; i + + ) {
vlc = svq1_motion_component_vlc [ 32 ] ;
int mx , my , pred_x , pred_y , dxy ;
int16_t * motion_ptr ;
motion_ptr = h263_pred_motion ( & s - > m , 0 , 0 , & pred_x , & pred_y ) ;
if ( s - > m . mb_type [ x + y * s - > m . mb_stride ] & CANDIDATE_MB_TYPE_INTER ) {
for ( i = 0 ; i < 6 ; i + + )
init_put_bits ( & s - > reorder_pb [ i ] , reorder_buffer [ 1 ] [ i ] , 7 * 32 ) ;
put_bits ( & s - > reorder_pb [ 5 ] , vlc [ 1 ] , vlc [ 0 ] ) ;
score [ 1 ] + = vlc [ 1 ] * lambda ;
s - > m . pb = s - > reorder_pb [ 5 ] ;
mx = motion_ptr [ 0 ] ;
my = motion_ptr [ 1 ] ;
assert ( mx > = - 32 & & mx < = 31 ) ;
assert ( my > = - 32 & & my < = 31 ) ;
assert ( pred_x > = - 32 & & pred_x < = 31 ) ;
assert ( pred_y > = - 32 & & pred_y < = 31 ) ;
ff_h263_encode_motion ( & s - > m , mx - pred_x , 1 ) ;
ff_h263_encode_motion ( & s - > m , my - pred_y , 1 ) ;
s - > reorder_pb [ 5 ] = s - > m . pb ;
score [ 1 ] + = lambda * put_bits_count ( & s - > reorder_pb [ 5 ] ) ;
dxy = ( mx & 1 ) + 2 * ( my & 1 ) ;
s - > dsp . put_pixels_tab [ 0 ] [ dxy ] ( temp + 16 , ref + ( mx > > 1 ) + stride * ( my > > 1 ) , stride , 16 ) ;
score [ 1 ] + = encode_block ( s , src + 16 * x , temp + 16 , decoded , stride , 5 , 64 , lambda , 0 ) ;
best = score [ 1 ] < = score [ 0 ] ;
}
score [ 1 ] + = encode_block ( s , src + 16 * x , ref , decoded , stride , 5 , 64 , lambda , 0 ) ;
best = score [ 1 ] < = score [ 0 ] ;
#if 0
if ( skiped_score < = score [ best ] ) {
best = 3 ;
. . .
}
# endif
if ( best = = 1 ) {
for ( i = 0 ; i < 6 ; i + + ) {
count [ 1 ] [ i ] = put_bits_count ( & s - > reorder_pb [ i ] ) ;
flush_put_bits ( & s - > reorder_pb [ i ] ) ;
}
} else {
motion_ptr [ 0 ] = motion_ptr [ 1 ] =
motion_ptr [ 2 ] = motion_ptr [ 3 ] =
motion_ptr [ 0 + 2 * s - > m . b8_stride ] = motion_ptr [ 1 + 2 * s - > m . b8_stride ] =
motion_ptr [ 2 + 2 * s - > m . b8_stride ] = motion_ptr [ 3 + 2 * s - > m . b8_stride ] = 0 ;
}
} else
best = 0 ;
}
s - > rd_total + = score [ best ] ;
@ -1636,6 +1753,7 @@ av_log(s->avctx, AV_LOG_INFO, " split to level %d\n", level - 1);
}
# endif
}
s - > m . first_slice_line = 0 ;
}
}
@ -1691,6 +1809,14 @@ static int svq1_encode_init(AVCodecContext *avctx)
s - > c_block_width = ( s - > frame_width / 4 + 15 ) / 16 ;
s - > c_block_height = ( s - > frame_height / 4 + 15 ) / 16 ;
s - > avctx = avctx ;
s - > m . me . scratchpad = av_mallocz ( ( avctx - > width + 64 ) * 2 * 16 * 2 * sizeof ( uint8_t ) ) ;
s - > m . me . map = av_mallocz ( ME_MAP_SIZE * sizeof ( uint32_t ) ) ;
s - > m . me . score_map = av_mallocz ( ME_MAP_SIZE * sizeof ( uint32_t ) ) ;
s - > mb_type = av_mallocz ( ( s - > y_block_width + 1 ) * s - > y_block_height * sizeof ( int16_t ) ) ;
s - > dummy = av_mallocz ( ( s - > y_block_width + 1 ) * s - > y_block_height * sizeof ( int32_t ) ) ;
h263_encode_init ( & s - > m ) ; //mv_penalty
av_log ( s - > avctx , AV_LOG_INFO , " Hey: %d x %d, %d x %d, %d x %d \n " ,
s - > frame_width , s - > frame_height ,
s - > y_block_width , s - > y_block_height ,
@ -1746,7 +1872,7 @@ static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
svq1_write_header ( s , p - > pict_type ) ;
for ( i = 0 ; i < 3 ; i + + ) {
svq1_encode_plane ( s ,
svq1_encode_plane ( s , i ,
s - > picture . data [ i ] , s - > last_picture . data [ i ] , s - > current_picture . data [ i ] ,
s - > frame_width / ( i ? 4 : 1 ) , s - > frame_height / ( i ? 4 : 1 ) ,
s - > picture . linesize [ i ] , s - > current_picture . linesize [ i ] ) ;
@ -1764,10 +1890,21 @@ static int svq1_encode_frame(AVCodecContext *avctx, unsigned char *buf,
static int svq1_encode_end ( AVCodecContext * avctx )
{
SVQ1Context * const s = avctx - > priv_data ;
int i ;
av_log ( avctx , AV_LOG_DEBUG , " RD: %f \n " , s - > rd_total / ( double ) ( avctx - > width * avctx - > height * avctx - > frame_number ) ) ;
av_free ( s - > c_plane ) ;
av_freep ( & s - > c_plane ) ;
av_freep ( & s - > m . me . scratchpad ) ;
av_freep ( & s - > m . me . map ) ;
av_freep ( & s - > m . me . score_map ) ;
av_freep ( & s - > mb_type ) ;
av_freep ( & s - > dummy ) ;
for ( i = 0 ; i < 3 ; i + + ) {
av_freep ( & s - > motion_val8 [ i ] ) ;
av_freep ( & s - > motion_val16 [ i ] ) ;
}
return 0 ;
}