summaryrefslogtreecommitdiff
path: root/libavcodec/pngdec.c
diff options
context:
space:
mode:
authorLeo Izen <leo.izen@gmail.com>2023-01-17 11:09:29 -0500
committerLeo Izen <leo.izen@gmail.com>2023-01-25 08:09:16 -0500
commit2548c32cc10f256cc0ff90457631ef7ef94070af (patch)
tree4b869f29ca8079402f3bded4faafa68b8bbe67f9 /libavcodec/pngdec.c
parent843a4467131fd677aacb46b8bbdea898e4fe12d5 (diff)
downloadffmpeg-2548c32cc10f256cc0ff90457631ef7ef94070af.tar.gz
avcodec/png: use libavutil/csp.h for cHRM chunks
The cHRM chunk is descriptive. That is, it describes the primaries that should be used to interpret the pixel data in the PNG file. This is notably different from Mastering Display Metadata, which describes which subset of the presented gamut is relevant. MDM describes a gamut and says colors outside the gamut are not required to be preserved, but it does not actually describe the gamut that the pixel data from the frame resides in. Thus, to decode a cHRM chunk present in a PNG file to Mastering Display Metadata is incorrect. This commit changes this behavior so the cHRM chunk, if present, is decoded to color metadata. For example, if the cHRM chunk describes BT.709 primaries, the resulting AVFrame will be tagged with AVCOL_PRI_BT709, as a description of its pixel data. To do this, it utilizes libavutil/csp.h, which exposes a funcction av_csp_primaries_id_from_desc, to detect which enum value accurately describes the white point and primaries represented by the cHRM chunk. This commit also changes pngenc.c to utilize the libavuitl/csp.h API, since it previously duplicated code contained in that API. Instead, taking advantage of the API that exists makes more sense. pngenc.c does properly utilize the color tags rather than incorrectly using MDM, so that required no change. Signed-off-by: Leo Izen <leo.izen@gmail.com>
Diffstat (limited to 'libavcodec/pngdec.c')
-rw-r--r--libavcodec/pngdec.c46
1 files changed, 26 insertions, 20 deletions
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index f1cad26c52..32e7773bcb 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -26,10 +26,12 @@
#include "libavutil/avassert.h"
#include "libavutil/bprint.h"
#include "libavutil/crc.h"
+#include "libavutil/csp.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
+#include "libavutil/pixfmt.h"
+#include "libavutil/rational.h"
#include "libavutil/stereo3d.h"
-#include "libavutil/mastering_display_metadata.h"
#include "avcodec.h"
#include "bytestream.h"
@@ -1472,6 +1474,7 @@ static void clear_frame_metadata(PNGDecContext *s)
static int output_frame(PNGDecContext *s, AVFrame *f)
{
+ AVCodecContext *avctx = s->avctx;
int ret;
if (s->iccp_data) {
@@ -1483,8 +1486,30 @@ static int output_frame(PNGDecContext *s, AVFrame *f)
memcpy(sd->data, s->iccp_data, s->iccp_data_len);
av_dict_set(&sd->metadata, "name", s->iccp_name, 0);
+ } else if (s->have_chrm) {
+ AVColorPrimariesDesc desc;
+ enum AVColorPrimaries prim;
+ desc.wp.x = av_make_q(s->white_point[0], 100000);
+ desc.wp.y = av_make_q(s->white_point[1], 100000);
+ desc.prim.r.x = av_make_q(s->display_primaries[0][0], 100000);
+ desc.prim.r.y = av_make_q(s->display_primaries[0][1], 100000);
+ desc.prim.g.x = av_make_q(s->display_primaries[1][0], 100000);
+ desc.prim.g.y = av_make_q(s->display_primaries[1][1], 100000);
+ desc.prim.b.x = av_make_q(s->display_primaries[2][0], 100000);
+ desc.prim.b.y = av_make_q(s->display_primaries[2][1], 100000);
+ prim = av_csp_primaries_id_from_desc(&desc);
+ if (prim != AVCOL_PRI_UNSPECIFIED)
+ avctx->color_primaries = f->color_primaries = prim;
+ else
+ av_log(avctx, AV_LOG_WARNING, "unknown cHRM primaries\n");
}
+ /* this chunk overrides gAMA */
+ if (s->iccp_data)
+ av_dict_set(&s->frame_metadata, "gamma", NULL, 0);
+
+ avctx->colorspace = f->colorspace = AVCOL_SPC_RGB;
+
if (s->stereo_mode >= 0) {
AVStereo3D *stereo3d = av_stereo3d_create_side_data(f);
if (!stereo3d) {
@@ -1496,25 +1521,6 @@ static int output_frame(PNGDecContext *s, AVFrame *f)
stereo3d->flags = s->stereo_mode ? 0 : AV_STEREO3D_FLAG_INVERT;
}
- if (s->have_chrm) {
- AVMasteringDisplayMetadata *mdm = av_mastering_display_metadata_create_side_data(f);
- if (!mdm) {
- ret = AVERROR(ENOMEM);
- goto fail;
- }
-
- mdm->white_point[0] = av_make_q(s->white_point[0], 100000);
- mdm->white_point[1] = av_make_q(s->white_point[1], 100000);
-
- /* RGB Primaries */
- for (int i = 0; i < 3; i++) {
- mdm->display_primaries[i][0] = av_make_q(s->display_primaries[i][0], 100000);
- mdm->display_primaries[i][1] = av_make_q(s->display_primaries[i][1], 100000);
- }
-
- mdm->has_primaries = 1;
- }
-
FFSWAP(AVDictionary*, f->metadata, s->frame_metadata);
return 0;