|
|
@@ -19,6 +19,7 @@ |
|
|
|
#include <string.h> |
|
|
|
|
|
|
|
#include "libavutil/avstring.h" |
|
|
|
#include "libavutil/pixdesc.h" |
|
|
|
#include "libavfilter/buffersink.h" |
|
|
|
|
|
|
|
#include "ffmpeg.h" |
|
|
@@ -282,10 +283,7 @@ void hw_device_free_all(void) |
|
|
|
nb_hw_devices = 0; |
|
|
|
} |
|
|
|
|
|
|
|
static HWDevice *hw_device_match_by_codec(const AVCodec *codec, |
|
|
|
enum AVPixelFormat format, |
|
|
|
int possible_methods, |
|
|
|
int *matched_methods) |
|
|
|
static HWDevice *hw_device_match_by_codec(const AVCodec *codec) |
|
|
|
{ |
|
|
|
const AVCodecHWConfig *config; |
|
|
|
HWDevice *dev; |
|
|
@@ -294,18 +292,11 @@ static HWDevice *hw_device_match_by_codec(const AVCodec *codec, |
|
|
|
config = avcodec_get_hw_config(codec, i); |
|
|
|
if (!config) |
|
|
|
return NULL; |
|
|
|
if (format != AV_PIX_FMT_NONE && |
|
|
|
config->pix_fmt != AV_PIX_FMT_NONE && |
|
|
|
config->pix_fmt != format) |
|
|
|
continue; |
|
|
|
if (!(config->methods & possible_methods)) |
|
|
|
if (!(config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX)) |
|
|
|
continue; |
|
|
|
dev = hw_device_get_by_type(config->device_type); |
|
|
|
if (dev) { |
|
|
|
if (matched_methods) |
|
|
|
*matched_methods = config->methods & possible_methods; |
|
|
|
if (dev) |
|
|
|
return dev; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -351,9 +342,7 @@ int hw_device_setup_for_decode(InputStream *ist) |
|
|
|
if (!dev) |
|
|
|
err = hw_device_init_from_type(type, NULL, &dev); |
|
|
|
} else { |
|
|
|
dev = hw_device_match_by_codec(ist->dec, AV_PIX_FMT_NONE, |
|
|
|
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX, |
|
|
|
NULL); |
|
|
|
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. |
|
|
@@ -429,37 +418,57 @@ int hw_device_setup_for_decode(InputStream *ist) |
|
|
|
|
|
|
|
int hw_device_setup_for_encode(OutputStream *ost) |
|
|
|
{ |
|
|
|
HWDevice *dev; |
|
|
|
AVBufferRef *frames_ref; |
|
|
|
int methods = AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX; |
|
|
|
int matched_methods; |
|
|
|
const AVCodecHWConfig *config; |
|
|
|
HWDevice *dev = NULL; |
|
|
|
AVBufferRef *frames_ref = NULL; |
|
|
|
int i; |
|
|
|
|
|
|
|
if (ost->filter) { |
|
|
|
frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter); |
|
|
|
if (frames_ref && |
|
|
|
((AVHWFramesContext*)frames_ref->data)->format == |
|
|
|
ost->enc_ctx->pix_fmt) |
|
|
|
methods |= AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX; |
|
|
|
ost->enc_ctx->pix_fmt) { |
|
|
|
// Matching format, will try to use hw_frames_ctx. |
|
|
|
} else { |
|
|
|
frames_ref = NULL; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
dev = hw_device_match_by_codec(ost->enc, ost->enc_ctx->pix_fmt, |
|
|
|
methods, &matched_methods); |
|
|
|
if (dev) { |
|
|
|
if (matched_methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) { |
|
|
|
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); |
|
|
|
if (!ost->enc_ctx->hw_device_ctx) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} |
|
|
|
if (matched_methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) { |
|
|
|
for (i = 0;; i++) { |
|
|
|
config = avcodec_get_hw_config(ost->enc, i); |
|
|
|
if (!config) |
|
|
|
break; |
|
|
|
|
|
|
|
if (frames_ref && |
|
|
|
config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX && |
|
|
|
(config->pix_fmt == AV_PIX_FMT_NONE || |
|
|
|
config->pix_fmt == ost->enc_ctx->pix_fmt)) { |
|
|
|
av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input " |
|
|
|
"frames context (format %s) with %s encoder.\n", |
|
|
|
av_get_pix_fmt_name(ost->enc_ctx->pix_fmt), |
|
|
|
ost->enc->name); |
|
|
|
ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref); |
|
|
|
if (!ost->enc_ctx->hw_frames_ctx) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
|
|
|
|
if (!dev && |
|
|
|
config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) |
|
|
|
dev = hw_device_get_by_type(config->device_type); |
|
|
|
} |
|
|
|
|
|
|
|
if (dev) { |
|
|
|
av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s " |
|
|
|
"(type %s) with %s encoder.\n", dev->name, |
|
|
|
av_hwdevice_get_type_name(dev->type), ost->enc->name); |
|
|
|
ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref); |
|
|
|
if (!ost->enc_ctx->hw_device_ctx) |
|
|
|
return AVERROR(ENOMEM); |
|
|
|
} else { |
|
|
|
// No device required, or no device available. |
|
|
|
return 0; |
|
|
|
} |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input) |
|
|
|