Merge commit 'ed9a20ebe4a89de119ea97bdccf688ece8c6648c' into merge-libav-new
authorClément Bœsch <clement@stupeflix.com>
Wed, 29 Jun 2016 15:31:44 +0000 (17:31 +0200)
committerClément Bœsch <clement@stupeflix.com>
Wed, 29 Jun 2016 15:32:05 +0000 (17:32 +0200)
* commit 'ed9a20ebe4a89de119ea97bdccf688ece8c6648c':
  h264: split reading the ref list modifications and actually building the ref list

ref_modifications.val are read as u32 instead of u8 in FFmpeg.

Merged-by: Clément Bœsch <clement@stupeflix.com>
1  2 
libavcodec/h264.h
libavcodec/h264_refs.c
libavcodec/h264_slice.c

@@@ -406,6 -391,11 +406,11 @@@ typedef struct H264SliceContext 
      H264Ref ref_list[2][48];        /**< 0..15: frame refs, 16..47: mbaff field refs.
                                           *   Reordered version of default_ref_list
                                           *   according to picture reordering in slice header */
 -        uint8_t val;
+     struct {
+         uint8_t op;
++        uint32_t val;
+     } ref_modifications[2][32];
+     int nb_ref_modifications[2];
  
      const uint8_t *intra_pcm_ptr;
      int16_t *dc_val_base;
@@@ -714,7 -661,8 +719,8 @@@ int ff_h264_get_slice_type(const H264Sl
   */
  int ff_h264_alloc_tables(H264Context *h);
  
- int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl);
+ int ff_h264_decode_ref_pic_list_reordering(const H264Context *h, H264SliceContext *sl);
 -int ff_h264_build_ref_list(const H264Context *h, H264SliceContext *sl);
