Commit 558af81b authored by michael's avatar michael

H.264 b ref pic list order and long term pictures patch by (Loic Le Loarer...

H.264 b ref pic list order and long term pictures patch by (Loic Le Loarer <loic.le-loarer polytechnique org>)


git-svn-id: file:///var/local/repositories/ffmpeg/trunk@3851 9553f0bf-9b14-0410-a0b8-cfaf0461ba5b
parent a1deae42
...@@ -913,6 +913,7 @@ static inline void pred_motion(H264Context * const h, int n, int part_width, int ...@@ -913,6 +913,7 @@ static inline void pred_motion(H264Context * const h, int n, int part_width, int
diagonal_ref= fetch_diagonal_mv(h, &C, index8, list, part_width); diagonal_ref= fetch_diagonal_mv(h, &C, index8, list, part_width);
match_count= (diagonal_ref==ref) + (top_ref==ref) + (left_ref==ref); match_count= (diagonal_ref==ref) + (top_ref==ref) + (left_ref==ref);
tprintf("pred_motion match_count=%d\n", match_count);
if(match_count > 1){ //most common if(match_count > 1){ //most common
*mx= mid_pred(A[0], B[0], C[0]); *mx= mid_pred(A[0], B[0], C[0]);
*my= mid_pred(A[1], B[1], C[1]); *my= mid_pred(A[1], B[1], C[1]);
...@@ -1075,6 +1076,8 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){ ...@@ -1075,6 +1076,8 @@ static inline void pred_direct_motion(H264Context * const h, int *mb_type){
if(!is_b8x8) if(!is_b8x8)
*mb_type |= MB_TYPE_DIRECT2; *mb_type |= MB_TYPE_DIRECT2;
tprintf("mb_type = %08x, sub_mb_type = %08x, is_b8x8 = %d, mb_type_col = %08x\n", *mb_type, sub_mb_type, is_b8x8, mb_type_col);
if(h->direct_spatial_mv_pred){ if(h->direct_spatial_mv_pred){
int ref[2]; int ref[2];
int mv[2][2]; int mv[2][2];
...@@ -2600,7 +2603,6 @@ static void frame_start(H264Context *h){ ...@@ -2600,7 +2603,6 @@ static void frame_start(H264Context *h){
MPV_frame_start(s, s->avctx); MPV_frame_start(s, s->avctx);
ff_er_frame_start(s); ff_er_frame_start(s);
h->mmco_index=0;
assert(s->linesize && s->uvlinesize); assert(s->linesize && s->uvlinesize);
...@@ -2843,12 +2845,14 @@ static void hl_decode_mb(H264Context *h){ ...@@ -2843,12 +2845,14 @@ static void hl_decode_mb(H264Context *h){
static int fill_default_ref_list(H264Context *h){ static int fill_default_ref_list(H264Context *h){
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
int i; int i;
int smallest_poc_greater_than_current = -1;
Picture sorted_short_ref[16]; Picture sorted_short_ref[16];
if(h->slice_type==B_TYPE){ if(h->slice_type==B_TYPE){
int out_i; int out_i;
int limit= -1; int limit= -1;
/* sort frame according to poc in B slice */
for(out_i=0; out_i<h->short_ref_count; out_i++){ for(out_i=0; out_i<h->short_ref_count; out_i++){
int best_i=-1; int best_i=-1;
int best_poc=INT_MAX; int best_poc=INT_MAX;
...@@ -2865,37 +2869,62 @@ static int fill_default_ref_list(H264Context *h){ ...@@ -2865,37 +2869,62 @@ static int fill_default_ref_list(H264Context *h){
limit= best_poc; limit= best_poc;
sorted_short_ref[out_i]= *h->short_ref[best_i]; sorted_short_ref[out_i]= *h->short_ref[best_i];
tprintf("sorted poc: %d->%d poc:%d fn:%d\n", best_i, out_i, sorted_short_ref[out_i].poc, sorted_short_ref[out_i].frame_num);
if (-1 == smallest_poc_greater_than_current) {
if (h->short_ref[best_i]->poc >= s->current_picture_ptr->poc) {
smallest_poc_greater_than_current = out_i;
}
}
} }
} }
if(s->picture_structure == PICT_FRAME){ if(s->picture_structure == PICT_FRAME){
if(h->slice_type==B_TYPE){ if(h->slice_type==B_TYPE){
const int current_poc= s->current_picture_ptr->poc;
int list; int list;
tprintf("current poc: %d, smallest_poc_greater_than_current: %d\n", s->current_picture_ptr->poc, smallest_poc_greater_than_current);
// find the largest poc
for(list=0; list<2; list++){ for(list=0; list<2; list++){
int index=0; int index = 0;
int swap_first_L1 = 0;
for(i=0; i<h->short_ref_count && index < h->ref_count[list]; i++){
const int i2= list ? i : h->short_ref_count - i - 1;
const int poc= sorted_short_ref[i2].poc;
if(sorted_short_ref[i2].reference != 3) continue; //FIXME refernce field shit
if((list==1 && poc > current_poc) || (list==0 && poc < current_poc)){ if (0 == list) {
h->default_ref_list[list][index ]= sorted_short_ref[i2]; for(i=smallest_poc_greater_than_current-1; i>=0 && index < h->ref_count[list]; i--) {
h->default_ref_list[list][index++].pic_id= sorted_short_ref[i2].frame_num; if(sorted_short_ref[i].reference != 3) continue;
h->default_ref_list[list][index ]= sorted_short_ref[i];
h->default_ref_list[list][index++].pic_id= sorted_short_ref[i].frame_num;
}
for(i=smallest_poc_greater_than_current; i<h->short_ref_count && index < h->ref_count[list]; i++) {
if(sorted_short_ref[i].reference != 3) continue;
h->default_ref_list[list][index ]= sorted_short_ref[i];
h->default_ref_list[list][index++].pic_id= sorted_short_ref[i].frame_num;
}
} else {
for(i=smallest_poc_greater_than_current; i<h->short_ref_count && index < h->ref_count[list]; i++) {
if(sorted_short_ref[i].reference != 3) continue;
swap_first_L1 |= 1;
h->default_ref_list[list][index ]= sorted_short_ref[i];
h->default_ref_list[list][index++].pic_id= sorted_short_ref[i].frame_num;
}
for(i=smallest_poc_greater_than_current-1; i>=0 && index < h->ref_count[list]; i--) {
if(sorted_short_ref[i].reference != 3) continue;
swap_first_L1 |= 2;
h->default_ref_list[list][index ]= sorted_short_ref[i];
h->default_ref_list[list][index++].pic_id= sorted_short_ref[i].frame_num;
} }
} }
for(i=0; i<h->long_ref_count && index < h->ref_count[ list ]; i++){ for(i = 0; i < 16 && index < h->ref_count[ list ]; i++){
if(h->long_ref[i] == NULL) continue;
if(h->long_ref[i]->reference != 3) continue; if(h->long_ref[i]->reference != 3) continue;
h->default_ref_list[ list ][index ]= *h->long_ref[i]; h->default_ref_list[ list ][index ]= *h->long_ref[i];
h->default_ref_list[ list ][index++].pic_id= i;; h->default_ref_list[ list ][index++].pic_id= i;;
} }
if(h->long_ref_count > 1 && h->short_ref_count==0){ if(list && (3 == swap_first_L1) && (1 < index)){
// swap the two first elements of L1 when
// L0 and L1 are identical
Picture temp= h->default_ref_list[1][0]; Picture temp= h->default_ref_list[1][0];
h->default_ref_list[1][0] = h->default_ref_list[1][1]; h->default_ref_list[1][0] = h->default_ref_list[1][1];
h->default_ref_list[1][0] = temp; h->default_ref_list[1][0] = temp;
...@@ -2911,7 +2940,8 @@ static int fill_default_ref_list(H264Context *h){ ...@@ -2911,7 +2940,8 @@ static int fill_default_ref_list(H264Context *h){
h->default_ref_list[0][index ]= *h->short_ref[i]; h->default_ref_list[0][index ]= *h->short_ref[i];
h->default_ref_list[0][index++].pic_id= h->short_ref[i]->frame_num; h->default_ref_list[0][index++].pic_id= h->short_ref[i]->frame_num;
} }
for(i=0; i<h->long_ref_count && index < h->ref_count[0]; i++){ for(i = 0; i < 16 && index < h->ref_count[0]; i++){
if(h->long_ref[i] == NULL) continue;
if(h->long_ref[i]->reference != 3) continue; if(h->long_ref[i]->reference != 3) continue;
h->default_ref_list[0][index ]= *h->long_ref[i]; h->default_ref_list[0][index ]= *h->long_ref[i];
h->default_ref_list[0][index++].pic_id= i;; h->default_ref_list[0][index++].pic_id= i;;
...@@ -2925,13 +2955,28 @@ static int fill_default_ref_list(H264Context *h){ ...@@ -2925,13 +2955,28 @@ static int fill_default_ref_list(H264Context *h){
//FIXME second field balh //FIXME second field balh
} }
} }
#ifdef TRACE
for (i=0; i<h->ref_count[0]; i++) {
tprintf("List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].data[0]);
}
if(h->slice_type==B_TYPE){
for (i=0; i<h->ref_count[1]; i++) {
tprintf("List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[0][i].data[0]);
}
}
#endif
return 0; return 0;
} }
static void print_short_term(H264Context *h);
static void print_long_term(H264Context *h);
static int decode_ref_pic_list_reordering(H264Context *h){ static int decode_ref_pic_list_reordering(H264Context *h){
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
int list; int list;
print_short_term(h);
print_long_term(h);
if(h->slice_type==I_TYPE || h->slice_type==SI_TYPE) return 0; //FIXME move beofre func if(h->slice_type==I_TYPE || h->slice_type==SI_TYPE) return 0; //FIXME move beofre func
for(list=0; list<2; list++){ for(list=0; list<2; list++){
...@@ -3059,7 +3104,6 @@ static int pred_weight_table(H264Context *h){ ...@@ -3059,7 +3104,6 @@ static int pred_weight_table(H264Context *h){
static void implicit_weight_table(H264Context *h){ static void implicit_weight_table(H264Context *h){
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
int list, i;
int ref0, ref1; int ref0, ref1;
int cur_poc = s->current_picture_ptr->poc; int cur_poc = s->current_picture_ptr->poc;
...@@ -3156,23 +3200,49 @@ static Picture * remove_short(H264Context *h, int frame_num){ ...@@ -3156,23 +3200,49 @@ static Picture * remove_short(H264Context *h, int frame_num){
static Picture * remove_long(H264Context *h, int i){ static Picture * remove_long(H264Context *h, int i){
Picture *pic; Picture *pic;
if(i >= h->long_ref_count) return NULL;
pic= h->long_ref[i]; pic= h->long_ref[i];
if(pic==NULL) return NULL;
h->long_ref[i]= NULL; h->long_ref[i]= NULL;
memmove(&h->long_ref[i], &h->long_ref[i+1], (h->long_ref_count - i - 1)*sizeof(Picture*)); if(pic) h->long_ref_count--;
h->long_ref_count--;
return pic; return pic;
} }
/**
* print short term list
*/
static void print_short_term(H264Context *h) {
uint32_t i;
if(h->s.avctx->debug&FF_DEBUG_MMCO) {
av_log(h->s.avctx, AV_LOG_DEBUG, "short term list:\n");
for(i=0; i<h->short_ref_count; i++){
Picture *pic= h->short_ref[i];
av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
}
}
}
/**
* print long term list
*/
static void print_long_term(H264Context *h) {
uint32_t i;
if(h->s.avctx->debug&FF_DEBUG_MMCO) {
av_log(h->s.avctx, AV_LOG_DEBUG, "long term list:\n");
for(i = 0; i < 16; i++){
Picture *pic= h->long_ref[i];
if (pic) {
av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
}
}
}
}
/** /**
* Executes the reference picture marking (memory management control operations). * Executes the reference picture marking (memory management control operations).
*/ */
static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
MpegEncContext * const s = &h->s; MpegEncContext * const s = &h->s;
int i; int i, j;
int current_is_long=0; int current_is_long=0;
Picture *pic; Picture *pic;
...@@ -3213,12 +3283,10 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ ...@@ -3213,12 +3283,10 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
break; break;
case MMCO_SET_MAX_LONG: case MMCO_SET_MAX_LONG:
assert(mmco[i].long_index <= 16); assert(mmco[i].long_index <= 16);
while(mmco[i].long_index < h->long_ref_count){ // just remove the long term which index is greater than new max
pic= remove_long(h, mmco[i].long_index); for(j = mmco[i].long_index; j<16; j++){
pic->reference=0; pic = remove_long(h, j);
} if (pic) pic->reference=0;
while(mmco[i].long_index > h->long_ref_count){
h->long_ref[ h->long_ref_count++ ]= NULL;
} }
break; break;
case MMCO_RESET: case MMCO_RESET:
...@@ -3226,9 +3294,9 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ ...@@ -3226,9 +3294,9 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
pic= remove_short(h, h->short_ref[0]->frame_num); pic= remove_short(h, h->short_ref[0]->frame_num);
pic->reference=0; pic->reference=0;
} }
while(h->long_ref_count){ for(j = 0; j < 16; j++) {
pic= remove_long(h, h->long_ref_count-1); pic= remove_long(h, j);
pic->reference=0; if(pic) pic->reference=0;
} }
break; break;
default: assert(0); default: assert(0);
...@@ -3250,6 +3318,8 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ ...@@ -3250,6 +3318,8 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
h->short_ref_count++; h->short_ref_count++;
} }
print_short_term(h);
print_long_term(h);
return 0; return 0;
} }
...@@ -4772,6 +4842,7 @@ static int decode_mb_cabac(H264Context *h) { ...@@ -4772,6 +4842,7 @@ static int decode_mb_cabac(H264Context *h) {
return -1; return -1;
} }
tprintf("pic:%d mb:%d/%d\n", h->frame_num, s->mb_x, s->mb_y);
if( h->slice_type != I_TYPE && h->slice_type != SI_TYPE ) { if( h->slice_type != I_TYPE && h->slice_type != SI_TYPE ) {
/* read skip flags */ /* read skip flags */
if( decode_cabac_mb_skip( h ) ) { if( decode_cabac_mb_skip( h ) ) {
...@@ -5273,6 +5344,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5273,6 +5344,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */ pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */
pix[0] = clip_uint8( q0 - i_delta ); /* q0' */ pix[0] = clip_uint8( q0 - i_delta ); /* q0' */
//tprintf("filter_mb_edgecv i:%d d:%d, qp:%d, indexA:%d, alpha:%d, beta:%d, tc:%d\n# bS:%d -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, qp, index_a, alpha, beta, tc, bS[i], pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
} }
pix += stride; pix += stride;
} }
...@@ -5290,6 +5362,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4 ...@@ -5290,6 +5362,7 @@ static void filter_mb_edgecv( H264Context *h, uint8_t *pix, int stride, int bS[4
pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */ pix[-1] = ( 2*p1 + p0 + q1 + 2 ) >> 2; /* p0' */
pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */ pix[0] = ( 2*q1 + q0 + p1 + 2 ) >> 2; /* q0' */
//tprintf("filter_mb_edgecv i:%d d:%d\n# bS:4 -> [%02x, %02x, %02x, %02x, %02x, %02x] =>[%02x, %02x, %02x, %02x]\n", i, d, pix[-3], p1, p0, q0, q1, pix[2], p1, pix[-1], pix[0], q1);
} }
pix += stride; pix += stride;
} }
...@@ -5534,8 +5607,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 ...@@ -5534,8 +5607,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
bS[i] = 1; bS[i] = 1;
else else
bS[i] = 0; bS[i] = 0;
} } else {
else {
/* FIXME Add support for B frame */ /* FIXME Add support for B frame */
return; return;
} }
...@@ -5547,6 +5619,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 ...@@ -5547,6 +5619,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
/* Filter edge */ /* Filter edge */
qp = ( s->qscale + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1; qp = ( s->qscale + s->current_picture.qscale_table[mbn_xy] + 1 ) >> 1;
//tprintf("filter mb:%d/%d dir:%d edge:%d, QPy:%d, QPc:%d, QPcn:%d\n", mb_x, mb_y, dir, edge, qp, h->chroma_qp, s->current_picture.qscale_table[mbn_xy]);
if( dir == 0 ) { if( dir == 0 ) {
filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp ); filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp );
if( (edge&1) == 0 ) { if( (edge&1) == 0 ) {
...@@ -6175,8 +6248,6 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ ...@@ -6175,8 +6248,6 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){
} }
if(s->current_picture_ptr->reference) if(s->current_picture_ptr->reference)
execute_ref_pic_marking(h, h->mmco, h->mmco_index); execute_ref_pic_marking(h, h->mmco, h->mmco_index);
else
assert(h->mmco_index==0);
ff_er_frame_end(s); ff_er_frame_end(s);
...@@ -6286,11 +6357,13 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -6286,11 +6357,13 @@ static int decode_frame(AVCodecContext *avctx,
} }
{ {
//#define DECODE_ORDER
Picture *out = s->current_picture_ptr;
#ifndef DECODE_ORDER
/* Sort B-frames into display order /* Sort B-frames into display order
* FIXME doesn't allow for multiple delayed frames */ * FIXME doesn't allow for multiple delayed frames */
Picture *cur = s->current_picture_ptr; Picture *cur = s->current_picture_ptr;
Picture *prev = h->delayed_pic[0]; Picture *prev = h->delayed_pic[0];
Picture *out;
if(s->low_delay if(s->low_delay
&& (cur->pict_type == B_TYPE && (cur->pict_type == B_TYPE
...@@ -6312,6 +6385,7 @@ static int decode_frame(AVCodecContext *avctx, ...@@ -6312,6 +6385,7 @@ static int decode_frame(AVCodecContext *avctx,
prev->reference = 0; prev->reference = 0;
h->delayed_pic[0] = cur; h->delayed_pic[0] = cur;
} }
#endif
*pict= *(AVFrame*)out; *pict= *(AVFrame*)out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment