[FFmpeg-cvslog] Merge commit '61f168ae348f94f39e7afc6971654455a5de0e4d'

Clément Bœsch git at videolan.org
Sat Jul 9 13:58:38 CEST 2016


ffmpeg | branch: master | Clément Bœsch <u at pkh.me> | Sat Jul  9 13:50:16 2016 +0200| [f512e4a39037ef798ec78170f734c7733abe3231] | committer: Clément Bœsch

Merge commit '61f168ae348f94f39e7afc6971654455a5de0e4d'

* commit '61f168ae348f94f39e7afc6971654455a5de0e4d':
  h264: factor out setting the parameter sets for a frame

Michael's changes on top of the merge undo parts of the original diff
that are not factorization:

"The call point is left where it was before. Such a change should be in
a separate commit and has multiple issues, one being null pointer
dereferences the other is that some safety checks would become
conditional.

I tried to split the PPS init between the new and old functions
similarly to the SPS code."

Merged-by: Clément Bœsch <u at pkh.me>
Merged-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=f512e4a39037ef798ec78170f734c7733abe3231
---

 libavcodec/h264.h       |    2 +
 libavcodec/h264_slice.c |  261 ++++++++++++++++++++++++-----------------------
 2 files changed, 138 insertions(+), 125 deletions(-)

diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 078105c..ed8498a 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -413,6 +413,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;
 
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 22916f1..444d281 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -1004,6 +1004,125 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
     }
 }
 
+static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_slice)
+{
+    const SPS *sps;
+    int needs_reinit = 0, must_reinit, ret;
+
+    if (first_slice) {
+        av_buffer_unref(&h->ps.pps_ref);
+        h->ps.pps = NULL;
+        h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[sl->pps_id]);
+        if (!h->ps.pps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.pps = (const PPS*)h->ps.pps_ref->data;
+    }
+
+    if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
+        av_buffer_unref(&h->ps.sps_ref);
+        h->ps.sps = NULL;
+        h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]);
+        if (!h->ps.sps_ref)
+            return AVERROR(ENOMEM);
+        h->ps.sps = (const SPS*)h->ps.sps_ref->data;
+
+        if (h->mb_width  != h->ps.sps->mb_width ||
+            h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) ||
+            h->cur_bit_depth_luma    != h->ps.sps->bit_depth_luma ||
+            h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc
+        )
+            needs_reinit = 1;
+
+        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;
+
+    must_reinit = (h->context_initialized &&
+                    (   16*sps->mb_width != h->avctx->coded_width
+                     || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height
+                     || h->cur_bit_depth_luma    != sps->bit_depth_luma
+                     || h->cur_chroma_format_idc != sps->chroma_format_idc
+                     || h->mb_width  != sps->mb_width
+                     || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)
+                    ));
+    if (h->avctx->pix_fmt == AV_PIX_FMT_NONE
+        || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0))))
+        must_reinit = 1;
+
+    if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio))
+        must_reinit = 1;
+
+    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;
+
+        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 > 0 ? 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 || must_reinit || needs_reinit) {
+        int flush_changes = h->context_initialized;
+        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;
+        }
+
+        av_assert1(first_slice);
+
+        if (flush_changes)
+            ff_h264_flush_change(h);
+
+        if ((ret = get_pixel_format(h, 1)) < 0)
+            return ret;
+        h->avctx->pix_fmt = ret;
+
+        av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, "
+               "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(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.
@@ -1011,10 +1130,12 @@ static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
 static int h264_field_start(H264Context *h, const H264SliceContext *sl)
 {
     int i;
-    const SPS *sps = h->ps.sps;
+    const SPS *sps;
 
     int last_pic_structure, last_pic_droppable, ret;
 
+    sps = h->ps.sps;
+
     last_pic_droppable   = h->droppable;
     last_pic_structure   = h->picture_structure;
     h->droppable         = (h->nal_ref_idc == 0);
@@ -1205,11 +1326,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 must_reinit;
-    int needs_reinit = 0;
     int field_pic_flag, bottom_field_flag;
     int first_slice = sl == h->slice_ctx && !h->current_slice;
     int frame_num, droppable, picture_structure;
@@ -1299,152 +1417,45 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
         }
     }
 
-    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;
     }
 
-    pps = (const PPS*)h->ps.pps_list[pps_id]->data;
+    pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
 
     if (!h->ps.sps_list[pps->sps_id]) {
         av_log(h->avctx, AV_LOG_ERROR,
-               "non-existing SPS %u referenced\n",
-               pps->sps_id);
+               "non-existing SPS %u referenced\n", pps->sps_id);
         return AVERROR_INVALIDDATA;
     }
