Re: [FFmpeg-devel] [PATCH v4 2/3] avformat/flvenc: support enhanced flv PacketTypeMetadata
> 2024年3月2日 22:59,Andreas Rheinhardt 写道: > > zhupengfei via ffmpeg-devel: >> From: Zhu Pengfei <411294...@qq.com> >> >> Signed-off-by: Zhu Pengfei <411294...@qq.com> >> --- >> libavformat/flvenc.c | 142 +++ >> 1 file changed, 142 insertions(+) >> >> diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c >> index f6d10f331c..ae7ea84bad 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; > > Should be metadata_pkt_written to be consistent with its semantics. > >> } FLVContext; >> >> static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) >> @@ -478,6 +480,145 @@ 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; > > Can be constified. > >> +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) { > > You can avoid one level of indentation by returning early here. > >> +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); >> + >> +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,
Re: [FFmpeg-devel] [PATCH v4 2/3] avformat/flvenc: support enhanced flv PacketTypeMetadata
zhupengfei via ffmpeg-devel: > From: Zhu Pengfei <411294...@qq.com> > > Signed-off-by: Zhu Pengfei <411294...@qq.com> > --- > libavformat/flvenc.c | 142 +++ > 1 file changed, 142 insertions(+) > > diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c > index f6d10f331c..ae7ea84bad 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; Should be metadata_pkt_written to be consistent with its semantics. > } FLVContext; > > static int get_audio_flags(AVFormatContext *s, AVCodecParameters *par) > @@ -478,6 +480,145 @@ 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; Can be constified. > +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) { You can avoid one level of indentation by returning early here. > +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); > + > +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 &&
[FFmpeg-devel] [PATCH v4 2/3] avformat/flvenc: support enhanced flv PacketTypeMetadata
From: Zhu Pengfei <411294...@qq.com> Signed-off-by: Zhu Pengfei <411294...@qq.com> --- libavformat/flvenc.c | 142 +++ 1 file changed, 142 insertions(+) diff --git a/libavformat/flvenc.c b/libavformat/flvenc.c index f6d10f331c..ae7ea84bad 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,145 @@ 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); + +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,