From: zhupengfei via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: 411294962@qq.com
Subject: [FFmpeg-devel] [PATCH 2/2] avformat/flvdec: support enhanced flv PacketTypeMetadata
Date: Wed, 15 Nov 2023 22:40:18 +0800
Message-ID: <tencent_B9DCD1B361EE91197340C756B867C44C8A0A@qq.com> (raw)
From: Zhu Pengfei <411294962@qq.com>
Signed-off-by: Zhu Pengfei <411294962@qq.com>
---
libavformat/flvdec.c | 171 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 170 insertions(+), 1 deletion(-)
diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index e25b5bd163..46bb0825ca 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -34,6 +34,7 @@
#include "libavutil/intfloat.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/mathematics.h"
+#include "libavutil/mastering_display_metadata.h"
#include "avformat.h"
#include "demux.h"
#include "internal.h"
@@ -45,6 +46,28 @@
#define MAX_DEPTH 16 ///< arbitrary limit to prevent unbounded recursion
+typedef struct FLVMasteringMeta {
+ double r_x;
+ double r_y;
+ double g_x;
+ double g_y;
+ double b_x;
+ double b_y;
+ double white_x;
+ double white_y;
+ double max_luminance;
+ double min_luminance;
+} FLVMasteringMeta;
+
+typedef struct FLVMetaVideoColor {
+ uint64_t matrix_coefficients;
+ uint64_t transfer_characteristics;
+ uint64_t primaries;
+ uint64_t max_cll;
+ uint64_t max_fall;
+ FLVMasteringMeta mastering_meta;
+} FLVMetaVideoColor;
+
typedef struct FLVContext {
const AVClass *class; ///< Class for private options.
int trust_metadata; ///< configure streams according onMetaData
@@ -80,6 +103,8 @@ typedef struct FLVContext {
int64_t time_offset;
int64_t time_pos;
+ FLVMetaVideoColor *metaVideoColor;
+ int meta_color_info_flag;
} FLVContext;
/* AMF date type */
@@ -524,6 +549,7 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
FLVContext *flv = s->priv_data;
AVIOContext *ioc;
AMFDataType amf_type;
+ FLVMetaVideoColor *meta_video_color = flv->metaVideoColor;
char str_val[1024];
double num_val;
amf_date date;
@@ -655,6 +681,36 @@ static int amf_parse_object(AVFormatContext *s, AVStream *astream,
} else if (!strcmp(key, "height") && vpar) {
vpar->height = num_val;
}
+ } else if (!strcmp(key, "colorPrimaries") && meta_video_color) {
+ meta_video_color->primaries = num_val;
+ } else if (!strcmp(key, "transferCharacteristics") && meta_video_color) {
+ meta_video_color->transfer_characteristics = num_val;
+ } else if (!strcmp(key, "matrixCoefficients") && meta_video_color) {
+ meta_video_color->matrix_coefficients = num_val;
+ } else if (!strcmp(key, "maxFall") && meta_video_color) {
+ meta_video_color->max_fall = num_val;
+ } else if (!strcmp(key, "maxCLL") && meta_video_color) {
+ meta_video_color->max_cll = num_val;
+ } else if (!strcmp(key, "redX") && meta_video_color) {
+ meta_video_color->mastering_meta.r_x = num_val;
+ } else if (!strcmp(key, "redY") && meta_video_color) {
+ meta_video_color->mastering_meta.r_y = num_val;
+ } else if (!strcmp(key, "greenX") && meta_video_color) {
+ meta_video_color->mastering_meta.g_x = num_val;
+ } else if (!strcmp(key, "greenY") && meta_video_color) {
+ meta_video_color->mastering_meta.g_y = num_val;
+ } else if (!strcmp(key, "blueX") && meta_video_color) {
+ meta_video_color->mastering_meta.b_x = num_val;
+ } else if (!strcmp(key, "blueY") && meta_video_color) {
+ meta_video_color->mastering_meta.b_y = num_val;
+ } else if (!strcmp(key, "whitePointX") && meta_video_color) {
+ meta_video_color->mastering_meta.white_x = num_val;
+ } else if (!strcmp(key, "whitePointY") && meta_video_color) {
+ meta_video_color->mastering_meta.white_y = num_val;
+ } else if (!strcmp(key, "maxLuminance") && meta_video_color) {
+ meta_video_color->mastering_meta.max_luminance = num_val;
+ } else if (!strcmp(key, "minLuminance") && meta_video_color) {
+ meta_video_color->mastering_meta.min_luminance = num_val;
}
}
if (amf_type == AMF_DATA_TYPE_STRING) {
@@ -824,6 +880,7 @@ static int flv_read_close(AVFormatContext *s)
av_freep(&flv->new_extradata[i]);
av_freep(&flv->keyframe_times);
av_freep(&flv->keyframe_filepositions);
+ av_freep(&flv->metaVideoColor);
return 0;
}
@@ -1028,6 +1085,104 @@ static int resync(AVFormatContext *s)
return AVERROR_EOF;
}
+static int flv_parse_video_color_info(AVFormatContext *s, AVStream *st, int64_t next_pos)
+{
+ FLVContext *flv = s->priv_data;
+ AMFDataType type;
+ AVIOContext *ioc;
+ char buffer[32];
+ ioc = s->pb;
+
+ // first object needs to be "colorInfo" string
+ type = avio_r8(ioc);
+ if (type != AMF_DATA_TYPE_STRING ||
+ amf_get_string(ioc, buffer, sizeof(buffer)) < 0)
+ return TYPE_UNKNOWN;
+
+ if (strcmp(buffer, "colorInfo")) {
+ av_log(s, AV_LOG_DEBUG, "Unknown type %s\n", buffer);
+ return TYPE_UNKNOWN;
+ }
+
+ flv->metaVideoColor = av_mallocz(sizeof(FLVMetaVideoColor));
+ if (!flv->metaVideoColor) {
+ return AVERROR(ENOMEM);
+ }
+ flv->meta_color_info_flag = 1;
+ amf_parse_object(s, NULL, NULL, buffer, next_pos, 0); // parse metadata
+ return 0;
+}
+
+static int flv_update_video_color_info(AVFormatContext *s, AVStream *st)
+{
+ FLVContext *flv = s->priv_data;
+ const FLVMetaVideoColor* meta_video_color = flv->metaVideoColor;
+ const FLVMasteringMeta *mastering_meta = &meta_video_color->mastering_meta;
+
+ int has_mastering_primaries, has_mastering_luminance;
+ // Mastering primaries are CIE 1931 coords, and must be > 0.
+ has_mastering_primaries =
+ mastering_meta->r_x > 0 && mastering_meta->r_y > 0 &&
+ mastering_meta->g_x > 0 && mastering_meta->g_y > 0 &&
+ mastering_meta->b_x > 0 && mastering_meta->b_y > 0 &&
+ mastering_meta->white_x > 0 && mastering_meta->white_y > 0;
+ has_mastering_luminance = mastering_meta->max_luminance >= 0 && mastering_meta->min_luminance >= 0;
+
+ if (meta_video_color->matrix_coefficients != AVCOL_SPC_RESERVED)
+ st->codecpar->color_space = meta_video_color->matrix_coefficients;
+ if (meta_video_color->primaries != AVCOL_PRI_RESERVED &&
+ meta_video_color->primaries != AVCOL_PRI_RESERVED0)
+ st->codecpar->color_primaries = meta_video_color->primaries;
+ if (meta_video_color->transfer_characteristics != AVCOL_TRC_RESERVED &&
+ meta_video_color->transfer_characteristics != AVCOL_TRC_RESERVED0)
+ st->codecpar->color_trc = meta_video_color->transfer_characteristics;
+
+ if (meta_video_color->max_cll && meta_video_color->max_fall) {
+ size_t size = 0;
+ AVContentLightMetadata *metadata = av_content_light_metadata_alloc(&size);
+ if (!metadata)
+ return AVERROR(ENOMEM);
+ if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data,
+ AV_PKT_DATA_CONTENT_LIGHT_LEVEL, metadata, size, 0)) {
+ av_freep(&metadata);
+ return AVERROR(ENOMEM);
+ }
+ metadata->MaxCLL = meta_video_color->max_cll;
+ metadata->MaxFALL = meta_video_color->max_fall;
+ }
+
+ if (has_mastering_primaries || has_mastering_luminance) {
+ AVMasteringDisplayMetadata *metadata;
+ AVPacketSideData *sd = av_packet_side_data_new(&st->codecpar->coded_side_data,
+ &st->codecpar->nb_coded_side_data,
+ AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
+ sizeof(AVMasteringDisplayMetadata), 0);
+ if (!sd)
+ return AVERROR(ENOMEM);
+ metadata = (AVMasteringDisplayMetadata*)sd->data;
+ memset(metadata, 0, sizeof(AVMasteringDisplayMetadata));
+ // hdrCll
+ if (has_mastering_luminance) {
+ metadata->max_luminance = av_d2q(mastering_meta->max_luminance, INT_MAX);
+ metadata->min_luminance = av_d2q(mastering_meta->min_luminance, INT_MAX);
+ metadata->has_luminance = 1;
+ }
+ // hdrMdcv
+ if (has_mastering_primaries) {
+ metadata->display_primaries[0][0] = av_d2q(mastering_meta->r_x, INT_MAX);
+ metadata->display_primaries[0][1] = av_d2q(mastering_meta->r_y, INT_MAX);
+ metadata->display_primaries[1][0] = av_d2q(mastering_meta->g_x, INT_MAX);
+ metadata->display_primaries[1][1] = av_d2q(mastering_meta->g_y, INT_MAX);
+ metadata->display_primaries[2][0] = av_d2q(mastering_meta->b_x, INT_MAX);
+ metadata->display_primaries[2][1] = av_d2q(mastering_meta->b_y, INT_MAX);
+ metadata->white_point[0] = av_d2q(mastering_meta->white_x, INT_MAX);
+ metadata->white_point[1] = av_d2q(mastering_meta->white_y, INT_MAX);
+ metadata->has_primaries = 1;
+ }
+ }
+ return 0;
+}
+
static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
{
FLVContext *flv = s->priv_data;
@@ -1100,8 +1255,17 @@ retry:
video_codec_id = avio_rb32(s->pb);
size -= 4;
}
- if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD)
+
+ if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO && (flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) {
+ type = flags & 0x0F;
+ if (type == PacketTypeMetadata) {
+ int ret = flv_parse_video_color_info(s, st, next);
+ av_log(s, AV_LOG_INFO, "enhanced flv parse metadata ret %d and skip\n", ret);
+ }
+ goto skip;
+ } else if ((flags & FLV_VIDEO_FRAMETYPE_MASK) == FLV_FRAME_VIDEO_INFO_CMD) {
goto skip;
+ }
} else if (type == FLV_TAG_TYPE_META) {
stream_type=FLV_STREAM_TYPE_SUBTITLE;
if (size > 13 + 1 + 4) { // Header-type metadata stuff
@@ -1287,6 +1451,11 @@ retry_duration:
goto leave;
}
+ if (enhanced_flv && stream_type == FLV_STREAM_TYPE_VIDEO && flv->meta_color_info_flag) {
+ flv_update_video_color_info(s, st); // update av packet side data
+ flv->meta_color_info_flag = 0;
+ }
+
if (st->codecpar->codec_id == AV_CODEC_ID_H264 || st->codecpar->codec_id == AV_CODEC_ID_MPEG4 ||
(st->codecpar->codec_id == AV_CODEC_ID_HEVC && type == PacketTypeCodedFrames)) {
// sign extension
--
2.42.1
_______________________________________________
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".
next reply other threads:[~2023-11-15 14:40 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-15 14:40 zhupengfei via ffmpeg-devel [this message]
2023-12-04 21:32 ` James Almer
2023-12-13 13:41 ` 朱鹏飞 via ffmpeg-devel
2023-12-17 16:24 ` [FFmpeg-devel] [PATCH v2 1/2] avformat/flvenc: " zhupengfei via ffmpeg-devel
2023-12-17 18:22 ` James Almer
2023-12-21 13:46 ` zhupengfei via ffmpeg-devel
2023-12-17 16:24 ` [FFmpeg-devel] [PATCH v2 2/2] avformat/flvdec: " zhupengfei via ffmpeg-devel
2024-01-11 16:15 ` [FFmpeg-devel] [PATCH v3 1/2] " zhupengfei via ffmpeg-devel
2024-01-11 16:17 ` [FFmpeg-devel] [PATCH v3 2/2] avformat/flvenc: " zhupengfei via ffmpeg-devel
2024-01-11 16:37 ` zhupengfei via ffmpeg-devel
2024-03-02 8:51 ` [FFmpeg-devel] [PATCH v4 1/3] avformat/flvdec: " zhupengfei via ffmpeg-devel
2024-03-02 14:25 ` James Almer
2024-03-02 15:05 ` Andreas Rheinhardt
2024-03-02 8:51 ` [FFmpeg-devel] [PATCH v4 2/3] avformat/flvenc: " zhupengfei via ffmpeg-devel
2024-03-02 14:59 ` Andreas Rheinhardt
2024-03-03 3:33 ` zhupengfei via ffmpeg-devel
2024-03-02 8:51 ` [FFmpeg-devel] [PATCH v4 3/3] fate/flvenc: " zhupengfei via ffmpeg-devel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=tencent_B9DCD1B361EE91197340C756B867C44C8A0A@qq.com \
--to=ffmpeg-devel@ffmpeg.org \
--cc=411294962@qq.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git