-
-    if (first_slice) {
-        av_buffer_unref(&h->ps.pps_ref);
-        h->ps.pps = NULL;
-        h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[pps_id]);
-        if (!h->ps.pps_ref)
-            return AVERROR(ENOMEM);
-        h->ps.pps = (const PPS*)h->ps.pps_ref->data;
-    } else {
+    if (!first_slice) {
         if (h->ps.pps->sps_id != pps->sps_id ||
             h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||
             (h->setup_finished && h->ps.pps != pps)*/) {
             av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
             return AVERROR_INVALIDDATA;
         }
-    }
-
-    if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
-        if (!first_slice) {
+        if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
             av_log(h->avctx, AV_LOG_ERROR,
                "SPS changed in the middle of the frame\n");
             return AVERROR_INVALIDDATA;
         }
-
-        av_buffer_unref(&h->ps.sps_ref);
-        h->ps.sps = NULL;
-        h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]);
-        if (!h->ps.sps_ref)
-            return AVERROR(ENOMEM);
-        h->ps.sps = (const SPS*)h->ps.sps_ref->data;
-
-        if (h->mb_width  != h->ps.sps->mb_width ||
-            h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) ||
-            h->cur_bit_depth_luma    != h->ps.sps->bit_depth_luma ||
-            h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc
-        )
-            needs_reinit = 1;
-
-        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;
-
-    must_reinit = (h->context_initialized &&
-                    (   16*sps->mb_width != h->avctx->coded_width
-                     || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height
-                     || h->cur_bit_depth_luma    != sps->bit_depth_luma
-                     || h->cur_chroma_format_idc != sps->chroma_format_idc
-                     || h->mb_width  != sps->mb_width
-                     || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)
-                    ));
-    if (h->avctx->pix_fmt == AV_PIX_FMT_NONE
-        || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0))))
-        must_reinit = 1;
-
-    if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio))
-        must_reinit = 1;
-
-    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;
-
-        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 > 0 ? 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 || must_reinit || needs_reinit) {
-        int flush_changes = h->context_initialized;
-        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;
-        }
-
-        av_assert1(first_slice);
-
-        if(flush_changes)
-            ff_h264_flush_change(h);
-
-        if ((ret = get_pixel_format(h, 1)) < 0)
-            return ret;
-        h->avctx->pix_fmt = ret;
-
-        av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, "
-               "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt));
+    // TODO: should probably be moved to h264_field_start()
+    ret = h264_init_ps(h, sl, first_slice);
+    if (ret < 0)
+        return ret;
 
-        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 (!first_slice) {


======================================================================

diff --cc libavcodec/h264_slice.c
index 22916f1,f55c2f6..444d281
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@@ -987,34 -900,106 +987,155 @@@ static int h264_slice_header_init(H264C
      h->context_initialized = 1;
  
      return 0;
 +fail:
 +    ff_h264_free_tables(h);
 +    h->context_initialized = 0;
 +    return ret;
  }
  
 -static int h264_init_ps(H264Context *h, const H264SliceContext *sl)
 +static enum AVPixelFormat non_j_pixfmt(enum AVPixelFormat a)
 +{
 +    switch (a) {
 +    case AV_PIX_FMT_YUVJ420P: return AV_PIX_FMT_YUV420P;
 +    case AV_PIX_FMT_YUVJ422P: return AV_PIX_FMT_YUV422P;
 +    case AV_PIX_FMT_YUVJ444P: return AV_PIX_FMT_YUV444P;
 +    default:
 +        return a;
 +    }
 +}
 +
++static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_slice)
+ {
+     const SPS *sps;
 -    int needs_reinit = 0, ret;
++    int needs_reinit = 0, must_reinit, ret;
++
++    if (first_slice) {
++        av_buffer_unref(&h->ps.pps_ref);
++        h->ps.pps = NULL;
++        h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[sl->pps_id]);
++        if (!h->ps.pps_ref)
++            return AVERROR(ENOMEM);
++        h->ps.pps = (const PPS*)h->ps.pps_ref->data;
++    }
+ 
 -    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;
++        av_buffer_unref(&h->ps.sps_ref);
++        h->ps.sps = NULL;
++        h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]);
++        if (!h->ps.sps_ref)
++            return AVERROR(ENOMEM);
++        h->ps.sps = (const SPS*)h->ps.sps_ref->data;
++
++        if (h->mb_width  != h->ps.sps->mb_width ||
++            h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) ||
++            h->cur_bit_depth_luma    != h->ps.sps->bit_depth_luma ||
++            h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc
++        )
++            needs_reinit = 1;
+ 
+         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;
++    must_reinit = (h->context_initialized &&
++                    (   16*sps->mb_width != h->avctx->coded_width
++                     || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height
++                     || h->cur_bit_depth_luma    != sps->bit_depth_luma
++                     || h->cur_chroma_format_idc != sps->chroma_format_idc
++                     || h->mb_width  != sps->mb_width
++                     || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)
++                    ));
++    if (h->avctx->pix_fmt == AV_PIX_FMT_NONE
++        || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0))))
++        must_reinit = 1;
++
++    if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio))
++        must_reinit = 1;
+ 
 -    if (h->mb_width  != sps->mb_width ||
 -        h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag))
 -        needs_reinit = 1;
