changeset 2441:358813ec4ca2 libavcodec

H.264 b ref pic list order and long term pictures patch by (Loic Le Loarer <loic.le-loarer polytechnique org>)
author michael
date Wed, 19 Jan 2005 17:35:51 +0000
parents cf97353f94c6
children ba01b8552bd4
files h264.c
diffstat 1 files changed, 112 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/h264.c	Wed Jan 19 13:24:43 2005 +0000
+++ b/h264.c	Wed Jan 19 17:35:51 2005 +0000
@@ -913,6 +913,7 @@
 
     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 @@
     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 @@
 
     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 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 @@
             
             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 @@
                 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 @@
             //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 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_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 @@
             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 @@
                 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 @@
         h->short_ref_count++;
     }
     
+    print_short_term(h);
+    print_long_term(h);
     return 0; 
 }
 
@@ -4772,6 +4842,7 @@
         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 @@
 
                     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 @@
 
                     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 @@
                             bS[i] = 1;
                         else
                             bS[i] = 0;
-                    }
-                    else {
+                    } else {
                         /* FIXME Add support for B frame */
                         return;
                     }
@@ -5547,6 +5619,7 @@
 
             /* 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 @@
     }
     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 @@
     }
 
     {
+//#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 @@
                 prev->reference = 0;
             h->delayed_pic[0] = cur;
         }
+#endif
 
         *pict= *(AVFrame*)out;
     }