[FFmpeg-devel] [PATCH 2/2] ffmpeg: Set default output format for dummy hwaccels

Philip Langdale philipl at overt.org
Mon Jun 26 00:27:06 EEST 2017


Dummy hwaccels, of which cuvid is the best example, behave differently
from real hwaccels. In the past, one of these behaviours was that
selecting the hwaccel would automatically cause the decoder (and
remember it's a dedicated decoder) to use the native hardware output
format.

This meant that transcoding command lines would pass frames through
device memory automatically once the right hwaccel and decoder/encoder
were selected.

With the generic hwaccel code path, dummy decoders end up following
the 'real' hwaccel path where the output format defaults to a software
format.

To avoid users facing an unexpected change in behaviour, we now
indicate whether an hwaccel is a dummy, and if it is, we set the
default output format appropriately.

To make this process easier, I updated ffmpeg to pass the HWAccel
struct to the init() call so that we know which decoder we are
dealing with.

Signed-off-by: Philip Langdale <philipl at overt.org>
---
 ffmpeg.c              |  2 +-
 ffmpeg.h              | 15 +++++++++++----
 ffmpeg_dxva2.c        |  2 +-
 ffmpeg_hw.c           |  5 ++++-
 ffmpeg_opt.c          | 21 ++++++++++++++-------
 ffmpeg_qsv.c          |  2 +-
 ffmpeg_videotoolbox.c |  2 +-
 7 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/ffmpeg.c b/ffmpeg.c
index 6dae6e9078..32d8ba4895 100644
--- a/ffmpeg.c
+++ b/ffmpeg.c
@@ -2833,7 +2833,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat
             (ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id))
             continue;
 