++    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;
+ 
 -    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->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->b_stride = h->mb_width * 4;
+ 
 -    h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p
++        h->chroma_y_shift = sps->chroma_format_idc <= 1; // 400 uses yuv420p
+ 
 -    h->width  = 16 * h->mb_width;
 -    h->height = 16 * h->mb_height;
++        h->width  = 16 * h->mb_width;
++        h->height = 16 * h->mb_height;
+ 
 -    ret = init_dimensions(h);
 -    if (ret < 0)
 -        return ret;
++        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 (sps->video_signal_type_present_flag) {
++            h->avctx->color_range = sps->full_range > 0 ? 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) {
++    if (!h->context_initialized || must_reinit || needs_reinit) {
++        int flush_changes = h->context_initialized;
+         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);
++        av_assert1(first_slice);
++
++        if (flush_changes)
++            ff_h264_flush_change(h);
+ 
 -        if ((ret = get_pixel_format(h)) < 0)
++        if ((ret = get_pixel_format(h, 1)) < 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);
++               "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(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)
  {
 +    int i;
-     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);
@@@ -1205,54 -1167,20 +1326,51 @@@ static int h264_slice_header_parse(H264
  {
      const SPS *sps;
      const PPS *pps;
-     unsigned int pps_id;
      int ret;
      unsigned int slice_type, tmp, i;
-     int must_reinit;
-     int needs_reinit = 0;
      int field_pic_flag, bottom_field_flag;
 +    int first_slice = sl == h->slice_ctx && !h->current_slice;
      int frame_num, droppable, picture_structure;
 -    int mb_aff_frame = 0;
 +    int mb_aff_frame, last_mb_aff_frame;
 +
 +    if (first_slice)
 +        av_assert0(!h->setup_finished);
  
 -    sl->first_mb_addr = get_ue_golomb(&sl->gb);
 +    sl->first_mb_addr = get_ue_golomb_long(&sl->gb);
  
      if (sl->first_mb_addr == 0) { // FIXME better field boundary detection
 -        if (h->current_slice && h->cur_pic_ptr && FIELD_PICTURE(h)) {
 -            ff_h264_field_end(h, sl, 1);
 +        if (h->current_slice) {
 +            if (h->setup_finished) {
 +                av_log(h->avctx, AV_LOG_ERROR, "Too many fields\n");
 +                return AVERROR_INVALIDDATA;
 +            }
 +            if (h->max_contexts > 1) {
 +                if (!h->single_decode_warning) {
 +                    av_log(h->avctx, AV_LOG_WARNING, "Cannot decode multiple access units as slice threads\n");
 +                    h->single_decode_warning = 1;
 +                }
 +                h->max_contexts = 1;
 +                return SLICE_SINGLETHREAD;
 +            }
 +
 +            if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {
 +                ret = ff_h264_field_end(h, h->slice_ctx, 1);
 +                h->current_slice = 0;
 +                if (ret < 0)
 +                    return ret;
 +            } else if (h->cur_pic_ptr && !FIELD_PICTURE(h) && !h->first_field && h->nal_unit_type  == NAL_IDR_SLICE) {
 +                av_log(h, AV_LOG_WARNING, "Broken frame packetizing\n");
 +                ret = ff_h264_field_end(h, h->slice_ctx, 1);
 +                h->current_slice = 0;
 +                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0);
 +                ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1);
 +                h->cur_pic_ptr = NULL;
 +                if (ret < 0)
 +                    return ret;
 +            } else
 +                return AVERROR_INVALIDDATA;
          }
  
 -        h->current_slice = 0;
          if (!h->first_field) {
              if (h->cur_pic_ptr && !h->droppable) {
                  ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
@@@ -1288,173 -1213,32 +1406,66 @@@
          return AVERROR_INVALIDDATA;
      }
  
 +    if (h->current_slice == 0 && !h->first_field) {
 +        if (
 +            (h->avctx->skip_frame >= AVDISCARD_NONREF && !h->nal_ref_idc) ||
 +            (h->avctx->skip_frame >= AVDISCARD_BIDIR  && sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
 +            (h->avctx->skip_frame >= AVDISCARD_NONINTRA && sl->slice_type_nos != AV_PICTURE_TYPE_I) ||
 +            (h->avctx->skip_frame >= AVDISCARD_NONKEY && h->nal_unit_type != NAL_IDR_SLICE && h->sei.recovery_point.recovery_frame_cnt < 0) ||
 +            h->avctx->skip_frame >= AVDISCARD_ALL) {
 +            return SLICE_SKIPED;
 +        }
 +    }
 +
-     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->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[pps_id]->data;
+     pps = (const PPS*)h->ps.pps_list[sl->pps_id]->data;
  
      if (!h->ps.sps_list[pps->sps_id]) {
          av_log(h->avctx, AV_LOG_ERROR,
-                "non-existing SPS %u referenced\n",
-                pps->sps_id);
+                "non-existing SPS %u referenced\n", pps->sps_id);
          return AVERROR_INVALIDDATA;
      }
- 
-     if (first_slice) {
-         av_buffer_unref(&h->ps.pps_ref);
-         h->ps.pps = NULL;
-         h->ps.pps_ref = av_buffer_ref(h->ps.pps_list[pps_id]);
-         if (!h->ps.pps_ref)
-             return AVERROR(ENOMEM);
-         h->ps.pps = (const PPS*)h->ps.pps_ref->data;
-     } else {
++    if (!first_slice) {
 +        if (h->ps.pps->sps_id != pps->sps_id ||
 +            h->ps.pps->transform_8x8_mode != pps->transform_8x8_mode /*||
 +            (h->setup_finished && h->ps.pps != pps)*/) {
 +            av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
 +            return AVERROR_INVALIDDATA;
 +        }
-     }
- 
-     if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
-         if (!first_slice) {
++        if (h->ps.sps != (const SPS*)h->ps.sps_list[h->ps.pps->sps_id]->data) {
 +            av_log(h->avctx, AV_LOG_ERROR,
 +               "SPS changed in the middle of the frame\n");
 +            return AVERROR_INVALIDDATA;
 +        }
- 
-         av_buffer_unref(&h->ps.sps_ref);
-         h->ps.sps = NULL;
-         h->ps.sps_ref = av_buffer_ref(h->ps.sps_list[h->ps.pps->sps_id]);
-         if (!h->ps.sps_ref)
-             return AVERROR(ENOMEM);
-         h->ps.sps = (const SPS*)h->ps.sps_ref->data;
- 
-         if (h->mb_width  != h->ps.sps->mb_width ||
-             h->mb_height != h->ps.sps->mb_height * (2 - h->ps.sps->frame_mbs_only_flag) ||
-             h->cur_bit_depth_luma    != h->ps.sps->bit_depth_luma ||
-             h->cur_chroma_format_idc != h->ps.sps->chroma_format_idc
-         )
-             needs_reinit = 1;
- 
-         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;
- 
-     must_reinit = (h->context_initialized &&
-                     (   16*sps->mb_width != h->avctx->coded_width
-                      || 16*sps->mb_height * (2 - sps->frame_mbs_only_flag) != h->avctx->coded_height
-                      || h->cur_bit_depth_luma    != sps->bit_depth_luma
-                      || h->cur_chroma_format_idc != sps->chroma_format_idc
-                      || h->mb_width  != sps->mb_width
-                      || h->mb_height != sps->mb_height * (2 - sps->frame_mbs_only_flag)
-                     ));
-     if (h->avctx->pix_fmt == AV_PIX_FMT_NONE
-         || (non_j_pixfmt(h->avctx->pix_fmt) != non_j_pixfmt(get_pixel_format(h, 0))))
-         must_reinit = 1;
- 
-     if (first_slice && av_cmp_q(sps->sar, h->avctx->sample_aspect_ratio))
-         must_reinit = 1;
- 
-     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;
- 
-         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 > 0 ? 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 || must_reinit || needs_reinit) {
-         int flush_changes = h->context_initialized;
-         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;
-         }
- 
-         av_assert1(first_slice);
- 
-         if(flush_changes)
-             ff_h264_flush_change(h);
- 
-         if ((ret = get_pixel_format(h, 1)) < 0)
-             return ret;
-         h->avctx->pix_fmt = ret;
- 
-         av_log(h->avctx, AV_LOG_VERBOSE, "Reinit context to %dx%d, "
-                "pix_fmt: %s\n", h->width, h->height, av_get_pix_fmt_name(h->avctx->pix_fmt));
++    // TODO: should probably be moved to h264_field_start()
++    ret = h264_init_ps(h, sl, first_slice);
++    if (ret < 0)
++        return ret;
 +
-         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 (!first_slice) {
 +        if (h->poc.frame_num != frame_num) {
 +            av_log(h->avctx, AV_LOG_ERROR, "Frame num change from %d to %d\n",
 +                   h->poc.frame_num, frame_num);
 +            return AVERROR_INVALIDDATA;
 +        }
 +    }
 +
      if (!h->setup_finished)
          h->poc.frame_num = frame_num;
  



More information about the ffmpeg-cvslog mailing list