summaryrefslogtreecommitdiffstats
path: root/video/decode/vd_lavc.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/decode/vd_lavc.c')
-rw-r--r--video/decode/vd_lavc.c61
1 files changed, 44 insertions, 17 deletions
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index dfca042ba0..c3e9ce5860 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -59,7 +59,7 @@
#include "core/m_option.h"
-static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec);
+static void init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec);
static void uninit_avctx(sh_video_t *sh);
static void setup_refcounting_hw(struct AVCodecContext *s);
static void draw_slice_hwdec(struct AVCodecContext *s, const AVFrame *src,
@@ -101,7 +101,7 @@ enum hwdec_type {
struct hwdec {
enum hwdec_type api;
- char *codec, *hw_codec;
+ const char *codec, *hw_codec;
};
static const struct hwdec hwdec[] = {
@@ -135,6 +135,18 @@ static struct hwdec *find_hwcodec(enum hwdec_type api, const char *codec)
return NULL;
}
+static bool hwdec_codec_allowed(sh_video_t *sh, struct hwdec *hwdec)
+{
+ bstr s = bstr0(sh->opts->hwdec_codecs);
+ while (s.len) {
+ bstr item;
+ bstr_split_tok(s, ",", &item, &s);
+ if (bstr_equals0(item, "all") || bstr_equals0(item, hwdec->codec))
+ return true;
+ }
+ return false;
+}
+
static enum AVDiscard str2AVDiscard(char *str)
{
if (!str) return AVDISCARD_DEFAULT;
@@ -155,28 +167,31 @@ static int init(sh_video_t *sh, const char *decoder)
ctx->non_dr1_pool = talloc_steal(ctx, mp_image_pool_new(16));
struct hwdec *hwdec = find_hwcodec(sh->opts->hwdec_api, decoder);
- if (hwdec) {
+ struct hwdec *use_hwdec = NULL;
+ if (hwdec && hwdec_codec_allowed(sh, hwdec)) {
AVCodec *lavc_hwcodec = avcodec_find_decoder_by_name(hwdec->hw_codec);
if (lavc_hwcodec) {
ctx->software_fallback_decoder = talloc_strdup(ctx, decoder);
decoder = lavc_hwcodec->name;
+ use_hwdec = hwdec;
} else {
mp_tmsg(MSGT_DECVIDEO, MSGL_WARN, "Decoder '%s' not found in "
"libavcodec, using software decoding.\n", hwdec->hw_codec);
- hwdec = NULL;
}
}
- if (!init_avctx(sh, decoder, hwdec)) {
+ init_avctx(sh, decoder, use_hwdec);
+ if (!ctx->avctx) {
if (ctx->software_fallback_decoder) {
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Error initializing hardware "
"decoding, falling back to software decoding.\n");
decoder = ctx->software_fallback_decoder;
ctx->software_fallback_decoder = NULL;
- if (!init_avctx(sh, decoder, NULL)) {
- uninit(sh);
- return 0;
- }
+ init_avctx(sh, decoder, NULL);
+ }
+ if (!ctx->avctx) {
+ uninit(sh);
+ return 0;
}
}
return 1;
@@ -240,12 +255,14 @@ static void set_from_bih(AVCodecContext *avctx, uint32_t format,
avctx->coded_height = bih->biHeight;
}
-static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
+static void init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
{
vd_ffmpeg_ctx *ctx = sh->context;
struct lavc_param *lavc_param = &sh->opts->lavc_param;
bool mp_rawvideo = false;
+ assert(!ctx->avctx);
+
if (strcmp(decoder, "mp-rawvideo") == 0) {
mp_rawvideo = true;
decoder = "rawvideo";
@@ -253,7 +270,7 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
AVCodec *lavc_codec = avcodec_find_decoder_by_name(decoder);
if (!lavc_codec)
- return 0;
+ return;
ctx->do_dr1 = ctx->do_hw_dr1 = 0;
ctx->pix_fmt = PIX_FMT_NONE;
@@ -268,6 +285,16 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
avctx->thread_count = lavc_param->threads;
+ // Hack to allow explicitly selecting vdpau hw decoders
+ if (!hwdec && (lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)) {
+ ctx->hwdec = talloc(ctx, struct hwdec);
+ *ctx->hwdec = (struct hwdec) {
+ .api = HWDEC_VDPAU,
+ .codec = sh->gsh->codec,
+ .hw_codec = decoder,
+ };
+ }
+
if (ctx->hwdec && ctx->hwdec->api == HWDEC_VDPAU) {
assert(lavc_codec->capabilities & CODEC_CAP_HWACCEL_VDPAU);
ctx->do_hw_dr1 = true;
@@ -325,8 +352,8 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
mp_msg(MSGT_DECVIDEO, MSGL_ERR,
"Your options /%s/ look like gibberish to me pal\n",
lavc_param->avopt);
- uninit(sh);
- return 0;
+ uninit_avctx(sh);
+ return;
}
}
@@ -356,9 +383,8 @@ static int init_avctx(sh_video_t *sh, const char *decoder, struct hwdec *hwdec)
if (avcodec_open2(avctx, lavc_codec, NULL) < 0) {
mp_tmsg(MSGT_DECVIDEO, MSGL_ERR, "Could not open codec.\n");
uninit_avctx(sh);
- return 0;
+ return;
}
- return 1;
}
static void uninit_avctx(sh_video_t *sh)
@@ -374,7 +400,7 @@ static void uninit_avctx(sh_video_t *sh)
av_freep(&avctx->slice_offset);
}
- av_freep(&avctx);
+ av_freep(&ctx->avctx);
avcodec_free_frame(&ctx->pic);
#if !HAVE_AVUTIL_REFCOUNTING
@@ -711,7 +737,8 @@ static struct mp_image *decode_with_fallback(struct sh_video *sh,
"decoding, falling back to software decoding.\n");
const char *decoder = ctx->software_fallback_decoder;
ctx->software_fallback_decoder = NULL;
- if (init_avctx(sh, decoder, NULL)) {
+ init_avctx(sh, decoder, NULL);
+ if (ctx->avctx) {
mpi = NULL;
decode(sh, packet, flags, reordered_pts, &mpi);
return mpi;