@ -480,22 +480,49 @@ static void print_long_term(H264Context *h) {
}
}
void ff_generate_sliding_window_mmcos ( H264Context * h ) {
MpegEncContext * const s = & h - > s ;
static int check_opcodes ( MMCO * mmco1 , MMCO * mmco2 , int n_mmcos )
{
int i ;
for ( i = 0 ; i < n_mmcos ; i + + ) {
if ( mmco1 [ i ] . opcode ! = mmco2 [ i ] . opcode )
return - 1 ;
}
return 0 ;
}
h - > mmco_index = 0 ;
if ( h - > short_ref_count & & h - > long_ref_count + h - > short_ref_count > = h - > sps . ref_frame_count & &
! ( FIELD_PICTURE & & ! s - > first_field & & s - > current_picture_ptr - > f . reference ) ) {
h - > mmco [ 0 ] . opcode = MMCO_SHORT2UNUSED ;
h - > mmco [ 0 ] . short_pic_num = h - > short_ref [ h - > short_ref_count - 1 ] - > frame_num ;
h - > mmco_index = 1 ;
void ff_generate_sliding_window_mmcos ( H264Context * h , int first_slice )
{
MpegEncContext * const s = & h - > s ;
MMCO mmco_temp [ MAX_MMCO_COUNT ] , * mmco = first_slice ? h - > mmco : mmco_temp ;
int mmco_index = 0 , i ;
if ( h - > short_ref_count & &
h - > long_ref_count + h - > short_ref_count > = h - > sps . ref_frame_count & &
! ( FIELD_PICTURE & & ! s - > first_field & &
s - > current_picture_ptr - > f . reference ) ) {
mmco [ 0 ] . opcode = MMCO_SHORT2UNUSED ;
mmco [ 0 ] . short_pic_num = h - > short_ref [ h - > short_ref_count - 1 ] - > frame_num ;
mmco_index = 1 ;
if ( FIELD_PICTURE ) {
h - > mmco [ 0 ] . short_pic_num * = 2 ;
h - > mmco [ 1 ] . opcode = MMCO_SHORT2UNUSED ;
h - > mmco [ 1 ] . short_pic_num = h - > mmco [ 0 ] . short_pic_num + 1 ;
h - > mmco_index = 2 ;
mmco [ 0 ] . short_pic_num * = 2 ;
mmco [ 1 ] . opcode = MMCO_SHORT2UNUSED ;
mmco [ 1 ] . short_pic_num = mmco [ 0 ] . short_pic_num + 1 ;
mmco_index = 2 ;
}
}
if ( first_slice ) {
h - > mmco_index = mmco_index ;
} else if ( ! first_slice & & mmco_index > = 0 & &
( mmco_index ! = h - > mmco_index | |
( i = check_opcodes ( h - > mmco , mmco_temp , mmco_index ) ) ) ) {
av_log ( h - > s . avctx , AV_LOG_ERROR ,
" Inconsistent MMCO state between slices [%d, %d, %d] \n " ,
mmco_index , h - > mmco_index , i ) ;
return AVERROR_INVALIDDATA ;
}
}
int ff_h264_execute_ref_pic_marking ( H264Context * h , MMCO * mmco , int mmco_count ) {
@ -665,52 +692,83 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
return ( h - > s . avctx - > err_recognition & AV_EF_EXPLODE ) ? err : 0 ;
}
int ff_h264_decode_ref_pic_marking ( H264Context * h , GetBitContext * gb ) {
int ff_h264_decode_ref_pic_marking ( H264Context * h , GetBitContext * gb ,
int first_slice )
{
MpegEncContext * const s = & h - > s ;
int i ;
h - > mmco_index = 0 ;
if ( h - > nal_unit_type = = NAL_IDR_SLICE ) { //FIXME fields
s - > broken_link = get_bits1 ( gb ) - 1 ;
if ( get_bits1 ( gb ) ) {
h - > mmco [ 0 ] . opcode = MMCO_LONG ;
h - > mmco [ 0 ] . long_arg = 0 ;
h - > mmco_index = 1 ;
MMCO mmco_temp [ MAX_MMCO_COUNT ] , * mmco = first_slice ? h - > mmco : mmco_temp ;
int mmco_index = 0 ;
if ( h - > nal_unit_type = = NAL_IDR_SLICE ) { // FIXME fields
s - > broken_link = get_bits1 ( gb ) - 1 ;
if ( get_bits1 ( gb ) ) {
mmco [ 0 ] . opcode = MMCO_LONG ;
mmco [ 0 ] . long_arg = 0 ;
mmco_index = 1 ;
}
} else {
if ( get_bits1 ( gb ) ) { // adaptive_ref_pic_marking_mode_flag
for ( i = 0 ; i < MAX_MMCO_COUNT ; i + + ) {
MMCOOpcode opcode = get_ue_golomb_31 ( gb ) ;
h - > mmco [ i ] . opcode = opcode ;
if ( opcode = = MMCO_SHORT2UNUSED | | opcode = = MMCO_SHORT2LONG ) {
h - > mmco [ i ] . short_pic_num = ( h - > curr_pic_num - get_ue_golomb ( gb ) - 1 ) & ( h - > max_pic_num - 1 ) ;
/* if(h->mmco[i].short_pic_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_pic_num ] == NULL){
av_log ( s - > avctx , AV_LOG_ERROR , " illegal short ref in memory management control operation %d \n " , mmco ) ;
} else {
if ( get_bits1 ( gb ) ) { // adaptive_ref_pic_marking_mode_flag
for ( i = 0 ; i < MAX_MMCO_COUNT ; i + + ) {
MMCOOpcode opcode = get_ue_golomb_31 ( gb ) ;
mmco [ i ] . opcode = opcode ;
if ( opcode = = MMCO_SHORT2UNUSED | | opcode = = MMCO_SHORT2LONG ) {
mmco [ i ] . short_pic_num =
( h - > curr_pic_num - get_ue_golomb ( gb ) - 1 ) &
( h - > max_pic_num - 1 ) ;
#if 0
if ( mmco [ i ] . short_pic_num > = h - > short_ref_count | |
h - > short_ref [ mmco [ i ] . short_pic_num ] = = NULL ) {
av_log ( s - > avctx , AV_LOG_ERROR ,
" illegal short ref in memory management control "
" operation %d \n " , mmco ) ;
return - 1 ;
} */
}
# endif
}
if ( opcode = = MMCO_SHORT2LONG | | opcode = = MMCO_LONG2UNUSED | | opcode = = MMCO_LONG | | opcode = = MMCO_SET_MAX_LONG ) {
unsigned int long_arg = get_ue_golomb_31 ( gb ) ;
if ( long_arg > = 32 | | ( long_arg > = 16 & & ! ( opcode = = MMCO_SET_MAX_LONG & & long_arg = = 16 ) & & ! ( opcode = = MMCO_LONG2UNUSED & & FIELD_PICTURE ) ) ) {
av_log ( h - > s . avctx , AV_LOG_ERROR , " illegal long ref in memory management control operation %d \n " , opcode ) ;
if ( opcode = = MMCO_SHORT2LONG | | opcode = = MMCO_LONG2UNUSED | |
opcode = = MMCO_LONG | | opcode = = MMCO_SET_MAX_LONG ) {
unsigned int long_arg = get_ue_golomb_31 ( gb ) ;
if ( long_arg > = 32 | |
( long_arg > = 16 & & ! ( opcode = = MMCO_SET_MAX_LONG & &
long_arg = = 16 ) & &
! ( opcode = = MMCO_LONG2UNUSED & & FIELD_PICTURE ) ) ) {
av_log ( h - > s . avctx , AV_LOG_ERROR ,
" illegal long ref in memory management control "
" operation %d \n " , opcode ) ;
return - 1 ;
}
h - > mmco [ i ] . long_arg = long_arg ;
mmco [ i ] . long_arg = long_arg ;
}
if ( opcode > ( unsigned ) MMCO_LONG ) {
av_log ( h - > s . avctx , AV_LOG_ERROR , " illegal memory management control operation %d \n " , opcode ) ;
if ( opcode > ( unsigned ) MMCO_LONG ) {
av_log ( h - > s . avctx , AV_LOG_ERROR ,
" illegal memory management control operation %d \n " ,
opcode ) ;
return - 1 ;
}
if ( opcode = = MMCO_END )
if ( opcode = = MMCO_END )
break ;
}
h - > mmco_index = i ;
} else {
ff_generate_sliding_window_mmcos ( h ) ;
mmco_index = i ;
} else {
if ( first_slice )
ff_generate_sliding_window_mmcos ( h , first_slice ) ;
mmco_index = - 1 ;
}
}
if ( first_slice & & mmco_index ! = - 1 ) {
h - > mmco_index = mmco_index ;
} else if ( ! first_slice & & mmco_index > = 0 & &
( mmco_index ! = h - > mmco_index | |
( i = check_opcodes ( h - > mmco , mmco_temp , mmco_index ) ) ) ) {
av_log ( h - > s . avctx , AV_LOG_ERROR ,
" Inconsistent MMCO state between slices [%d, %d, %d] \n " ,
mmco_index , h - > mmco_index , i ) ;
return AVERROR_INVALIDDATA ;
}
return 0 ;
}