From patchwork Tue Oct 25 04:03:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aman Karmani X-Patchwork-Id: 38973 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:4a86:b0:9d:28a3:170e with SMTP id fn6csp2579600pzb; Mon, 24 Oct 2022 21:04:20 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6ao9PiyUZs8armu0jAFnoDLCDDe6ojbbnL0vWLqGCUILOLw8MzNl4mOJnCorIFwtBzBLQb X-Received: by 2002:a17:907:2d2c:b0:78d:d289:7efd with SMTP id gs44-20020a1709072d2c00b0078dd2897efdmr30509162ejc.166.1666670649413; Mon, 24 Oct 2022 21:04:09 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666670649; cv=none; d=google.com; s=arc-20160816; b=wVlH+g1TXlWz9UdcIpr8fNKnicT/4xUazQfVfCezDdi5yIVg02SlXCZ8CRw2PTKRSK KG1tKbCoxjLxa6ziuhAGYcGdeBuDFW+QhtnZqvsrMRxlp+fCP9SHMUUUV+GfPlWNmoWR exv6bJdmzVwQt/QlbfPsC8oobpr2awaRL78kFCxNDiytFQ4UieaaekA2tjiQnRGQLeXc xquhIwvgGs9qK/TSTb5W9At0cGAcy7UOi4wkOB3UakWSwTBMRGWkDhUrltUAuOH/+F2R 8XFZIDRdtODSuP9reD4NVM6KBpKyDTywcMMk2tyL7vaVdhtKttZWZZ0kDPGd9371mZPA ShsA== 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=ESeDmtaCOVL9fPr/mWnlT2qJaSKbXX94vpX/V9balEc=; b=kSKaMe5VOCBa3LmxcKGBi5RaRf7h8AyleDJETfSJ+eM+U6vNToNOTXSZFolg67WCDm r1+X68HPAXf9RF/dIf7/nIRLTwogufygdBsuH2o49cti4CuF31YX1M4ToxMWCcMA7pwi DgoDvoe0tB5KW8vDqD8/gr2LyZJkw2X/HwQwvpyzGa3FR+0jTpg6O0JYus57dzPJzTlH oZCbQ6kP8iFjAjIQ13OvHbydv+TH58lhDWBDc3IRX/zGNm/UlBn5d1jzCGdAWWZe6Pra 802af9CpqfU2tJwGLWOIVpizY9r7cp/fAXDVNw7VlfW0kBU8VaRTpwi+KJqZwbzboDGn I+5A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=Tce65Myu; 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 js15-20020a17090797cf00b0077e6bb482adsi1172700ejc.658.2022.10.24.21.04.09; Mon, 24 Oct 2022 21:04:09 -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=Tce65Myu; 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 D17FC68BC9D; Tue, 25 Oct 2022 07:03:54 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id AF44968BC0F for ; Tue, 25 Oct 2022 07:03:41 +0300 (EEST) Received: by mail-pj1-f45.google.com with SMTP id m14-20020a17090a3f8e00b00212dab39bcdso8489129pjc.0; 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=p2xcvwUlF9dYCA7qXogpTer+/e1nGWcUbpuxmgBDyF8=; b=Tce65MyuOD+lmv6pz+F8UGpWo4IOMJ9dSHqOm+baOZdrUrj1uOPTbb8jWT2HRj7zE+ hClWu4GN7yC6gIoFCj+nJ6r0cAfqCkj0JRTcyXoSbhHmqb4z33yPktFB3Qcsx2cRfR5+ QZhuMzc48MNPQqFJd+kzs7Tky7++xdSpP8NQXenm6dZ4MywyQ5JOnkigosZYHlreQlQe T1WXjgiwoH+Ok1O01xo17LjNS0CxJnEhWrhYlr0V1SWXypCrgULG9NQ5HTWxPGuzQA+h De6VocHVxqWSloePBsBZ+8LqqwtIeOsU3oRuqSKpumnLmATmFkHYfrlUPhLpPBWGP6+a qj+A== 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=p2xcvwUlF9dYCA7qXogpTer+/e1nGWcUbpuxmgBDyF8=; b=G1E2cP39thBYD27PRFvGGCbxMlgkePaWcP3TNIWCC31TPsaFsqpreG/9b6rL7EPelz EPU1exa8MeqrGeVjcdOGgiC5fq68K+3P4Ru/Vq+ezeQq6z4pPEPoX8bmvWHX0X6gZKr4 nXjPNx+o5jTzk0oVqdPAZx57zB0qd+teXfXn+a+unbUQ6OcZ5kifDC1hIY9yjApdFrJ0 jpoNKqWg4Jne/BQ18osbbctdC+GkLs3x47qnlOLYpqBjb52+HO86Yud0kAzyZnL+vtf3 FIEeisTfuicCVzDYXjtOErT6fdQrftj8p6XsFibSQH61ym4QGdvTWRRqJBMZYJM23ntg GLmA== X-Gm-Message-State: ACrzQf3shFP6R2kfulTxhs2FacQeywromQ+4WSbcwJAnEM49vbbyoXQT 5Oz7CTCD1bLZY0XBpkaCSPESKGo1vGI= X-Received: by 2002:a17:90b:17d0:b0:213:2ef2:6bb1 with SMTP id me16-20020a17090b17d000b002132ef26bb1mr4961154pjb.125.1666670619927; 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 x20-20020a634a14000000b00434272fe870sm441604pga.88.2022.10.24.21.03.39 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Oct 2022 21:03:39 -0700 (PDT) From: softworkz X-Google-Original-From: softworkz Message-Id: <51b234c8d0a3372f53410397ae34909ac74e27c7.1666670616.git.ffmpegagent@gmail.com> In-Reply-To: References: Date: Tue, 25 Oct 2022 04:03:35 +0000 Fcc: Sent MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Subject: [FFmpeg-devel] [PATCH v6 2/3] avcodec/h264dec: make h264_export_frame_props() accessible 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: ZZ7LOHaEI7zz From: softworkz Signed-off-by: softworkz --- libavcodec/h264_sei.c | 197 ++++++++++++++++++++++++++++++++++++++++ libavcodec/h264_sei.h | 2 + libavcodec/h264_slice.c | 190 +------------------------------------- 3 files changed, 200 insertions(+), 189 deletions(-) diff --git a/libavcodec/h264_sei.c b/libavcodec/h264_sei.c index 034ddb8f1c..d3612fdbc0 100644 --- a/libavcodec/h264_sei.c +++ b/libavcodec/h264_sei.c @@ -38,6 +38,10 @@ #include "h264_ps.h" #include "h264_sei.h" #include "sei.h" +#include "libavutil/display.h" +#include "libavutil/film_grain_params.h" +#include "libavutil/stereo3d.h" +#include "libavutil/timecode.h" #define AVERROR_PS_NOT_FOUND FFERRTAG(0xF8,'?','P','S') @@ -587,3 +591,196 @@ const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h) return NULL; } } + +int ff_h264_set_sei_to_frame(AVCodecContext *avctx, H264SEIContext *sei, AVFrame *out, const SPS *sps, uint64_t seed) +{ + if (sei->frame_packing.present && + sei->frame_packing.arrangement_type <= 6 && + sei->frame_packing.content_interpretation_type > 0 && + sei->frame_packing.content_interpretation_type < 3) { + H264SEIFramePacking *fp = &sei->frame_packing; + AVStereo3D *stereo = av_stereo3d_create_side_data(out); + if (stereo) { + switch (fp->arrangement_type) { + case H264_SEI_FPA_TYPE_CHECKERBOARD: + stereo->type = AV_STEREO3D_CHECKERBOARD; + break; + case H264_SEI_FPA_TYPE_INTERLEAVE_COLUMN: + stereo->type = AV_STEREO3D_COLUMNS; + break; + case H264_SEI_FPA_TYPE_INTERLEAVE_ROW: + stereo->type = AV_STEREO3D_LINES; + break; + case H264_SEI_FPA_TYPE_SIDE_BY_SIDE: + if (fp->quincunx_sampling_flag) + stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; + else + stereo->type = AV_STEREO3D_SIDEBYSIDE; + break; + case H264_SEI_FPA_TYPE_TOP_BOTTOM: + stereo->type = AV_STEREO3D_TOPBOTTOM; + break; + case H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL: + stereo->type = AV_STEREO3D_FRAMESEQUENCE; + break; + case H264_SEI_FPA_TYPE_2D: + stereo->type = AV_STEREO3D_2D; + break; + } + + if (fp->content_interpretation_type == 2) + stereo->flags = AV_STEREO3D_FLAG_INVERT; + + if (fp->arrangement_type == H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL) { + if (fp->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)) { + H264SEIDisplayOrientation *o = &sei->display_orientation; + double angle = o->anticlockwise_rotation * 360 / (double) (1 << 16); + AVFrameSideData *rotation = av_frame_new_side_data(out, + AV_FRAME_DATA_DISPLAYMATRIX, + sizeof(int32_t) * 9); + if (rotation) { + /* 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 * !!o->hflip) * (1 - 2 * !!o->vflip); + av_display_rotation_set((int32_t *)rotation->data, angle); + av_display_matrix_flip((int32_t *)rotation->data, + o->hflip, o->vflip); + } + } + + if (sei->afd.present) { + AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, + sizeof(uint8_t)); + + if (sd) { + *sd->data = sei->afd.active_format_description; + sei->afd.present = 0; + } + } + + if (sei->a53_caption.buf_ref) { + H264SEIA53Caption *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; + + avctx->properties |= FF_CODEC_PROPERTY_CLOSED_CAPTIONS; + } + + for (int i = 0; i < sei->unregistered.nb_buf_ref; i++) { + H264SEIUnregistered *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 (sps && sei->film_grain_characteristics.present) { + H264SEIFilmGrainCharacteristics *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; + + 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 = sps->bit_depth_luma; + fgp->codec.h274.bit_depth_chroma = sps->bit_depth_chroma; + if (sps->video_signal_type_present_flag) + fgp->codec.h274.color_range = sps->full_range + 1; + else + fgp->codec.h274.color_range = AVCOL_RANGE_UNSPECIFIED; + if (sps->colour_description_present_flag) { + fgp->codec.h274.color_primaries = sps->color_primaries; + fgp->codec.h274.color_trc = sps->color_trc; + fgp->codec.h274.color_space = sps->colorspace; + } 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->repetition_period; + + avctx->properties |= FF_CODEC_PROPERTY_FILM_GRAIN; + } + + if (sei->picture_timing.timecode_cnt > 0) { + 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->picture_timing.timecode_cnt; + + for (int i = 0; i < tc_sd[0]; i++) { + int drop = sei->picture_timing.timecode[i].dropframe; + int hh = sei->picture_timing.timecode[i].hours; + int mm = sei->picture_timing.timecode[i].minutes; + int ss = sei->picture_timing.timecode[i].seconds; + int ff = sei->picture_timing.timecode[i].frame; + + tc_sd[i + 1] = av_timecode_get_smpte(avctx->framerate, drop, hh, mm, ss, ff); + av_timecode_make_smpte_tc_string2(tcbuf, avctx->framerate, tc_sd[i + 1], 0, 0); + av_dict_set(&out->metadata, "timecode", tcbuf, 0); + } + sei->picture_timing.timecode_cnt = 0; + } + + return 0; +} diff --git a/libavcodec/h264_sei.h b/libavcodec/h264_sei.h index f9166b45df..05945523da 100644 --- a/libavcodec/h264_sei.h +++ b/libavcodec/h264_sei.h @@ -221,4 +221,6 @@ const char *ff_h264_sei_stereo_mode(const H264SEIFramePacking *h); int ff_h264_sei_process_picture_timing(H264SEIPictureTiming *h, const SPS *sps, void *logctx); +int ff_h264_set_sei_to_frame(AVCodecContext *avctx, H264SEIContext *sei, AVFrame *out, const SPS *sps, uint64_t seed); + #endif /* AVCODEC_H264_SEI_H */ diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 6f0a7c1fb7..c66329f064 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -1244,195 +1244,7 @@ static int h264_export_frame_props(H264Context *h) } } - if (h->sei.frame_packing.present && - h->sei.frame_packing.arrangement_type <= 6 && - 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(out); - if (stereo) { - switch (fp->arrangement_type) { - case H264_SEI_FPA_TYPE_CHECKERBOARD: - stereo->type = AV_STEREO3D_CHECKERBOARD; - break; - case H264_SEI_FPA_TYPE_INTERLEAVE_COLUMN: - stereo->type = AV_STEREO3D_COLUMNS; - break; - case H264_SEI_FPA_TYPE_INTERLEAVE_ROW: - stereo->type = AV_STEREO3D_LINES; - break; - case H264_SEI_FPA_TYPE_SIDE_BY_SIDE: - if (fp->quincunx_sampling_flag) - stereo->type = AV_STEREO3D_SIDEBYSIDE_QUINCUNX; - else - stereo->type = AV_STEREO3D_SIDEBYSIDE; - break; - case H264_SEI_FPA_TYPE_TOP_BOTTOM: - stereo->type = AV_STEREO3D_TOPBOTTOM; - break; - case H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL: - stereo->type = AV_STEREO3D_FRAMESEQUENCE; - break; - case H264_SEI_FPA_TYPE_2D: - stereo->type = AV_STEREO3D_2D; - break; - } - - if (fp->content_interpretation_type == 2) - stereo->flags = AV_STEREO3D_FLAG_INVERT; - - if (fp->arrangement_type == H264_SEI_FPA_TYPE_INTERLEAVE_TEMPORAL) { - if (fp->current_frame_is_frame0_flag) - stereo->view = AV_STEREO3D_VIEW_LEFT; - else - stereo->view = AV_STEREO3D_VIEW_RIGHT; - } - } - } - - if (h->sei.display_orientation.present && - (h->sei.display_orientation.anticlockwise_rotation || - h->sei.display_orientation.hflip || - 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(out, - AV_FRAME_DATA_DISPLAYMATRIX, - sizeof(int32_t) * 9); - if (rotation) { - /* 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 * !!o->hflip) * (1 - 2 * !!o->vflip); - av_display_rotation_set((int32_t *)rotation->data, angle); - av_display_matrix_flip((int32_t *)rotation->data, - o->hflip, o->vflip); - } - } - - if (h->sei.afd.present) { - AVFrameSideData *sd = av_frame_new_side_data(out, AV_FRAME_DATA_AFD, - sizeof(uint8_t)); - - if (sd) { - *sd->data = h->sei.afd.active_format_description; - h->sei.afd.present = 0; - } - } - - if (h->sei.a53_caption.buf_ref) { - H264SEIA53Caption *a53 = &h->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; - - 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.film_grain_characteristics.present) { - H264SEIFilmGrainCharacteristics *fgc = &h->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 = cur->poc + (h->poc_offset << 5); - - 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 = sps->bit_depth_luma; - fgp->codec.h274.bit_depth_chroma = sps->bit_depth_chroma; - if (sps->video_signal_type_present_flag) - fgp->codec.h274.color_range = sps->full_range + 1; - else - fgp->codec.h274.color_range = AVCOL_RANGE_UNSPECIFIED; - if (sps->colour_description_present_flag) { - fgp->codec.h274.color_primaries = sps->color_primaries; - fgp->codec.h274.color_trc = sps->color_trc; - fgp->codec.h274.color_space = sps->colorspace; - } 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->repetition_period; - - h->avctx->properties |= FF_CODEC_PROPERTY_FILM_GRAIN; - } - - if (h->sei.picture_timing.timecode_cnt > 0) { - 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] = h->sei.picture_timing.timecode_cnt; - - for (int i = 0; i < tc_sd[0]; i++) { - 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] = 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; - } - - return 0; + return ff_h264_set_sei_to_frame(h->avctx, &h->sei, out, sps, cur->poc + (h->poc_offset << 5)); } static int h264_select_output_frame(H264Context *h)