From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTP id D665C49BBF for ; Mon, 4 Mar 2024 13:52:26 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1481968D3E4; Mon, 4 Mar 2024 15:52:24 +0200 (EET) Received: from out162-62-57-252.mail.qq.com (out162-62-57-252.mail.qq.com [162.62.57.252]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 326DF68D3C0 for ; Mon, 4 Mar 2024 15:52:15 +0200 (EET) Received: from localhost.localdomain ([163.125.127.26]) by newxmesmtplogicsvrszc5-1.qq.com (NewEsmtp) with SMTP id D058000E; Mon, 04 Mar 2024 21:52:05 +0800 X-QQ-mid: xmsmtpt1709560325tcvnl6veh Message-ID: X-QQ-XMAILINFO: OOPJ7pYMv25tlcWpFY31R5qp9IUQM4GtDlTv2k4579OiTJyL0jDMKt4OGck+Fi ymdZYIzqPQtOJ+CdyKNnIKjPb0W3P/ed3siRmpO4IQj4ntCnfmoirdro6fUhALeQBryacNo0xkgO ZS+7vGdoK3KS2Q7yU3CtH8mXMY/6bIssPvJEUVab4c7n/x35fY1JGXoBsnTIs8d/kBCPn0iMIO9H InOchXzB1ypPtmh+VZ36/B66Kk4Wmv6V/5lIqmqEmW0VL1/UjFm4IbSeQTouW4jkLb3a4UeNOXdE zxFZQqA65DySdS3dhYBB+Qw2hOQszHIvCOimHWQj1FmvAw4FoiAfBkUMn3fFbm2Zm4E0O4yvb1a8 Fc3QgULr2vG7Zb337uXT/BIH/uY7sf8iEz4F/A807JNQMPrfQK9eBEwDJMTC4i7XCwlq2B2QUtvn hWaIwggVBZJ8D8jXKLnokLiwpPOZHfbQXBjP8ugnP/9RW29PoPfL+001LR8WuW1vKfpd8oVt7NqA YnO+13SMFV3tsKuXWE6c9dxpHP74DS+7ZRjOA5fGfdH4mZ7uyReEmBOQWb2SPVlnIsjdDRyh8Tin u88Rb/Hl196+m7XNuJNQ69JZ77XBJeWB7YDYgsYPUJHNtQTGN8GAUFeDSheQpWmv9GTbR91vkijv 1npnWnF4riXUtqa5mpuvHCStYXQR6LlqHSzWHa0QYRKAkQaq3a21NQ3NgEaRw9Sw82O3atNkERV9 Oprs3AO04j0TLXa7cOdz7I16MHqvfOtNOywCCB/li92wZoeGncySXA7B5Lbf49gVejWPW6Wh3Ezc Ck//OyvrQTunvIdzQOm8LIzpun/9ggNe+2Eggd5hdHokl3XzvA5s9D++gOVhOkj36LHxenVcCVAz OtQ31VOMgbTEQQQ3qjuViYrtrZ7aVPogo03e0khvwQ2uoRH5JT4Ay+1BeQQ3XXmFa1apebS6yFSy qLxLqhPMU2Afyr9Iu6hgvGsiyhGaQf3rTZRJNlrM8= X-QQ-XMRINFO: OD9hHCdaPRBwq3WW+NvGbIU= To: ffmpeg-devel@ffmpeg.org Date: Mon, 4 Mar 2024 21:52:04 +0800 X-OQ-MSGID: <20240304135204.1304-1-411294962@qq.com> X-Mailer: git-send-email 2.44.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v5 2/3] 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: , From: zhupengfei via ffmpeg-devel Reply-To: FFmpeg development discussions and patches Cc: 411294962@qq.com Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Archived-At: List-Archive: List-Post: From: Zhu Pengfei <411294962@qq.com> Signed-off-by: Zhu Pengfei <411294962@qq.com> --- libavformat/flvenc.c | 139 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index f6d10f331c..261e5d800c 100644 --- a/libavformat/flvenc.c +++ b/libavformat/flvenc.c @@ -23,6 +23,7 @@ #include "libavutil/dict.h" #include "libavutil/intfloat.h" #include "libavutil/avassert.h" +#include "libavutil/mastering_display_metadata.h" #include "libavutil/mathematics.h" #include "libavcodec/codec_desc.h" #include "libavcodec/mpeg4audio.h" @@ -124,6 +125,7 @@ typedef struct FLVContext { int flags; int64_t last_ts[FLV_STREAM_TYPE_NB]; + int metadata_pkt_written; } FLVContext; static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) @@ -478,6 +480,142 @@ 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; + int64_t metadata_size_pos = 0; + int64_t total_size = 0; + const AVPacketSideData *side_data = NULL; + + if (flv->metadata_pkt_written) return; + if (par->codec_id == AV_CODEC_ID_HEVC || par->codec_id == AV_CODEC_ID_AV1 || + par->codec_id == AV_CODEC_ID_VP9) { + int flags_size = 5; + 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); + + if (par->color_trc != AVCOL_TRC_UNSPECIFIED && + par->color_trc < AVCOL_TRC_NB) { + put_amf_string(pb, "transferCharacteristics"); // color_trc + put_amf_double(pb, par->color_trc); + } + + if (par->color_space != AVCOL_SPC_UNSPECIFIED && + par->color_space < AVCOL_SPC_NB) { + put_amf_string(pb, "matrixCoefficients"); // colorspace + put_amf_double(pb, par->color_space); + } + + if (par->color_primaries != AVCOL_PRI_UNSPECIFIED && + par->color_primaries < AVCOL_PRI_NB) { + 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_skip(pb, total_size + 10 - 3); + avio_wb32(pb, total_size + 11); // previous tag size + flv->metadata_pkt_written = 1; + } +} + static int unsupported_codec(AVFormatContext *s, const char* type, int codec_id) { @@ -878,6 +1016,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) -- 2.44.0 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".