mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-12-05 01:56:41 +00:00
avconv: Use codec hardware config to configure hwaccels
Removes specific support for all hwaccels supported by the generic code (CUVID, DXVA2, D3D11VA, VAAPI and VDPAU).
This commit is contained in:
parent
2117725dc5
commit
ddea22a684
@ -1631,44 +1631,77 @@ static void print_sdp(void)
|
||||
av_freep(&avc);
|
||||
}
|
||||
|
||||
static const HWAccel *get_hwaccel(enum AVPixelFormat pix_fmt)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
if (hwaccels[i].pix_fmt == pix_fmt)
|
||||
return &hwaccels[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat *pix_fmts)
|
||||
{
|
||||
InputStream *ist = s->opaque;
|
||||
const enum AVPixelFormat *p;
|
||||
int ret;
|
||||
|
||||
for (p = pix_fmts; *p != -1; p++) {
|
||||
for (p = pix_fmts; *p != AV_PIX_FMT_NONE; p++) {
|
||||
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(*p);
|
||||
const HWAccel *hwaccel;
|
||||
const AVCodecHWConfig *config = NULL;
|
||||
int i;
|
||||
|
||||
if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL))
|
||||
break;
|
||||
|
||||
hwaccel = get_hwaccel(*p);
|
||||
if (!hwaccel ||
|
||||
(ist->active_hwaccel_id && ist->active_hwaccel_id != hwaccel->id) ||
|
||||
(ist->hwaccel_id != HWACCEL_AUTO && ist->hwaccel_id != hwaccel->id))
|
||||
continue;
|
||||
if (ist->hwaccel_id == HWACCEL_GENERIC ||
|
||||
ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(s->codec, i);
|
||||
if (!config)
|
||||
break;
|
||||
if (!(config->methods &
|
||||
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
|
||||
continue;
|
||||
if (config->pix_fmt == *p)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (config) {
|
||||
if (config->device_type != ist->hwaccel_device_type) {
|
||||
// Different hwaccel offered, ignore.
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwaccel->init(s);
|
||||
if (ret < 0) {
|
||||
if (ist->hwaccel_id == hwaccel->id) {
|
||||
ret = hwaccel_decode_init(s);
|
||||
if (ret < 0) {
|
||||
if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"%s hwaccel requested for input stream #%d:%d, "
|
||||
"but cannot be initialized.\n",
|
||||
av_hwdevice_get_type_name(config->device_type),
|
||||
ist->file_index, ist->st->index);
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
const HWAccel *hwaccel = NULL;
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (hwaccels[i].pix_fmt == *p) {
|
||||
hwaccel = &hwaccels[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hwaccel) {
|
||||
// No hwaccel supporting this pixfmt.
|
||||
continue;
|
||||
}
|
||||
if (hwaccel->id != ist->hwaccel_id) {
|
||||
// Does not match requested hwaccel.
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = hwaccel->init(s);
|
||||
if (ret < 0) {
|
||||
av_log(NULL, AV_LOG_FATAL,
|
||||
"%s hwaccel requested for input stream #%d:%d, "
|
||||
"but cannot be initialized.\n", hwaccel->name,
|
||||
ist->file_index, ist->st->index);
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ist->hw_frames_ctx) {
|
||||
@ -1677,8 +1710,7 @@ static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPixelFormat
|
||||
return AV_PIX_FMT_NONE;
|
||||
}
|
||||
|
||||
ist->active_hwaccel_id = hwaccel->id;
|
||||
ist->hwaccel_pix_fmt = *p;
|
||||
ist->hwaccel_pix_fmt = *p;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -52,13 +52,9 @@
|
||||
enum HWAccelID {
|
||||
HWACCEL_NONE = 0,
|
||||
HWACCEL_AUTO,
|
||||
HWACCEL_VDPAU,
|
||||
HWACCEL_DXVA2,
|
||||
HWACCEL_GENERIC,
|
||||
HWACCEL_VDA,
|
||||
HWACCEL_QSV,
|
||||
HWACCEL_VAAPI,
|
||||
HWACCEL_D3D11VA,
|
||||
HWACCEL_CUVID,
|
||||
};
|
||||
|
||||
typedef struct HWAccel {
|
||||
@ -66,7 +62,6 @@ typedef struct HWAccel {
|
||||
int (*init)(AVCodecContext *s);
|
||||
enum HWAccelID id;
|
||||
enum AVPixelFormat pix_fmt;
|
||||
enum AVHWDeviceType device_type;
|
||||
} HWAccel;
|
||||
|
||||
typedef struct HWDevice {
|
||||
@ -301,11 +296,11 @@ typedef struct InputStream {
|
||||
|
||||
/* hwaccel options */
|
||||
enum HWAccelID hwaccel_id;
|
||||
enum AVHWDeviceType hwaccel_device_type;
|
||||
char *hwaccel_device;
|
||||
enum AVPixelFormat hwaccel_output_format;
|
||||
|
||||
/* hwaccel context */
|
||||
enum HWAccelID active_hwaccel_id;
|
||||
void *hwaccel_ctx;
|
||||
void (*hwaccel_uninit)(AVCodecContext *s);
|
||||
int (*hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags);
|
||||
|
@ -62,6 +62,31 @@ static HWDevice *hw_device_add(void)
|
||||
return hw_devices[nb_hw_devices++];
|
||||
}
|
||||
|
||||
static char *hw_device_default_name(enum AVHWDeviceType type)
|
||||
{
|
||||
// Make an automatic name of the form "type%d". We arbitrarily
|
||||
// limit at 1000 anonymous devices of the same type - there is
|
||||
// probably something else very wrong if you get to this limit.
|
||||
const char *type_name = av_hwdevice_get_type_name(type);
|
||||
char *name;
|
||||
size_t index_pos;
|
||||
int index, index_limit = 1000;
|
||||
index_pos = strlen(type_name);
|
||||
name = av_malloc(index_pos + 4);
|
||||
if (!name)
|
||||
return NULL;
|
||||
for (index = 0; index < index_limit; index++) {
|
||||
snprintf(name, index_pos + 4, "%s%d", type_name, index);
|
||||
if (!hw_device_get_by_name(name))
|
||||
break;
|
||||
}
|
||||
if (index >= index_limit) {
|
||||
av_freep(&name);
|
||||
return NULL;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
{
|
||||
// "type=name:device,key=value,key2=value2"
|
||||
@ -109,27 +134,11 @@ int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
|
||||
|
||||
p += 1 + k;
|
||||
} else {
|
||||
// Give the device an automatic name of the form "type%d".
|
||||
// We arbitrarily limit at 1000 anonymous devices of the same
|
||||
// type - there is probably something else very wrong if you
|
||||
// get to this limit.
|
||||
size_t index_pos;
|
||||
int index, index_limit = 1000;
|
||||
index_pos = strlen(type_name);
|
||||
name = av_malloc(index_pos + 4);
|
||||
name = hw_device_default_name(type);
|
||||
if (!name) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
for (index = 0; index < index_limit; index++) {
|
||||
snprintf(name, index_pos + 4, "%s%d", type_name, index);
|
||||
if (!hw_device_get_by_name(name))
|
||||
break;
|
||||
}
|
||||
if (index >= index_limit) {
|
||||
errmsg = "too many devices";
|
||||
goto invalid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!*p) {
|
||||
@ -212,6 +221,49 @@ fail:
|
||||
goto done;
|
||||
}
|
||||
|
||||
static int hw_device_init_from_type(enum AVHWDeviceType type,
|
||||
const char *device,
|
||||
HWDevice **dev_out)
|
||||
{
|
||||
AVBufferRef *device_ref = NULL;
|
||||
HWDevice *dev;
|
||||
char *name;
|
||||
int err;
|
||||
|
||||
name = hw_device_default_name(type);
|
||||
if (!name) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
|
||||
if (err < 0) {
|
||||
av_log(NULL, AV_LOG_ERROR,
|
||||
"Device creation failed: %d.\n", err);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev = hw_device_add();
|
||||
if (!dev) {
|
||||
err = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dev->name = name;
|
||||
dev->type = type;
|
||||
dev->device_ref = device_ref;
|
||||
|
||||
if (dev_out)
|
||||
*dev_out = dev;
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
av_freep(&name);
|
||||
av_buffer_unref(&device_ref);
|
||||
return err;
|
||||
}
|
||||
|
||||
void hw_device_free_all(void)
|
||||
{
|
||||
int i;
|
||||
@ -224,85 +276,130 @@ void hw_device_free_all(void)
|
||||
nb_hw_devices = 0;
|
||||
}
|
||||
|
||||
static enum AVHWDeviceType hw_device_match_type_by_hwaccel(enum HWAccelID hwaccel_id)
|
||||
static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
HWDevice *dev;
|
||||
int i;
|
||||
if (hwaccel_id == HWACCEL_NONE)
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (hwaccels[i].id == hwaccel_id)
|
||||
return hwaccels[i].device_type;
|
||||
for (i = 0;; i++) {
|
||||
config = avcodec_get_hw_config(codec, i);
|
||||
if (!config)
|
||||
return NULL;
|
||||
if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
|
||||
continue;
|
||||
dev = hw_device_get_by_type(config->device_type);
|
||||
if (dev)
|
||||
return dev;
|
||||
}
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
}
|
||||
|
||||
static enum AVHWDeviceType hw_device_match_type_in_name(const char *codec_name)
|
||||
{
|
||||
const char *type_name;
|
||||
enum AVHWDeviceType type;
|
||||
for (type = av_hwdevice_iterate_types(AV_HWDEVICE_TYPE_NONE);
|
||||
type != AV_HWDEVICE_TYPE_NONE;
|
||||
type = av_hwdevice_iterate_types(type)) {
|
||||
type_name = av_hwdevice_get_type_name(type);
|
||||
if (strstr(codec_name, type_name))
|
||||
return type;
|
||||
}
|
||||
return AV_HWDEVICE_TYPE_NONE;
|
||||
}
|
||||
|
||||
int hw_device_setup_for_decode(InputStream *ist)
|
||||
{
|
||||
const AVCodecHWConfig *config;
|
||||
enum AVHWDeviceType type;
|
||||
HWDevice *dev;
|
||||
const char *type_name;
|
||||
int err;
|
||||
HWDevice *dev = NULL;
|
||||
int err, auto_device = 0;
|
||||
|
||||
if (ist->hwaccel_device) {
|
||||
dev = hw_device_get_by_name(ist->hwaccel_device);
|
||||
if (!dev) {
|
||||
char *tmp;
|
||||
size_t len;
|
||||
type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
|
||||
if (type == AV_HWDEVICE_TYPE_NONE) {
|
||||
// No match - this isn't necessarily invalid, though,
|
||||
// because an explicit device might not be needed or
|
||||
// the hwaccel setup could be handled elsewhere.
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
auto_device = 1;
|
||||
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
type = ist->hwaccel_device_type;
|
||||
err = hw_device_init_from_type(type, ist->hwaccel_device,
|
||||
&dev);
|
||||
} else {
|
||||
// This will be dealt with by API-specific initialisation
|
||||
// (using hwaccel_device), so nothing further needed here.
|
||||
return 0;
|
||||
}
|
||||
type_name = av_hwdevice_get_type_name(type);
|
||||
len = strlen(type_name) + 1 +
|
||||
strlen(ist->hwaccel_device) + 1;
|
||||
tmp = av_malloc(len);
|
||||
if (!tmp)
|
||||
return AVERROR(ENOMEM);
|
||||
snprintf(tmp, len, "%s:%s", type_name, ist->hwaccel_device);
|
||||
err = hw_device_init_from_string(tmp, &dev);
|
||||
av_free(tmp);
|
||||
if (err < 0)
|
||||
return err;
|
||||
} else {
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
ist->hwaccel_device_type = dev->type;
|
||||
} else if (ist->hwaccel_device_type != dev->type) {
|
||||
av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
|
||||
"specified for decoder: device %s of type %s is not "
|
||||
"usable with hwaccel %s.\n", dev->name,
|
||||
av_hwdevice_get_type_name(dev->type),
|
||||
av_hwdevice_get_type_name(ist->hwaccel_device_type));
|
||||
return AVERROR(EINVAL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ist->hwaccel_id != HWACCEL_NONE)
|
||||
type = hw_device_match_type_by_hwaccel(ist->hwaccel_id);
|
||||
else
|
||||
type = hw_device_match_type_in_name(ist->dec->name);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
if (ist->hwaccel_id == HWACCEL_AUTO) {
|
||||
auto_device = 1;
|
||||
} else if (ist->hwaccel_id == HWACCEL_GENERIC) {
|
||||
type = ist->hwaccel_device_type;
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (!dev) {
|
||||
hw_device_init_from_string(av_hwdevice_get_type_name(type),
|
||||
&dev);
|
||||
}
|
||||
if (!dev)
|
||||
err = hw_device_init_from_type(type, NULL, &dev);
|
||||
} else {
|
||||
// No device required.
|
||||
dev = hw_device_match_by_codec(ist->dec);
|
||||
if (!dev) {
|
||||
// No device for this codec, but not using generic hwaccel
|
||||
// and therefore may well not need one - ignore.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (auto_device) {
|
||||
int i;
|
||||
if (!avcodec_get_hw_config(ist->dec, 0)) {
|
||||
// Decoder does not support any hardware devices.
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; !dev; i++) {
|
||||
config = avcodec_get_hw_config(ist->dec, i);
|
||||
if (!config)
|
||||
break;
|
||||
type = config->device_type;
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (dev) {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with existing device %s.\n",
|
||||
av_hwdevice_get_type_name(type), dev->name);
|
||||
}
|
||||
}
|
||||
for (i = 0; !dev; i++) {
|
||||
config = avcodec_get_hw_config(ist->dec, i);
|
||||
if (!config)
|
||||
break;
|
||||
type = config->device_type;
|
||||
// Try to make a new device of this type.
|
||||
err = hw_device_init_from_type(type, ist->hwaccel_device,
|
||||
&dev);
|
||||
if (err < 0) {
|
||||
// Can't make a device of this type.
|
||||
continue;
|
||||
}
|
||||
if (ist->hwaccel_device) {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new device created "
|
||||
"from %s.\n", av_hwdevice_get_type_name(type),
|
||||
ist->hwaccel_device);
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
|
||||
"hwaccel type %s with new default device.\n",
|
||||
av_hwdevice_get_type_name(type));
|
||||
}
|
||||
}
|
||||
if (dev) {
|
||||
ist->hwaccel_device_type = type;
|
||||
} else {
|
||||
av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
|
||||
"disabled: no device found.\n");
|
||||
ist->hwaccel_id = HWACCEL_NONE;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dev) {
|
||||
av_log(ist->dec_ctx, AV_LOG_WARNING, "No device available "
|
||||
"for decoder (device type %s for codec %s).\n",
|
||||
av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
|
||||
"for decoder: device type %s needed for codec %s.\n",
|
||||
av_hwdevice_get_type_name(type), ist->dec->name);
|
||||
return 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
ist->dec_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
|
||||
@ -314,24 +411,16 @@ int hw_device_setup_for_decode(InputStream *ist)
|
||||
|
||||
int hw_device_setup_for_encode(OutputStream *ost)
|
||||
{
|
||||
enum AVHWDeviceType type;
|
||||
HWDevice *dev;
|
||||
|
||||
type = hw_device_match_type_in_name(ost->enc->name);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
dev = hw_device_get_by_type(type);
|
||||
if (!dev) {
|
||||
av_log(ost->enc_ctx, AV_LOG_WARNING, "No device available "
|
||||
"for encoder (device type %s for codec %s).\n",
|
||||
av_hwdevice_get_type_name(type), ost->enc->name);
|
||||
return 0;
|
||||
}
|
||||
dev = hw_device_match_by_codec(ost->enc);
|
||||
if (dev) {
|
||||
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
|
||||
if (!ost->enc_ctx->hw_device_ctx)
|
||||
return AVERROR(ENOMEM);
|
||||
return 0;
|
||||
} else {
|
||||
// No device required.
|
||||
// No device required, or no device available.
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -56,33 +56,11 @@
|
||||
}
|
||||
|
||||
const HWAccel hwaccels[] = {
|
||||
#if HAVE_VDPAU_X11
|
||||
{ "vdpau", hwaccel_decode_init, HWACCEL_VDPAU, AV_PIX_FMT_VDPAU,
|
||||
AV_HWDEVICE_TYPE_VDPAU },
|
||||
#endif
|
||||
#if CONFIG_D3D11VA
|
||||
{ "d3d11va", hwaccel_decode_init, HWACCEL_D3D11VA, AV_PIX_FMT_D3D11,
|
||||
AV_HWDEVICE_TYPE_D3D11VA },
|
||||
#endif
|
||||
#if CONFIG_DXVA2
|
||||
{ "dxva2", hwaccel_decode_init, HWACCEL_DXVA2, AV_PIX_FMT_DXVA2_VLD,
|
||||
AV_HWDEVICE_TYPE_DXVA2 },
|
||||
#endif
|
||||
#if CONFIG_VDA
|
||||
{ "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
{ "vda", vda_init, HWACCEL_VDA, AV_PIX_FMT_VDA },
|
||||
#endif
|
||||
#if CONFIG_LIBMFX
|
||||
{ "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV,
|
||||
AV_HWDEVICE_TYPE_NONE },
|
||||
#endif
|
||||
#if CONFIG_VAAPI
|
||||
{ "vaapi", hwaccel_decode_init, HWACCEL_VAAPI, AV_PIX_FMT_VAAPI,
|
||||
AV_HWDEVICE_TYPE_VAAPI },
|
||||
#endif
|
||||
#if CONFIG_CUVID
|
||||
{ "cuvid", hwaccel_decode_init, HWACCEL_CUVID, AV_PIX_FMT_CUDA,
|
||||
AV_HWDEVICE_TYPE_CUDA },
|
||||
{ "qsv", qsv_init, HWACCEL_QSV, AV_PIX_FMT_QSV },
|
||||
#endif
|
||||
{ 0 },
|
||||
};
|
||||
@ -201,12 +179,15 @@ static double parse_frame_aspect_ratio(const char *arg)
|
||||
|
||||
static int show_hwaccels(void *optctx, const char *opt, const char *arg)
|
||||
{
|
||||
enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
|
||||
int i;
|
||||
|
||||
printf("Supported hardware acceleration:\n");
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
while ((type = av_hwdevice_iterate_types(type)) !=
|
||||
AV_HWDEVICE_TYPE_NONE)
|
||||
printf("%s\n", av_hwdevice_get_type_name(type));
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
printf("%s\n", hwaccels[i].name);
|
||||
}
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@ -623,6 +604,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
else if (!strcmp(hwaccel, "auto"))
|
||||
ist->hwaccel_id = HWACCEL_AUTO;
|
||||
else {
|
||||
enum AVHWDeviceType type;
|
||||
int i;
|
||||
for (i = 0; hwaccels[i].name; i++) {
|
||||
if (!strcmp(hwaccels[i].name, hwaccel)) {
|
||||
@ -631,10 +613,23 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ist->hwaccel_id) {
|
||||
type = av_hwdevice_find_type_by_name(hwaccel);
|
||||
if (type != AV_HWDEVICE_TYPE_NONE) {
|
||||
ist->hwaccel_id = HWACCEL_GENERIC;
|
||||
ist->hwaccel_device_type = type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ist->hwaccel_id) {
|
||||
av_log(NULL, AV_LOG_FATAL, "Unrecognized hwaccel: %s.\n",
|
||||
hwaccel);
|
||||
av_log(NULL, AV_LOG_FATAL, "Supported hwaccels: ");
|
||||
type = AV_HWDEVICE_TYPE_NONE;
|
||||
while ((type = av_hwdevice_iterate_types(type)) !=
|
||||
AV_HWDEVICE_TYPE_NONE)
|
||||
av_log(NULL, AV_LOG_FATAL, "%s ",
|
||||
av_hwdevice_get_type_name(type));
|
||||
for (i = 0; hwaccels[i].name; i++)
|
||||
av_log(NULL, AV_LOG_FATAL, "%s ", hwaccels[i].name);
|
||||
av_log(NULL, AV_LOG_FATAL, "\n");
|
||||
|
Loading…
Reference in New Issue
Block a user