diff options
author | wm4 <wm4@nowhere> | 2018-01-16 11:46:16 +0100 |
---|---|---|
committer | Kevin Mitchell <kevmitch@gmail.com> | 2018-01-18 00:59:07 -0800 |
commit | cda7203934012c56072d3da91e019673a4f9feab (patch) | |
tree | 2b5ee3339e19e907f66041a2656b57d8c7ea8d17 /video/mp_image_pool.c | |
parent | 0536ef306c5cdf03d4593f783cda9c0b6cebec60 (diff) | |
download | mpv-cda7203934012c56072d3da91e019673a4f9feab.tar.bz2 mpv-cda7203934012c56072d3da91e019673a4f9feab.tar.xz |
mp_image_pool: add helper functions for FFmpeg hw frames pools
FFmpeg has its own rather "special" image pools (AVHWFramesContext)
specifically for hardware decoding. So it's not really practical to use
our own pool implementation. Add these helpers, which make it easier to
use FFmpeg's code in mpv.
Diffstat (limited to 'video/mp_image_pool.c')
-rw-r--r-- | video/mp_image_pool.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/video/mp_image_pool.c b/video/mp_image_pool.c index c526772981..17d1087740 100644 --- a/video/mp_image_pool.c +++ b/video/mp_image_pool.c @@ -344,3 +344,76 @@ done: mp_image_copy_attributes(hw_img, src); return ok; } + +bool mp_update_av_hw_frames_pool(struct AVBufferRef **hw_frames_ctx, + struct AVBufferRef *hw_device_ctx, + int imgfmt, int sw_imgfmt, int w, int h) +{ + enum AVPixelFormat format = imgfmt2pixfmt(imgfmt); + enum AVPixelFormat sw_format = imgfmt2pixfmt(sw_imgfmt); + + if (format == AV_PIX_FMT_NONE || sw_format == AV_PIX_FMT_NONE || + !hw_device_ctx || w < 1 || h < 1) + { + av_buffer_unref(hw_frames_ctx); + return false; + } + + if (*hw_frames_ctx) { + AVHWFramesContext *hw_frames = (void *)(*hw_frames_ctx)->data; + + if (hw_frames->device_ref->data != hw_device_ctx->data || + hw_frames->format != format || hw_frames->sw_format != sw_format || + hw_frames->width != w || hw_frames->height != h) + av_buffer_unref(hw_frames_ctx); + } + + if (!*hw_frames_ctx) { + *hw_frames_ctx = av_hwframe_ctx_alloc(hw_device_ctx); + if (!*hw_frames_ctx) + return false; + + AVHWFramesContext *hw_frames = (void *)(*hw_frames_ctx)->data; + hw_frames->format = format; + hw_frames->sw_format = sw_format; + hw_frames->width = w; + hw_frames->height = h; + if (av_hwframe_ctx_init(*hw_frames_ctx) < 0) { + av_buffer_unref(hw_frames_ctx); + return false; + } + } + + return true; +} + +struct mp_image *mp_av_pool_image_hw_upload(struct AVBufferRef *hw_frames_ctx, + struct mp_image *src) +{ + AVFrame *av_frame = av_frame_alloc(); + if (!av_frame) + return NULL; + if (av_hwframe_get_buffer(hw_frames_ctx, av_frame, 0) < 0) { + av_frame_free(&av_frame); + return NULL; + } + struct mp_image *dst = mp_image_from_av_frame(av_frame); + av_frame_free(&av_frame); + if (!dst) + return NULL; + + if (dst->w < src->w || dst->h < src->h) { + talloc_free(dst); + return NULL; + } + + mp_image_set_size(dst, src->w, src->h); + + if (!mp_image_hw_upload(dst, src)) { + talloc_free(dst); + return NULL; + } + + mp_image_copy_attributes(dst, src); + return dst; +} |