+static void clear_frame_metadata(PNGDecContext *s)
+{
+ av_freep(&s->iccp_data);
+ s->iccp_data_len = 0;
+ s->iccp_name[0] = 0;
+
+ s->stereo_mode = -1;
+
+ s->have_chrm = 0;
+
+ av_dict_free(&s->frame_metadata);
+}
+
+static int output_frame(PNGDecContext *s, AVFrame *f,
+ const AVFrame *src)
+{
+ int ret;
+
+ ret = av_frame_ref(f, src);
+ if (ret < 0)
+ return ret;
+
+ if (s->iccp_data) {
+ AVFrameSideData *sd = av_frame_new_side_data(f, AV_FRAME_DATA_ICC_PROFILE, s->iccp_data_len);
+ if (!sd) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+ memcpy(sd->data, s->iccp_data, s->iccp_data_len);
+
+ av_dict_set(&sd->metadata, "name", s->iccp_name, 0);
+ }
+
+ if (s->stereo_mode >= 0) {
+ AVStereo3D *stereo3d = av_stereo3d_create_side_data(f);
+ if (!stereo3d) {
+ ret = AVERROR(ENOMEM);
+ goto fail;
+ }
+
+ stereo3d->type = AV_STEREO3D_SIDEBYSIDE;
+ 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;
+fail:
+ av_frame_unref(f);
+ return ret;
+}
+