h264: factor out setting the parameter sets for a frame
authorAnton Khirnov <anton@khirnov.net>
Thu, 12 May 2016 12:37:35 +0000 (14:37 +0200)
committerAnton Khirnov <anton@khirnov.net>
Sun, 12 Jun 2016 18:27:53 +0000 (20:27 +0200)
libavcodec/h264.h
libavcodec/h264_slice.c

index dd89b49..3fdd3bc 100644 (file)
@@ -399,6 +399,8 @@ typedef struct H264SliceContext {
     } ref_modifications[2][32];
     int nb_ref_modifications[2];
 
+    unsigned int pps_id;
+
     const uint8_t *intra_pcm_ptr;
     int16_t *dc_val_base;
 
index 422c163..f55c2f6 100644 (file)
@@ -902,16 +902,104 @@ static int h264_slice_header_init(H264Context *h)
     return 0;
 }
 
+static int h264_init_ps(H264Context *h, const H264SliceContext *sl)
+{
+    const SPS *sps;
+    int needs_reinit = 0, ret;
+
+    h->ps.pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
+    if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
+        h->ps.sps = (SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data;
+
+        if (h->bit_depth_luma    != h->ps.sps->bit_depth_luma ||
+            h->chroma_format_idc != h->ps.sps->chroma_format_idc)
+            needs_reinit         = 1;
+    }
+    sps = h->ps.sps;
+
+    h->avctx->profile = ff_h264_get_profile(sps);
+    h->avctx->level   = sps->level_idc;
+    h->avctx->refs    = sps->ref_frame_count;
+
+    if (h->mb_width  != sps->mb_width ||
+        h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag))
+        needs_reinit = 1;
+
+    h->mb_width  = sps->mb_width;
+    h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag);
+    h->mb_num    = h->mb_width * h->mb_height;
+    h->mb_stride = h->mb_width + 1;
+
+    h->b_stride = h->mb_width * 4;
+
+    h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p
+
+    h->width  = 16 * h->mb_width;
+    h->height = 16 * h->mb_height;
+
+    ret = init_dimensions(h);
+    if (ret < 0)
+        return ret;
+
+    if (sps->video_signal_type_present_flag) {
+        h->avctx->color_range = sps->full_range ? AVCOL_RANGE_JPEG
+            : AVCOL_RANGE_MPEG;
+        if (sps->colour_description_present_flag) {
+            if (h->avctx->colorspace != sps->colorspace)
+                needs_reinit = 1;
+            h->avctx->color_primaries = sps->color_primaries;
+            h->avctx->color_trc       = sps->color_trc;
+            h->avctx->colorspace      = sps->colorspace;
+        }
+    }
+
+    if (!h->context_initialized || needs_reinit) {
+        h->context_initialized = 0;
+        if (sl != h->slice_ctx) {
+            av_log(h->avctx, AV_LOG_ERROR,
+                   "changing width %d -> %d / height %d -> %d on "
+                   "slice %d\n",
+                   h->width, h->avctx->coded_width,
+                   h->height, h->avctx->coded_height,
+                   h->current_slice + 1);
+            return AVERROR_INVALIDDATA;
+        }
+
+        ff_h264_flush_change(h);
+
+        if ((ret = get_pixel_format(h)) < 0)
+            return ret;
+        h->avctx->pix_fmt = ret;
+
+        av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, "
+               "pix_fmt: %d\n", h->width, h->height, h->avctx->pix_fmt);
+
+        if ((ret = h264_slice_header_init(h)) < 0) {
+            av_log(h->avctx, AV_LOG_ERROR,
+                   "h264_slice_header_init() failed\n");
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
 /* This function is called right after decoding the slice header for a first
  * slice in a field (or a frame). It decides whether we are decoding a new frame
  * or a second field in a pair and does the necessary setup.
  */
 static int h264_field_start(H264Context *h, const H264SliceContext *sl)
 {
-    const SPS *sps = h->ps.sps;
+    const SPS *sps;
 
     int last_pic_structure, last_pic_droppable, ret;
 
+    ret = h264_init_ps(h, sl);
+    if (ret < 0)
+        return ret;
+
+    sps = h->ps.sps;
+
     last_pic_droppable   = h->droppable;
     last_pic_structure   = h->picture_structure;
     h->droppable         = (h->nal_ref_idc == 0);
@@ -1079,10 +1167,8 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
 {
     const SPS *sps;
     const PPS *pps;
-    unsigned int pps_id;
     int ret;
     unsigned int slice_type, tmp, i;
-    int needs_reinit = 0;
     int field_pic_flag, bottom_field_flag;
     int frame_num, droppable, picture_structure;
     int mb_aff_frame = 0;
@@ -1127,107 +1213,30 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
         return AVERROR_INVALIDDATA;
     }
 
-    pps_id = get_ue_golomb(&sl->gb);
-    if (pps_id >= MAX_PPS_COUNT) {
-        av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", pps_id);
+    sl->pps_id = get_ue_golomb(&sl->gb);
+    if (sl->pps_id >= MAX_PPS_COUNT) {
+        av_log(h->avctx, AV_LOG_ERROR, "pps_id %u out of range\n", sl->pps_id);
         return AVERROR_INVALIDDATA;
     }
-    if (!h->ps.pps_list[pps_id]) {
+    if (!h->ps.pps_list[sl->pps_id]) {
         av_log(h->avctx, AV_LOG_ERROR,
                "non-existing PPS %u referenced\n",
-               pps_id);
+               sl->pps_id);
         return AVERROR_INVALIDDATA;
     }
-    if (!h->setup_finished) {
-        h->ps.pps = (const PPS*)h->ps.pps_list[pps_id]->data;
-    } else if (h->ps.pps != (const PPS*)h->ps.pps_list[pps_id]->data) {
+    if (h->current_slice > 0 &&
+        h->ps.pps != (const PPS*)h->ps.pps_list[sl->pps_id]->data) {
         av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
         return AVERROR_INVALIDDATA;
     }
+    pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
 
-    if (!h->ps.sps_list[h->ps.pps->sps_id]) {
+    if (!h->ps.sps_list[pps->sps_id]) {
         av_log(h->avctx, AV_LOG_ERROR,
-               "non-existing SPS %u referenced\n",
-               h->ps.pps->sps_id);
+               "non-existing SPS %u referenced\n", pps->sps_id);
         return AVERROR_INVALIDDATA;
     }
-
-    if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
-        h->ps.sps = (SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data;
-
-        if (h->bit_depth_luma    != h->ps.sps->bit_depth_luma ||
-            h->chroma_format_idc != h->ps.sps->chroma_format_idc)
-            needs_reinit         = 1;
-    }
-
-    pps = h->ps.pps;
-    sps = h->ps.sps;
-
-    if (!h->setup_finished) {
-        h->avctx->profile = ff_h264_get_profile(sps);
-        h->avctx->level   = sps->level_idc;
-        h->avctx->refs    = sps->ref_frame_count;
-
-        if (h->mb_width  != sps->mb_width ||
-            h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag))
-            needs_reinit = 1;
-
-        h->mb_width  = sps->mb_width;
-        h->mb_height = sps->mb_height * (2 - sps->frame_mbs_only_flag);
-        h->mb_num    = h->mb_width * h->mb_height;
-        h->mb_stride = h->mb_width + 1;
-
-        h->b_stride = h->mb_width * 4;
-
-        h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p
-
-        h->width  = 16 * h->mb_width;
-        h->height = 16 * h->mb_height;
-
-        ret = init_dimensions(h);
-        if (ret < 0)
-            return ret;
-
-        if (sps->video_signal_type_present_flag) {
-            h->avctx->color_range = sps->full_range ? AVCOL_RANGE_JPEG
-                : AVCOL_RANGE_MPEG;
-            if (sps->colour_description_present_flag) {
-                if (h->avctx->colorspace != sps->colorspace)
-                    needs_reinit = 1;
-                h->avctx->color_primaries = sps->color_primaries;
-                h->avctx->color_trc       = sps->color_trc;
-                h->avctx->colorspace      = sps->colorspace;
-            }
-        }
-    }
-
-    if (!h->context_initialized || needs_reinit) {
-        h->context_initialized = 0;
-        if (sl != h->slice_ctx) {
-            av_log(h->avctx, AV_LOG_ERROR,
-                   "changing width %d -> %d / height %d -> %d on "
-                   "slice %d\n",
-                   h->width, h->avctx->coded_width,
-                   h->height, h->avctx->coded_height,
-                   h->current_slice + 1);
-            return AVERROR_INVALIDDATA;
-        }
-
-        ff_h264_flush_change(h);
-
-        if ((ret = get_pixel_format(h)) < 0)
-            return ret;
-        h->avctx->pix_fmt = ret;
-
-        av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, "
-               "pix_fmt: %d\n", h->width, h->height, h->avctx->pix_fmt);
-
-        if ((ret = h264_slice_header_init(h)) < 0) {
-            av_log(h->avctx, AV_LOG_ERROR,
-                   "h264_slice_header_init() failed\n");
-            return ret;
-        }
-    }
+    sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data;
 
     frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
     if (!h->setup_finished)