Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 0/2] PNG cLLi and mDVc chunk support
@ 2024-02-03  2:28 Leo Izen
  2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 1/2] avcodec/pngdec: read cLLi and mDVc chunks Leo Izen
  2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 2/2] avcodec/pngenc: write " Leo Izen
  0 siblings, 2 replies; 3+ messages in thread
From: Leo Izen @ 2024-02-03  2:28 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Leo Izen

This adds support for cLLi and mDVc chunks in the PNG specification[1].

[1]: https://www.w3.org/TR/png-3/


Leo Izen (2):
  avcodec/pngdec: read cLLi and mDVc chunks
  avcodec/pngenc: write cLLi and mDVc chunks

 libavcodec/pngdec.c | 63 +++++++++++++++++++++++++++++++++++++++++++++
 libavcodec/pngenc.c | 32 ++++++++++++++++++++---
 2 files changed, 92 insertions(+), 3 deletions(-)

-- 
2.43.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".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [FFmpeg-devel] [PATCH 1/2] avcodec/pngdec: read cLLi and mDVc chunks
  2024-02-03  2:28 [FFmpeg-devel] [PATCH 0/2] PNG cLLi and mDVc chunk support Leo Izen
@ 2024-02-03  2:28 ` Leo Izen
  2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 2/2] avcodec/pngenc: write " Leo Izen
  1 sibling, 0 replies; 3+ messages in thread
From: Leo Izen @ 2024-02-03  2:28 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Leo Izen

These chunks contain the Content Light Level Information and the
Mastering Display Color Volume information that FFmpeg already supports
as AVFrameSideData. This patch adds support for the png decoder to read
these chunks if present and attach the corresponding side data to the
decoded frame.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
---
 libavcodec/pngdec.c | 63 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 63 insertions(+)

diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index d1aae4c70e..026da30c25 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -29,6 +29,7 @@
 #include "libavutil/csp.h"
 #include "libavutil/imgutils.h"
 #include "libavutil/intreadwrite.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/pixfmt.h"
 #include "libavutil/rational.h"
 #include "libavutil/stereo3d.h"
@@ -81,6 +82,14 @@ typedef struct PNGDecContext {
     enum AVColorPrimaries cicp_primaries;
     enum AVColorTransferCharacteristic cicp_trc;
     enum AVColorRange cicp_range;
+    int have_clli;
+    uint32_t clli_max;
+    uint32_t clli_avg;
+    int have_mdvc;
+    uint16_t mdvc_primaries[3][2];
+    uint16_t mdvc_white_point[2];
+    uint32_t mdvc_max_lum;
+    uint32_t mdvc_min_lum;
 
     enum PNGHeaderState hdr_state;
     enum PNGImageState pic_state;
@@ -731,6 +740,36 @@ static int populate_avctx_color_fields(AVCodecContext *avctx, AVFrame *frame)
     if (!s->has_trns && s->significant_bits > 0)
         avctx->bits_per_raw_sample = s->significant_bits;
 
+    if (s->have_clli) {
+        AVContentLightMetadata *clli =
+            av_content_light_metadata_create_side_data(frame);
+        if (!clli)
+            return AVERROR(ENOMEM);
+        /*
+         * 0.0001 divisor value
+         * see: https://www.w3.org/TR/png-3/#cLLi-chunk
+         */
+        clli->MaxCLL = s->clli_max / 10000;
+        clli->MaxFALL = s->clli_avg / 10000;
+    }
+
+    if (s->have_mdvc) {
+        AVMasteringDisplayMetadata *mdvc =
+            av_mastering_display_metadata_create_side_data(frame);
+        if (!mdvc)
+            return AVERROR(ENOMEM);
+        mdvc->has_primaries = 1;
+        for (int i = 0; i < 3; i++) {
+            mdvc->display_primaries[i][0] = av_make_q(s->mdvc_primaries[i][0], 50000);
+            mdvc->display_primaries[i][1] = av_make_q(s->mdvc_primaries[i][1], 50000);
+        }
+        mdvc->white_point[0] = av_make_q(s->mdvc_white_point[0], 50000);
+        mdvc->white_point[1] = av_make_q(s->mdvc_white_point[1], 50000);
+        mdvc->has_luminance = 1;
+        mdvc->max_luminance = av_make_q(s->mdvc_max_lum, 10000);
+        mdvc->min_luminance = av_make_q(s->mdvc_min_lum, 10000);
+    }
+
     return 0;
 }
 
@@ -1508,6 +1547,30 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
 
             break;
         }
+        case MKTAG('c', 'L', 'L', 'i'):
+            if (bytestream2_get_bytes_left(&gb_chunk) != 8) {
+                av_log(avctx, AV_LOG_WARNING, "Invalid cLLi chunk size: %d\n", bytestream2_get_bytes_left(&gb_chunk));
+                break;
+            }
+            s->have_clli = 1;
+            s->clli_max = bytestream2_get_be32u(&gb_chunk);
+            s->clli_avg = bytestream2_get_be32u(&gb_chunk);
+            break;
+        case MKTAG('m', 'D', 'V', 'c'):
+            if (bytestream2_get_bytes_left(&gb_chunk) != 24) {
+                av_log(avctx, AV_LOG_WARNING, "Invalid mDVc chunk size: %d\n", bytestream2_get_bytes_left(&gb_chunk));
+                break;
+            }
+            s->have_mdvc = 1;
+            for (int i = 0; i < 3; i++) {
+                s->mdvc_primaries[i][0] = bytestream2_get_be16u(&gb_chunk);
+                s->mdvc_primaries[i][1] = bytestream2_get_be16u(&gb_chunk);
+            }
+            s->mdvc_white_point[0] = bytestream2_get_be16u(&gb_chunk);
+            s->mdvc_white_point[1] = bytestream2_get_be16u(&gb_chunk);
+            s->mdvc_max_lum = bytestream2_get_be32u(&gb_chunk);
+            s->mdvc_min_lum = bytestream2_get_be32u(&gb_chunk);
+            break;
         case MKTAG('I', 'E', 'N', 'D'):
             if (!(s->pic_state & PNG_ALLIMAGE))
                 av_log(avctx, AV_LOG_ERROR, "IEND without all image\n");
-- 
2.43.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".

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [FFmpeg-devel] [PATCH 2/2] avcodec/pngenc: write cLLi and mDVc chunks
  2024-02-03  2:28 [FFmpeg-devel] [PATCH 0/2] PNG cLLi and mDVc chunk support Leo Izen
  2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 1/2] avcodec/pngdec: read cLLi and mDVc chunks Leo Izen
@ 2024-02-03  2:28 ` Leo Izen
  1 sibling, 0 replies; 3+ messages in thread
