@ -41,24 +41,57 @@ static void free_buffers(VP8Context *s)
av_freep ( & s - > top_nnz ) ;
av_freep ( & s - > edge_emu_buffer ) ;
av_freep ( & s - > top_border ) ;
av_freep ( & s - > segmentation_map ) ;
s - > macroblocks = NULL ;
}
static void vp8_decode_flush ( AVCodecContext * avctx )
static int vp8_alloc_frame ( VP8Context * s , AVFrame * f )
{
int ret ;
if ( ( ret = ff_thread_get_buffer ( s - > avctx , f ) ) < 0 )
return ret ;
if ( ! s - > maps_are_invalid & & s - > num_maps_to_be_freed ) {
f - > ref_index [ 0 ] = s - > segmentation_maps [ - - s - > num_maps_to_be_freed ] ;
} else if ( ! ( f - > ref_index [ 0 ] = av_mallocz ( s - > mb_width * s - > mb_height ) ) ) {
ff_thread_release_buffer ( s - > avctx , f ) ;
return AVERROR ( ENOMEM ) ;
}
return 0 ;
}
static void vp8_release_frame ( VP8Context * s , AVFrame * f , int is_close )
{
if ( ! is_close ) {
if ( f - > ref_index [ 0 ] ) {
assert ( s - > num_maps_to_be_freed < FF_ARRAY_ELEMS ( s - > segmentation_maps ) ) ;
s - > segmentation_maps [ s - > num_maps_to_be_freed + + ] = f - > ref_index [ 0 ] ;
f - > ref_index [ 0 ] = NULL ;
}
} else {
av_freep ( & f - > ref_index [ 0 ] ) ;
}
ff_thread_release_buffer ( s - > avctx , f ) ;
}
static void vp8_decode_flush_impl ( AVCodecContext * avctx , int force , int is_close )
{
VP8Context * s = avctx - > priv_data ;
int i ;
if ( ! avctx - > is_copy ) {
if ( ! avctx - > is_copy | | force ) {
for ( i = 0 ; i < 5 ; i + + )
if ( s - > frames [ i ] . data [ 0 ] )
ff_thread_release_buffer ( avctx , & s - > frames [ i ] ) ;
vp8_release_frame ( s , & s - > frames [ i ] , is_close ) ;
}
memset ( s - > framep , 0 , sizeof ( s - > framep ) ) ;
free_buffers ( s ) ;
s - > maps_are_invalid = 1 ;
}
static void vp8_decode_flush ( AVCodecContext * avctx )
{
vp8_decode_flush_impl ( avctx , 0 , 0 ) ;
}
static int update_dimensions ( VP8Context * s , int width , int height )
@ -68,7 +101,7 @@ static int update_dimensions(VP8Context *s, int width, int height)
if ( av_image_check_size ( width , height , 0 , s - > avctx ) )
return AVERROR_INVALIDDATA ;
vp8_decode_flush ( s - > avctx ) ;
vp8_decode_flush_impl ( s - > avctx , 1 , 0 ) ;
avcodec_set_dimensions ( s - > avctx , width , height ) ;
}
@ -81,10 +114,9 @@ static int update_dimensions(VP8Context *s, int width, int height)
s - > intra4x4_pred_mode_top = av_mallocz ( s - > mb_width * 4 ) ;
s - > top_nnz = av_mallocz ( s - > mb_width * sizeof ( * s - > top_nnz ) ) ;
s - > top_border = av_mallocz ( ( s - > mb_width + 1 ) * sizeof ( * s - > top_border ) ) ;
s - > segmentation_map = av_mallocz ( s - > mb_width * s - > mb_height ) ;
if ( ! s - > macroblocks_base | | ! s - > filter_strength | | ! s - > intra4x4_pred_mode_top | |
! s - > top_nnz | | ! s - > top_border | | ! s - > segmentation_map )
! s - > top_nnz | | ! s - > top_border )
return AVERROR ( ENOMEM ) ;
s - > macroblocks = s - > macroblocks_base + 1 ;
@ -1508,6 +1540,14 @@ static void filter_mb_row_simple(VP8Context *s, AVFrame *curframe, int mb_y)
}
}
static void release_queued_segmaps ( VP8Context * s , int is_close )
{
int leave_behind = is_close ? 0 : ! s - > maps_are_invalid ;
while ( s - > num_maps_to_be_freed > leave_behind )
av_freep ( & s - > segmentation_maps [ - - s - > num_maps_to_be_freed ] ) ;
s - > maps_are_invalid = 0 ;
}
static int vp8_decode_frame ( AVCodecContext * avctx , void * data , int * data_size ,
AVPacket * avpkt )
{
@ -1516,6 +1556,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
enum AVDiscard skip_thresh ;
AVFrame * av_uninit ( curframe ) , * prev_frame = s - > framep [ VP56_FRAME_CURRENT ] ;
release_queued_segmaps ( s , 0 ) ;
if ( ( ret = decode_frame_header ( s , avpkt - > data , avpkt - > size ) ) < 0 )
return ret ;
@ -1538,7 +1580,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
& s - > frames [ i ] ! = s - > framep [ VP56_FRAME_PREVIOUS ] & &
& s - > frames [ i ] ! = s - > framep [ VP56_FRAME_GOLDEN ] & &
& s - > frames [ i ] ! = s - > framep [ VP56_FRAME_GOLDEN2 ] )
ff_thread_release_buffer ( avctx , & s - > frames [ i ] ) ;
vp8_release_frame ( s , & s - > frames [ i ] , 0 ) ;
// find a free buffer
for ( i = 0 ; i < 5 ; i + + )
@ -1559,8 +1601,7 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
curframe - > key_frame = s - > keyframe ;
curframe - > pict_type = s - > keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P ;
curframe - > reference = referenced ? 3 : 0 ;
curframe - > ref_index [ 0 ] = s - > segmentation_map ;
if ( ( ret = ff_thread_get_buffer ( avctx , curframe ) ) ) {
if ( ( ret = vp8_alloc_frame ( s , curframe ) ) ) {
av_log ( avctx , AV_LOG_ERROR , " get_buffer() failed! \n " ) ;
return ret ;
}
@ -1652,8 +1693,8 @@ static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
s - > dsp . prefetch ( dst [ 0 ] + ( mb_x & 3 ) * 4 * s - > linesize + 64 , s - > linesize , 4 ) ;
s - > dsp . prefetch ( dst [ 1 ] + ( mb_x & 7 ) * s - > uvlinesize + 64 , dst [ 2 ] - dst [ 1 ] , 2 ) ;
decode_mb_mode ( s , mb , mb_x , mb_y , s - > segmentation_map + mb_xy ,
prev_frame ? prev_frame - > ref_index [ 0 ] + mb_xy : NULL ) ;
decode_mb_mode ( s , mb , mb_x , mb_y , curframe - > ref_index [ 0 ] + mb_xy ,
prev_frame & & prev_frame - > ref_index [ 0 ] ? prev_frame - > ref_index [ 0 ] + mb_xy : NULL ) ;
prefetch_motion ( s , mb , mb_x , mb_y , mb_xy , VP56_FRAME_PREVIOUS ) ;
@ -1736,7 +1777,8 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx)
static av_cold int vp8_decode_free ( AVCodecContext * avctx )
{
vp8_decode_flush ( avctx ) ;
vp8_decode_flush_impl ( avctx , 0 , 1 ) ;
release_queued_segmaps ( avctx - > priv_data , 1 ) ;
return 0 ;
}