*/
#include "libavutil/avassert.h"
+#include "libavutil/display.h"
#include "libavutil/imgutils.h"
+#include "libavutil/stereo3d.h"
#include "libavutil/timer.h"
#include "internal.h"
#include "cabac.h"
#include "cabac_functions.h"
#include "error_resilience.h"
#include "avcodec.h"
-#include "h264.h"
+#include "h264dec.h"
#include "h264data.h"
#include "h264chroma.h"
#include "h264_mvpred.h"
h->coded_picture_number = h1->coded_picture_number;
h->first_field = h1->first_field;
h->picture_structure = h1->picture_structure;
+ h->mb_aff_frame = h1->mb_aff_frame;
h->droppable = h1->droppable;
for (i = 0; i < H264_MAX_PICTURE_COUNT; i++) {
memcpy(&h->poc, &h1->poc, sizeof(h->poc));
- h->curr_pic_num = h1->curr_pic_num;
- h->max_pic_num = h1->max_pic_num;
-
memcpy(h->short_ref, h1->short_ref, sizeof(h->short_ref));
memcpy(h->long_ref, h1->long_ref, sizeof(h->long_ref));
memcpy(h->delayed_pic, h1->delayed_pic, sizeof(h->delayed_pic));
h->postpone_filter = 0;
+ h->mb_aff_frame = h->ps.sps->mb_aff && (h->picture_structure == PICT_FRAME);
+
assert(h->cur_pic_ptr->long_ref == 0);
return 0;
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;
+}
+
+static int h264_export_frame_props(H264Context *h)
+{
+ const SPS *sps = h->ps.sps;
+ H264Picture *cur = h->cur_pic_ptr;
+
+ cur->f->interlaced_frame = 0;
+ cur->f->repeat_pict = 0;
+
+ /* Signal interlacing information externally. */
+ /* Prioritize picture timing SEI information over used
+ * decoding process if it exists. */
+
+ if (sps->pic_struct_present_flag) {
+ H264SEIPictureTiming *pt = &h->sei.picture_timing;
+ switch (pt->pic_struct) {
+ case SEI_PIC_STRUCT_FRAME:
+ break;
+ case SEI_PIC_STRUCT_TOP_FIELD:
+ case SEI_PIC_STRUCT_BOTTOM_FIELD:
+ cur->f->interlaced_frame = 1;
+ break;
+ case SEI_PIC_STRUCT_TOP_BOTTOM:
+ case SEI_PIC_STRUCT_BOTTOM_TOP:
+ if (FIELD_OR_MBAFF_PICTURE(h))
+ cur->f->interlaced_frame = 1;
+ else
+ // try to flag soft telecine progressive
+ cur->f->interlaced_frame = h->prev_interlaced_frame;
+ break;
+ case SEI_PIC_STRUCT_TOP_BOTTOM_TOP:
+ case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM:
+ /* Signal the possibility of telecined film externally
+ * (pic_struct 5,6). From these hints, let the applications
+ * decide if they apply deinterlacing. */
+ cur->f->repeat_pict = 1;
+ break;
+ case SEI_PIC_STRUCT_FRAME_DOUBLING:
+ cur->f->repeat_pict = 2;
+ break;
+ case SEI_PIC_STRUCT_FRAME_TRIPLING:
+ cur->f->repeat_pict = 4;
+ break;
+ }
+
+ if ((pt->ct_type & 3) &&
+ pt->pic_struct <= SEI_PIC_STRUCT_BOTTOM_TOP)
+ cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0;
+ } else {
+ /* Derive interlacing flag from used decoding process. */
+ cur->f->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h);
+ }
+ h->prev_interlaced_frame = cur->f->interlaced_frame;
+
+ if (cur->field_poc[0] != cur->field_poc[1]) {
+ /* Derive top_field_first from field pocs. */
+ cur->f->top_field_first = cur->field_poc[0] < cur->field_poc[1];
+ } else {
+ if (cur->f->interlaced_frame || sps->pic_struct_present_flag) {
+ /* Use picture timing SEI information. Even if it is a
+ * information of a past frame, better than nothing. */
+ if (h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM ||
+ h->sei.picture_timing.pic_struct == SEI_PIC_STRUCT_TOP_BOTTOM_TOP)
+ cur->f->top_field_first = 1;
+ else
+ cur->f->top_field_first = 0;
+ } else {
+ /* Most likely progressive */
+ cur->f->top_field_first = 0;
+ }
+ }
+
+ if (h->sei.frame_packing.present &&
+ h->sei.frame_packing.arrangement_type >= 0 &&
+ h->sei.frame_packing.arrangement_type <= 6 &&
+ h->sei.frame_packing.content_interpretation_type > 0 &&
+ h->sei.frame_packing.content_interpretation_type < 3) {
+ H264SEIFramePacking *fp = &h->sei.frame_packing;
+ AVStereo3D *stereo = av_stereo3d_create_side_data(cur->f);
+ if (!stereo)
+ return AVERROR(ENOMEM);
+
+ switch (fp->arrangement_type) {
+ case 0:
+ stereo->type = AV_STEREO3D_CHECKERBOARD;
+ break;
+ case 1:
+ stereo->type = AV_STEREO3D_COLUMNS;
+ break;
+ case 2:
+ stereo->type = AV_STEREO3D_LINES;
+ break;
+ case 3:
+ if (fp->quincunx_subsampling)
+ stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX;
+ else
+ stereo->type = AV_STEREO3D_SIDEBYSIDE;
+ break;
+ case 4:
+ stereo->type = AV_STEREO3D_TOPBOTTOM;
+ break;
+ case 5:
+ stereo->type = AV_STEREO3D_FRAMESEQUENCE;
+ break;
+ case 6:
+ stereo->type = AV_STEREO3D_2D;
+ break;
+ }
+
+ if (fp->content_interpretation_type == 2)
+ stereo->flags = AV_STEREO3D_FLAG_INVERT;
+ }
+
+ if (h->sei.display_orientation.present &&
+ (h->sei.display_orientation.anticlockwise_rotation ||
+ h->sei.display_orientation.hflip ||
+ h->sei.display_orientation.vflip)) {
+ H264SEIDisplayOrientation *o = &h->sei.display_orientation;
+ double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16);
+ AVFrameSideData *rotation = av_frame_new_side_data(cur->f,
+ AV_FRAME_DATA_DISPLAYMATRIX,
+ sizeof(int32_t) * 9);
+ if (!rotation)
+ return AVERROR(ENOMEM);
+
+ av_display_rotation_set((int32_t *)rotation->data, angle);
+ av_display_matrix_flip((int32_t *)rotation->data,
+ o->hflip, o->vflip);
+ }
+
+ if (h->sei.afd.present) {
+ AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD,
+ sizeof(uint8_t));
+ if (!sd)
+ return AVERROR(ENOMEM);
+
+ *sd->data = h->sei.afd.active_format_description;
+ h->sei.afd.present = 0;
+ }
+
+ if (h->sei.a53_caption.a53_caption) {
+ H264SEIA53Caption *a53 = &h->sei.a53_caption;
+ AVFrameSideData *sd = av_frame_new_side_data(cur->f,
+ AV_FRAME_DATA_A53_CC,
+ a53->a53_caption_size);
+ if (!sd)
+ return AVERROR(ENOMEM);
+
+ memcpy(sd->data, a53->a53_caption, a53->a53_caption_size);
+ av_freep(&a53->a53_caption);
+ a53->a53_caption_size = 0;
+ }
+
+ 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)
+static int h264_field_start(H264Context *h, const H264SliceContext *sl,
+ const H2645NAL *nal)
{
- 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);
+ h->droppable = (nal->ref_idc == 0);
h->picture_structure = sl->picture_structure;
+ h->poc.frame_num = sl->frame_num;
+ h->poc.poc_lsb = sl->poc_lsb;
+ h->poc.delta_poc_bottom = sl->delta_poc_bottom;
+ h->poc.delta_poc[0] = sl->delta_poc[0];
+ h->poc.delta_poc[1] = sl->delta_poc[1];
+
/* Shorten frame num gaps so we don't have to allocate reference
* frames just to throw them away */
if (h->poc.frame_num != h->poc.prev_frame_num) {
release_unused_pictures(h, 0);
}
+ ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc,
+ h->ps.sps, &h->poc, h->picture_structure, nal->ref_idc);
+
+ memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco));
+ h->nb_mmco = sl->nb_mmco;
+ h->explicit_ref_marking = sl->explicit_ref_marking;
+
+ /* Set the frame properties/side data. Only done for the second field in
+ * field coded frames, since some SEI information is present for each field
+ * and is merged by the SEI parsing code. */
+ if (!FIELD_PICTURE(h) || !h->first_field) {
+ ret = h264_export_frame_props(h);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
-static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
+static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl,
+ const H2645NAL *nal)
{
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;
+ int droppable, picture_structure;
sl->first_mb_addr = get_ue_golomb(&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);
- }
-
- 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,
- h->picture_structure == PICT_BOTTOM_FIELD);
- }
- h->cur_pic_ptr = NULL;
- }
- }
-
slice_type = get_ue_golomb_31(&sl->gb);
if (slice_type > 9) {
av_log(h->avctx, AV_LOG_ERROR,
sl->slice_type = slice_type;
sl->slice_type_nos = slice_type & 3;
- if (h->nal_unit_type == NAL_IDR_SLICE &&
+ if (nal->type == NAL_IDR_SLICE &&
sl->slice_type_nos != AV_PICTURE_TYPE_I) {
av_log(h->avctx, AV_LOG_ERROR, "A non-intra slice in an IDR NAL unit.\n");
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);
- 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) {
- av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
+ sl->pps_id);
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;
}
+ sps = (const SPS*)h->ps.sps_list[pps->sps_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;
- }
-
- 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;
- }
- }
-
- frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
- if (!h->setup_finished)
- h->poc.frame_num = frame_num;
+ sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num);
sl->mb_mbaff = 0;
- droppable = h->nal_ref_idc == 0;
+ droppable = nal->ref_idc == 0;
if (sps->frame_mbs_only_flag) {
picture_structure = PICT_FRAME;
} else {
picture_structure = PICT_TOP_FIELD + bottom_field_flag;
} else {
picture_structure = PICT_FRAME;
- mb_aff_frame = sps->mb_aff;
}
}
- if (!h->setup_finished) {
- h->mb_aff_frame = mb_aff_frame;
- }
sl->picture_structure = picture_structure;
sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
- if (h->current_slice != 0) {
- if (h->picture_structure != picture_structure ||
- h->droppable != droppable) {
- av_log(h->avctx, AV_LOG_ERROR,
- "Changing field mode (%d -> %d) between slices is not allowed\n",
- h->picture_structure, picture_structure);
- return AVERROR_INVALIDDATA;
- } else if (!h->cur_pic_ptr) {
- av_log(h->avctx, AV_LOG_ERROR,
- "unset cur_pic_ptr on slice %d\n",
- h->current_slice + 1);
- return AVERROR_INVALIDDATA;
- }
- }
-
if (picture_structure == PICT_FRAME) {
- h->curr_pic_num = h->poc.frame_num;
- h->max_pic_num = 1 << sps->log2_max_frame_num;
+ sl->curr_pic_num = sl->frame_num;
+ sl->max_pic_num = 1 << sps->log2_max_frame_num;
} else {
- h->curr_pic_num = 2 * h->poc.frame_num + 1;
- h->max_pic_num = 1 << (sps->log2_max_frame_num + 1);
+ sl->curr_pic_num = 2 * sl->frame_num + 1;
+ sl->max_pic_num = 1 << (sps->log2_max_frame_num + 1);
}
- if (h->nal_unit_type == NAL_IDR_SLICE)
+ if (nal->type == NAL_IDR_SLICE)
get_ue_golomb(&sl->gb); /* idr_pic_id */
if (sps->poc_type == 0) {
- int poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
-
- if (!h->setup_finished)
- h->poc.poc_lsb = poc_lsb;
+ sl->poc_lsb = get_bits(&sl->gb, sps->log2_max_poc_lsb);
- if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) {
- int delta_poc_bottom = get_se_golomb(&sl->gb);
- if (!h->setup_finished)
- h->poc.delta_poc_bottom = delta_poc_bottom;
- }
+ if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
+ sl->delta_poc_bottom = get_se_golomb(&sl->gb);
}
if (sps->poc_type == 1 && !sps->delta_pic_order_always_zero_flag) {
- int delta_poc = get_se_golomb(&sl->gb);
-
- if (!h->setup_finished)
- h->poc.delta_poc[0] = delta_poc;
+ sl->delta_poc[0] = get_se_golomb(&sl->gb);
- if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) {
- delta_poc = get_se_golomb(&sl->gb);
-
- if (!h->setup_finished)
- h->poc.delta_poc[1] = delta_poc;
- }
+ if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME)
+ sl->delta_poc[1] = get_se_golomb(&sl->gb);
}
if (pps->redundant_pic_cnt_present)
sl->slice_type_nos, &sl->pwt);
sl->explicit_ref_marking = 0;
- if (h->nal_ref_idc) {
+ if (nal->ref_idc) {
ret = ff_h264_decode_ref_pic_marking(h, sl, &sl->gb);
if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
return AVERROR_INVALIDDATA;
*
* @return 0 if okay, <0 if an error occurred
*/
-int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
+int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl,
+ const H2645NAL *nal)
{
int i, j, ret = 0;
- ret = h264_slice_header_parse(h, sl);
+ ret = h264_slice_header_parse(h, sl, nal);
if (ret < 0)
return ret;
- if (h->current_slice == 0) {
- ret = h264_field_start(h, sl);
- if (ret < 0)
- return ret;
+ if (!h->setup_finished) {
+ 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);
+ }
+
+ 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,
+ h->picture_structure == PICT_BOTTOM_FIELD);
+ }
+ h->cur_pic_ptr = NULL;
+ }
+ }
+
+ if (h->current_slice == 0) {
+ ret = h264_field_start(h, sl, nal);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ if (h->current_slice > 0) {
+ if (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;
+ }
+
+ if (h->picture_structure != sl->picture_structure ||
+ h->droppable != (nal->ref_idc == 0)) {
+ av_log(h->avctx, AV_LOG_ERROR,
+ "Changing field mode (%d -> %d) between slices is not allowed\n",
+ h->picture_structure, sl->picture_structure);
+ return AVERROR_INVALIDDATA;
+ } else if (!h->cur_pic_ptr) {
+ av_log(h->avctx, AV_LOG_ERROR,
+ "unset cur_pic_ptr on slice %d\n",
+ h->current_slice + 1);
+ return AVERROR_INVALIDDATA;
+ }
}
assert(h->mb_num == h->mb_width * h->mb_height);
sl->resync_mb_y = sl->mb_y = sl->mb_y + 1;
assert(sl->mb_y < h->mb_height);
- if (!h->setup_finished) {
- ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc,
- h->ps.sps, &h->poc, h->picture_structure, h->nal_ref_idc);
-
- memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco));
- h->nb_mmco = sl->nb_mmco;
- h->explicit_ref_marking = sl->explicit_ref_marking;
- }
-
ret = ff_h264_build_ref_list(h, sl);
if (ret < 0)
return ret;
(h->avctx->skip_loop_filter >= AVDISCARD_BIDIR &&
sl->slice_type_nos == AV_PICTURE_TYPE_B) ||
(h->avctx->skip_loop_filter >= AVDISCARD_NONREF &&
- h->nal_ref_idc == 0))
+ nal->ref_idc == 0))
sl->deblocking_filter = 0;
if (sl->deblocking_filter == 1 && h->nb_slice_ctx > 1) {
sl->mb_y * h->mb_width + sl->mb_x,
av_get_picture_type_char(sl->slice_type),
sl->slice_type_fixed ? " fix" : "",
- h->nal_unit_type == NAL_IDR_SLICE ? " IDR" : "",
+ nal->type == NAL_IDR_SLICE ? " IDR" : "",
h->poc.frame_num,
h->cur_pic_ptr->field_poc[0],
h->cur_pic_ptr->field_poc[1],