diff options
author | Loic Le Loarer <lll+ffmpeg@m4x.org> | 2005-01-19 17:35:51 +0000 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2005-01-19 17:35:51 +0000 |
commit | 827c91bfb795359aa69663411237cb9df40b1c22 (patch) | |
tree | 3aa0c5246c6e6a9ff5fa4aef7695dd25f7587995 | |
parent | eed4ebd22cddc238fed06e773d64ffb69dbdb6b7 (diff) | |
download | ffmpeg-827c91bfb795359aa69663411237cb9df40b1c22.tar.gz |
H.264 b ref pic list order and long term pictures patch by (Loic Le Loarer <loic.le-loarer polytechnique org>)
Originally committed as revision 3851 to svn://svn.ffmpeg.org/ffmpeg/trunk
-rw-r--r-- | libavcodec/h264.c | 148 |
1 files changed, 111 insertions, 37 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c index ade316b2e8..bbe8a32a55 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -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); 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 *mx= mid_pred(A[0], B[0], C[0]); *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){ if(!is_b8x8) *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){ int ref[2]; int mv[2][2]; @@ -2600,7 +2603,6 @@ static void frame_start(H264Context *h){ MPV_frame_start(s, s->avctx); ff_er_frame_start(s); - h->mmco_index=0; assert(s->linesize && s->uvlinesize); @@ -2843,12 +2845,14 @@ static void hl_decode_mb(H264Context *h){ static int fill_default_ref_list(H264Context *h){ MpegEncContext * const s = &h->s; int i; + int smallest_poc_greater_than_current = -1; Picture sorted_short_ref[16]; if(h->slice_type==B_TYPE){ int out_i; int limit= -1; + /* sort frame according to poc in B slice */ for(out_i=0; out_i<h->short_ref_count; out_i++){ int best_i=-1; int best_poc=INT_MAX; @@ -2865,37 +2869,62 @@ static int fill_default_ref_list(H264Context *h){ limit= best_poc; 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(h->slice_type==B_TYPE){ - const int current_poc= s->current_picture_ptr->poc; 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++){ - int index=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)){ - h->default_ref_list[list][index ]= sorted_short_ref[i2]; - h->default_ref_list[list][index++].pic_id= sorted_short_ref[i2].frame_num; + int index = 0; + int swap_first_L1 = 0; + + if (0 == list) { + for(i=smallest_poc_greater_than_current-1; i>=0 && 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; + } + 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; h->default_ref_list[ list ][index ]= *h->long_ref[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]; h->default_ref_list[1][0] = h->default_ref_list[1][1]; h->default_ref_list[1][0] = temp; @@ -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++].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; h->default_ref_list[0][index ]= *h->long_ref[i]; h->default_ref_list[0][index++].pic_id= i;; @@ -2925,13 +2955,28 @@ static int fill_default_ref_list(H264Context *h){ //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; } +static void print_short_term(H264Context *h); +static void print_long_term(H264Context *h); + static int decode_ref_pic_list_reordering(H264Context *h){ MpegEncContext * const s = &h->s; 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 for(list=0; list<2; list++){ @@ -3059,7 +3104,6 @@ static int pred_weight_table(H264Context *h){ static void implicit_weight_table(H264Context *h){ MpegEncContext * const s = &h->s; - int list, i; int ref0, ref1; int cur_poc = s->current_picture_ptr->poc; @@ -3156,23 +3200,49 @@ static Picture * remove_short(H264Context *h, int frame_num){ static Picture * remove_long(H264Context *h, int i){ Picture *pic; - if(i >= h->long_ref_count) return NULL; pic= h->long_ref[i]; - if(pic==NULL) return NULL; - h->long_ref[i]= NULL; - memmove(&h->long_ref[i], &h->long_ref[i+1], (h->long_ref_count - i - 1)*sizeof(Picture*)); - h->long_ref_count--; + if(pic) h->long_ref_count--; 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). */ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ MpegEncContext * const s = &h->s; - int i; + int i, j; int current_is_long=0; Picture *pic; @@ -3213,12 +3283,10 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ break; case MMCO_SET_MAX_LONG: assert(mmco[i].long_index <= 16); - while(mmco[i].long_index < h->long_ref_count){ - pic= remove_long(h, mmco[i].long_index); - pic->reference=0; - } - while(mmco[i].long_index > h->long_ref_count){ - h->long_ref[ h->long_ref_count++ ]= NULL; + // just remove the long term which index is greater than new max + for(j = mmco[i].long_index; j<16; j++){ + pic = remove_long(h, j); + if (pic) pic->reference=0; } break; case MMCO_RESET: @@ -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->reference=0; } - while(h->long_ref_count){ - pic= remove_long(h, h->long_ref_count-1); - pic->reference=0; + for(j = 0; j < 16; j++) { + pic= remove_long(h, j); + if(pic) pic->reference=0; } break; default: assert(0); @@ -3250,6 +3318,8 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ h->short_ref_count++; } + print_short_term(h); + print_long_term(h); return 0; } @@ -4772,6 +4842,7 @@ static int decode_mb_cabac(H264Context *h) { 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 ) { /* read skip flags */ 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 pix[-1] = clip_uint8( p0 + i_delta ); /* p0' */ 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; } @@ -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[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; } @@ -5534,8 +5607,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 bS[i] = 1; else bS[i] = 0; - } - else { + } else { /* FIXME Add support for B frame */ return; } @@ -5547,6 +5619,7 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8 /* Filter edge */ 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 ) { filter_mb_edgev( h, &img_y[4*edge], linesize, bS, qp ); if( (edge&1) == 0 ) { @@ -6175,8 +6248,6 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ } if(s->current_picture_ptr->reference) execute_ref_pic_marking(h, h->mmco, h->mmco_index); - else - assert(h->mmco_index==0); ff_er_frame_end(s); @@ -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 * FIXME doesn't allow for multiple delayed frames */ Picture *cur = s->current_picture_ptr; Picture *prev = h->delayed_pic[0]; - Picture *out; if(s->low_delay && (cur->pict_type == B_TYPE @@ -6312,6 +6385,7 @@ static int decode_frame(AVCodecContext *avctx, prev->reference = 0; h->delayed_pic[0] = cur; } +#endif *pict= *(AVFrame*)out; } |