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; diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c index ca1a186ca8..4333d5837f 100644 --- a/libavcodec/pngenc.c +++ b/libavcodec/pngenc.c @@ -29,10 +29,12 @@ #include "zlib_wrapper.h" #include "libavutil/avassert.h" +#include "libavutil/color_utils.h" #include "libavutil/crc.h" +#include "libavutil/csp.h" #include "libavutil/libm.h" #include "libavutil/opt.h" -#include "libavutil/color_utils.h" +#include "libavutil/rational.h" #include "libavutil/stereo3d.h" #include @@ -294,45 +296,22 @@ static int png_write_row(AVCodecContext *avctx, const uint8_t *data, int size) } #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)) static int png_get_chrm(enum AVColorPrimaries prim, uint8_t *buf) { - double rx, ry, gx, gy, bx, by, wx = 0.3127, wy = 0.3290; - switch (prim) { - case AVCOL_PRI_BT709: - rx = 0.640; ry = 0.330; - gx = 0.300; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_BT470M: - rx = 0.670; ry = 0.330; - gx = 0.210; gy = 0.710; - bx = 0.140; by = 0.080; - wx = 0.310; wy = 0.316; - break; - case AVCOL_PRI_BT470BG: - rx = 0.640; ry = 0.330; - gx = 0.290; gy = 0.600; - bx = 0.150; by = 0.060; - break; - case AVCOL_PRI_SMPTE170M: - case AVCOL_PRI_SMPTE240M: - rx = 0.630; ry = 0.340; - gx = 0.310; gy = 0.595; - bx = 0.155; by = 0.070; - break; - case AVCOL_PRI_BT2020: - rx = 0.708; ry = 0.292; - gx = 0.170; gy = 0.797; - bx = 0.131; by = 0.046; - break; - default: - return 0; - } + const AVColorPrimariesDesc *desc = av_csp_primaries_desc_from_id(prim); + if (!desc) + return 0; + + AV_WB32_PNG_D(buf, desc->wp.x); + AV_WB32_PNG_D(buf + 4, desc->wp.y); + AV_WB32_PNG_D(buf + 8, desc->prim.r.x); + AV_WB32_PNG_D(buf + 12, desc->prim.r.y); + AV_WB32_PNG_D(buf + 16, desc->prim.g.x); + AV_WB32_PNG_D(buf + 20, desc->prim.g.y); + AV_WB32_PNG_D(buf + 24, desc->prim.b.x); + AV_WB32_PNG_D(buf + 28, desc->prim.b.y); - AV_WB32_PNG(buf , wx); AV_WB32_PNG(buf + 4 , wy); - AV_WB32_PNG(buf + 8 , rx); AV_WB32_PNG(buf + 12, ry); - AV_WB32_PNG(buf + 16, gx); AV_WB32_PNG(buf + 20, gy); - AV_WB32_PNG(buf + 24, bx); AV_WB32_PNG(buf + 28, by); return 1; } diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc index 92fa0e526b..14de544639 100644 --- a/tests/ref/fate/png-icc +++ b/tests/ref/fate/png-icc @@ -33,7 +33,7 @@ interlaced_frame=0 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data index f40f14fea1..a4c16eb395 100644 --- a/tests/ref/fate/png-side-data +++ b/tests/ref/fate/png-side-data @@ -25,7 +25,7 @@ interlaced_frame=1 top_field_first=0 repeat_pict=0 color_range=pc -color_space=unknown +color_space=gbr color_primaries=unknown color_transfer=unknown chroma_location=unspecified @@ -34,15 +34,4 @@ side_data_type=ICC profile name=Photoshop ICC profile size=3144 [/SIDE_DATA] -[SIDE_DATA] -side_data_type=Mastering display metadata -red_x=63999/100000 -red_y=33001/100000 -green_x=30000/100000 -green_y=60000/100000 -blue_x=15000/100000 -blue_y=5999/100000 -white_point_x=31269/100000 -white_point_y=32899/100000 -[/SIDE_DATA] [/FRAME]