aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorLeo Izen <leo.izen@gmail.com>2024-02-04 04:35:57 -0500
committerLeo Izen <leo.izen@gmail.com>2024-02-11 08:57:40 -0500
commitc7a57b0f70f8d1574aa0f0dbe98db85d8ac91c76 (patch)
treeb5447f6683452f25a0d2e76610d84ca91588c7af /libavcodec
parenteb4df2709ec41923b598650051c39b1eda392c8b (diff)
downloadffmpeg-c7a57b0f70f8d1574aa0f0dbe98db85d8ac91c76.tar.gz
avcodec/pngdec: read cLLi and mDVc chunks
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>
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/pngdec.c63
1 files changed, 63 insertions, 0 deletions
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");