summaryrefslogtreecommitdiffstats
path: root/video/mp_image_pool.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-01-16 11:46:16 +0100
committerKevin Mitchell <kevmitch@gmail.com>2018-01-18 00:59:07 -0800
commitcda7203934012c56072d3da91e019673a4f9feab (patch)
tree2b5ee3339e19e907f66041a2656b57d8c7ea8d17 /video/mp_image_pool.c
parent0536ef306c5cdf03d4593f783cda9c0b6cebec60 (diff)
downloadmpv-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.c73
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;
+}