summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-02-20 08:39:55 +0100
committerwm4 <wm4@nowhere>2017-02-20 08:39:55 +0100
commit6aa4efd1e3205c9b1385865df1b5b09646d2160c (patch)
tree4a0f78718f21f7f644f9ca7de4fbcfb8a83aafa9
parent6e2d3d991912f230ee66448307e8e2657237ffd2 (diff)
downloadmpv-6aa4efd1e3205c9b1385865df1b5b09646d2160c.tar.bz2
mpv-6aa4efd1e3205c9b1385865df1b5b09646d2160c.tar.xz
vd_lavc, vaapi: move hw device creation to generic code
hw_vaapi.c didn't do much interesting anymore. Other than the function to create a device for decoding with vaapi-copy, everything can be done by generic code. Other libavcodec hwaccels are planned to provide the same API as vaapi. It will be possible to drop the other hw_ files in the future. They will use this generic code instead.
-rw-r--r--video/decode/hw_vaapi.c142
-rw-r--r--video/decode/hw_vaapi_old.c10
-rw-r--r--video/decode/lavc.h10
-rw-r--r--video/decode/vd_lavc.c77
-rw-r--r--video/hwdec.c2
-rw-r--r--video/hwdec.h6
-rw-r--r--video/vaapi.c13
-rw-r--r--video/vaapi.h4
-rw-r--r--wscript_build.py1
9 files changed, 104 insertions, 161 deletions
diff --git a/video/decode/hw_vaapi.c b/video/decode/hw_vaapi.c
deleted file mode 100644
index 81854207e2..0000000000
--- a/video/decode/hw_vaapi.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * This file is part of mpv.
- *
- * mpv is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * mpv is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with mpv. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stddef.h>
-#include <assert.h>
-
-#include <libavcodec/avcodec.h>
-#include <libavutil/common.h>
-#include <libavutil/hwcontext.h>
-#include <libavutil/hwcontext_vaapi.h>
-
-#include "config.h"
-
-#include "lavc.h"
-#include "common/common.h"
-#include "common/av_common.h"
-#include "video/fmt-conversion.h"
-#include "video/vaapi.h"
-#include "video/mp_image_pool.h"
-#include "video/hwdec.h"
-#include "video/filter/vf.h"
-
-struct priv {
- struct mp_log *log;
- struct mp_vaapi_ctx *ctx;
-};
-
-static void uninit(struct lavc_ctx *ctx)
-{
- struct priv *p = ctx->hwdec_priv;
-
- if (!p)
- return;
-
- va_destroy(p->ctx);
-
- talloc_free(p);
- ctx->hwdec_priv = NULL;
- ctx->hwdec_dev = NULL;
-}
-
-static int init(struct lavc_ctx *ctx, bool direct)
-{
- struct priv *p = talloc_ptrtype(NULL, p);
- *p = (struct priv) {
- .log = mp_log_new(p, ctx->log, "vaapi"),
- };
-
- if (direct) {
- ctx->hwdec_dev = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VAAPI);
- } else {
- p->ctx = va_create_standalone(ctx->log, false);
- if (!p->ctx) {
- talloc_free(p);
- return -1;
- }
- ctx->hwdec_dev = &p->ctx->hwctx;
- }
-
- ctx->hwdec_priv = p;
-
- if (!ctx->hwdec_dev->av_device_ref)
- return -1;
-
- return 0;
-}
-
-static int init_direct(struct lavc_ctx *ctx)
-{
- return init(ctx, true);
-}
-
-static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
- const char *codec)
-{
- if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VAAPI))
- return HWDEC_ERR_NO_CTX;
- return 0;
-}
-
-static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
- const char *codec)
-{
- struct mp_vaapi_ctx *dummy = va_create_standalone(ctx->log, true);
- if (!dummy)
- return HWDEC_ERR_NO_CTX;
- bool emulated = va_guess_if_emulated(dummy);
- va_destroy(dummy);
- if (emulated)
- return HWDEC_ERR_EMULATED;
- return 0;
-}
-
-static int init_copy(struct lavc_ctx *ctx)
-{
- return init(ctx, false);
-}
-
-const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
- .type = HWDEC_VAAPI,
- .image_format = IMGFMT_VAAPI,
- .probe = probe,
- .init = init_direct,
- .uninit = uninit,
- .generic_hwaccel = true,
- .static_pool = true,
- .pixfmt_map = (const enum AVPixelFormat[][2]) {
- {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_P010},
- {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12},
- {AV_PIX_FMT_NONE}
- },
-};
-
-const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
- .type = HWDEC_VAAPI_COPY,
- .copying = true,
- .image_format = IMGFMT_VAAPI,
- .probe = probe_copy,
- .init = init_copy,
- .uninit = uninit,
- .generic_hwaccel = true,
- .static_pool = true,
- .pixfmt_map = (const enum AVPixelFormat[][2]) {
- {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_P010},
- {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12},
- {AV_PIX_FMT_NONE}
- },
-};
diff --git a/video/decode/hw_vaapi_old.c b/video/decode/hw_vaapi_old.c
index 88379dfed8..fb0fc40110 100644
--- a/video/decode/hw_vaapi_old.c
+++ b/video/decode/hw_vaapi_old.c
@@ -327,11 +327,12 @@ static int init(struct lavc_ctx *ctx, bool direct)
if (direct) {
p->ctx = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VAAPI)->ctx;
} else {
- p->ctx = va_create_standalone(ctx->log, false);
- if (!p->ctx) {
+ struct mp_hwdec_ctx *hwctx = va_create_standalone(NULL, ctx->log, false);
+ if (!hwctx) {
talloc_free(p);
return -1;
}
+ p->ctx = hwctx->ctx;
p->own_ctx = true;
}
@@ -368,9 +369,10 @@ static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec,
const char *codec)
{
- struct mp_vaapi_ctx *dummy = va_create_standalone(ctx->log, true);
- if (!dummy)
+ struct mp_hwdec_ctx *hwctx = va_create_standalone(NULL, ctx->log, true);
+ if (!hwctx)
return HWDEC_ERR_NO_CTX;
+ struct mp_vaapi_ctx *dummy = hwctx->ctx;
bool emulated = va_guess_if_emulated(dummy);
va_destroy(dummy);
if (!hwdec_check_codec_support(codec, profiles))
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index b41d56ce2f..dfce9c3bfd 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -19,6 +19,8 @@
// This value does not yet include HWDEC_DELAY_QUEUE_COUNT.
#define HWDEC_EXTRA_SURFACES 4
+struct mpv_global;
+
typedef struct lavc_ctx {
struct mp_log *log;
struct MPOpts *opts;
@@ -95,9 +97,11 @@ struct vd_lavc_hwdec {
struct mp_image *(*allocate_image)(struct lavc_ctx *ctx, int w, int h);
// Process the image returned by the libavcodec decoder.
struct mp_image *(*process_image)(struct lavc_ctx *ctx, struct mp_image *img);
- // Optional; if a special hardware decoder is needed (instead of "hwaccel").
- const char *(*get_codec)(struct lavc_ctx *ctx, const char *codec);
- // Suffix for libavcodec decoder. If non-NULL, get_codec() is overridden
+ // For copy hwdecs. If probing is true, don't log errors if unavailable.
+ // The returned device must be freed with mp_hwdec_ctx->destroy.
+ struct mp_hwdec_ctx *(*create_dev)(struct mpv_global *global,
+ struct mp_log *log, bool probing);
+ // Suffix for libavcodec decoder. If non-NULL, the codec is overridden
// with hwdec_find_decoder.
// Intuitively, this will force the corresponding wrapper decoder.
const char *lavc_suffix;
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index cd054f7ea4..f89ec7e6cd 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -129,8 +129,6 @@ extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau;
extern const struct vd_lavc_hwdec mp_vd_lavc_vdpau_copy;
extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox;
extern const struct vd_lavc_hwdec mp_vd_lavc_videotoolbox_copy;
-extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi;
-extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy;
extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2;
extern const struct vd_lavc_hwdec mp_vd_lavc_dxva2_copy;
extern const struct vd_lavc_hwdec mp_vd_lavc_d3d11va;
@@ -172,6 +170,41 @@ static const struct vd_lavc_hwdec mp_vd_lavc_crystalhd = {
.copying = true,
};
+#if HAVE_VAAPI_HWACCEL
+#if HAVE_VAAPI_HWACCEL_NEW
+const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
+ .type = HWDEC_VAAPI,
+ .image_format = IMGFMT_VAAPI,
+ .generic_hwaccel = true,
+ .static_pool = true,
+ .pixfmt_map = (const enum AVPixelFormat[][2]) {
+ {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_P010},
+ {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12},
+ {AV_PIX_FMT_NONE}
+ },
+};
+
+#include "video/vaapi.h"
+
+const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
+ .type = HWDEC_VAAPI_COPY,
+ .copying = true,
+ .image_format = IMGFMT_VAAPI,
+ .generic_hwaccel = true,
+ .static_pool = true,
+ .create_dev = va_create_standalone,
+ .pixfmt_map = (const enum AVPixelFormat[][2]) {
+ {AV_PIX_FMT_YUV420P10, AV_PIX_FMT_P010},
+ {AV_PIX_FMT_YUV420P, AV_PIX_FMT_NV12},
+ {AV_PIX_FMT_NONE}
+ },
+};
+#else
+extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi;
+extern const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy;
+#endif
+#endif
+
static const struct vd_lavc_hwdec *const hwdec_list[] = {
#if HAVE_RPI
&mp_vd_lavc_rpi,
@@ -309,13 +342,37 @@ static bool hwdec_is_wrapper(struct vd_lavc_hwdec *hwdec, const char *decoder)
return bstr_endswith0(bstr0(decoder), hwdec->lavc_suffix);
}
+static struct mp_hwdec_ctx *hwdec_create_dev(struct dec_video *vd,
+ struct vd_lavc_hwdec *hwdec,
+ bool autoprobe)
+{
+ if (hwdec->create_dev)
+ return hwdec->create_dev(vd->global, vd->log, autoprobe);
+ if (vd->hwdec_devs) {
+ hwdec_devices_request(vd->hwdec_devs, hwdec->type);
+ return hwdec_devices_get(vd->hwdec_devs, hwdec->type);
+ }
+ return NULL;
+}
+
static int hwdec_probe(struct dec_video *vd, struct vd_lavc_hwdec *hwdec,
- const char *codec)
+ const char *codec, bool autoprobe)
{
vd_ffmpeg_ctx *ctx = vd->priv;
int r = 0;
if (hwdec->probe)
r = hwdec->probe(ctx, hwdec, codec);
+ if (hwdec->generic_hwaccel) {
+ assert(!hwdec->probe && !hwdec->init && !hwdec->init_decoder &&
+ !hwdec->uninit && !hwdec->allocate_image && !hwdec->process_image);
+ struct mp_hwdec_ctx *dev = hwdec_create_dev(vd, hwdec, autoprobe);
+ if (!dev)
+ return hwdec->copying ? -1 : HWDEC_ERR_NO_CTX;
+ if (dev->emulated)
+ r = HWDEC_ERR_EMULATED;
+ if (hwdec->create_dev && dev->destroy)
+ dev->destroy(dev);
+ }
if (r >= 0) {
if (hwdec->lavc_suffix && !hwdec_find_decoder(codec, hwdec->lavc_suffix))
return HWDEC_ERR_NO_CODEC;
@@ -333,7 +390,7 @@ static struct vd_lavc_hwdec *probe_hwdec(struct dec_video *vd, bool autoprobe,
MP_VERBOSE(vd, "Requested hardware decoder not compiled.\n");
return NULL;
}
- int r = hwdec_probe(vd, hwdec, codec);
+ int r = hwdec_probe(vd, hwdec, codec, autoprobe);
if (r == HWDEC_ERR_EMULATED) {
if (autoprobe)
return NULL;
@@ -421,8 +478,6 @@ static void reinit(struct dec_video *vd)
if (hwdec) {
const char *orig_decoder = decoder;
- if (hwdec->get_codec)
- decoder = hwdec->get_codec(ctx, decoder);
if (hwdec->lavc_suffix)
decoder = hwdec_find_decoder(codec, hwdec->lavc_suffix);
MP_VERBOSE(vd, "Trying hardware decoding.\n");
@@ -505,6 +560,11 @@ static void init_avctx(struct dec_video *vd, const char *decoder,
avctx->get_buffer2 = get_buffer2_hwdec;
if (ctx->hwdec->init && ctx->hwdec->init(ctx) < 0)
goto error;
+ if (ctx->hwdec->generic_hwaccel) {
+ ctx->hwdec_dev = hwdec_create_dev(vd, ctx->hwdec, false);
+ if (!ctx->hwdec_dev)
+ goto error;
+ }
ctx->max_delay_queue = ctx->hwdec->delay_queue;
ctx->hw_probing = true;
} else {
@@ -584,6 +644,11 @@ static void uninit_avctx(struct dec_video *vd)
av_freep(&ctx->avctx->extradata);
}
+ if (ctx->hwdec_dev && ctx->hwdec && ctx->hwdec->generic_hwaccel &&
+ ctx->hwdec_dev->destroy)
+ ctx->hwdec_dev->destroy(ctx->hwdec_dev);
+ ctx->hwdec_dev = NULL;
+
if (ctx->hwdec && ctx->hwdec->uninit)
ctx->hwdec->uninit(ctx);
ctx->hwdec = NULL;
diff --git a/video/hwdec.c b/video/hwdec.c
index 6db8d57869..371c368fa3 100644
--- a/video/hwdec.c
+++ b/video/hwdec.c
@@ -72,8 +72,6 @@ void hwdec_devices_set_loader(struct mp_hwdec_devices *devs,
devs->load_api_ctx = load_api_ctx;
}
-// Cause VO to lazily load the requested device, and will block until this is
-// done (even if not available).
void hwdec_devices_request(struct mp_hwdec_devices *devs, enum hwdec_type type)
{
if (devs->load_api && !hwdec_devices_get_first(devs))
diff --git a/video/hwdec.h b/video/hwdec.h
index f8a089e8c6..86b5521975 100644
--- a/video/hwdec.h
+++ b/video/hwdec.h
@@ -53,6 +53,9 @@ struct mp_hwdec_ctx {
// List of IMGFMT_s, terminated with 0. NULL if N/A.
int *supported_formats;
+ // Hint to generic code: it's using a wrapper API
+ bool emulated;
+
// Optional. Legacy. (New code should use AVHWFramesContext and
// mp_image_hw_download().)
// Allocates a software image from the pool, downloads the hw image from
@@ -62,6 +65,9 @@ struct mp_hwdec_ctx {
struct mp_image *(*download_image)(struct mp_hwdec_ctx *ctx,
struct mp_image *mpi,
struct mp_image_pool *swpool);
+
+ // Optional. Do not set for VO-bound devices.
+ void (*destroy)(struct mp_hwdec_ctx *ctx);
};
// Used to communicate hardware decoder device handles from VO to video decoder.
diff --git a/video/vaapi.c b/video/vaapi.c
index 5c8ce4c693..171ccdfcbd 100644
--- a/video/vaapi.c
+++ b/video/vaapi.c
@@ -210,6 +210,8 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
// libva drivers (such as the vdpau wraper). So don't error out on failure.
open_lavu_vaapi_device(res);
+ res->hwctx.emulated = va_guess_if_emulated(res);
+
return res;
error:
@@ -716,7 +718,13 @@ static const struct va_native_display *const native_displays[] = {
NULL
};
-struct mp_vaapi_ctx *va_create_standalone(struct mp_log *plog, bool probing)
+static void va_destroy_ctx(struct mp_hwdec_ctx *ctx)
+{
+ va_destroy(ctx->ctx);
+}
+
+struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
+ struct mp_log *plog, bool probing)
{
for (int n = 0; native_displays[n]; n++) {
VADisplay *display = NULL;
@@ -731,7 +739,8 @@ struct mp_vaapi_ctx *va_create_standalone(struct mp_log *plog, bool probing)
}
ctx->native_ctx = native_ctx;
ctx->destroy_native_ctx = native_displays[n]->destroy;
- return ctx;
+ ctx->hwctx.destroy = va_destroy_ctx;
+ return &ctx->hwctx;
}
}
return NULL;
diff --git a/video/vaapi.h b/video/vaapi.h
index de7d6d98d8..d21e3a34ee 100644
--- a/video/vaapi.h
+++ b/video/vaapi.h
@@ -73,6 +73,8 @@ void va_surface_init_subformat(struct mp_image *mpi);
bool va_guess_if_emulated(struct mp_vaapi_ctx *ctx);
-struct mp_vaapi_ctx *va_create_standalone(struct mp_log *plog, bool probing);
+struct mpv_global;
+struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
+ struct mp_log *plog, bool probing);
#endif
diff --git a/wscript_build.py b/wscript_build.py
index 82d1a879eb..4371426f1f 100644
--- a/wscript_build.py
+++ b/wscript_build.py
@@ -309,7 +309,6 @@ def build(ctx):
( "video/decode/hw_cuda.c", "cuda-hwaccel" ),
( "video/decode/hw_dxva2.c", "d3d-hwaccel" ),
( "video/decode/hw_d3d11va.c", "d3d-hwaccel" ),
- ( "video/decode/hw_vaapi.c", "vaapi-hwaccel-new" ),
( "video/decode/hw_vaapi_old.c", "vaapi-hwaccel-old" ),
( "video/decode/hw_vdpau.c", "vdpau-hwaccel" ),
( "video/decode/hw_videotoolbox.c", "videotoolbox-hwaccel" ),