summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/av_common.c35
-rw-r--r--common/av_common.h3
-rw-r--r--video/decode/vd_lavc.c6
-rw-r--r--video/mp_image.c26
4 files changed, 62 insertions, 8 deletions
diff --git a/common/av_common.c b/common/av_common.c
index c91da79634..d3237250ef 100644
--- a/common/av_common.c
+++ b/common/av_common.c
@@ -352,3 +352,38 @@ int mp_set_avopts(struct mp_log *log, void *avobj, char **kv)
}
return success;
}
+
+AVFrameSideData *ffmpeg_garbage(AVFrame *frame,
+ enum AVFrameSideDataType type,
+ AVBufferRef *buf)
+{
+ AVFrameSideData *ret, **tmp;
+
+ if (!buf)
+ return NULL;
+
+ if (frame->nb_side_data > INT_MAX / sizeof(*frame->side_data) - 1)
+ goto fail;
+
+ tmp = av_realloc(frame->side_data,
+ (frame->nb_side_data + 1) * sizeof(*frame->side_data));
+ if (!tmp)
+ goto fail;
+ frame->side_data = tmp;
+
+ ret = av_mallocz(sizeof(*ret));
+ if (!ret)
+ goto fail;
+
+ ret->buf = buf;
+ ret->data = ret->buf->data;
+ ret->size = buf->size;
+ ret->type = type;
+
+ frame->side_data[frame->nb_side_data++] = ret;
+
+ return ret;
+fail:
+ av_buffer_unref(&buf);
+ return NULL;
+}
diff --git a/common/av_common.h b/common/av_common.h
index 1d30fab71f..6d0c823b8d 100644
--- a/common/av_common.h
+++ b/common/av_common.h
@@ -46,5 +46,8 @@ const char *mp_codec_from_av_codec_id(int codec_id);
void mp_set_avdict(struct AVDictionary **dict, char **kv);
void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d);
int mp_set_avopts(struct mp_log *log, void *avobj, char **kv);
+AVFrameSideData *ffmpeg_garbage(AVFrame *frame,
+ enum AVFrameSideDataType type,
+ AVBufferRef *buf);
#endif
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index f036a630b5..513eded9a4 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -1167,12 +1167,6 @@ static bool decode_frame(struct dec_video *vd)
mp_pts_from_av(av_frame_get_pkt_duration(ctx->pic), &ctx->codec_timebase);
#endif
-#if HAVE_AVUTIL_ICC_PROFILE
- sd = av_frame_get_side_data(ctx->pic, AV_FRAME_DATA_ICC_PROFILE);
- if (sd)
- mpi->icc_profile = av_buffer_ref(sd->buf);
-#endif
-
update_image_params(vd, ctx->pic, &mpi->params);
av_frame_unref(ctx->pic);
diff --git a/video/mp_image.c b/video/mp_image.c
index 401144424a..18d700df15 100644
--- a/video/mp_image.c
+++ b/video/mp_image.c
@@ -29,6 +29,7 @@
#include "mpv_talloc.h"
#include "config.h"
+#include "common/av_common.h"
#include "common/common.h"
#include "hwdec.h"
#include "mp_image.h"
@@ -826,6 +827,7 @@ void mp_image_params_guess_csp(struct mp_image_params *params)
struct mp_image *mp_image_from_av_frame(struct AVFrame *src)
{
struct mp_image *dst = &(struct mp_image){0};
+ AVFrameSideData *sd;
for (int p = 0; p < MP_MAX_PLANES; p++)
dst->bufs[p] = src->buf[p];
@@ -880,9 +882,16 @@ struct mp_image *mp_image_from_av_frame(struct AVFrame *src)
}
#endif
+#if HAVE_AVUTIL_ICC_PROFILE
+ sd = av_frame_get_side_data(src, AV_FRAME_DATA_ICC_PROFILE);
+ if (sd)
+ dst->icc_profile = av_buffer_ref(sd->buf);
+#endif
+
return mp_image_new_ref(dst);
}
+
// Convert the mp_image reference to a AVFrame reference.
struct AVFrame *mp_image_to_av_frame(struct mp_image *src)
{
@@ -894,10 +903,13 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src)
return NULL;
}
- for (int p = 0; p < MP_MAX_PLANES; p++)
+ for (int p = 0; p < MP_MAX_PLANES; p++) {
dst->buf[p] = new_ref->bufs[p];
+ new_ref->bufs[p] = NULL;
+ }
dst->hw_frames_ctx = new_ref->hwctx;
+ new_ref->hwctx = NULL;
dst->format = imgfmt2pixfmt(src->imgfmt);
dst->width = src->w;
@@ -935,8 +947,18 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src)
*(struct mp_image_params *)dst->opaque_ref->data = src->params;
#endif
- *new_ref = (struct mp_image){0};
+#if HAVE_AVUTIL_ICC_PROFILE
+ if (src->icc_profile) {
+ AVFrameSideData *sd =
+ ffmpeg_garbage(dst, AV_FRAME_DATA_ICC_PROFILE, new_ref->icc_profile);
+ if (!sd)
+ abort();
+ new_ref->icc_profile = NULL;
+ }
+#endif
+
talloc_free(new_ref);
+
if (dst->format == AV_PIX_FMT_NONE)
av_frame_free(&dst);
return dst;