From: Leo Izen @ 2024-02-03  2:28 UTC (permalink / raw)
  To: ffmpeg-devel; +Cc: Leo Izen

These chunks contain the Content Light Level Information and the
Mastering Display Color Volume information that FFmpeg already supports
as AVFrameSideData. This patch adds support for the png encoder to save
this metadata as the corresponding chunks in the PNG stream.

Signed-off-by: Leo Izen <leo.izen@gmail.com>
---
 libavcodec/pngenc.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index f0650962d2..aab56d6d07 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -32,6 +32,7 @@
 #include "libavutil/crc.h"
 #include "libavutil/csp.h"
 #include "libavutil/libm.h"
+#include "libavutil/mastering_display_metadata.h"
 #include "libavutil/opt.h"
 #include "libavutil/rational.h"
 #include "libavutil/stereo3d.h"
@@ -294,8 +295,9 @@ static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size)
     return 0;
 }
 
-#define AV_WB32_PNG(buf, n) AV_WB32(buf, lrint((n) * 100000))
-#define AV_WB32_PNG_D(buf, d) AV_WB32_PNG(buf, av_q2d(d))
+#define PNG_LRINT(d, divisor) lrint((d) * (divisor))
+#define PNG_Q2D(q, divisor) PNG_LRINT(av_q2d(q), (divisor))
+#define AV_WB32_PNG_D(buf, q) AV_WB32(buf, PNG_Q2D(q, 10000))
 static int png_get_chrm(enum AVColorPrimaries prim,  uint8_t *buf)
 {
     const AVColorPrimariesDesc *desc = av_csp_primaries_desc_from_id(prim);
@@ -320,7 +322,7 @@ static int png_get_gama(enum AVColorTransferCharacteristic trc, uint8_t *buf)
     if (gamma <= 1e-6)
         return 0;
 
-    AV_WB32_PNG(buf, 1.0 / gamma);
+    AV_WB32(buf, PNG_LRINT(1.0 / gamma, 10000));
     return 1;
 }
 
@@ -437,6 +439,30 @@ static int encode_headers(AVCodecContext *avctx, const AVFrame *pict)
         png_write_chunk(&s->bytestream, MKTAG('c', 'I', 'C', 'P'), s->buf, 4);
     }
 
+    side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL);
+    if (side_data) {
+        AVContentLightMetadata *clli = (AVContentLightMetadata *) side_data->data;
+        AV_WB32(s->buf, clli->MaxCLL * 10000);
+        AV_WB32(s->buf + 4, clli->MaxFALL * 10000);
+        png_write_chunk(&s->bytestream, MKTAG('c', 'L', 'L', 'i'), s->buf, 8);
+    }
+
+    side_data = av_frame_get_side_data(pict, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA);
+    if (side_data) {
+        AVMasteringDisplayMetadata *mdvc = (AVMasteringDisplayMetadata *) side_data->data;
+        if (mdvc->has_luminance && mdvc->has_primaries) {
+            for (int i = 0; i < 3; i++) {
+                AV_WB16(s->buf + 2*i, PNG_Q2D(mdvc->display_primaries[i][0], 50000));
+                AV_WB16(s->buf + 2*i + 2, PNG_Q2D(mdvc->display_primaries[i][1], 50000));
+            }
+            AV_WB16(s->buf + 12, PNG_Q2D(mdvc->white_point[0], 50000));
+            AV_WB16(s->buf + 14, PNG_Q2D(mdvc->white_point[1], 50000));
+            AV_WB32(s->buf + 16, PNG_Q2D(mdvc->max_luminance, 10000));
+            AV_WB32(s->buf + 20, PNG_Q2D(mdvc->min_luminance, 10000));
+            png_write_chunk(&s->bytestream, MKTAG('m', 'D', 'V', 'c'), s->buf, 24);
+        }
+    }
+
     if (png_get_chrm(pict->color_primaries, s->buf))
         png_write_chunk(&s->bytestream, MKTAG('c', 'H', 'R', 'M'), s->buf, 32);
     if (png_get_gama(pict->color_trc, s->buf))
-- 
2.43.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".

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-02-03  2:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-03  2:28 [FFmpeg-devel] [PATCH 0/2] PNG cLLi and mDVc chunk support Leo Izen
2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 1/2] avcodec/pngdec: read cLLi and mDVc chunks Leo Izen
2024-02-03  2:28 ` [FFmpeg-devel] [PATCH 2/2] avcodec/pngenc: write " Leo Izen

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