summaryrefslogtreecommitdiffstats
path: root/video/mp_image_pool.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-01-12 12:51:55 +0100
committerwm4 <wm4@nowhere>2017-01-12 13:58:28 +0100
commit06b30cc81f86ce31ad35399ccfc432a316a09e0d (patch)
treecb008b92b49e1eed3e52ae9d26e7bd159ce0c9f1 /video/mp_image_pool.c
parent162c2e2d00c46c989fdf116181a21f8701ad99be (diff)
downloadmpv-06b30cc81f86ce31ad35399ccfc432a316a09e0d.tar.bz2
mpv-06b30cc81f86ce31ad35399ccfc432a316a09e0d.tar.xz
vaapi: use libavutil functions for copying hw surfaces to memory
Makes va_surface_download() call mp_image_hw_download() for libavutil-allocated surfaces, which in turn calls av_hwframe_transfer_data(). mp_image_hw_download() is actually not specific to vaapi, and can be used for any hw surface allocated by libavutil.
Diffstat (limited to 'video/mp_image_pool.c')
-rw-r--r--video/mp_image_pool.c63
1 files changed, 62 insertions, 1 deletions
diff --git a/video/mp_image_pool.c b/video/mp_image_pool.c
index 10966eeefc..de835b4d93 100644
--- a/video/mp_image_pool.c
+++ b/video/mp_image_pool.c
@@ -23,12 +23,14 @@
#include <assert.h>
#include <libavutil/buffer.h>
+#include <libavutil/hwcontext.h>
#include "mpv_talloc.h"
#include "common/common.h"
-#include "video/mp_image.h"
+#include "fmt-conversion.h"
+#include "mp_image.h"
#include "mp_image_pool.h"
static pthread_mutex_t pool_mutex = PTHREAD_MUTEX_INITIALIZER;
@@ -247,3 +249,62 @@ void mp_image_pool_set_lru(struct mp_image_pool *pool)
{
pool->use_lru = true;
}
+
+
+// Copies the contents of the HW surface img to system memory and retuns it.
+// If swpool is not NULL, it's used to allocate the target image.
+// img must be a hw surface with a AVHWFramesContext attached. If not, you
+// must use the legacy mp_hwdec_ctx.download_image.
+// The returned image is cropped as needed.
+// Returns NULL on failure.
+struct mp_image *mp_image_hw_download(struct mp_image *src,
+ struct mp_image_pool *swpool)
+{
+ if (!src->hwctx)
+ return NULL;
+ AVHWFramesContext *fctx = (void *)src->hwctx->data;
+
+ // Try to find the first format which we can apparently use.
+ int imgfmt = 0;
+ enum AVPixelFormat *fmts;
+ if (av_hwframe_transfer_get_formats(src->hwctx,
+ AV_HWFRAME_TRANSFER_DIRECTION_FROM, &fmts, 0) < 0)
+ return NULL;
+ for (int n = 0; fmts[n] != AV_PIX_FMT_NONE; n++) {
+ imgfmt = pixfmt2imgfmt(fmts[n]);
+ if (imgfmt)
+ break;
+ }
+ av_free(fmts);
+
+ if (!imgfmt)
+ return NULL;
+
+ struct mp_image *dst =
+ mp_image_pool_get(swpool, imgfmt, fctx->width, fctx->height);
+ if (!dst)
+ return NULL;
+
+ // Target image must be writable, so unref it.
+ AVFrame *dstav = mp_image_to_av_frame_and_unref(dst);
+ if (!dstav)
+ return NULL;
+
+ AVFrame *srcav = mp_image_to_av_frame(src);
+ if (!srcav) {
+ av_frame_unref(dstav);
+ return NULL;
+ }
+
+ int res = av_hwframe_transfer_data(dstav, srcav, 0);
+ av_frame_unref(srcav);
+ dst = mp_image_from_av_frame(dstav);
+ av_frame_unref(dstav);
+ if (res >= 0) {
+ mp_image_set_size(dst, src->w, src->h);
+ mp_image_copy_attributes(dst, src);
+ } else {
+ mp_image_unrefp(&dst);
+ }
+ return dst;
+}