From patchwork Thu Jan 11 16:17:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Diego Felix de Souza via ffmpeg-devel X-Patchwork-Id: 45569 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bf2f:b0:199:de12:6fa6 with SMTP id gc47csp1799238pzb; Thu, 11 Jan 2024 08:17:29 -0800 (PST) X-Google-Smtp-Source: AGHT+IHRmmABF31ys5Q5XVnW6evVa2eYXVHJrGNo3oHL4ZC592qaHalBAnpgTjwG2exsQG8mG4zr X-Received: by 2002:a2e:3816:0:b0:2cd:8414:30b with SMTP id f22-20020a2e3816000000b002cd8414030bmr1604868lja.5.1704989849243; Thu, 11 Jan 2024 08:17:29 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704989849; cv=none; d=google.com; s=arc-20160816; b=XCB2L6EtK4vdvTZGkZrSVHdFb5n7X+7iTQK4rFgOXgvUn5iXYLjbsCP735iwUIRN/b su2HyS8ljmvebFZMnNkJrzPs7cPHh97sQqBfJ/G2YuIo3UqZqPvq3ZarhYwOgSYJYA9R XZSFOu7kjnUIDceLZPsnWXd+6nUJgp7liLDMG8aimb4wf32B5ktEY9jn62uq46vC8+2w JnxTFoXh27OxgufTwb9ptyjeb30VGLoz4Zp4dzJQWcmLa3Spn7aePi4w0zmOB1HwjUzi EFpnN/yl/FfSGhhmI11WgKNx0Du4fn881K/C/BnrQz2mgfylq89LhsZlQPvi91/PxX2+ ezZQ== 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:from :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to:date :to:message-id:delivered-to; bh=/yd/Mqz1Py4iAOA+CEKezkT+eUKR9FwjbOacq1OWdXQ=; fh=frUT2hx60kzuIVmkNUv7bM3Y/kw3lxlKoLH+4fdDqZk=; b=i9C+20k+jew4nch28hEPnUhitxmNwl1XmSrto71uIoY4NXp8y7D536nJpeE47VZoBU RwnktwPN0J4BW/dQRDz0dcQuWqCQ/LU1ZkKn1zD2WeQ8Q1WKUH44dIW35vPECgcQG1PC FmiV6AS1Cgg8oAHanJOP5On3TGN2QtntSAqsFG2K2aRA+mLGT3P+td3b+zNNb4k0TJ9c lKptTJOJB/RkkqqmVJxiLGszlwPZZrdi04Ns7Rzwn/0x7tSwNb2KMvQEY21lCy7toFBo WGiwGI94LLO13Sqk1/gQVvjQFaS0y9PGsKkH3wl+C+X8JhATD10k7kMqwJXqimOThfCV QSNA== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id c8-20020a50d648000000b00558b0d81dffsi273477edj.434.2024.01.11.08.17.28; Thu, 11 Jan 2024 08:17:29 -0800 (PST) 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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 798B168D060; Thu, 11 Jan 2024 18:17:26 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from out203-205-251-73.mail.qq.com (out203-205-251-73.mail.qq.com [203.205.251.73]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 2DF5C68CA1F for ; Thu, 11 Jan 2024 18:17:18 +0200 (EET) Received: from localhost.localdomain ([103.102.203.208]) by newxmesmtplogicsvrszc5-1.qq.com (NewEsmtp) with SMTP id 44D8145D; Fri, 12 Jan 2024 00:17:13 +0800 X-QQ-mid: xmsmtpt1704989833t1qvo959j Message-ID: X-QQ-XMAILINFO: NLLC220q1X5wOWeFwWBoS8A/hMZm9OCgfLZZTWXSLLfw5dUJXKB+ic9vnQ07Ck mmMmvzeioirgmdh0J8aeptAmtsRqHyjBEpbnCClvdYho5J206D5BPLoJ9DgObqbw4CacAwRhlI5c /j+vG60IjG24Gt/Yc0PQoaHe2yHXAUV8ha1rGj0DJhqb8ESwrv5Y4Fupjd3VYoClVKLmmktajBHc 4mGeC8Ny3+9ohRpch0d57t94M/z4NhaccAGzg865N3J2fh6gxFLTOdUE4GB4gSKy3ETPglCgPIQl Pc/SiGLeEK4Ie8/JzZ33A+57FbZsmGeE1IxKzt15BNUXAQoei5NMvtfVVN1EtGlLZPYPbCBh3L22 EFR47dkdCkaUN/6g4WEwLkQDbJOTJ6Q6xOkUb941fYD0oB99YA9bFrB95eawyn5ioEr2CR/oyDug mKlS7Wi2E8jP7T6oOK4W4vCa0yMpSXufc0m0LzVjZwWYApGOM36HPzy+hYHOqlGqnE+rCjl8lW2h kO4pe/riVUZ/2NaPwwUyIc4M5as6NQnqG7u6SSCpa1Ph45f2HPsaIY1voy3KoQIEqU4o9U9Dvm1S 1wWnu4NfIYSF+Iwh3eK5DGaoPvX5zMk71jDNBc3IyDSa+qFjT5IWrg7xNnAkyLYr0xFhmuSUyPua Se601GRfN1TGvWT8NxeDqyVOnwOGt4t82weqtAp3WZmJXh42MkCn0p58jrVosYGDRr2naJ2Bkbz+ WCn2oeBTIg+LOf3KU8UGIeOuSLxQtC35REPK+I1P2LhYX8ofDyY/ldz5oOeureZ3SmutNlZBfPwh o9Nma5r7AZ516ThrrPLMAl3GRPZmm3/O73mA0RfXTWk3bNHHgtPNu3PuL+B5zE3AvnABF0/JTIp5 9C3vv9K3EdxtpHSRL/86ZAR+WZqFcZVCxgPr1XHQ8aAkNhJeCEoau/QlQhx3Y1NZEr4OeknpNsoP yrql3PFw3AcWPrjLhoWyqploZnIJ7vHB6PSu5OUoTOlQ5gYs9szKUB2s+NaA+E X-QQ-XMRINFO: M/715EihBoGSf6IYSX1iLFg= To: ffmpeg-devel@ffmpeg.org Date: Fri, 12 Jan 2024 00:17:08 +0800 X-OQ-MSGID: <20240111161708.22517-1-411294962@qq.com> X-Mailer: git-send-email 2.42.1 In-Reply-To: <29ed7620-f60f-4f31-bc22-3f0903456c07@gmail.com> References: <29ed7620-f60f-4f31-bc22-3f0903456c07@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v3 2/2] avformat/flvenc: support enhanced flv PacketTypeMetadata 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: , X-Patchwork-Original-From: zhupengfei via ffmpeg-devel From: Diego Felix de Souza via ffmpeg-devel Reply-To: FFmpeg development discussions and patches Cc: 411294962@qq.com Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: oObCMEXZOXtm From: Zhu Pengfei <411294962@qq.com> Signed-off-by: Zhu Pengfei <411294962@qq.com> --- libavformat/flvenc.c | 133 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index f6d10f331c..4485aba03c 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -24,6 +24,7 @@ #include "libavutil/intfloat.h" #include "libavutil/avassert.h" #include "libavutil/mathematics.h" +#include "libavutil/mastering_display_metadata.h" #include "libavcodec/codec_desc.h" #include "libavcodec/mpeg4audio.h" #include "avio.h" @@ -124,6 +125,7 @@ typedef struct FLVContext { int flags; int64_t last_ts[FLV_STREAM_TYPE_NB]; + int write_metadata_pkt; } FLVContext; static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) @@ -478,6 +480,136 @@ static void write_metadata(AVFormatContext *s, unsigned int ts) avio_wb32(pb, flv->metadata_totalsize + 11); } +static void flv_write_metadata_packet(AVFormatContext *s, AVCodecParameters *par, unsigned int ts) +{ + AVIOContext *pb = s->pb; + FLVContext *flv = s->priv_data; + AVContentLightMetadata *lightMetadata = NULL; + AVMasteringDisplayMetadata *displayMetadata = NULL; + const int flags_size = 5; + int64_t metadata_size_pos = 0; + int64_t total_size = 0; + const AVPacketSideData *side_data = NULL; + + if (par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1 || + par->codec_id == AV_CODEC_ID_VP9) { + if (flv->write_metadata_pkt) return; + + side_data = av_packet_side_data_get(par->coded_side_data, par->nb_coded_side_data, + AV_PKT_DATA_CONTENT_LIGHT_LEVEL); + if (side_data) + lightMetadata = (AVContentLightMetadata *)side_data->data; + + side_data = av_packet_side_data_get(par->coded_side_data, par->nb_coded_side_data, + AV_PKT_DATA_MASTERING_DISPLAY_METADATA); + if (side_data) + displayMetadata = (AVMasteringDisplayMetadata *)side_data->data; + + /* + * Reference Enhancing FLV + * https://github.com/veovera/enhanced-rtmp/blob/main/enhanced-rtmp.pdf + * */ + avio_w8(pb, FLV_TAG_TYPE_VIDEO); //write video tag type + metadata_size_pos = avio_tell(pb); + avio_wb24(pb, 0 + flags_size); + put_timestamp(pb, ts); //ts = pkt->dts, gen + avio_wb24(pb, flv->reserved); + + if (par->codec_id == AV_CODEC_ID_HEVC) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeMetadata| FLV_FRAME_VIDEO_INFO_CMD); // ExVideoTagHeader mode with PacketTypeMetadata + avio_write(pb, "hvc1", 4); + } else if (par->codec_id == AV_CODEC_ID_AV1 || par->codec_id == AV_CODEC_ID_VP9) { + avio_w8(pb, FLV_IS_EX_HEADER | PacketTypeMetadata| FLV_FRAME_VIDEO_INFO_CMD); + avio_write(pb, par->codec_id == AV_CODEC_ID_AV1 ? "av01" : "vp09", 4); + } + + avio_w8(pb, AMF_DATA_TYPE_STRING); + put_amf_string(pb, "colorInfo"); + + avio_w8(pb, AMF_DATA_TYPE_OBJECT); + + put_amf_string(pb, "colorConfig"); // colorConfig + + avio_w8(pb, AMF_DATA_TYPE_OBJECT); + + put_amf_string(pb, "transferCharacteristics"); // color_trc + put_amf_double(pb, par->color_trc); + + put_amf_string(pb, "matrixCoefficients"); // colorspace + put_amf_double(pb, par->color_space); + + put_amf_string(pb, "colorPrimaries"); // color_primaries + put_amf_double(pb, par->color_primaries); + + put_amf_string(pb, ""); + avio_w8(pb, AMF_END_OF_OBJECT); + + if (lightMetadata) { + put_amf_string(pb, "hdrCll"); + avio_w8(pb, AMF_DATA_TYPE_OBJECT); + + put_amf_string(pb, "maxFall"); + put_amf_double(pb, lightMetadata->MaxFALL); + + put_amf_string(pb, "maxCLL"); + put_amf_double(pb, lightMetadata->MaxCLL); + + put_amf_string(pb, ""); + avio_w8(pb, AMF_END_OF_OBJECT); + } + + if (displayMetadata && (displayMetadata->has_primaries || displayMetadata->has_luminance)) { + put_amf_string(pb, "hdrMdcv"); + avio_w8(pb, AMF_DATA_TYPE_OBJECT); + if (displayMetadata->has_primaries) { + put_amf_string(pb, "redX"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[0][0])); + + put_amf_string(pb, "redY"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[0][1])); + + put_amf_string(pb, "greenX"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[1][0])); + + put_amf_string(pb, "greenY"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[1][1])); + + put_amf_string(pb, "blueX"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[2][0])); + + put_amf_string(pb, "blueY"); + put_amf_double(pb, av_q2d(displayMetadata->display_primaries[2][1])); + + put_amf_string(pb, "whitePointX"); + put_amf_double(pb, av_q2d(displayMetadata->white_point[0])); + + put_amf_string(pb, "whitePointY"); + put_amf_double(pb, av_q2d(displayMetadata->white_point[1])); + } + if (displayMetadata->has_luminance) { + put_amf_string(pb, "maxLuminance"); + put_amf_double(pb, av_q2d(displayMetadata->max_luminance)); + + put_amf_string(pb, "minLuminance"); + put_amf_double(pb, av_q2d(displayMetadata->min_luminance)); + } + put_amf_string(pb, ""); + avio_w8(pb, AMF_END_OF_OBJECT); + } + put_amf_string(pb, ""); + avio_w8(pb, AMF_END_OF_OBJECT); + + total_size = avio_tell(pb) - metadata_size_pos - 10; + avio_seek(pb, metadata_size_pos, SEEK_SET); + avio_wb24(pb, total_size); + avio_tell(pb); + avio_skip(pb, total_size + 10 - 3); + avio_tell(pb); + avio_wb32(pb, total_size + 11); // previous tag size + flv->write_metadata_pkt = 1; + } +} + static int unsupported_codec(AVFormatContext *s, const char* type, int codec_id) { @@ -878,6 +1010,7 @@ static int flv_write_packet(AVFormatContext *s, AVPacket *pkt) memcpy(par->extradata, side, side_size); flv_write_codec_header(s, par, pkt->dts); } + flv_write_metadata_packet(s, par, pkt->dts); } if (flv->delay == AV_NOPTS_VALUE)