Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Lynne via ffmpeg-devel <ffmpeg-devel@ffmpeg.org>
To: ffmpeg-devel@ffmpeg.org
Cc: Lynne <code@ffmpeg.org>
Subject: [FFmpeg-devel] [PATCH] ID3v2 fixes for FLAC, add V-Log transfer function (PR #20533)
Date: Tue, 16 Sep 2025 15:17:06 -0000
Message-ID: <175803582731.25.7871988420394065661@463a07221176> (raw)

PR #20533 opened by Lynne
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20533
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20533.patch


>From f46d078521e6ce8fe2ce2648ae7d29367eb9c928 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 27 Aug 2025 17:39:16 +0900
Subject: [PATCH 1/6] lavf/id3v2: report incorrect BOM value on error

---
 libavformat/id3v2.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c
index 037d1a2e23..849f22c60d 100644
--- a/libavformat/id3v2.c
+++ b/libavformat/id3v2.c
@@ -273,13 +273,14 @@ static int decode_str(AVFormatContext *s, AVIOContext *pb, int encoding,
             *dst = NULL;
             return AVERROR_INVALIDDATA;
         }
-        switch (avio_rb16(pb)) {
+        uint16_t bom = avio_rb16(pb);
+        switch (bom) {
         case 0xfffe:
             get = avio_rl16;
         case 0xfeff:
             break;
         default:
-            av_log(s, AV_LOG_ERROR, "Incorrect BOM value\n");
+            av_log(s, AV_LOG_ERROR, "Incorrect BOM value: 0x%x\n", bom);
             ffio_free_dyn_buf(&dynbuf);
             *dst = NULL;
             *maxread = left;
-- 
2.49.1


>From d8469a806842e8dacc67dbe9bfea64452a29fc38 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 17 Sep 2025 00:11:11 +0900
Subject: [PATCH 2/6] lavf: fix demuxing of FLAC files with id3v2 tags

Due to the recent id3v2 refactor, FLAC was left out due to
id3v2 tags not being that popular for FLAC.

A lot of rips from Asia still use id3v2, however. This fixes
their demuxing.
---
 libavformat/flacdec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavformat/flacdec.c b/libavformat/flacdec.c
index fc90c01ddf..bca0faaa2f 100644
--- a/libavformat/flacdec.c
+++ b/libavformat/flacdec.c
@@ -374,7 +374,7 @@ static int flac_seek(AVFormatContext *s, int stream_index, int64_t timestamp, in
 const FFInputFormat ff_flac_demuxer = {
     .p.name         = "flac",
     .p.long_name    = NULL_IF_CONFIG_SMALL("raw FLAC"),
-    .p.flags        = AVFMT_GENERIC_INDEX,
+    .p.flags        = AVFMT_GENERIC_INDEX | AVFMT_FLAG_ID3V2_AUTO,
     .p.extensions   = "flac",
     .p.priv_class   = &ff_raw_demuxer_class,
     .read_probe     = flac_probe,
-- 
2.49.1


>From 898daa0f9ca83614e0f710730ba8d3942f596b21 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Wed, 27 Aug 2025 21:50:32 +0900
Subject: [PATCH 3/6] lavu: add support for Panasonic V-Log transfer function

---
 libavcodec/fflcms2.c        |  1 +
 libavfilter/vf_libplacebo.c |  1 +
 libavfilter/vf_setparams.c  |  1 +
 libavutil/csp.c             | 28 ++++++++++++++++++++++++++++
 libavutil/pixdesc.c         |  1 +
 libavutil/pixfmt.h          |  6 ++++++
 libswscale/format.c         |  3 ++-
 7 files changed, 40 insertions(+), 1 deletion(-)

diff --git a/libavcodec/fflcms2.c b/libavcodec/fflcms2.c
index 3b67e62d3a..3d3241f5a3 100644
--- a/libavcodec/fflcms2.c
+++ b/libavcodec/fflcms2.c
@@ -128,6 +128,7 @@ static int get_curve(FFIccContext *s, enum AVColorTransferCharacteristic trc,
     case AVCOL_TRC_BT1361_ECG:
     case AVCOL_TRC_SMPTE2084:
     case AVCOL_TRC_ARIB_STD_B67:
+    case AVCOL_TRC_V_LOG:
         return AVERROR_PATCHWELCOME;
 
     default:
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 5e0a678ff2..f5a3c55aa8 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -1612,6 +1612,7 @@ static const AVOption libplacebo_options[] = {
     {"bt2020-12",                      NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_BT2020_12},    INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
     {"smpte2084",                      NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084},    INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
     {"arib-std-b67",                   NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
+    {"vlog",                           NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_V_LOG},        INT_MIN, INT_MAX, STATIC, .unit = "color_trc"},
 
     {"rotate", "rotate the input clockwise", OFFSET(rotation), AV_OPT_TYPE_INT, {.i64=PL_ROTATION_0}, PL_ROTATION_0, PL_ROTATION_360, DYNAMIC, .unit = "rotation"},
     {"0",                              NULL,  0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_0},   .flags = STATIC, .unit = "rotation"},
diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c
index f32757f940..be0323fd83 100644
--- a/libavfilter/vf_setparams.c
+++ b/libavfilter/vf_setparams.c
@@ -101,6 +101,7 @@ static const AVOption setparams_options[] = {
     {"smpte2084",                      NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE2084},    0, 0, FLAGS, .unit = "color_trc"},
     {"smpte428",                       NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_SMPTE428},     0, 0, FLAGS, .unit = "color_trc"},
     {"arib-std-b67",                   NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_ARIB_STD_B67}, 0, 0, FLAGS, .unit = "color_trc"},
+    {"vlog",                           NULL,  0, AV_OPT_TYPE_CONST, {.i64=AVCOL_TRC_V_LOG},        0, 0, FLAGS, .unit = "color_trc"},
 
     {"colorspace", "select colorspace", OFFSET(colorspace), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVCOL_SPC_NB-1, FLAGS, .unit = "colorspace"},
     {"auto", "keep the same colorspace",  0, AV_OPT_TYPE_CONST, {.i64=-1},                          0, 0, FLAGS, .unit = "colorspace"},
diff --git a/libavutil/csp.c b/libavutil/csp.c
index 75ac871616..8ea47d6c55 100644
--- a/libavutil/csp.c
+++ b/libavutil/csp.c
@@ -378,6 +378,32 @@ static double trc_arib_std_b67_inv(double E)
         (E <= 0.5 ? E * E / 3.0 : (exp((E - c) / a) + b) / 12.0);
 }
 
+#define VLOG_c1 0.01
+#define VLOG_c2 0.181
+#define VLOG_b  0.00873
+#define VLOG_c  0.241514
+#define VLOG_d  0.598206
+
+static double trc_vlog(double E)
+{
+    const double c2 = VLOG_c2;
+    const double b = VLOG_b;
+    const double c = VLOG_c;
+    const double d = VLOG_d;
+    return (E < c2) ? (E - 0.125) / 5.6 :
+        (pow(10.0, ((E - d) / c)) - b);
+}
+
+static double trc_vlog_inv(double E)
+{
+    const double c1 = VLOG_c1;
+    const double b = VLOG_b;
+    const double c = VLOG_c;
+    const double d = VLOG_d;
+    return (E < c1) ? (5.6 * E + 0.125) :
+        (c * log10(E + b) + d);
+}
+
 static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = {
     [AVCOL_TRC_BT709] = trc_bt709,
     [AVCOL_TRC_GAMMA22] = trc_gamma22,
@@ -395,6 +421,7 @@ static const av_csp_trc_function trc_funcs[AVCOL_TRC_NB] = {
     [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084,
     [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1,
     [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67,
+    [AVCOL_TRC_V_LOG] = trc_vlog,
 };
 
 av_csp_trc_function av_csp_trc_func_from_id(enum AVColorTransferCharacteristic trc)
@@ -421,6 +448,7 @@ static const av_csp_trc_function trc_inv_funcs[AVCOL_TRC_NB] = {
     [AVCOL_TRC_SMPTE2084] = trc_smpte_st2084_inv,
     [AVCOL_TRC_SMPTE428] = trc_smpte_st428_1_inv,
     [AVCOL_TRC_ARIB_STD_B67] = trc_arib_std_b67_inv,
+    [AVCOL_TRC_V_LOG] = trc_vlog_inv,
 };
 
 av_csp_trc_function av_csp_trc_func_inv_from_id(enum AVColorTransferCharacteristic trc)
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index 3c31ee2132..0ce12cbc6f 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -3312,6 +3312,7 @@ static const char * const color_transfer_names[] = {
     [AVCOL_TRC_SMPTE2084] = "smpte2084",
     [AVCOL_TRC_SMPTE428] = "smpte428",
     [AVCOL_TRC_ARIB_STD_B67] = "arib-std-b67",
+    [AVCOL_TRC_V_LOG] = "vlog",
 };
 
 static const char * const color_space_names[] = {
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index 6aa1c94cec..0be397d978 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -680,6 +680,12 @@ enum AVColorTransferCharacteristic {
     AVCOL_TRC_SMPTE428     = 17, ///< SMPTE ST 428-1
     AVCOL_TRC_SMPTEST428_1 = AVCOL_TRC_SMPTE428,
     AVCOL_TRC_ARIB_STD_B67 = 18, ///< ARIB STD-B67, known as "Hybrid log-gamma"
+
+    /**
+     * NOTE: The following transfer functions are not a part of H.274
+     */
+
+    AVCOL_TRC_V_LOG        = 256, ///< Panasonic V-Log
     AVCOL_TRC_NB                 ///< Not part of ABI
 };
 
diff --git a/libswscale/format.c b/libswscale/format.c
index 9741688e98..e5798bc865 100644
--- a/libswscale/format.c
+++ b/libswscale/format.c
@@ -1270,9 +1270,10 @@ static AVRational *generate_bayer_matrix(const int size_log2)
 
 static bool trc_is_hdr(enum AVColorTransferCharacteristic trc)
 {
-    static_assert(AVCOL_TRC_NB == 19, "Update this list when adding TRCs");
+    static_assert(AVCOL_TRC_NB == 257, "Update this list when adding TRCs");
     switch (trc) {
     case AVCOL_TRC_LOG:
+    case AVCOL_TRC_V_LOG:
     case AVCOL_TRC_LOG_SQRT:
     case AVCOL_TRC_SMPTEST2084:
     case AVCOL_TRC_ARIB_STD_B67:
-- 
2.49.1


>From 6cb16c86d8aacd547a0d6252eb21eb4c2f5bad52 Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 28 Aug 2025 15:10:26 +0900
Subject: [PATCH 4/6] prores_raw: set color_trc based on the vendor tag

This is the only identifiable piece of information about the
colorspace, apart from the XML embedded in the MOV comments.
---
 libavcodec/prores_raw.c        | 17 ++++++++++++++++-
 libavcodec/prores_raw_parser.c | 17 ++++++++++++++++-
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index b2aa97ddda..71056014fc 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -359,7 +359,22 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     /* Vendor header (e.g. "peac" for Panasonic or "atm0" for Atmos) */
-    bytestream2_skip(&gb_hdr, 4);
+    uint32_t vendor = bytestream2_get_be32(&gb_hdr);
+    switch (vendor) {
+    case MKBETAG('p','e','a','c'):
+        /* Internal recording from a Panasonic camera, V-Log */
+        avctx->color_trc = AVCOL_TRC_V_LOG;
+        break;
+    case MKBETAG('a','t','m','0'):
+        /* External recording from an Atomos recorder. Cameras universally
+         * record in their own native log curve internally, but linearize it
+         * when outputting RAW externally */
+        avctx->color_trc = AVCOL_TRC_LINEAR;
+        break;
+    default:
+        avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
+        break;
+    }
 
     /* Width and height must always be even */
     int w = bytestream2_get_be16(&gb_hdr);
diff --git a/libavcodec/prores_raw_parser.c b/libavcodec/prores_raw_parser.c
index fca3ec37fb..d0dfdd9e86 100644
--- a/libavcodec/prores_raw_parser.c
+++ b/libavcodec/prores_raw_parser.c
@@ -61,7 +61,22 @@ static int prores_raw_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     }
 
     /* Vendor header (e.g. "peac" for Panasonic or "atm0" for Atmos) */
-    bytestream2_skip(&gb, 4);
+    uint32_t vendor = bytestream2_get_be32(&gb);
+    switch (vendor) {
+    case MKBETAG('p','e','a','c'):
+        /* Internal recording from a Panasonic camera, V-Log */
+        avctx->color_trc = AVCOL_TRC_V_LOG;
+        break;
+    case MKBETAG('a','t','m','0'):
+        /* External recording from an Atomos recorder. Cameras universally
+         * record in their own native log curve internally, but linearize it
+         * when outputting RAW externally */
+        avctx->color_trc = AVCOL_TRC_LINEAR;
+        break;
+    default:
+        avctx->color_trc = AVCOL_TRC_UNSPECIFIED;
+        break;
+    }
 
     s->width = bytestream2_get_be16(&gb);
     s->height = bytestream2_get_be16(&gb);
-- 
2.49.1


>From cd97b2e07848c6752133dbf7be5689ed1259a5bd Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 28 Aug 2025 15:12:52 +0900
Subject: [PATCH 5/6] prores_raw: set profile based on the codec tag

This is the same as what the parser does.
---
 libavcodec/prores_raw.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index 71056014fc..ad47e144bf 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -334,6 +334,21 @@ static int decode_frame(AVCodecContext *avctx,
     DECLARE_ALIGNED(32, uint8_t, qmat)[64];
     memset(qmat, 1, 64);
 
+    switch (avctx->codec_tag) {
+    case 0:
+        break;
+    case MKTAG('a','p','r','n'):
+        avctx->profile = AV_PROFILE_PRORES_RAW;
+        break;
+    case MKTAG('a','p','r','h'):
+        avctx->profile = AV_PROFILE_PRORES_RAW_HQ;
+        break;
+    default:
+        avpriv_request_sample(avctx, "Profile %d", avctx->codec_tag);
+        return AVERROR_PATCHWELCOME;
+        break;
+    }
+
     GetByteContext gb;
     bytestream2_init(&gb, avpkt->data, avpkt->size);
     if (bytestream2_get_be32(&gb) != avpkt->size)
-- 
2.49.1


>From 7720356401e8aa87479deb87bb0213f8ee306aaf Mon Sep 17 00:00:00 2001
From: Lynne <dev@lynne.ee>
Date: Thu, 28 Aug 2025 15:14:03 +0900
Subject: [PATCH 6/6] prores_raw: use MKBETAG for the frame header tag

Equivalent, but more explicit. All values in the header are big endian.
---
 libavcodec/prores_raw.c        | 2 +-
 libavcodec/prores_raw_parser.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index ad47e144bf..beb11aa23f 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -355,7 +355,7 @@ static int decode_frame(AVCodecContext *avctx,
         return AVERROR_INVALIDDATA;
 
     /* ProRes RAW frame */
-    if (bytestream2_get_le32(&gb) != MKTAG('p','r','r','f'))
+    if (bytestream2_get_be32(&gb) != MKBETAG('p','r','r','f'))
         return AVERROR_INVALIDDATA;
 
     int header_len = bytestream2_get_be16(&gb);
diff --git a/libavcodec/prores_raw_parser.c b/libavcodec/prores_raw_parser.c
index d0dfdd9e86..fb690f243d 100644
--- a/libavcodec/prores_raw_parser.c
+++ b/libavcodec/prores_raw_parser.c
@@ -46,7 +46,7 @@ static int prores_raw_parse(AVCodecParserContext *s, AVCodecContext *avctx,
     if (bytestream2_get_be32(&gb) != buf_size) /* Packet size */
         return buf_size;
 
-    if (bytestream2_get_le32(&gb) != MKTAG('p','r','r','f')) /* Frame header */
+    if (bytestream2_get_be32(&gb) != MKBETAG('p','r','r','f')) /* Frame header */
         return buf_size;
 
     int header_size = bytestream2_get_be16(&gb);
-- 
2.49.1

_______________________________________________
ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org
To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org

             reply	other threads:[~2025-09-16 15:17 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-09-16 15:17 Lynne via ffmpeg-devel [this message]
2025-09-16 20:56 ` [FFmpeg-devel] " Kieran Kunhya 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=175803582731.25.7871988420394065661@463a07221176 \
    --to=ffmpeg-devel@ffmpeg.org \
    --cc=code@ffmpeg.org \
    /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