From patchwork Tue Oct 25 04:03:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aman Karmani X-Patchwork-Id: 38972 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp2579509pzb; Mon, 24 Oct 2022 21:03:59 -0700 (PDT) X-Google-Smtp-Source: AMsMyM5O++EpJu+TvpIItkXhMT0RCUyjKAk0doNZ4OhuvDH9Vogt43dFoq2sSvtlGRAW+FHJ6vOY X-Received: by 2002:a05:6402:d0b:b0:458:a244:4e99 with SMTP id eb11-20020a0564020d0b00b00458a2444e99mr33905525edb.46.1666670638925; Mon, 24 Oct 2022 21:03:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666670638; cv=none; d=google.com; s=arc-20160816; b=a3XclFb038UChzzIOYMRjmXzlGebTjx0KDpftoalCUcRdbPf6IPNSXQBjPWlxk4bud 23BxnU4qwUE92hjUVm9VcGxYs95ZNk4EobN/e2yxiGaQMSurBOvmFXm6Am4Khm8nezy+ TpaYM5hIJeYsTqVEoI0z438VLOLWC+shv5MDrIOUrbqW405TmoveK0PrxWq3YdeFjnGv hwjK+ebuXLbAoQgTvV1TnGZwGXgmFxvJok03a8elbdxdp0boZkE/iVQkdw615Guj0vIL ILsy2fxdXIuA5zonhCP+imrsDRRNWEtOC3knTJne7L74jMu9iURh1MSp3ptZSIiel1KC 3D3A== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:to:mime-version:fcc:date:references :in-reply-to:message-id:from:dkim-signature:delivered-to; bh=wkbEgooUfxo5V6xDZ2NZXFK0vXtioLChTFjxtWTpy4I=; b=KYUe3xF7x/8+dqkbXmxL4rwI3DImPwxLJHxpPjkgaBzo6uEcP/9f/t2Tv32nFR8sRA 243LobgJqRnaJHw9yLaAg3iUUOU08IDR+iToX1k2UP9j4z8sLj/cn7bNNjyxUezAKKHq 6Q5bZZrGzj4J0YS64yV4fmKuaEjp5B2STfxsw/YyGfw6dkwZ/FZPfD6oSjX9Lt0KNYm9 fqNZiLkNwNt4CnQgI/jKVLtLWQXbyBADySvGRs14N3tUn4OTqr8Ba2Wzm1uwwFr28Bh4 tVR4yBuJH+Rn2nkV8TZ4dKMn62rzyMsMQDHoU2jKs/amdw3N1Zj8juny/p3rO+xO/dbx ynjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=mfA23HZn; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id fy9-20020a170906b7c900b0078b88453306si1453192ejb.285.2022.10.24.21.03.57; Mon, 24 Oct 2022 21:03:58 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=mfA23HZn; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id AAA7968BB4C; Tue, 25 Oct 2022 07:03:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf1-f175.google.com (mail-pf1-f175.google.com [209.85.210.175]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6AC1C68B965 for ; Tue, 25 Oct 2022 07:03:41 +0300 (EEST) Received: by mail-pf1-f175.google.com with SMTP id g62so6740876pfb.10; Mon, 24 Oct 2022 21:03:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date :references:in-reply-to:message-id:from:from:to:cc:subject:date :message-id:reply-to; bh=/Pmg/iOWuzHDLbSYwDqSMa10lemIUrsYRBJficJKUdg=; b=mfA23HZnDfZtpx5c7s97v4d/ePD5LbGm2e6xZQPIA7SQpgEPlSAbtCay377sRkWwc5 kbAP3Y5E15N0V78W/gBpjfPthvGQRh2ur7sGqygw/YPWfir/g5VWGjMhiv3vk3vz/UAz sNvnqZy0xuSjew39qTLriA2PC8NyDHA1QQUcbS9O5/YWob73yPFIkDzU5LJfTeRlKpN2 AuJOWYgwSdTYo0uQOUyjTq4TulNcjj374as+x6oKzQgctlzZGCSTQd1osW7juaonJuZ9 T+40y4Y89t/duGjHOOvpUVmSHXUNsG66nt2B5wmAJsoW1b9eR8OytVfGobBNlH5hAxKk M2iA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:mime-version:content-transfer-encoding:fcc:subject:date :references:in-reply-to:message-id:from:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=/Pmg/iOWuzHDLbSYwDqSMa10lemIUrsYRBJficJKUdg=; b=SyQhe5PaJBujxJaKjOAP+RHhyrjCQUTS+Q1LegNQfjVwo6xU/QLkU5ddaLyqEopDse VXgkHgizJPL0LK8aYLz3eDQrzpYOsKH/bB3UZSiK6I3v0j+Usz+Qqd6EVZ/3fMve6ser UWRvkTLo2StM7u8SCzzmabSYAsbW+Wo3FWq+ZiISvcBu15GXWAX2pLABfwmpmx+hLclz c0FiuwG/BnURftP8fx6zvP6nGxH4P9w6OHc4RqLFB+uIWycscsZR8osqkIX9VYjcQdXn gcGfDRgRnoJPVDCmru1/TC1QLJCvK6UJvfmE40W83F/mJ6NsUtqHTwYOzc+OPVd5OwJa xe7A== X-Gm-Message-State: ACrzQf1LseKBh2lfpPbQg+aLhtmtgXsySrckSIf+pcuFOqaxa5H9HV5V N3v7e0LiMrX4xsevuvgP6D6m7xpYDno= X-Received: by 2002:a63:3141:0:b0:46f:18bf:c043 with SMTP id x62-20020a633141000000b0046f18bfc043mr5047494pgx.613.1666670619139; Mon, 24 Oct 2022 21:03:39 -0700 (PDT) Received: from [127.0.0.1] (master.gitmailbox.com. [34.83.118.50]) by smtp.gmail.com with ESMTPSA id n66-20020a622745000000b0056bf878eeccsm536287pfn.47.2022.10.24.21.03.38 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Oct 2022 21:03:38 -0700 (PDT) From: softworkz X-Google-Original-From: softworkz Message-Id: <4e9adcd90a283aa16df84d945759bd96e22d8005.1666670616.git.ffmpegagent@gmail.com> In-Reply-To: References: Date: Tue, 25 Oct 2022 04:03:34 +0000 Fcc: Sent MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH v6 1/3] avcodec/hevcdec: factor out ff_hevc_set_set_to_frame X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Kieran Kunhya , softworkz , "Xiang, Haihao" , Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: MzDJt13Uz8I4 From: softworkz Signed-off-by: softworkz --- libavcodec/hevc_sei.c | 252 ++++++++++++++++++++++++++++++++++++++++++ libavcodec/hevc_sei.h | 3 + libavcodec/hevcdec.c | 249 +---------------------------------------- 3 files changed, 260 insertions(+), 244 deletions(-) diff --git a/libavcodec/hevc_sei.c b/libavcodec/hevc_sei.c index 631373e06f..6fd066e44f 100644 --- a/libavcodec/hevc_sei.c +++ b/libavcodec/hevc_sei.c @@ -30,6 +30,12 @@ #include "hevc_ps.h" #include "hevc_sei.h" +#include "libavutil/display.h" +#include "libavutil/film_grain_params.h" +#include "libavutil/mastering_display_metadata.h" +#include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" + static int decode_nal_sei_decoded_picture_hash(HEVCSEIPictureHash *s, GetByteContext *gb) { @@ -578,3 +584,249 @@ void ff_hevc_reset_sei(HEVCSEI *s) av_buffer_unref(&s->dynamic_hdr_plus.info); av_buffer_unref(&s->dynamic_hdr_vivid.info); } + +int ff_hevc_set_sei_to_frame(AVCodecContext *logctx, HEVCSEI *sei, AVFrame *out, AVRational framerate, uint64_t seed, const VUI *vui, int bit_depth_luma, int bit_depth_chroma) +{ + if (sei->frame_packing.present && + sei->frame_packing.arrangement_type >= 3 && + sei->frame_packing.arrangement_type <= 5 && + sei->frame_packing.content_interpretation_type > 0 && + sei->frame_packing.content_interpretation_type < 3) { + AVStereo3D *stereo = av_stereo3d_create_side_data(out); + if (!stereo) + return AVERROR(ENOMEM); + + switch (sei->frame_packing.arrangement_type) { + case 3: + if (sei->frame_packing.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; + } + + if (sei->frame_packing.content_interpretation_type == 2) + stereo->flags = AV_STEREO3D_FLAG_INVERT; + + if (sei->frame_packing.arrangement_type == 5) { + if (sei->frame_packing.current_frame_is_frame0_flag) + stereo->view = AV_STEREO3D_VIEW_LEFT; + else + stereo->view = AV_STEREO3D_VIEW_RIGHT; + } + } + + if (sei->display_orientation.present && + (sei->display_orientation.anticlockwise_rotation || + sei->display_orientation.hflip || sei->display_orientation.vflip)) { + double angle = sei->display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); + AVFrameSideData *rotation = av_frame_new_side_data(out, + AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (!rotation) + return AVERROR(ENOMEM); + + /* av_display_rotation_set() expects the angle in the clockwise + * direction, hence the first minus. + * The below code applies the flips after the rotation, yet + * the H.2645 specs require flipping to be applied first. + * Because of R O(phi) = O(-phi) R (where R is flipping around + * an arbitatry axis and O(phi) is the proper rotation by phi) + * we can create display matrices as desired by negating + * the degree once for every flip applied. */ + angle = -angle * (1 - 2 * !!sei->display_orientation.hflip) + * (1 - 2 * !!sei->display_orientation.vflip); + av_display_rotation_set((int32_t *)rotation->data, angle); + av_display_matrix_flip((int32_t *)rotation->data, + sei->display_orientation.hflip, + sei->display_orientation.vflip); + } + + if (sei->mastering_display.present) { + // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b + const int mapping[3] = {2, 0, 1}; + const int chroma_den = 50000; + const int luma_den = 10000; + int i; + AVMasteringDisplayMetadata *metadata = + av_mastering_display_metadata_create_side_data(out); + if (!metadata) + return AVERROR(ENOMEM); + + for (i = 0; i < 3; i++) { + const int j = mapping[i]; + metadata->display_primaries[i][0].num = sei->mastering_display.display_primaries[j][0]; + metadata->display_primaries[i][0].den = chroma_den; + metadata->display_primaries[i][1].num = sei->mastering_display.display_primaries[j][1]; + metadata->display_primaries[i][1].den = chroma_den; + } + metadata->white_point[0].num = sei->mastering_display.white_point[0]; + metadata->white_point[0].den = chroma_den; + metadata->white_point[1].num = sei->mastering_display.white_point[1]; + metadata->white_point[1].den = chroma_den; + + metadata->max_luminance.num = sei->mastering_display.max_luminance; + metadata->max_luminance.den = luma_den; + metadata->min_luminance.num = sei->mastering_display.min_luminance; + metadata->min_luminance.den = luma_den; + metadata->has_luminance = 1; + metadata->has_primaries = 1; + + av_log(logctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); + av_log(logctx, AV_LOG_DEBUG, + "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", + av_q2d(metadata->display_primaries[0][0]), + av_q2d(metadata->display_primaries[0][1]), + av_q2d(metadata->display_primaries[1][0]), + av_q2d(metadata->display_primaries[1][1]), + av_q2d(metadata->display_primaries[2][0]), + av_q2d(metadata->display_primaries[2][1]), + av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); + av_log(logctx, AV_LOG_DEBUG, + "min_luminance=%f, max_luminance=%f\n", + av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); + } + if (sei->content_light.present) { + AVContentLightMetadata *metadata = + av_content_light_metadata_create_side_data(out); + if (!metadata) + return AVERROR(ENOMEM); + metadata->MaxCLL = sei->content_light.max_content_light_level; + metadata->MaxFALL = sei->content_light.max_pic_average_light_level; + + av_log(logctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); + av_log(logctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", + metadata->MaxCLL, metadata->MaxFALL); + } + + if (sei->a53_caption.buf_ref) { + HEVCSEIA53Caption *a53 = &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 < sei->unregistered.nb_buf_ref; i++) { + HEVCSEIUnregistered *unreg = &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; + } + } + sei->unregistered.nb_buf_ref = 0; + + if (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] = sei->timecode.num_clock_ts; + + for (int i = 0; i < tc_sd[0]; i++) { + int drop = sei->timecode.cnt_dropped_flag[i]; + int hh = sei->timecode.hours_value[i]; + int mm = sei->timecode.minutes_value[i]; + int ss = sei->timecode.seconds_value[i]; + int ff = sei->timecode.n_frames[i]; + + tc_sd[i + 1] = av_timecode_get_smpte(framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); + } + + sei->timecode.num_clock_ts = 0; + } + + if (sei->film_grain_characteristics.present) { + HEVCSEIFilmGrainCharacteristics *fgc = &sei->film_grain_characteristics; + AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(out); + if (!fgp) + return AVERROR(ENOMEM); + + fgp->type = AV_FILM_GRAIN_PARAMS_H274; + fgp->seed = seed; /* no poc_offset in HEVC */ + fgp->codec.h274.model_id = fgc->model_id; + if (fgc->separate_colour_description_present_flag) { + fgp->codec.h274.bit_depth_luma = fgc->bit_depth_luma; + fgp->codec.h274.bit_depth_chroma = fgc->bit_depth_chroma; + fgp->codec.h274.color_range = fgc->full_range + 1; + fgp->codec.h274.color_primaries = fgc->color_primaries; + fgp->codec.h274.color_trc = fgc->transfer_characteristics; + fgp->codec.h274.color_space = fgc->matrix_coeffs; + } else { + fgp->codec.h274.bit_depth_luma = bit_depth_luma; + fgp->codec.h274.bit_depth_chroma = bit_depth_chroma; + if (vui->video_signal_type_present_flag) + fgp->codec.h274.color_range = vui->video_full_range_flag + 1; + else + fgp->codec.h274.color_range = AVCOL_RANGE_UNSPECIFIED; + if (vui->colour_description_present_flag) { + fgp->codec.h274.color_primaries = vui->colour_primaries; + fgp->codec.h274.color_trc = vui->transfer_characteristic; + fgp->codec.h274.color_space = vui->matrix_coeffs; + } else { + fgp->codec.h274.color_primaries = AVCOL_PRI_UNSPECIFIED; + fgp->codec.h274.color_trc = AVCOL_TRC_UNSPECIFIED; + fgp->codec.h274.color_space = AVCOL_SPC_UNSPECIFIED; + } + } + fgp->codec.h274.blending_mode_id = fgc->blending_mode_id; + fgp->codec.h274.log2_scale_factor = fgc->log2_scale_factor; + + memcpy(&fgp->codec.h274.component_model_present, &fgc->comp_model_present_flag, + sizeof(fgp->codec.h274.component_model_present)); + memcpy(&fgp->codec.h274.num_intensity_intervals, &fgc->num_intensity_intervals, + sizeof(fgp->codec.h274.num_intensity_intervals)); + memcpy(&fgp->codec.h274.num_model_values, &fgc->num_model_values, + sizeof(fgp->codec.h274.num_model_values)); + memcpy(&fgp->codec.h274.intensity_interval_lower_bound, &fgc->intensity_interval_lower_bound, + sizeof(fgp->codec.h274.intensity_interval_lower_bound)); + memcpy(&fgp->codec.h274.intensity_interval_upper_bound, &fgc->intensity_interval_upper_bound, + sizeof(fgp->codec.h274.intensity_interval_upper_bound)); + memcpy(&fgp->codec.h274.comp_model_value, &fgc->comp_model_value, + sizeof(fgp->codec.h274.comp_model_value)); + + fgc->present = fgc->persistence_flag; + } + + if (sei->dynamic_hdr_plus.info) { + AVBufferRef *info_ref = av_buffer_ref(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); + } + } + + if (sei->dynamic_hdr_vivid.info) { + AVBufferRef *info_ref = av_buffer_ref(sei->dynamic_hdr_vivid.info); + if (!info_ref) + return AVERROR(ENOMEM); + + if (!av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DYNAMIC_HDR_VIVID, info_ref)) { + av_buffer_unref(&info_ref); + return AVERROR(ENOMEM); + } + } + + return 0; +} diff --git a/libavcodec/hevc_sei.h b/libavcodec/hevc_sei.h index ef987f6781..9bb5c9e62f 100644 --- a/libavcodec/hevc_sei.h +++ b/libavcodec/hevc_sei.h @@ -27,6 +27,7 @@ #include "get_bits.h" #include "hevc.h" +#include "hevc_ps.h" #include "sei.h" @@ -166,4 +167,6 @@ int ff_hevc_decode_nal_sei(GetBitContext *gb, void *logctx, HEVCSEI *s, */ void ff_hevc_reset_sei(HEVCSEI *s); +int ff_hevc_set_sei_to_frame(AVCodecContext *logctx, HEVCSEI *sei, AVFrame *out, AVRational framerate, uint64_t seed, const VUI *vui, int bit_depth_luma, int bit_depth_chroma); + #endif /* AVCODEC_HEVC_SEI_H */ diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index fb44d8d3f2..6e24df37ab 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2725,67 +2725,7 @@ static int set_side_data(HEVCContext *s) { AVFrame *out = s->ref->frame; int ret; - - if (s->sei.frame_packing.present && - s->sei.frame_packing.arrangement_type >= 3 && - s->sei.frame_packing.arrangement_type <= 5 && - s->sei.frame_packing.content_interpretation_type > 0 && - s->sei.frame_packing.content_interpretation_type < 3) { - AVStereo3D *stereo = av_stereo3d_create_side_data(out); - if (!stereo) - return AVERROR(ENOMEM); - - switch (s->sei.frame_packing.arrangement_type) { - case 3: - if (s->sei.frame_packing.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; - } - - if (s->sei.frame_packing.content_interpretation_type == 2) - stereo->flags = AV_STEREO3D_FLAG_INVERT; - - if (s->sei.frame_packing.arrangement_type == 5) { - if (s->sei.frame_packing.current_frame_is_frame0_flag) - stereo->view = AV_STEREO3D_VIEW_LEFT; - else - stereo->view = AV_STEREO3D_VIEW_RIGHT; - } - } - - if (s->sei.display_orientation.present && - (s->sei.display_orientation.anticlockwise_rotation || - s->sei.display_orientation.hflip || s->sei.display_orientation.vflip)) { - double angle = s->sei.display_orientation.anticlockwise_rotation * 360 / (double) (1 << 16); - AVFrameSideData *rotation = av_frame_new_side_data(out, - AV_FRAME_DATA_DISPLAYMATRIX, - sizeof(int32_t) * 9); - if (!rotation) - return AVERROR(ENOMEM); - - /* av_display_rotation_set() expects the angle in the clockwise - * direction, hence the first minus. - * The below code applies the flips after the rotation, yet - * the H.2645 specs require flipping to be applied first. - * Because of R O(phi) = O(-phi) R (where R is flipping around - * an arbitatry axis and O(phi) is the proper rotation by phi) - * we can create display matrices as desired by negating - * the degree once for every flip applied. */ - angle = -angle * (1 - 2 * !!s->sei.display_orientation.hflip) - * (1 - 2 * !!s->sei.display_orientation.vflip); - av_display_rotation_set((int32_t *)rotation->data, angle); - av_display_matrix_flip((int32_t *)rotation->data, - s->sei.display_orientation.hflip, - s->sei.display_orientation.vflip); - } + const HEVCSPS *sps = s->ps.sps; // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 // so the side data persists for the entire coded video sequence. @@ -2793,185 +2733,17 @@ static int set_side_data(HEVCContext *s) IS_IRAP(s) && s->no_rasl_output_flag) { s->sei.mastering_display.present--; } - if (s->sei.mastering_display.present) { - // HEVC uses a g,b,r ordering, which we convert to a more natural r,g,b - const int mapping[3] = {2, 0, 1}; - const int chroma_den = 50000; - const int luma_den = 10000; - int i; - AVMasteringDisplayMetadata *metadata = - av_mastering_display_metadata_create_side_data(out); - if (!metadata) - return AVERROR(ENOMEM); - - for (i = 0; i < 3; i++) { - const int j = mapping[i]; - metadata->display_primaries[i][0].num = s->sei.mastering_display.display_primaries[j][0]; - metadata->display_primaries[i][0].den = chroma_den; - metadata->display_primaries[i][1].num = s->sei.mastering_display.display_primaries[j][1]; - metadata->display_primaries[i][1].den = chroma_den; - } - metadata->white_point[0].num = s->sei.mastering_display.white_point[0]; - metadata->white_point[0].den = chroma_den; - metadata->white_point[1].num = s->sei.mastering_display.white_point[1]; - metadata->white_point[1].den = chroma_den; - - metadata->max_luminance.num = s->sei.mastering_display.max_luminance; - metadata->max_luminance.den = luma_den; - metadata->min_luminance.num = s->sei.mastering_display.min_luminance; - metadata->min_luminance.den = luma_den; - metadata->has_luminance = 1; - metadata->has_primaries = 1; - - av_log(s->avctx, AV_LOG_DEBUG, "Mastering Display Metadata:\n"); - av_log(s->avctx, AV_LOG_DEBUG, - "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f)\n", - av_q2d(metadata->display_primaries[0][0]), - av_q2d(metadata->display_primaries[0][1]), - av_q2d(metadata->display_primaries[1][0]), - av_q2d(metadata->display_primaries[1][1]), - av_q2d(metadata->display_primaries[2][0]), - av_q2d(metadata->display_primaries[2][1]), - av_q2d(metadata->white_point[0]), av_q2d(metadata->white_point[1])); - av_log(s->avctx, AV_LOG_DEBUG, - "min_luminance=%f, max_luminance=%f\n", - av_q2d(metadata->min_luminance), av_q2d(metadata->max_luminance)); - } // Decrement the mastering display flag when IRAP frame has no_rasl_output_flag=1 // so the side data persists for the entire coded video sequence. if (s->sei.content_light.present > 0 && IS_IRAP(s) && s->no_rasl_output_flag) { s->sei.content_light.present--; } - if (s->sei.content_light.present) { - AVContentLightMetadata *metadata = - av_content_light_metadata_create_side_data(out); - if (!metadata) - return AVERROR(ENOMEM); - metadata->MaxCLL = s->sei.content_light.max_content_light_level; - metadata->MaxFALL = s->sei.content_light.max_pic_average_light_level; - - av_log(s->avctx, AV_LOG_DEBUG, "Content Light Level Metadata:\n"); - av_log(s->avctx, AV_LOG_DEBUG, "MaxCLL=%d, MaxFALL=%d\n", - metadata->MaxCLL, metadata->MaxFALL); - } - - 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.film_grain_characteristics.present) { - HEVCSEIFilmGrainCharacteristics *fgc = &s->sei.film_grain_characteristics; - AVFilmGrainParams *fgp = av_film_grain_params_create_side_data(out); - if (!fgp) - return AVERROR(ENOMEM); - - fgp->type = AV_FILM_GRAIN_PARAMS_H274; - fgp->seed = s->ref->poc; /* no poc_offset in HEVC */ - - fgp->codec.h274.model_id = fgc->model_id; - if (fgc->separate_colour_description_present_flag) { - fgp->codec.h274.bit_depth_luma = fgc->bit_depth_luma; - fgp->codec.h274.bit_depth_chroma = fgc->bit_depth_chroma; - fgp->codec.h274.color_range = fgc->full_range + 1; - fgp->codec.h274.color_primaries = fgc->color_primaries; - fgp->codec.h274.color_trc = fgc->transfer_characteristics; - fgp->codec.h274.color_space = fgc->matrix_coeffs; - } else { - const HEVCSPS *sps = s->ps.sps; - const VUI *vui = &sps->vui; - fgp->codec.h274.bit_depth_luma = sps->bit_depth; - fgp->codec.h274.bit_depth_chroma = sps->bit_depth_chroma; - if (vui->video_signal_type_present_flag) - fgp->codec.h274.color_range = vui->video_full_range_flag + 1; - else - fgp->codec.h274.color_range = AVCOL_RANGE_UNSPECIFIED; - if (vui->colour_description_present_flag) { - fgp->codec.h274.color_primaries = vui->colour_primaries; - fgp->codec.h274.color_trc = vui->transfer_characteristic; - fgp->codec.h274.color_space = vui->matrix_coeffs; - } else { - fgp->codec.h274.color_primaries = AVCOL_PRI_UNSPECIFIED; - fgp->codec.h274.color_trc = AVCOL_TRC_UNSPECIFIED; - fgp->codec.h274.color_space = AVCOL_SPC_UNSPECIFIED; - } - } - fgp->codec.h274.blending_mode_id = fgc->blending_mode_id; - fgp->codec.h274.log2_scale_factor = fgc->log2_scale_factor; - - memcpy(&fgp->codec.h274.component_model_present, &fgc->comp_model_present_flag, - sizeof(fgp->codec.h274.component_model_present)); - memcpy(&fgp->codec.h274.num_intensity_intervals, &fgc->num_intensity_intervals, - sizeof(fgp->codec.h274.num_intensity_intervals)); - memcpy(&fgp->codec.h274.num_model_values, &fgc->num_model_values, - sizeof(fgp->codec.h274.num_model_values)); - memcpy(&fgp->codec.h274.intensity_interval_lower_bound, &fgc->intensity_interval_lower_bound, - sizeof(fgp->codec.h274.intensity_interval_lower_bound)); - memcpy(&fgp->codec.h274.intensity_interval_upper_bound, &fgc->intensity_interval_upper_bound, - sizeof(fgp->codec.h274.intensity_interval_upper_bound)); - memcpy(&fgp->codec.h274.comp_model_value, &fgc->comp_model_value, - sizeof(fgp->codec.h274.comp_model_value)); - - fgc->present = fgc->persistence_flag; - } - - 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); - } - } + if ((ret = ff_hevc_set_sei_to_frame(s->avctx, &s->sei, out, s->avctx->framerate, s->ref->poc, &sps->vui, sps->bit_depth, sps->bit_depth_chroma) < 0)) + return ret; - if (s->rpu_buf) { + if (s && s->rpu_buf) { AVFrameSideData *rpu = av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DOVI_RPU_BUFFER, s->rpu_buf); if (!rpu) return AVERROR(ENOMEM); @@ -2979,20 +2751,9 @@ static int set_side_data(HEVCContext *s) s->rpu_buf = NULL; } - if ((ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) + if (s && (ret = ff_dovi_attach_side_data(&s->dovi_ctx, out)) < 0) return ret; - if (s->sei.dynamic_hdr_vivid.info) { - AVBufferRef *info_ref = av_buffer_ref(s->sei.dynamic_hdr_vivid.info); - if (!info_ref) - return AVERROR(ENOMEM); - - if (!av_frame_new_side_data_from_buf(out, AV_FRAME_DATA_DYNAMIC_HDR_VIVID, info_ref)) { - av_buffer_unref(&info_ref); - return AVERROR(ENOMEM); - } - } - return 0; }