[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