summaryrefslogtreecommitdiff
path: root/libavcodec
diff options
context:
space:
mode:
authorAnton Khirnov <anton@khirnov.net>2016-05-12 14:37:35 +0200
committerAnton Khirnov <anton@khirnov.net>2016-06-12 20:27:53 +0200
commit61f168ae348f94f39e7afc6971654455a5de0e4d (patch)
treecb1572478da5a0b8755d4d822dadad602d988f71 /libavcodec
parent6e92181bf836f48627a4733b6fd240a99fd36365 (diff)
h264: factor out setting the parameter sets for a frame
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/h264.h2
-rw-r--r--libavcodec/h264_slice.c191
2 files changed, 102 insertions, 91 deletions
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index dd89b490f2..3fdd3bcd90 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -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;
diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c
index 422c16320e..f55c2f6426 100644
--- a/libavcodec/h264_slice.c
+++ b/libavcodec/h264_slice.c
@@ -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)