summaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--video/mp_image_pool.c73
-rw-r--r--video/mp_image_pool.h8
2 files changed, 81 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;
+}
diff --git a/video/mp_image_pool.h b/video/mp_image_pool.h
index a49771ffbb..7c9f0463cb 100644
--- a/video/mp_image_pool.h
+++ b/video/mp_image_pool.h
@@ -31,4 +31,12 @@ struct mp_image *mp_image_hw_download(struct mp_image *img,
bool mp_image_hw_upload(struct mp_image *hw_img, struct mp_image *src);
+struct AVBufferRef;
+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);
+
+struct mp_image *mp_av_pool_image_hw_upload(struct AVBufferRef *hw_frames_ctx,
+ struct mp_image *src);
+
#endif