diff options
-rw-r--r-- | common/av_common.c | 35 | ||||
-rw-r--r-- | common/av_common.h | 3 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 6 | ||||
-rw-r--r-- | video/mp_image.c | 26 |
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; |