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)
{
- const SPS *sps = h->ps.sps;
+ int i;
+ 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);
{
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,
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);
+ 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;
+ }
+ }
+
+ 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;