diff mbox

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

Message ID 20170625212706.10384-3-philipl@overt.org
State New
Headers show

Commit Message

Philip Langdale June 25, 2017, 9:27 p.m. UTC
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@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(-)

Comments

wm4 June 26, 2017, 7:50 a.m. UTC | #1
On Sun, 25 Jun 2017 14:27:06 -0700
Philip Langdale <philipl@overt.org> wrote:

> 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@overt.org>
> ---

Doesn't this still mean hwaccels will push sw frames to filters, but
cuvid pushes hw frames? I thought we were trying to get rid of this
inconsistency?
Michael Niedermayer June 26, 2017, 7:19 p.m. UTC | #2
On Sun, Jun 25, 2017 at 02:27:06PM -0700, Philip Langdale wrote:
> 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@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(-)

breaks build on mingw64

CC      ffmpeg_dxva2.o
src/ffmpeg_dxva2.c:409:5: error: conflicting types for ‘dxva2_init’
 int dxva2_init(const HWAccel *hwaccel, AVCodecContext *s)
     ^
In file included from src/ffmpeg_dxva2.c:33:0:
src/ffmpeg.h:671:5: note: previous declaration of ‘dxva2_init’ was here
 int dxva2_init(AVCodecContext *s);
     ^
make: *** [ffmpeg_dxva2.o] Error 1

[...]
Philip Langdale June 27, 2017, 3:46 a.m. UTC | #3
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Mon, 26 Jun 2017 21:19:28 +0200
Michael Niedermayer <michael@niedermayer.cc> wrote:

> On Sun, Jun 25, 2017 at 02:27:06PM -0700, Philip Langdale wrote:

> > 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@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(-)  

> 

> breaks build on mingw64

> 

> CC      ffmpeg_dxva2.o

> src/ffmpeg_dxva2.c:409:5: error: conflicting types for ‘dxva2_init’

>  int dxva2_init(const HWAccel *hwaccel, AVCodecContext *s)

>      ^

> In file included from src/ffmpeg_dxva2.c:33:0:

> src/ffmpeg.h:671:5: note: previous declaration of ‘dxva2_init’ was

> here int dxva2_init(AVCodecContext *s);

>      ^

> make: *** [ffmpeg_dxva2.o] Error 1

> 

> [...]


Thanks. Fixed locally.

- --phil
-----BEGIN PGP SIGNATURE-----

iEYEARECAAYFAllR1SgACgkQ+NaxlGp1aC7nqQCfTHxMgT3im0kFQmRgmkC1AWgr
j/oAn1XHGRsNncAp6cPqsHYvhOvkfZQ1
=qzKq
-----END PGP SIGNATURE-----
diff mbox

Patch

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;