X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fhevcdec.c;h=b2e196b2946738be2da3870b23cea5da0d40ae8a;hb=daf8b10eeb9c789cad5c2c263493249950c6f55f;hp=18395ce8335c47e9dff2eee78e14fe07c7278c2d;hpb=d2d8e797cc4f3cea3470d464bd5f51cd097fe371;p=ffmpeg diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 18395ce8335..b2e196b2946 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -32,6 +32,7 @@ #include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #include "bswapdsp.h" #include "bytestream.h" @@ -41,7 +42,7 @@ #include "hevc_data.h" #include "hevc_parse.h" #include "hevcdec.h" -#include "hwaccel.h" +#include "hwconfig.h" #include "profiles.h" const uint8_t ff_hevc_pel_weight[65] = { [2] = 0, [4] = 1, [6] = 2, [8] = 3, [12] = 4, [16] = 5, [24] = 6, [32] = 7, [48] = 8, [64] = 9 }; @@ -280,7 +281,6 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) rps->nb_refs = nb_sh + nb_sps; for (i = 0; i < rps->nb_refs; i++) { - uint8_t delta_poc_msb_present; if (i < nb_sps) { uint8_t lt_idx_sps = 0; @@ -295,8 +295,8 @@ static int decode_lt_rps(HEVCContext *s, LongTermRPS *rps, GetBitContext *gb) rps->used[i] = get_bits1(gb); } - delta_poc_msb_present = get_bits1(gb); - if (delta_poc_msb_present) { + rps->poc_msb_present[i] = get_bits1(gb); + if (rps->poc_msb_present[i]) { int64_t delta = get_ue_golomb_long(gb); int64_t poc; @@ -349,6 +349,15 @@ static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) avctx->colorspace = AVCOL_SPC_UNSPECIFIED; } + avctx->chroma_sample_location = AVCHROMA_LOC_UNSPECIFIED; + if (sps->chroma_format_idc == 1) { + if (sps->vui.chroma_loc_info_present_flag) { + if (sps->vui.chroma_sample_loc_type_top_field <= 5) + avctx->chroma_sample_location = sps->vui.chroma_sample_loc_type_top_field + 1; + } else + avctx->chroma_sample_location = AVCHROMA_LOC_LEFT; + } + if (vps->vps_timing_info_present_flag) { num = vps->vps_num_units_in_tick; den = vps->vps_time_scale; @@ -360,12 +369,22 @@ static void export_stream_params(HEVCContext *s, const HEVCSPS *sps) if (num != 0 && den != 0) av_reduce(&avctx->framerate.den, &avctx->framerate.num, num, den, 1 << 30); +} + +static int export_stream_params_from_sei(HEVCContext *s) +{ + AVCodecContext *avctx = s->avctx; + + if (s->sei.a53_caption.buf_ref) + s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; if (s->sei.alternative_transfer.present && av_color_transfer_name(s->sei.alternative_transfer.preferred_transfer_characteristics) && s->sei.alternative_transfer.preferred_transfer_characteristics != AVCOL_TRC_UNSPECIFIED) { avctx->color_trc = s->sei.alternative_transfer.preferred_transfer_characteristics; } + + return 0; } static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) @@ -415,6 +434,9 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #if CONFIG_HEVC_VIDEOTOOLBOX_HWACCEL *fmt++ = AV_PIX_FMT_VIDEOTOOLBOX; #endif +#if CONFIG_HEVC_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -425,11 +447,20 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps) #endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; +#endif + break; + case AV_PIX_FMT_YUV422P: + case AV_PIX_FMT_YUV422P10LE: +#if CONFIG_HEVC_VAAPI_HWACCEL + *fmt++ = AV_PIX_FMT_VAAPI; #endif break; case AV_PIX_FMT_YUV420P12: case AV_PIX_FMT_YUV444P10: case AV_PIX_FMT_YUV444P12: +#if CONFIG_HEVC_VDPAU_HWACCEL + *fmt++ = AV_PIX_FMT_VDPAU; +#endif #if CONFIG_HEVC_NVDEC_HWACCEL *fmt++ = AV_PIX_FMT_CUDA; #endif @@ -561,6 +592,10 @@ static int hls_slice_header(HEVCContext *s) s->max_ra = INT_MAX; } + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + sh->dependent_slice_segment_flag = 0; if (!sh->first_slice_in_pic_flag) { int slice_address_length; @@ -780,6 +815,11 @@ static int hls_slice_header(HEVCContext *s) if (s->ps.pps->pic_slice_level_chroma_qp_offsets_present_flag) { sh->slice_cb_qp_offset = get_se_golomb(gb); sh->slice_cr_qp_offset = get_se_golomb(gb); + if (sh->slice_cb_qp_offset < -12 || sh->slice_cb_qp_offset > 12 || + sh->slice_cr_qp_offset < -12 || sh->slice_cr_qp_offset > 12) { + av_log(s->avctx, AV_LOG_ERROR, "Invalid slice cx qp offset.\n"); + return AVERROR_INVALIDDATA; + } } else { sh->slice_cb_qp_offset = 0; sh->slice_cr_qp_offset = 0; @@ -2778,15 +2818,64 @@ static int set_side_data(HEVCContext *s) metadata->MaxCLL, metadata->MaxFALL); } - if (s->sei.a53_caption.a53_caption) { - AVFrameSideData* sd = av_frame_new_side_data(out, - AV_FRAME_DATA_A53_CC, - s->sei.a53_caption.a53_caption_size); - if (sd) - memcpy(sd->data, s->sei.a53_caption.a53_caption, s->sei.a53_caption.a53_caption_size); - av_freep(&s->sei.a53_caption.a53_caption); - s->sei.a53_caption.a53_caption_size = 0; - s->avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + if (s->sei.a53_caption.buf_ref) { + HEVCSEIA53Caption *a53 = &s->sei.a53_caption; + + 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; + } + + for (int i = 0; i < s->sei.unregistered.nb_buf_ref; i++) { + HEVCSEIUnregistered *unreg = &s->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; + } + } + s->sei.unregistered.nb_buf_ref = 0; + + if (s->sei.timecode.present) { + uint32_t *tc_sd; + char tcbuf[AV_TIMECODE_STR_SIZE]; + AVFrameSideData *tcside = av_frame_new_side_data(out, AV_FRAME_DATA_S12M_TIMECODE, + sizeof(uint32_t) * 4); + if (!tcside) + return AVERROR(ENOMEM); + + tc_sd = (uint32_t*)tcside->data; + tc_sd[0] = s->sei.timecode.num_clock_ts; + + for (int i = 0; i < tc_sd[0]; i++) { + int drop = s->sei.timecode.cnt_dropped_flag[i]; + int hh = s->sei.timecode.hours_value[i]; + int mm = s->sei.timecode.minutes_value[i]; + int ss = s->sei.timecode.seconds_value[i]; + int ff = s->sei.timecode.n_frames[i]; + + tc_sd[i + 1] = av_timecode_get_smpte(s->avctx->framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, s->avctx->framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); + } + + s->sei.timecode.num_clock_ts = 0; + } + + if (s->sei.dynamic_hdr_plus.info) { + AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_plus.info); + if (!info_ref) + return AVERROR(ENOMEM); + + if (!av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DYNAMIC_HDR_PLUS, info_ref)) { + av_buffer_unref(&info_ref); + return AVERROR(ENOMEM); + } } return 0; @@ -3077,7 +3166,7 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) if (s->avctx->skip_frame >= AVDISCARD_ALL || (s->avctx->skip_frame >= AVDISCARD_NONREF - && ff_hevc_nal_is_nonref(nal->type))) + && ff_hevc_nal_is_nonref(nal->type)) || nal->nuh_layer_id > 0) continue; ret = decode_nal_unit(s, nal); @@ -3189,6 +3278,11 @@ static int hevc_decode_extradata(HEVCContext *s, uint8_t *buf, int length, int f } } + /* export stream parameters from SEI */ + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + return 0; } @@ -3336,6 +3430,8 @@ static av_cold int hevc_decode_free(AVCodecContext *avctx) ff_h2645_packet_uninit(&s->pkt); + ff_hevc_reset_sei(&s->sei); + return 0; } @@ -3413,30 +3509,21 @@ static int hevc_update_thread_context(AVCodecContext *dst, if (s->ps.sps != s0->ps.sps) s->ps.sps = NULL; for (i = 0; i < FF_ARRAY_ELEMS(s->ps.vps_list); i++) { - av_buffer_unref(&s->ps.vps_list[i]); - if (s0->ps.vps_list[i]) { - s->ps.vps_list[i] = av_buffer_ref(s0->ps.vps_list[i]); - if (!s->ps.vps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.vps_list[i], s0->ps.vps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(s->ps.sps_list); i++) { - av_buffer_unref(&s->ps.sps_list[i]); - if (s0->ps.sps_list[i]) { - s->ps.sps_list[i] = av_buffer_ref(s0->ps.sps_list[i]); - if (!s->ps.sps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.sps_list[i], s0->ps.sps_list[i]); + if (ret < 0) + return ret; } for (i = 0; i < FF_ARRAY_ELEMS(s->ps.pps_list); i++) { - av_buffer_unref(&s->ps.pps_list[i]); - if (s0->ps.pps_list[i]) { - s->ps.pps_list[i] = av_buffer_ref(s0->ps.pps_list[i]); - if (!s->ps.pps_list[i]) - return AVERROR(ENOMEM); - } + ret = av_buffer_replace(&s->ps.pps_list[i], s0->ps.pps_list[i]); + if (ret < 0) + return ret; } if (s->ps.sps != s0->ps.sps) @@ -3461,12 +3548,43 @@ static int hevc_update_thread_context(AVCodecContext *dst, s->max_ra = INT_MAX; } + ret = av_buffer_replace(&s->sei.a53_caption.buf_ref, s0->sei.a53_caption.buf_ref); + if (ret < 0) + return ret; + + for (i = 0; i < s->sei.unregistered.nb_buf_ref; i++) + av_buffer_unref(&s->sei.unregistered.buf_ref[i]); + s->sei.unregistered.nb_buf_ref = 0; + + if (s0->sei.unregistered.nb_buf_ref) { + ret = av_reallocp_array(&s->sei.unregistered.buf_ref, + s0->sei.unregistered.nb_buf_ref, + sizeof(*s->sei.unregistered.buf_ref)); + if (ret < 0) + return ret; + + for (i = 0; i < s0->sei.unregistered.nb_buf_ref; i++) { + s->sei.unregistered.buf_ref[i] = av_buffer_ref(s0->sei.unregistered.buf_ref[i]); + if (!s->sei.unregistered.buf_ref[i]) + return AVERROR(ENOMEM); + s->sei.unregistered.nb_buf_ref++; + } + } + + ret = av_buffer_replace(&s->sei.dynamic_hdr_plus.info, s0->sei.dynamic_hdr_plus.info); + if (ret < 0) + return ret; + s->sei.frame_packing = s0->sei.frame_packing; s->sei.display_orientation = s0->sei.display_orientation; s->sei.mastering_display = s0->sei.mastering_display; s->sei.content_light = s0->sei.content_light; s->sei.alternative_transfer = s0->sei.alternative_transfer; + ret = export_stream_params_from_sei(s); + if (ret < 0) + return ret; + return 0; } #endif @@ -3476,8 +3594,6 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) HEVCContext *s = avctx->priv_data; int ret; - avctx->internal->allocate_progress = 1; - ret = hevc_init_context(avctx); if (ret < 0) return ret; @@ -3493,11 +3609,13 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) else s->threads_number = 1; - if (avctx->extradata_size > 0 && avctx->extradata) { - ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1); - if (ret < 0) { - hevc_decode_free(avctx); - return ret; + if (!avctx->internal->is_copy) { + if (avctx->extradata_size > 0 && avctx->extradata) { + ret = hevc_decode_extradata(s, avctx->extradata, avctx->extradata_size, 1); + if (ret < 0) { + hevc_decode_free(avctx); + return ret; + } } } @@ -3509,26 +3627,11 @@ static av_cold int hevc_decode_init(AVCodecContext *avctx) return 0; } -#if HAVE_THREADS -static av_cold int hevc_init_thread_copy(AVCodecContext *avctx) -{ - HEVCContext *s = avctx->priv_data; - int ret; - - memset(s, 0, sizeof(*s)); - - ret = hevc_init_context(avctx); - if (ret < 0) - return ret; - - return 0; -} -#endif - static void hevc_decode_flush(AVCodecContext *avctx) { HEVCContext *s = avctx->priv_data; ff_hevc_flush_dpb(s); + ff_hevc_reset_sei(&s->sei); s->max_ra = INT_MAX; s->eos = 1; } @@ -3563,10 +3666,10 @@ AVCodec ff_hevc_decoder = { .decode = hevc_decode_frame, .flush = hevc_decode_flush, .update_thread_context = ONLY_IF_THREADS_ENABLED(hevc_update_thread_context), - .init_thread_copy = ONLY_IF_THREADS_ENABLED(hevc_init_thread_copy), .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS, - .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING, + .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | FF_CODEC_CAP_EXPORTS_CROPPING | + FF_CODEC_CAP_ALLOCATE_PROGRESS, .profiles = NULL_IF_CONFIG_SMALL(ff_hevc_profiles), .hw_configs = (const AVCodecHWConfigInternal*[]) { #if CONFIG_HEVC_DXVA2_HWACCEL