1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-11-21 10:55:51 +02:00

h264: factor starting a new field out of parsing the slice header

This commit is contained in:
Anton Khirnov 2016-05-09 15:58:32 +02:00
parent bec993381c
commit 3fba16ecd9
2 changed files with 189 additions and 169 deletions

View File

@ -361,6 +361,7 @@ typedef struct H264SliceContext {
int mb_skip_run;
int is_complex;
int picture_structure;
int mb_field_decoding_flag;
int mb_mbaff; ///< mb_aff_frame && mb_field_decoding_flag

View File

@ -902,6 +902,179 @@ static int h264_slice_header_init(H264Context *h)
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 last_pic_structure, last_pic_droppable, ret;
last_pic_droppable = h->droppable;
last_pic_structure = h->picture_structure;
h->droppable = (h->nal_ref_idc == 0);
h->picture_structure = sl->picture_structure;
/* 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) {
int unwrap_prev_frame_num = h->poc.prev_frame_num;
int max_frame_num = 1 << sps->log2_max_frame_num;
if (unwrap_prev_frame_num > h->poc.frame_num)
unwrap_prev_frame_num -= max_frame_num;
if ((h->poc.frame_num - unwrap_prev_frame_num) > sps->ref_frame_count) {
unwrap_prev_frame_num = (h->poc.frame_num - sps->ref_frame_count) - 1;
if (unwrap_prev_frame_num < 0)
unwrap_prev_frame_num += max_frame_num;
h->poc.prev_frame_num = unwrap_prev_frame_num;
}
}
/* See if we have a decoded first field looking for a pair...
* Here, we're using that to see if we should mark previously
* decode frames as "finished".
* We have to do that before the "dummy" in-between frame allocation,
* since that can modify s->current_picture_ptr. */
if (h->first_field) {
assert(h->cur_pic_ptr);
assert(h->cur_pic_ptr->f->buf[0]);
assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
/* figure out if we have a complementary field pair */
if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such. */
if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
last_pic_structure == PICT_TOP_FIELD);
}
} else {
if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
/* This and previous field were reference, but had
* different frame_nums. Consider this field first in
* pair. Throw away previous field except for reference
* purposes. */
if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
last_pic_structure == PICT_TOP_FIELD);
}
} else {
/* Second field in complementary pair */
if (!((last_pic_structure == PICT_TOP_FIELD &&
h->picture_structure == PICT_BOTTOM_FIELD) ||
(last_pic_structure == PICT_BOTTOM_FIELD &&
h->picture_structure == PICT_TOP_FIELD))) {
av_log(h->avctx, AV_LOG_ERROR,
"Invalid field mode combination %d/%d\n",
last_pic_structure, h->picture_structure);
h->picture_structure = last_pic_structure;
h->droppable = last_pic_droppable;
return AVERROR_INVALIDDATA;
} else if (last_pic_droppable != h->droppable) {
avpriv_request_sample(h->avctx,
"Found reference and non-reference fields in the same frame, which");
h->picture_structure = last_pic_structure;
h->droppable = last_pic_droppable;
return AVERROR_PATCHWELCOME;
}
}
}
}
while (h->poc.frame_num != h->poc.prev_frame_num &&
h->poc.frame_num != (h->poc.prev_frame_num + 1) % (1 << sps->log2_max_frame_num)) {
H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
h->poc.frame_num, h->poc.prev_frame_num);
ret = initialize_cur_frame(h);
if (ret < 0) {
h->first_field = 0;
return ret;
}
h->poc.prev_frame_num++;
h->poc.prev_frame_num %= 1 << sps->log2_max_frame_num;
h->cur_pic_ptr->frame_num = h->poc.prev_frame_num;
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->explicit_ref_marking = 0;
ret = ff_h264_execute_ref_pic_marking(h);
if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
return ret;
/* Error concealment: If a ref is missing, copy the previous ref
* in its place.
* FIXME: Avoiding a memcpy would be nice, but ref handling makes
* many assumptions about there being no actual duplicates.
* FIXME: This does not copy padding for out-of-frame motion
* 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 &&
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,
prev->f->format,
h->mb_width * 16,
h->mb_height * 16);
h->short_ref[0]->poc = prev->poc + 2;
}
h->short_ref[0]->frame_num = h->poc.prev_frame_num;
}
}
/* See if we have a decoded first field looking for a pair...
* We're using that to see whether to continue decoding in that
* frame, or to allocate a new one. */
if (h->first_field) {
assert(h->cur_pic_ptr);
assert(h->cur_pic_ptr->f->buf[0]);
assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
/* figure out if we have a complementary field pair */
if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such. */
h->cur_pic_ptr = NULL;
h->first_field = FIELD_PICTURE(h);
} else {
if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
/* This and the previous field had different frame_nums.
* Consider this field first in pair. Throw away previous
* one except for reference purposes. */
h->first_field = 1;
h->cur_pic_ptr = NULL;
} else {
/* Second field in complementary pair */
h->first_field = 0;
}
}
} else {
/* Frame or first field in a potentially complementary pair */
h->first_field = FIELD_PICTURE(h);
}
if (!FIELD_PICTURE(h) || h->first_field) {
if (h264_frame_start(h) < 0) {
h->first_field = 0;
return AVERROR_INVALIDDATA;
}
} else {
release_unused_pictures(h, 0);
}
return 0;
}
static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
{
const SPS *sps;
@ -909,7 +1082,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
unsigned int pps_id;
int ret;
unsigned int slice_type, tmp, i;
int last_pic_structure, last_pic_droppable;
int needs_reinit = 0;
int field_pic_flag, bottom_field_flag;
int frame_num, droppable, picture_structure;
@ -1080,9 +1252,6 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
sl->mb_mbaff = 0;
last_pic_structure = h->picture_structure;
last_pic_droppable = h->droppable;
droppable = h->nal_ref_idc == 0;
if (sps->frame_mbs_only_flag) {
picture_structure = PICT_FRAME;
@ -1097,18 +1266,17 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
}
}
if (!h->setup_finished) {
h->droppable = droppable;
h->picture_structure = picture_structure;
h->mb_aff_frame = mb_aff_frame;
}
sl->mb_field_decoding_flag = h->picture_structure != PICT_FRAME;
sl->picture_structure = picture_structure;
sl->mb_field_decoding_flag = picture_structure != PICT_FRAME;
if (h->current_slice != 0) {
if (last_pic_structure != picture_structure ||
last_pic_droppable != droppable) {
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",
last_pic_structure, h->picture_structure);
h->picture_structure, picture_structure);
return AVERROR_INVALIDDATA;
} else if (!h->cur_pic_ptr) {
av_log(h->avctx, AV_LOG_ERROR,
@ -1116,164 +1284,9 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
h->current_slice + 1);
return AVERROR_INVALIDDATA;
}
} else {
/* 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) {
int unwrap_prev_frame_num = h->poc.prev_frame_num;
int max_frame_num = 1 << sps->log2_max_frame_num;
if (unwrap_prev_frame_num > h->poc.frame_num)
unwrap_prev_frame_num -= max_frame_num;
if ((h->poc.frame_num - unwrap_prev_frame_num) > sps->ref_frame_count) {
unwrap_prev_frame_num = (h->poc.frame_num - sps->ref_frame_count) - 1;
if (unwrap_prev_frame_num < 0)
unwrap_prev_frame_num += max_frame_num;
h->poc.prev_frame_num = unwrap_prev_frame_num;
}
}
/* See if we have a decoded first field looking for a pair...
* Here, we're using that to see if we should mark previously
* decode frames as "finished".
* We have to do that before the "dummy" in-between frame allocation,
* since that can modify s->current_picture_ptr. */
if (h->first_field) {
assert(h->cur_pic_ptr);
assert(h->cur_pic_ptr->f->buf[0]);
assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
/* figure out if we have a complementary field pair */
if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such. */
if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
last_pic_structure == PICT_TOP_FIELD);
}
} else {
if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
/* This and previous field were reference, but had
* different frame_nums. Consider this field first in
* pair. Throw away previous field except for reference
* purposes. */
if (!last_pic_droppable && last_pic_structure != PICT_FRAME) {
ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX,
last_pic_structure == PICT_TOP_FIELD);
}
} else {
/* Second field in complementary pair */
if (!((last_pic_structure == PICT_TOP_FIELD &&
h->picture_structure == PICT_BOTTOM_FIELD) ||
(last_pic_structure == PICT_BOTTOM_FIELD &&
h->picture_structure == PICT_TOP_FIELD))) {
av_log(h->avctx, AV_LOG_ERROR,
"Invalid field mode combination %d/%d\n",
last_pic_structure, h->picture_structure);
h->picture_structure = last_pic_structure;
h->droppable = last_pic_droppable;
return AVERROR_INVALIDDATA;
} else if (last_pic_droppable != h->droppable) {
avpriv_request_sample(h->avctx,
"Found reference and non-reference fields in the same frame, which");
h->picture_structure = last_pic_structure;
h->droppable = last_pic_droppable;
return AVERROR_PATCHWELCOME;
}
}
}
}
while (h->poc.frame_num != h->poc.prev_frame_num &&
h->poc.frame_num != (h->poc.prev_frame_num + 1) % (1 << sps->log2_max_frame_num)) {
H264Picture *prev = h->short_ref_count ? h->short_ref[0] : NULL;
av_log(h->avctx, AV_LOG_DEBUG, "Frame num gap %d %d\n",
h->poc.frame_num, h->poc.prev_frame_num);
ret = initialize_cur_frame(h);
if (ret < 0) {
h->first_field = 0;
return ret;
}
h->poc.prev_frame_num++;
h->poc.prev_frame_num %= 1 << sps->log2_max_frame_num;
h->cur_pic_ptr->frame_num = h->poc.prev_frame_num;
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->explicit_ref_marking = 0;
ret = ff_h264_execute_ref_pic_marking(h);
if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE))
return ret;
/* Error concealment: If a ref is missing, copy the previous ref
* in its place.
* FIXME: Avoiding a memcpy would be nice, but ref handling makes
* many assumptions about there being no actual duplicates.
* FIXME: This does not copy padding for out-of-frame motion
* 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 &&
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,
prev->f->format,
h->mb_width * 16,
h->mb_height * 16);
h->short_ref[0]->poc = prev->poc + 2;
}
h->short_ref[0]->frame_num = h->poc.prev_frame_num;
}
}
/* See if we have a decoded first field looking for a pair...
* We're using that to see whether to continue decoding in that
* frame, or to allocate a new one. */
if (h->first_field) {
assert(h->cur_pic_ptr);
assert(h->cur_pic_ptr->f->buf[0]);
assert(h->cur_pic_ptr->reference != DELAYED_PIC_REF);
/* figure out if we have a complementary field pair */
if (!FIELD_PICTURE(h) || h->picture_structure == last_pic_structure) {
/* Previous field is unmatched. Don't display it, but let it
* remain for reference if marked as such. */
h->cur_pic_ptr = NULL;
h->first_field = FIELD_PICTURE(h);
} else {
if (h->cur_pic_ptr->frame_num != h->poc.frame_num) {
/* This and the previous field had different frame_nums.
* Consider this field first in pair. Throw away previous
* one except for reference purposes. */
h->first_field = 1;
h->cur_pic_ptr = NULL;
} else {
/* Second field in complementary pair */
h->first_field = 0;
}
}
} else {
/* Frame or first field in a potentially complementary pair */
h->first_field = FIELD_PICTURE(h);
}
if (!FIELD_PICTURE(h) || h->first_field) {
if (h264_frame_start(h) < 0) {
h->first_field = 0;
return AVERROR_INVALIDDATA;
}
} else {
release_unused_pictures(h, 0);
}
}
if (h->picture_structure == PICT_FRAME) {
if (picture_structure == PICT_FRAME) {
h->curr_pic_num = h->poc.frame_num;
h->max_pic_num = 1 << sps->log2_max_frame_num;
} else {
@ -1290,7 +1303,7 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
if (!h->setup_finished)
h->poc.poc_lsb = poc_lsb;
if (pps->pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
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;
@ -1303,7 +1316,7 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
if (!h->setup_finished)
h->poc.delta_poc[0] = delta_poc;
if (pps->pic_order_present == 1 && h->picture_structure == PICT_FRAME) {
if (pps->pic_order_present == 1 && picture_structure == PICT_FRAME) {
delta_poc = get_se_golomb(&sl->gb);
if (!h->setup_finished)
@ -1319,7 +1332,7 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl)
ret = ff_h264_parse_ref_count(&sl->list_count, sl->ref_count,
&sl->gb, pps, sl->slice_type_nos,
h->picture_structure);
picture_structure);
if (ret < 0)
return ret;
@ -1422,6 +1435,12 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl)
if (ret < 0)
return ret;
if (h->current_slice == 0) {
ret = h264_field_start(h, sl);
if (ret < 0)
return ret;
}
assert(h->mb_num == h->mb_width * h->mb_height);
if (sl->first_mb_addr << FIELD_OR_MBAFF_PICTURE(h) >= h->mb_num ||
sl->first_mb_addr >= h->mb_num) {