|
|
@@ -274,6 +274,7 @@ typedef struct H264Context{ |
|
|
|
|
|
|
|
int direct_spatial_mv_pred; |
|
|
|
int dist_scale_factor[16]; |
|
|
|
int map_col_to_list0[2][16]; |
|
|
|
|
|
|
|
/** |
|
|
|
* num_ref_idx_l0/1_active_minus1 + 1 |
|
|
@@ -285,6 +286,7 @@ typedef struct H264Context{ |
|
|
|
Picture ref_list[2][32]; //FIXME size? |
|
|
|
Picture field_ref_list[2][32]; //FIXME size? |
|
|
|
Picture *delayed_pic[16]; //FIXME size? |
|
|
|
int delayed_output_poc; |
|
|
|
|
|
|
|
/** |
|
|
|
* memory management control operations buffer. |
|
|
@@ -1060,6 +1062,34 @@ static inline void direct_dist_scale_factor(H264Context * const h){ |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
static inline void direct_ref_list_init(H264Context * const h){ |
|
|
|
MpegEncContext * const s = &h->s; |
|
|
|
Picture * const ref1 = &h->ref_list[1][0]; |
|
|
|
Picture * const cur = s->current_picture_ptr; |
|
|
|
int list, i, j; |
|
|
|
if(cur->pict_type == I_TYPE) |
|
|
|
cur->ref_count[0] = 0; |
|
|
|
if(cur->pict_type != B_TYPE) |
|
|
|
cur->ref_count[1] = 0; |
|
|
|
for(list=0; list<2; list++){ |
|
|
|
cur->ref_count[list] = h->ref_count[list]; |
|
|
|
for(j=0; j<h->ref_count[list]; j++) |
|
|
|
cur->ref_poc[list][j] = h->ref_list[list][j].poc; |
|
|
|
} |
|
|
|
if(cur->pict_type != B_TYPE || h->direct_spatial_mv_pred) |
|
|
|
return; |
|
|
|
for(list=0; list<2; list++){ |
|
|
|
for(i=0; i<ref1->ref_count[list]; i++){ |
|
|
|
const int poc = ref1->ref_poc[list][i]; |
|
|
|
h->map_col_to_list0[list][i] = PART_NOT_AVAILABLE; |
|
|
|
for(j=0; j<h->ref_count[list]; j++) |
|
|
|
if(h->ref_list[list][j].poc == poc){ |
|
|
|
h->map_col_to_list0[list][i] = j; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static inline void pred_direct_motion(H264Context * const h, int *mb_type){ |
|
|
|
MpegEncContext * const s = &h->s; |
|
|
@@ -1069,6 +1099,7 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){ |
|
|
|
const int mb_type_col = h->ref_list[1][0].mb_type[mb_xy]; |
|
|
|
const int16_t (*l1mv0)[2] = (const int16_t (*)[2]) &h->ref_list[1][0].motion_val[0][b4_xy]; |
|
|
|
const int8_t *l1ref0 = &h->ref_list[1][0].ref_index[0][b8_xy]; |
|
|
|
const int8_t *l1ref1 = &h->ref_list[1][0].ref_index[1][b8_xy]; |
|
|
|
const int is_b8x8 = IS_8X8(*mb_type); |
|
|
|
int sub_mb_type; |
|
|
|
int i8, i4; |
|
|
@@ -1178,7 +1209,6 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){ |
|
|
|
} |
|
|
|
} |
|
|
|
}else{ /* direct temporal mv pred */ |
|
|
|
/* FIXME assumes that L1ref0 used the same ref lists as current frame */ |
|
|
|
if(IS_16X16(*mb_type)){ |
|
|
|
fill_rectangle(&h->ref_cache[1][scan8[0]], 4, 4, 8, 0, 1); |
|
|
|
if(IS_INTRA(mb_type_col)){ |
|
|
@@ -1186,7 +1216,9 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){ |
|
|
|
fill_rectangle(&h-> mv_cache[0][scan8[0]], 4, 4, 8, 0, 4); |
|
|
|
fill_rectangle(&h-> mv_cache[1][scan8[0]], 4, 4, 8, 0, 4); |
|
|
|
}else{ |
|
|
|
const int ref0 = l1ref0[0]; |
|
|
|
const int ref0 = l1ref0[0] >= 0 ? h->map_col_to_list0[0][l1ref0[0]] |
|
|
|
: h->map_col_to_list0[1][l1ref1[0]]; |
|
|
|
assert(ref0 >= 0); |
|
|
|
const int dist_scale_factor = h->dist_scale_factor[ref0]; |
|
|
|
const int16_t *mv_col = l1mv0[0]; |
|
|
|
int mv_l0[2]; |
|
|
@@ -1214,6 +1246,11 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){ |
|
|
|
} |
|
|
|
|
|
|
|
ref0 = l1ref0[x8 + y8*h->b8_stride]; |
|
|
|
if(ref0 >= 0) |
|
|
|
ref0 = h->map_col_to_list0[0][ref0]; |
|
|
|
else |
|
|
|
ref0 = h->map_col_to_list0[1][l1ref1[x8 + y8*h->b8_stride]]; |
|
|
|
assert(ref0 >= 0); |
|
|
|
dist_scale_factor = h->dist_scale_factor[ref0]; |
|
|
|
|
|
|
|
fill_rectangle(&h->ref_cache[0][scan8[i8*4]], 2, 2, 8, ref0, 1); |
|
|
@@ -2961,12 +2998,12 @@ static int fill_default_ref_list(H264Context *h){ |
|
|
|
} |
|
|
|
}else{ |
|
|
|
int index=0; |
|
|
|
for(i=0; i<h->short_ref_count && index < h->ref_count[0]; i++){ |
|
|
|
for(i=0; i<h->short_ref_count; i++){ |
|
|
|
if(h->short_ref[i]->reference != 3) continue; //FIXME refernce field shit |
|
|
|
h->default_ref_list[0][index ]= *h->short_ref[i]; |
|
|
|
h->default_ref_list[0][index++].pic_id= h->short_ref[i]->frame_num; |
|
|
|
} |
|
|
|
for(i = 0; i < 16 && index < h->ref_count[0]; i++){ |
|
|
|
for(i = 0; i < 16; i++){ |
|
|
|
if(h->long_ref[i] == NULL) continue; |
|
|
|
if(h->long_ref[i]->reference != 3) continue; |
|
|
|
h->default_ref_list[0][index ]= *h->long_ref[i]; |
|
|
@@ -3016,6 +3053,7 @@ static int decode_ref_pic_list_reordering(H264Context *h){ |
|
|
|
int reordering_of_pic_nums_idc= get_ue_golomb(&s->gb); |
|
|
|
int pic_id; |
|
|
|
int i; |
|
|
|
Picture *ref = NULL; |
|
|
|
|
|
|
|
if(reordering_of_pic_nums_idc==3) |
|
|
|
break; |
|
|
@@ -3038,31 +3076,21 @@ static int decode_ref_pic_list_reordering(H264Context *h){ |
|
|
|
else pred+= abs_diff_pic_num; |
|
|
|
pred &= h->max_pic_num - 1; |
|
|
|
|
|
|
|
for(i= h->ref_count[list]-1; i>=0; i--){ |
|
|
|
if(h->ref_list[list][i].data[0] != NULL && h->ref_list[list][i].pic_id == pred && h->ref_list[list][i].long_ref==0) // ignore non existing pictures by testing data[0] pointer |
|
|
|
for(i= h->short_ref_count-1; i>=0; i--){ |
|
|
|
ref = h->short_ref[i]; |
|
|
|
if(ref->data[0] != NULL && ref->frame_num == pred && ref->long_ref == 0) // ignore non existing pictures by testing data[0] pointer |
|
|
|
break; |
|
|
|
} |
|
|
|
}else{ |
|
|
|
pic_id= get_ue_golomb(&s->gb); //long_term_pic_idx |
|
|
|
|
|
|
|
for(i= h->ref_count[list]-1; i>=0; i--){ |
|
|
|
if(h->ref_list[list][i].pic_id == pic_id && h->ref_list[list][i].long_ref==1) // no need to ignore non existing pictures as non existing pictures have long_ref==0 |
|
|
|
break; |
|
|
|
} |
|
|
|
ref = h->long_ref[pic_id]; |
|
|
|
} |
|
|
|
|
|
|
|
if (i < 0) { |
|
|
|
av_log(h->s.avctx, AV_LOG_ERROR, "reference picture missing during reorder\n"); |
|
|
|
memset(&h->ref_list[list][index], 0, sizeof(Picture)); //FIXME |
|
|
|
} else if (i != index) /* this test is not necessary, it is only an optimisation to skip double copy of Picture structure in this case */ { |
|
|
|
Picture tmp= h->ref_list[list][i]; |
|
|
|
if (i < index) { |
|
|
|
i = h->ref_count[list]; |
|
|
|
} |
|
|
|
for(; i > index; i--){ |
|
|
|
h->ref_list[list][i]= h->ref_list[list][i-1]; |
|
|
|
} |
|
|
|
h->ref_list[list][index]= tmp; |
|
|
|
} else { |
|
|
|
h->ref_list[list][index]= *ref; |
|
|
|
} |
|
|
|
}else{ |
|
|
|
av_log(h->s.avctx, AV_LOG_ERROR, "illegal reordering_of_pic_nums_idc\n"); |
|
|
@@ -3076,6 +3104,7 @@ static int decode_ref_pic_list_reordering(H264Context *h){ |
|
|
|
|
|
|
|
if(h->slice_type==B_TYPE && !h->direct_spatial_mv_pred) |
|
|
|
direct_dist_scale_factor(h); |
|
|
|
direct_ref_list_init(h); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
@@ -3509,6 +3538,7 @@ static int decode_slice_header(H264Context *h){ |
|
|
|
int default_ref_list_done = 0; |
|
|
|
|
|
|
|
s->current_picture.reference= h->nal_ref_idc != 0; |
|
|
|
s->dropable= h->nal_ref_idc == 0; |
|
|
|
|
|
|
|
first_mb_in_slice= get_ue_golomb(&s->gb); |
|
|
|
|
|
|
@@ -6298,7 +6328,7 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ |
|
|
|
|
|
|
|
//FIXME move after where irt is set |
|
|
|
s->current_picture.pict_type= s->pict_type; |
|
|
|
s->current_picture.key_frame= s->pict_type == I_TYPE; |
|
|
|
s->current_picture.key_frame= s->pict_type == I_TYPE && h->nal_unit_type == NAL_IDR_SLICE; |
|
|
|
} |
|
|
|
|
|
|
|
if(!s->current_picture_ptr) return buf_index; //no frame |
|
|
@@ -6423,31 +6453,43 @@ static int decode_frame(AVCodecContext *avctx, |
|
|
|
//#define DECODE_ORDER |
|
|
|
Picture *out = s->current_picture_ptr; |
|
|
|
#ifndef DECODE_ORDER |
|
|
|
/* Sort B-frames into display order |
|
|
|
* FIXME doesn't allow for multiple delayed frames */ |
|
|
|
/* Sort B-frames into display order */ |
|
|
|
Picture *cur = s->current_picture_ptr; |
|
|
|
Picture *prev = h->delayed_pic[0]; |
|
|
|
|
|
|
|
if(s->low_delay |
|
|
|
&& (cur->pict_type == B_TYPE |
|
|
|
|| (!h->sps.gaps_in_frame_num_allowed_flag |
|
|
|
&& prev && cur->poc - prev->poc > 2))){ |
|
|
|
int out_idx = 0; |
|
|
|
int pics = 0; |
|
|
|
int i; |
|
|
|
out = NULL; |
|
|
|
|
|
|
|
while(h->delayed_pic[pics]) pics++; |
|
|
|
h->delayed_pic[pics++] = cur; |
|
|
|
out = h->delayed_pic[0]; |
|
|
|
for(i=0; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++) |
|
|
|
if(!out || h->delayed_pic[i]->poc < out->poc){ |
|
|
|
out = h->delayed_pic[i]; |
|
|
|
out_idx = i; |
|
|
|
} |
|
|
|
if(cur->reference == 0) |
|
|
|
cur->reference = 1; |
|
|
|
if(pics > FFMAX(1, s->avctx->has_b_frames)){ |
|
|
|
if(out->reference == 1) |
|
|
|
out->reference = 0; |
|
|
|
for(i=out_idx; h->delayed_pic[i]; i++) |
|
|
|
h->delayed_pic[i] = h->delayed_pic[i+1]; |
|
|
|
} |
|
|
|
|
|
|
|
for(i=0; h->delayed_pic[i]; i++) |
|
|
|
if(h->delayed_pic[i]->key_frame) |
|
|
|
h->delayed_output_poc = -1; |
|
|
|
|
|
|
|
if((h->delayed_output_poc >=0 && h->delayed_output_poc > cur->poc) |
|
|
|
|| (s->low_delay && (cur->pict_type == B_TYPE |
|
|
|
|| (!h->sps.gaps_in_frame_num_allowed_flag |
|
|
|
&& cur->poc - out->poc > 2)))){ |
|
|
|
s->low_delay = 0; |
|
|
|
s->avctx->has_b_frames = 1; |
|
|
|
if(prev && prev->poc > cur->poc) |
|
|
|
// too late to display this frame |
|
|
|
cur = prev; |
|
|
|
s->avctx->has_b_frames++; |
|
|
|
} |
|
|
|
|
|
|
|
if(s->low_delay || !prev || cur->pict_type == B_TYPE) |
|
|
|
out = cur; |
|
|
|
else |
|
|
|
out = prev; |
|
|
|
if(s->low_delay || !prev || out == prev){ |
|
|
|
if(prev && prev->reference == 1) |
|
|
|
prev->reference = 0; |
|
|
|
h->delayed_pic[0] = cur; |
|
|
|
} |
|
|
|
h->delayed_output_poc = out->poc; |
|
|
|
#endif |
|
|
|
|
|
|
|
*pict= *(AVFrame*)out; |
|
|
|