diff options
Diffstat (limited to 'video/decode/vd_lavc.c')
-rw-r--r-- | video/decode/vd_lavc.c | 61 |
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; |