-        ret = hwaccel->init(s);
+        ret = hwaccel->init(hwaccel, s);
         if (ret < 0) {
             if (ist->hwaccel_id == hwaccel->id) {
                 av_log(NULL, AV_LOG_FATAL,
diff --git a/ffmpeg.h b/ffmpeg.h
index fa81427471..946bcb75f2 100644
--- a/ffmpeg.h
+++ b/ffmpeg.h
@@ -70,13 +70,20 @@ enum HWAccelID {
     HWACCEL_CUVID,
 };
 
-typedef struct HWAccel {
+typedef struct HWAccel HWAccel;
+
+struct HWAccel {
     const char *name;
-    int (*init)(AVCodecContext *s);
+    int (*init)(const HWAccel *hwaccel, AVCodecContext *s);
     enum HWAccelID id;
     enum AVPixelFormat pix_fmt;
     enum AVHWDeviceType device_type;
-} HWAccel;
+    /*
+     * A dummy hwaccel is one which maps to a separate decoder rather
+     * than plugging into a standard decoder
+     */
+    int is_dummy;
+};
 
 typedef struct HWDevice {
     char *name;
@@ -673,6 +680,6 @@ void hw_device_free_all(void);
 int hw_device_setup_for_decode(InputStream *ist);
 int hw_device_setup_for_encode(OutputStream *ost);
 
-int hwaccel_decode_init(AVCodecContext *avctx);
+int hwaccel_decode_init(const HWAccel *hwaccel, AVCodecContext *avctx);
 
 #endif /* FFMPEG_H */
diff --git a/ffmpeg_dxva2.c b/ffmpeg_dxva2.c
index 1a391f82f3..8cbf5a9dff 100644
--- a/ffmpeg_dxva2.c
+++ b/ffmpeg_dxva2.c
@@ -406,7 +406,7 @@ fail:
     return AVERROR(EINVAL);
 }
 
-int dxva2_init(AVCodecContext *s)
+int dxva2_init(const HWAccel *hwaccel, AVCodecContext *s)
 {
     InputStream *ist = s->opaque;
     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
diff --git a/ffmpeg_hw.c b/ffmpeg_hw.c
index a4d1cada59..8518f267be 100644
--- a/ffmpeg_hw.c
+++ b/ffmpeg_hw.c
@@ -375,11 +375,14 @@ fail:
     return err;
 }
 
-int hwaccel_decode_init(AVCodecContext *avctx)
+int hwaccel_decode_init(const HWAccel *hwaccel, AVCodecContext *avctx)
 {
     InputStream *ist = avctx->opaque;
 
     ist->hwaccel_retrieve_data = &hwaccel_retrieve_data;
+    if (hwaccel->is_dummy && ist->hwaccel_output_format == AV_PIX_FMT_NONE) {
+        ist->hwaccel_output_format = hwaccel->pix_fmt;
+    }
 
     return 0;
 }
diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c
index 6dc4ad43d2..ec89f50cf9 100644
--- a/ffmpeg_opt.c
+++ b/ffmpeg_opt.c
@@ -68,31 +68,38 @@
 const HWAccel hwaccels[] = {
 #if HAVE_VDPAU_X11
     { "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
-      AV_HWDEVICE_TYPE_VDPAU },
+      AV_HWDEVICE_TYPE_VDPAU,
+      .is_dummy = 0 },
 #endif
 #if HAVE_DXVA2_LIB
     { "dxva2", dxva2_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
-      AV_HWDEVICE_TYPE_NONE },
+      AV_HWDEVICE_TYPE_NONE,
+      .is_dummy = 0 },
 #endif
 #if CONFIG_VDA
     { "vda",   videotoolbox_init,   HWACCEL_VDA,   AV_PIX_FMT_VDA,
-      AV_HWDEVICE_TYPE_NONE },
+      AV_HWDEVICE_TYPE_NONE,
+      .is_dummy = 0 },
 #endif
 #if CONFIG_VIDEOTOOLBOX
     { "videotoolbox",   videotoolbox_init,   HWACCEL_VIDEOTOOLBOX,   AV_PIX_FMT_VIDEOTOOLBOX,
-      AV_HWDEVICE_TYPE_NONE },
+      AV_HWDEVICE_TYPE_NONE,
+      .is_dummy = 0 },
 #endif
 #if CONFIG_LIBMFX
     { "qsv",   qsv_init,   HWACCEL_QSV,   AV_PIX_FMT_QSV,
-      AV_HWDEVICE_TYPE_NONE },
+      AV_HWDEVICE_TYPE_NONE,
+      .is_dummy = 0 },
 #endif
 #if CONFIG_VAAPI
     { "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI,
-      AV_HWDEVICE_TYPE_VAAPI },
+      AV_HWDEVICE_TYPE_VAAPI,
+      .is_dummy = 0 },
 #endif
 #if CONFIG_CUVID
     { "cuvid", hwaccel_decode_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA,
-      AV_HWDEVICE_TYPE_CUDA },
+      AV_HWDEVICE_TYPE_CUDA,
+      .is_dummy = 1 },
 #endif
     { 0 },
 };
diff --git a/ffmpeg_qsv.c b/ffmpeg_qsv.c
index 7442750029..4df27e9e6e 100644
--- a/ffmpeg_qsv.c
+++ b/ffmpeg_qsv.c
@@ -68,7 +68,7 @@ err_out:
     return err;
 }
 
-int qsv_init(AVCodecContext *s)
+int qsv_init(const HWAccel *hwaccel, AVCodecContext *s)
 {
     InputStream *ist = s->opaque;
     AVHWFramesContext *frames_ctx;
diff --git a/ffmpeg_videotoolbox.c b/ffmpeg_videotoolbox.c
index e9039654b9..4346145a4a 100644
--- a/ffmpeg_videotoolbox.c
+++ b/ffmpeg_videotoolbox.c
@@ -126,7 +126,7 @@ static void videotoolbox_uninit(AVCodecContext *s)
     av_freep(&ist->hwaccel_ctx);
 }
 
-int videotoolbox_init(AVCodecContext *s)
+int videotoolbox_init(const HWAccel *hwaccel, AVCodecContext *s)
 {
     InputStream *ist = s->opaque;
     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
-- 
2.11.0


More information about the ffmpeg-devel mailing list