X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fh264_slice.c;h=9c2301d7e0e0fe6a66af13e550d71cee17239fc5;hb=3749eede66c3774799766b1f246afae8a6ffc9bb;hp=1c9a270fb6cb2205f72bfb7fd6d7fee0747c2927;hpb=5c363d3e595a9e5b7c42897b7aab91b91b154ac1;p=ffmpeg diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 1c9a270fb6c..9c2301d7e0e 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -29,7 +29,6 @@ #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" @@ -244,6 +243,15 @@ static int alloc_picture(H264Context *h, H264Picture *pic) pic->ref_index[i] = pic->ref_index_buf[i]->data; } + pic->pps_buf = av_buffer_ref(h->ps.pps_ref); + if (!pic->pps_buf) + goto fail; + pic->pps = (const PPS*)pic->pps_buf->data; + + pic->mb_width = h->mb_width; + pic->mb_height = h->mb_height; + pic->mb_stride = h->mb_stride; + return 0; fail: ff_h264_unref_picture(h, pic); @@ -296,9 +304,8 @@ int ff_h264_update_thread_context(AVCodecContext *dst, if (dst == src) return 0; - // We can't fail if SPS isn't set at it breaks current skip_frame code - //if (!h1->ps.sps) - // return AVERROR_INVALIDDATA; + if (inited && !h1->ps.sps) + return AVERROR_INVALIDDATA; if (inited && (h->width != h1->width || @@ -317,37 +324,24 @@ int ff_h264_update_thread_context(AVCodecContext *dst, // SPS/PPS for (i = 0; i < FF_ARRAY_ELEMS(h->ps.sps_list); i++) { - av_buffer_unref(&h->ps.sps_list[i]); - if (h1->ps.sps_list[i]) { - h->ps.sps_list[i] = av_buffer_ref(h1->ps.sps_list[i]); - if (!h->ps.sps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&h->ps.sps_list[i], h1->ps.sps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(h->ps.pps_list); i++) { - av_buffer_unref(&h->ps.pps_list[i]); - if (h1->ps.pps_list[i]) { - h->ps.pps_list[i] = av_buffer_ref(h1->ps.pps_list[i]); - if (!h->ps.pps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&h->ps.pps_list[i], h1->ps.pps_list[i]); + if (ret < 0) + return ret; } - av_buffer_unref(&h->ps.pps_ref); - av_buffer_unref(&h->ps.sps_ref); + ret = av_buffer_replace(&h->ps.pps_ref, h1->ps.pps_ref); + if (ret < 0) + return ret; h->ps.pps = NULL; h->ps.sps = NULL; if (h1->ps.pps_ref) { - h->ps.pps_ref = av_buffer_ref(h1->ps.pps_ref); - if (!h->ps.pps_ref) - return AVERROR(ENOMEM); h->ps.pps = (const PPS*)h->ps.pps_ref->data; - } - if (h1->ps.sps_ref) { - h->ps.sps_ref = av_buffer_ref(h1->ps.sps_ref); - if (!h->ps.sps_ref) - return AVERROR(ENOMEM); - h->ps.sps = (const SPS*)h->ps.sps_ref->data; + h->ps.sps = h->ps.pps->sps; } if (need_reinit || !inited) { @@ -430,12 +424,29 @@ int ff_h264_update_thread_context(AVCodecContext *dst, h->frame_recovered = h1->frame_recovered; - av_buffer_unref(&h->sei.a53_caption.buf_ref); - if (h1->sei.a53_caption.buf_ref) { - h->sei.a53_caption.buf_ref = av_buffer_ref(h1->sei.a53_caption.buf_ref); - if (!h->sei.a53_caption.buf_ref) - return AVERROR(ENOMEM); + ret = av_buffer_replace(&h->sei.a53_caption.buf_ref, h1->sei.a53_caption.buf_ref); + if (ret < 0) + return ret; + + for (i = 0; i < h->sei.unregistered.nb_buf_ref; i++) + av_buffer_unref(&h->sei.unregistered.buf_ref[i]); + h->sei.unregistered.nb_buf_ref = 0; + + if (h1->sei.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&h->sei.unregistered.buf_ref, + h1->sei.unregistered.nb_buf_ref, + sizeof(*h->sei.unregistered.buf_ref)); + if (ret < 0) + return ret; + + for (i = 0; i < h1->sei.unregistered.nb_buf_ref; i++) { + h->sei.unregistered.buf_ref[i] = av_buffer_ref(h1->sei.unregistered.buf_ref[i]); + if (!h->sei.unregistered.buf_ref[i]) + return AVERROR(ENOMEM); + h->sei.unregistered.nb_buf_ref++; + } } + h->sei.unregistered.x264_build = h1->sei.unregistered.x264_build; if (!h->cur_pic_ptr) return 0; @@ -453,17 +464,23 @@ int ff_h264_update_thread_context(AVCodecContext *dst, return err; } +int ff_h264_update_thread_context_for_user(AVCodecContext *dst, + const AVCodecContext *src) +{ + H264Context *h = dst->priv_data; + const H264Context *h1 = src->priv_data; + + h->is_avc = h1->is_avc; + h->nal_length_size = h1->nal_length_size; + + return 0; +} + static int h264_frame_start(H264Context *h) { H264Picture *pic; int i, ret; const int pixel_shift = h->pixel_shift; - int c[4] = { - 1<<(h->ps.sps->bit_depth_luma-1), - 1<<(h->ps.sps->bit_depth_chroma-1), - 1<<(h->ps.sps->bit_depth_chroma-1), - -1 - }; if (!ff_thread_can_start_frame(h->avctx)) { av_log(h->avctx, AV_LOG_ERROR, "Attempt to start a frame outside SETUP state\n"); @@ -504,8 +521,6 @@ static int h264_frame_start(H264Context *h) if ((ret = alloc_picture(h, pic)) < 0) return ret; - if(!h->frame_recovered && !h->avctx->hwaccel) - ff_color_frame(pic->f, c); h->cur_pic_ptr = pic; ff_h264_unref_picture(h, &h->cur_pic); @@ -873,7 +888,7 @@ static enum AVPixelFormat get_pixel_format(H264Context *h, int force_callback) } /* export coded and cropped frame dimensions to AVCodecContext */ -static int init_dimensions(H264Context *h) +static void init_dimensions(H264Context *h) { const SPS *sps = (const SPS*)h->ps.sps; int cr = sps->crop_right; @@ -911,8 +926,6 @@ static int init_dimensions(H264Context *h) h->crop_left = cl; h->crop_top = ct; h->crop_bottom = cb; - - return 0; } static int h264_slice_header_init(H264Context *h) @@ -920,6 +933,11 @@ static int h264_slice_header_init(H264Context *h) const SPS *sps = h->ps.sps; int i, ret; + if (!sps) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + ff_set_sar(h->avctx, sps->sar); av_pix_fmt_get_chroma_sub_sample(h->avctx->pix_fmt, &h->chroma_x_shift, &h->chroma_y_shift); @@ -1024,13 +1042,8 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_sl h->ps.pps = (const PPS*)h->ps.pps_ref->data; } - if (h->ps.sps != (const 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->ps.sps != h->ps.pps->sps) { + h->ps.sps = (const SPS*)h->ps.pps->sps; if (h->mb_width != h->ps.sps->mb_width || h->mb_height != h->ps.sps->mb_height || @@ -1077,9 +1090,7 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_sl h->width = 16 * h->mb_width; h->height = 16 * h->mb_height; - ret = init_dimensions(h); - if (ret < 0) - return ret; + init_dimensions(h); if (sps->video_signal_type_present_flag) { h->avctx->color_range = sps->full_range > 0 ? AVCOL_RANGE_JPEG @@ -1092,7 +1103,14 @@ static int h264_init_ps(H264Context *h, const H264SliceContext *sl, int first_sl h->avctx->colorspace = sps->colorspace; } } + + if (h->sei.alternative_transfer.present && + av_color_transfer_name(h->sei.alternative_transfer.preferred_transfer_characteristics) && + h->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { + h->avctx->color_trc = h->sei.alternative_transfer.preferred_transfer_characteristics; + } } + h->avctx->chroma_sample_location = sps->chroma_location; if (!h->context_initialized || must_reinit || needs_reinit) { int flush_changes = h->context_initialized; @@ -1133,13 +1151,24 @@ static int h264_export_frame_props(H264Context *h) { const SPS *sps = h->ps.sps; H264Picture *cur = h->cur_pic_ptr; + AVFrame *out = cur->f; - cur->f->interlaced_frame = 0; - cur->f->repeat_pict = 0; + out->interlaced_frame = 0; + out->repeat_pict = 0; /* Signal interlacing information externally. */ /* Prioritize picture timing SEI information over used * decoding process if it exists. */ + if (h->sei.picture_timing.present) { + int ret = ff_h264_sei_process_picture_timing(&h->sei.picture_timing, sps, + h->avctx); + if (ret < 0) { + av_log(h->avctx, AV_LOG_ERROR, "Error processing a picture timing SEI\n"); + if (h->avctx->err_recognition & AV_EF_EXPLODE) + return ret; + h->sei.picture_timing.present = 0; + } + } if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { H264SEIPictureTiming *pt = &h->sei.picture_timing; @@ -1148,59 +1177,59 @@ static int h264_export_frame_props(H264Context *h) break; case H264_SEI_PIC_STRUCT_TOP_FIELD: case H264_SEI_PIC_STRUCT_BOTTOM_FIELD: - cur->f->interlaced_frame = 1; + out->interlaced_frame = 1; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM: case H264_SEI_PIC_STRUCT_BOTTOM_TOP: if (FIELD_OR_MBAFF_PICTURE(h)) - cur->f->interlaced_frame = 1; + out->interlaced_frame = 1; else // try to flag soft telecine progressive - cur->f->interlaced_frame = h->prev_interlaced_frame; + out->interlaced_frame = h->prev_interlaced_frame; break; case H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP: case H264_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; + out->repeat_pict = 1; break; case H264_SEI_PIC_STRUCT_FRAME_DOUBLING: - cur->f->repeat_pict = 2; + out->repeat_pict = 2; break; case H264_SEI_PIC_STRUCT_FRAME_TRIPLING: - cur->f->repeat_pict = 4; + out->repeat_pict = 4; break; } if ((pt->ct_type & 3) && pt->pic_struct <= H264_SEI_PIC_STRUCT_BOTTOM_TOP) - cur->f->interlaced_frame = (pt->ct_type & (1 << 1)) != 0; + out->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); + out->interlaced_frame = FIELD_OR_MBAFF_PICTURE(h); } - h->prev_interlaced_frame = cur->f->interlaced_frame; + h->prev_interlaced_frame = out->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]; + out->top_field_first = cur->field_poc[0] < cur->field_poc[1]; } else { if (sps->pic_struct_present_flag && h->sei.picture_timing.present) { /* 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 == H264_SEI_PIC_STRUCT_TOP_BOTTOM || h->sei.picture_timing.pic_struct == H264_SEI_PIC_STRUCT_TOP_BOTTOM_TOP) - cur->f->top_field_first = 1; + out->top_field_first = 1; else - cur->f->top_field_first = 0; - } else if (cur->f->interlaced_frame) { + out->top_field_first = 0; + } else if (out->interlaced_frame) { /* Default to top field first when pic_struct_present_flag * is not set but interlaced frame detected */ - cur->f->top_field_first = 1; + out->top_field_first = 1; } else { /* Most likely progressive */ - cur->f->top_field_first = 0; + out->top_field_first = 0; } } @@ -1209,7 +1238,7 @@ static int h264_export_frame_props(H264Context *h) 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); + AVStereo3D *stereo = av_stereo3d_create_side_data(out); if (stereo) { switch (fp->arrangement_type) { case H264_SEI_FPA_TYPE_CHECKERBOARD: @@ -1256,7 +1285,7 @@ static int h264_export_frame_props(H264Context *h) 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, + AVFrameSideData *rotation = av_frame_new_side_data(out, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); if (rotation) { @@ -1267,7 +1296,7 @@ static int h264_export_frame_props(H264Context *h) } if (h->sei.afd.present) { - AVFrameSideData *sd = av_frame_new_side_data(cur->f, AV_FRAME_DATA_AFD, + AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, sizeof(uint8_t)); if (sd) { @@ -1279,7 +1308,7 @@ static int h264_export_frame_props(H264Context *h) if (h->sei.a53_caption.buf_ref) { H264SEIA53Caption *a53 = &h->sei.a53_caption; - AVFrameSideData *sd = av_frame_new_side_data_from_buf(cur->f, AV_FRAME_DATA_A53_CC, a53->buf_ref); + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_A53_CC, a53->buf_ref); if (!sd) av_buffer_unref(&a53->buf_ref); a53->buf_ref = NULL; @@ -1287,11 +1316,25 @@ static int h264_export_frame_props(H264Context *h) h->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; } + for (int i = 0; i < h->sei.unregistered.nb_buf_ref; i++) { + H264SEIUnregistered *unreg = &h->sei.unregistered; + + if (unreg->buf_ref[i]) { + AVFrameSideData *sd = av_frame_new_side_data_from_buf(out, + AV_FRAME_DATA_SEI_UNREGISTERED, + unreg->buf_ref[i]); + if (!sd) + av_buffer_unref(&unreg->buf_ref[i]); + unreg->buf_ref[i] = NULL; + } + } + h->sei.unregistered.nb_buf_ref = 0; + if (h->sei.picture_timing.timecode_cnt > 0) { - uint32_t tc = 0; uint32_t *tc_sd; + char tcbuf[AV_TIMECODE_STR_SIZE]; - AVFrameSideData *tcside = av_frame_new_side_data(cur->f, + AVFrameSideData *tcside = av_frame_new_side_data(out, AV_FRAME_DATA_S12M_TIMECODE, sizeof(uint32_t)*4); if (!tcside) @@ -1301,43 +1344,19 @@ static int h264_export_frame_props(H264Context *h) tc_sd[0] = h->sei.picture_timing.timecode_cnt; for (int i = 0; i < tc_sd[0]; i++) { - uint32_t frames; - - /* For SMPTE 12-M timecodes, frame count is a special case if > 30 FPS. - See SMPTE ST 12-1:2014 Sec 12.1 for more info. */ - if (av_cmp_q(h->avctx->framerate, (AVRational) {30, 1}) == 1) { - frames = h->sei.picture_timing.timecode[i].frame / 2; - if (h->sei.picture_timing.timecode[i].frame % 2 == 1) { - if (av_cmp_q(h->avctx->framerate, (AVRational) {50, 1}) == 0) - tc |= (1 << 7); - else - tc |= (1 << 23); - } - } else { - frames = h->sei.picture_timing.timecode[i].frame; - } - - tc |= h->sei.picture_timing.timecode[i].dropframe << 30; - tc |= (frames / 10) << 28; - tc |= (frames % 10) << 24; - tc |= (h->sei.picture_timing.timecode[i].seconds / 10) << 20; - tc |= (h->sei.picture_timing.timecode[i].seconds % 10) << 16; - tc |= (h->sei.picture_timing.timecode[i].minutes / 10) << 12; - tc |= (h->sei.picture_timing.timecode[i].minutes % 10) << 8; - tc |= (h->sei.picture_timing.timecode[i].hours / 10) << 4; - tc |= (h->sei.picture_timing.timecode[i].hours % 10); + int drop = h->sei.picture_timing.timecode[i].dropframe; + int hh = h->sei.picture_timing.timecode[i].hours; + int mm = h->sei.picture_timing.timecode[i].minutes; + int ss = h->sei.picture_timing.timecode[i].seconds; + int ff = h->sei.picture_timing.timecode[i].frame; - tc_sd[i + 1] = tc; + tc_sd[i + 1] = av_timecode_get_smpte(h->avctx->framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, h->avctx->framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); } h->sei.picture_timing.timecode_cnt = 0; } - if (h->sei.alternative_transfer.present && - av_color_transfer_name(h->sei.alternative_transfer.preferred_transfer_characteristics) && - h->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { - h->avctx->color_trc = cur->f->color_trc = h->sei.alternative_transfer.preferred_transfer_characteristics; - } - return 0; } @@ -1582,6 +1601,13 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, * 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) { + int c[4] = { + 1<<(h->ps.sps->bit_depth_luma-1), + 1<<(h->ps.sps->bit_depth_chroma-1), + 1<<(h->ps.sps->bit_depth_chroma-1), + -1 + }; + if (prev && h->short_ref[0]->f->width == prev->f->width && h->short_ref[0]->f->height == prev->f->height && @@ -1589,15 +1615,17 @@ static int h264_field_start(H264Context *h, const H264SliceContext *sl, ff_thread_await_progress(&prev->tf, INT_MAX, 0); if (prev->field_picture) ff_thread_await_progress(&prev->tf, INT_MAX, 1); - 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, - prev->f->width, - prev->f->height); - h->short_ref[0]->poc = prev->poc + 2; - } + ff_thread_release_buffer(h->avctx, &h->short_ref[0]->tf); + h->short_ref[0]->tf.f = h->short_ref[0]->f; + ret = ff_thread_ref_frame(&h->short_ref[0]->tf, &prev->tf); + if (ret < 0) + return ret; + h->short_ref[0]->poc = prev->poc + 2U; + ff_thread_report_progress(&h->short_ref[0]->tf, INT_MAX, 0); + if (h->short_ref[0]->field_picture) + ff_thread_report_progress(&h->short_ref[0]->tf, INT_MAX, 1); + } else if (!h->frame_recovered && !h->avctx->hwaccel) + ff_color_frame(h->short_ref[0]->f, c); h->short_ref[0]->frame_num = h->poc.prev_frame_num; } } @@ -1773,13 +1801,7 @@ static int h264_slice_header_parse(const H264Context *h, H264SliceContext *sl, return AVERROR_INVALIDDATA; } 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); - return AVERROR_INVALIDDATA; - } - sps = (const SPS*)h->ps.sps_list[pps->sps_id]->data; + sps = pps->sps; sl->frame_num = get_bits(&sl->gb, sps->log2_max_frame_num); if (!first_slice) { @@ -2165,7 +2187,7 @@ int ff_h264_queue_decode_slice(H264Context *h, const H2645NAL *nal) 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 (h->ps.sps != pps->sps) { av_log(h->avctx, AV_LOG_ERROR, "SPS changed in the middle of the frame\n"); return AVERROR_INVALIDDATA; @@ -2621,7 +2643,6 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) ff_h264_init_cabac_states(h, sl); for (;;) { - // START_TIMER int ret, eos; 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", @@ -2632,7 +2653,6 @@ static int decode_slice(struct AVCodecContext *avctx, void *arg) } ret = ff_h264_decode_mb_cabac(h, sl); - // STOP_TIMER("decode_mb_cabac") if (ret >= 0) ff_h264_hl_decode_mb(h, sl);