++int ff_h264_build_ref_list(H264Context *h, H264SliceContext *sl);
  void ff_h264_remove_all_refs(H264Context *h);
  
  /**
@@@ -295,7 -252,7 +295,7 @@@ static void h264_fill_mbaff_ref_list(H2
      }
  }
  
- int ff_h264_decode_ref_pic_list_reordering(H264Context *h, H264SliceContext *sl)
 -int ff_h264_build_ref_list(const H264Context *h, H264SliceContext *sl)
++int ff_h264_build_ref_list(H264Context *h, H264SliceContext *sl)
  {
      int list, index, pic_structure;
  
      h264_initialise_ref_list(h, sl);
  
      for (list = 0; list < sl->list_count; list++) {
-         if (get_bits1(&sl->gb)) {    // ref_pic_list_modification_flag_l[01]
-             int pred = h->curr_pic_num;
-             for (index = 0; ; index++) {
-                 unsigned int modification_of_pic_nums_idc = get_ue_golomb_31(&sl->gb);
-                 unsigned int pic_id;
-                 int i;
-                 H264Picture *ref = NULL;
-                 if (modification_of_pic_nums_idc == 3)
-                     break;
-                 if (index >= sl->ref_count[list]) {
-                     av_log(h->avctx, AV_LOG_ERROR, "reference count overflow\n");
-                     return -1;
+         int pred = h->curr_pic_num;
+         for (index = 0; index < sl->nb_ref_modifications[list]; index++) {
+             unsigned int modification_of_pic_nums_idc = sl->ref_modifications[list][index].op;
+             unsigned int                          val = sl->ref_modifications[list][index].val;
+             unsigned int pic_id;
+             int i;
+             H264Picture *ref = NULL;
+             switch (modification_of_pic_nums_idc) {
+             case 0:
+             case 1: {
+                 const unsigned int abs_diff_pic_num = val + 1;
+                 int frame_num;
+                 if (abs_diff_pic_num > h->max_pic_num) {
+                     av_log(h->avctx, AV_LOG_ERROR,
+                            "abs_diff_pic_num overflow\n");
+                     return AVERROR_INVALIDDATA;
                  }
  
-                 switch (modification_of_pic_nums_idc) {
-                 case 0:
-                 case 1: {
-                     const unsigned int abs_diff_pic_num = get_ue_golomb_long(&sl->gb) + 1;
-                     int frame_num;
-                     if (abs_diff_pic_num > h->max_pic_num) {
-                         av_log(h->avctx, AV_LOG_ERROR,
-                                "abs_diff_pic_num overflow\n");
-                         return AVERROR_INVALIDDATA;
-                     }
-                     if (modification_of_pic_nums_idc == 0)
-                         pred -= abs_diff_pic_num;
-                     else
-                         pred += abs_diff_pic_num;
-                     pred &= h->max_pic_num - 1;
-                     frame_num = pic_num_extract(h, pred, &pic_structure);
-                     for (i = h->short_ref_count - 1; i >= 0; i--) {
-                         ref = h->short_ref[i];
-                         assert(ref->reference);
-                         assert(!ref->long_ref);
-                         if (ref->frame_num == frame_num &&
-                             (ref->reference & pic_structure))
-                             break;
-                     }
-                     if (i >= 0)
-                         ref->pic_id = pred;
-                     break;
-                 }
-                 case 2: {
-                     int long_idx;
-                     pic_id = get_ue_golomb(&sl->gb); // long_term_pic_idx
-                     long_idx = pic_num_extract(h, pic_id, &pic_structure);
-                     if (long_idx > 31U) {
-                         av_log(h->avctx, AV_LOG_ERROR,
-                                "long_term_pic_idx overflow\n");
-                         return AVERROR_INVALIDDATA;
-                     }
-                     ref = h->long_ref[long_idx];
-                     assert(!(ref && !ref->reference));
-                     if (ref && (ref->reference & pic_structure) && !mismatches_ref(h, ref)) {
-                         ref->pic_id = pic_id;
-                         assert(ref->long_ref);
-                         i = 0;
-                     } else {
-                         i = -1;
-                     }
-                     break;
+                 if (modification_of_pic_nums_idc == 0)
+                     pred -= abs_diff_pic_num;
+                 else
+                     pred += abs_diff_pic_num;
+                 pred &= h->max_pic_num - 1;
+                 frame_num = pic_num_extract(h, pred, &pic_structure);
+                 for (i = h->short_ref_count - 1; i >= 0; i--) {
+                     ref = h->short_ref[i];
+                     assert(ref->reference);
+                     assert(!ref->long_ref);
+                     if (ref->frame_num == frame_num &&
+                         (ref->reference & pic_structure))
+                         break;
                  }
-                 default:
+                 if (i >= 0)
+                     ref->pic_id = pred;
+                 break;
+             }
+             case 2: {
+                 int long_idx;
+                 pic_id = val; // long_term_pic_idx
+                 long_idx = pic_num_extract(h, pic_id, &pic_structure);
 -                if (long_idx > 31) {
++                if (long_idx > 31U) {
                      av_log(h->avctx, AV_LOG_ERROR,
-                            "illegal modification_of_pic_nums_idc %u\n",
-                            modification_of_pic_nums_idc);
+                            "long_term_pic_idx overflow\n");
                      return AVERROR_INVALIDDATA;
                  }
-                 if (i < 0) {
-                     av_log(h->avctx, AV_LOG_ERROR,
-                            "reference picture missing during reorder\n");
-                     memset(&sl->ref_list[list][index], 0, sizeof(sl->ref_list[0][0])); // FIXME
+                 ref = h->long_ref[long_idx];
+                 assert(!(ref && !ref->reference));
+                 if (ref && (ref->reference & pic_structure)) {
+                     ref->pic_id = pic_id;
+                     assert(ref->long_ref);
+                     i = 0;
                  } else {
-                     for (i = index; i + 1 < sl->ref_count[list]; i++) {
-                         if (sl->ref_list[list][i].parent &&
-                             ref->long_ref == sl->ref_list[list][i].parent->long_ref &&
-                             ref->pic_id   == sl->ref_list[list][i].pic_id)
-                             break;
-                     }
-                     for (; i > index; i--) {
-                         sl->ref_list[list][i] = sl->ref_list[list][i - 1];
-                     }
-                     ref_from_h264pic(&sl->ref_list[list][index], ref);
-                     if (FIELD_PICTURE(h)) {
-                         pic_as_field(&sl->ref_list[list][index], pic_structure);
-                     }
+                     i = -1;
+                 }
+                 break;
+             }
+             }
+             if (i < 0) {
+                 av_log(h->avctx, AV_LOG_ERROR,
+                        "reference picture missing during reorder\n");
+                 memset(&sl->ref_list[list][index], 0, sizeof(sl->ref_list[0][0])); // FIXME
+             } else {
+                 for (i = index; i + 1 < sl->ref_count[list]; i++) {
+                     if (sl->ref_list[list][i].parent &&
+                         ref->long_ref == sl->ref_list[list][i].parent->long_ref &&
+                         ref->pic_id   == sl->ref_list[list][i].pic_id)
+                         break;
+                 }
+                 for (; i > index; i--) {
+                     sl->ref_list[list][i] = sl->ref_list[list][i - 1];
+                 }
+                 ref_from_h264pic(&sl->ref_list[list][index], ref);
+                 if (FIELD_PICTURE(h)) {
+                     pic_as_field(&sl->ref_list[list][index], pic_structure);
                  }
              }
          }
      return 0;
  }
  
 -            sl->ref_modifications[list][index].val = get_ue_golomb(&sl->gb);
+ int ff_h264_decode_ref_pic_list_reordering(const H264Context *h, H264SliceContext *sl)
+ {
+     int list, index;
+     sl->nb_ref_modifications[0] = 0;
+     sl->nb_ref_modifications[1] = 0;
+     for (list = 0; list < sl->list_count; list++) {
+         if (!get_bits1(&sl->gb))    // ref_pic_list_modification_flag_l[01]
+             continue;
+         for (index = 0; ; index++) {
+             unsigned int op = get_ue_golomb_31(&sl->gb);
+             if (op == 3)
+                 break;
+             if (index >= sl->ref_count[list]) {
+                 av_log(h->avctx, AV_LOG_ERROR, "reference count overflow\n");
+                 return AVERROR_INVALIDDATA;
+             } else if (op > 2) {
+                 av_log(h->avctx, AV_LOG_ERROR,
+                        "illegal modification_of_pic_nums_idc %u\n",
+                        op);
+                 return AVERROR_INVALIDDATA;
+             }
++            sl->ref_modifications[list][index].val = get_ue_golomb_long(&sl->gb);
+             sl->ref_modifications[list][index].op  = op;
+             sl->nb_ref_modifications[list]++;
+         }
+     }
+     return 0;
+ }
  /**
   * Mark a picture as no longer needed for reference. The refmask
   * argument allows unreferencing of individual fields or the whole frame.
Simple merge