}
}
-#define IN_RANGE(a, b, size) (((a) >= (b)) && ((a) < ((b) + (size))))
+#define IN_RANGE(a, b, size) (((void*)(a) >= (void*)(b)) && ((void*)(a) < (void*)((b) + (size))))
#define REBASE_PICTURE(pic, new_ctx, old_ctx) \
(((pic) && (pic) >= (old_ctx)->DPB && \
int i;
for (i = 0; i < count; i++) {
- av_assert1((IN_RANGE(from[i], old_base, 1) ||
- IN_RANGE(from[i], old_base->DPB,
- H264_MAX_PICTURE_COUNT) ||
- !from[i]));
+ av_assert1(!from[i] ||
+ IN_RANGE(from[i], old_base, 1) ||
+ IN_RANGE(from[i], old_base->DPB, H264_MAX_PICTURE_COUNT));
to[i] = REBASE_PICTURE(from[i], new_base, old_base);
}
}
int needs_reinit = 0;
int field_pic_flag, bottom_field_flag;
int first_slice = sl == h->slice_ctx && !h->current_slice;
- int frame_num, picture_structure, droppable;
+ int frame_num, droppable, picture_structure;
int mb_aff_frame, last_mb_aff_frame;
PPS *pps;
+ if (first_slice)
+ av_assert0(!h->setup_finished);
+
h->qpel_put = h->h264qpel.put_h264_qpel_pixels_tab;
h->qpel_avg = h->h264qpel.avg_h264_qpel_pixels_tab;
if (first_mb_in_slice == 0) { // FIXME better field boundary detection
if (h->current_slice) {
+ av_assert0(!h->setup_finished);
if (h->cur_pic_ptr && FIELD_PICTURE(h) && h->first_field) {
ff_h264_field_end(h, h->slice_ctx, 1);
h->current_slice = 0;
}
// to make a few old functions happy, it's wrong though
- h->pict_type = sl->slice_type;
+ if (!h->setup_finished)
+ h->pict_type = sl->slice_type;
pps_id = get_ue_golomb(&sl->gb);
if (pps_id >= MAX_PPS_COUNT) {
h->pps.sps_id);
return AVERROR_INVALIDDATA;
}
- if (first_slice)
+
+ if (first_slice) {
h->pps = *h->pps_buffers[pps_id];
+ } else if (h->setup_finished && h->dequant_coeff_pps != pps_id) {
+ av_log(h->avctx, AV_LOG_ERROR, "PPS changed between slices\n");
+ return AVERROR_INVALIDDATA;
+ }
if (pps->sps_id != h->sps.sps_id ||
pps->sps_id != h->current_sps_id ||
}
- h->avctx->profile = ff_h264_get_profile(&h->sps);
- h->avctx->level = h->sps.level_idc;
- h->avctx->refs = h->sps.ref_frame_count;
-
must_reinit = (h->context_initialized &&
( 16*h->sps.mb_width != h->avctx->coded_width
|| 16*h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag) != h->avctx->coded_height
if (first_slice && av_cmp_q(h->sps.sar, h->avctx->sample_aspect_ratio))
must_reinit = 1;
- h->mb_width = h->sps.mb_width;
- h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
- h->mb_num = h->mb_width * h->mb_height;
- h->mb_stride = h->mb_width + 1;
+ if (!h->setup_finished) {
+ h->avctx->profile = ff_h264_get_profile(&h->sps);
+ h->avctx->level = h->sps.level_idc;
+ h->avctx->refs = h->sps.ref_frame_count;
- h->b_stride = h->mb_width * 4;
+ h->mb_width = h->sps.mb_width;
+ h->mb_height = h->sps.mb_height * (2 - h->sps.frame_mbs_only_flag);
+ h->mb_num = h->mb_width * h->mb_height;
+ h->mb_stride = h->mb_width + 1;
- h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
+ h->b_stride = h->mb_width * 4;
- h->width = 16 * h->mb_width;
- h->height = 16 * h->mb_height;
+ h->chroma_y_shift = h->sps.chroma_format_idc <= 1; // 400 uses yuv420p
- ret = init_dimensions(h);
- if (ret < 0)
- return ret;
+ h->width = 16 * h->mb_width;
+ h->height = 16 * h->mb_height;
+
+ ret = init_dimensions(h);
+ if (ret < 0)
+ return ret;
- if (h->sps.video_signal_type_present_flag) {
- h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
- : AVCOL_RANGE_MPEG;
- if (h->sps.colour_description_present_flag) {
- if (h->avctx->colorspace != h->sps.colorspace)
- needs_reinit = 1;
- h->avctx->color_primaries = h->sps.color_primaries;
- h->avctx->color_trc = h->sps.color_trc;
- h->avctx->colorspace = h->sps.colorspace;
+ if (h->sps.video_signal_type_present_flag) {
+ h->avctx->color_range = h->sps.full_range>0 ? AVCOL_RANGE_JPEG
+ : AVCOL_RANGE_MPEG;
+ if (h->sps.colour_description_present_flag) {
+ if (h->avctx->colorspace != h->sps.colorspace)
+ needs_reinit = 1;
+ h->avctx->color_primaries = h->sps.color_primaries;
+ h->avctx->color_trc = h->sps.color_trc;
+ h->avctx->colorspace = h->sps.colorspace;
+ }
}
}
}
}
+ if (!h->setup_finished)
+ h->frame_num = frame_num;
+
sl->mb_mbaff = 0;
mb_aff_frame = 0;
last_mb_aff_frame = h->mb_aff_frame;
last_pic_structure = h->picture_structure;
last_pic_droppable = h->droppable;
- droppable = h->nal_ref_idc == 0;
+
+ droppable = h->nal_ref_idc == 0;
if (h->sps.frame_mbs_only_flag) {
picture_structure = PICT_FRAME;
} else {
mb_aff_frame = h->sps.mb_aff;
}
}
+
if (h->current_slice) {
if (last_pic_structure != picture_structure ||
last_pic_droppable != droppable ||
}
h->picture_structure = picture_structure;
- h->droppable = droppable;
- h->frame_num = frame_num;
- h->mb_aff_frame = mb_aff_frame;
+ if (!h->setup_finished) {
+ h->droppable = droppable;
+ h->picture_structure = picture_structure;
+ h->mb_aff_frame = mb_aff_frame;
+ }
sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
if (h->current_slice == 0) {
* vectors. Given we are concealing a lost frame, this probably
* is not noticeable by comparison, but it should be fixed. */
if (h->short_ref_count) {
- if (prev) {
+ if (prev &&
+ h->short_ref[0]->f->width == prev->f->width &&
+ h->short_ref[0]->f->height == prev->f->height &&
+ h->short_ref[0]->f->format == prev->f->format) {
av_image_copy(h->short_ref[0]->f->data,
h->short_ref[0]->f->linesize,
(const uint8_t **)prev->f->data,
prev->f->linesize,
- h->avctx->pix_fmt,
- h->mb_width * 16,
- h->mb_height * 16);
+ prev->f->format,
+ prev->f->width,
+ prev->f->height);
h->short_ref[0]->poc = prev->poc + 2;
}
h->short_ref[0]->frame_num = h->prev_frame_num;
h->last_slice_type = -1;
}
-
- h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup
+ if (!h->setup_finished)
+ h->cur_pic_ptr->frame_num = h->frame_num; // FIXME frame_num cleanup
av_assert1(h->mb_num == h->mb_width * h->mb_height);
if (first_mb_in_slice << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
get_ue_golomb(&sl->gb); /* idr_pic_id */
if (h->sps.poc_type == 0) {
- h->poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+ int poc_lsb = get_bits(&sl->gb, h->sps.log2_max_poc_lsb);
+
+ if (!h->setup_finished)
+ h->poc_lsb = poc_lsb;
- if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
- h->delta_poc_bottom = get_se_golomb(&sl->gb);
+ if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+ int delta_poc_bottom = get_se_golomb(&sl->gb);
+ if (!h->setup_finished)
+ h->delta_poc_bottom = delta_poc_bottom;
+ }
}
if (h->sps.poc_type == 1 && !h->sps.delta_pic_order_always_zero_flag) {
- h->delta_poc[0] = get_se_golomb(&sl->gb);
+ int delta_poc = get_se_golomb(&sl->gb);
+
+ if (!h->setup_finished)
+ h->delta_poc[0] = delta_poc;
+
+ if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
+ delta_poc = get_se_golomb(&sl->gb);
- if (h->pps.pic_order_present == 1 && h->picture_structure == PICT_FRAME)
- h->delta_poc[1] = get_se_golomb(&sl->gb);
+ if (!h->setup_finished)
+ h->delta_poc[1] = delta_poc;
+ }
}
- ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
+ if (!h->setup_finished)
+ ff_init_poc(h, h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc);
if (h->pps.redundant_pic_cnt_present)
sl->redundant_pic_count = get_ue_golomb(&sl->gb);
for (;;) {
// START_TIMER
int ret, eos;
-
- if (sl->mb_x + sl->mb_y * h->mb_width >= sl->mb_index_end) {
- av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
- sl->mb_index_end);
+ if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) {
+ av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n",
+ sl->next_slice_idx);
er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
sl->mb_y, ER_MB_ERROR);
return AVERROR_INVALIDDATA;
for (;;) {
int ret;
- if (sl->mb_x + sl->mb_y * h->mb_width >= sl->mb_index_end) {
- av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps next at %d\n",
- sl->mb_index_end);
+ if (sl->mb_x + sl->mb_y * h->mb_width >= sl->next_slice_idx) {
+ av_log(h->avctx, AV_LOG_ERROR, "Slice overlaps with next at %d\n",
+ sl->next_slice_idx);
er_add_slice(sl, sl->resync_mb_x, sl->resync_mb_y, sl->mb_x,
sl->mb_y, ER_MB_ERROR);
return AVERROR_INVALIDDATA;
{
AVCodecContext *const avctx = h->avctx;
H264SliceContext *sl;
- int i;
+ int i, j;
av_assert0(context_count && h->slice_ctx[context_count - 1].mb_y < h->mb_height);
- h->slice_ctx[0].mb_index_end = INT_MAX;
+ h->slice_ctx[0].next_slice_idx = INT_MAX;
if (h->avctx->hwaccel ||
h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
return 0;
if (context_count == 1) {
- int ret = decode_slice(avctx, &h->slice_ctx[0]);
+ int ret;
+
+ h->slice_ctx[0].next_slice_idx = h->mb_width * h->mb_height;
+
+ ret = decode_slice(avctx, &h->slice_ctx[0]);
h->mb_y = h->slice_ctx[0].mb_y;
return ret;
} else {
- int j, mb_index;
av_assert0(context_count > 0);
for (i = 0; i < context_count; i++) {
- int mb_index_end = h->mb_width * h->mb_height;
+ int next_slice_idx = h->mb_width * h->mb_height;
+ int slice_idx;
+
sl = &h->slice_ctx[i];
- mb_index = sl->resync_mb_x + sl->resync_mb_y * h->mb_width;
if (CONFIG_ERROR_RESILIENCE) {
sl->er.error_count = 0;
}
+
+ /* make sure none of those slices overlap */
+ slice_idx = sl->mb_y * h->mb_width + sl->mb_x;
for (j = 0; j < context_count; j++) {
H264SliceContext *sl2 = &h->slice_ctx[j];
- int mb_index2 = sl2->resync_mb_x + sl2->resync_mb_y * h->mb_width;
+ int slice_idx2 = sl2->mb_y * h->mb_width + sl2->mb_x;
- if (i==j || mb_index > mb_index2)
+ if (i == j || slice_idx2 < slice_idx)
continue;
- mb_index_end = FFMIN(mb_index_end, mb_index2);
+ next_slice_idx = FFMIN(next_slice_idx, slice_idx2);
}
- sl->mb_index_end = mb_index_end;
+ sl->next_slice_idx = next_slice_idx;
}
avctx->execute(avctx, decode_slice, h->slice_ctx,