Commit e4a9748f authored by Philippe Gorley's avatar Philippe Gorley

accel: add hardware type as field

Nvidia's hardware type is named cuda, but its hardware encoders are
suffixed with "_nvenc" instead of "_cuda".

Change-Id: I2e55297b4254570249421d60dd48259971281f89
parent a73c77bf
...@@ -18,10 +18,6 @@ ...@@ -18,10 +18,6 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/ */
extern "C" {
#include <libavutil/hwcontext.h>
}
#include <algorithm> #include <algorithm>
#include "media_buffer.h" #include "media_buffer.h"
...@@ -36,6 +32,7 @@ namespace jami { namespace video { ...@@ -36,6 +32,7 @@ namespace jami { namespace video {
struct HardwareAPI struct HardwareAPI
{ {
std::string name; std::string name;
AVHWDeviceType hwType;
AVPixelFormat format; AVPixelFormat format;
AVPixelFormat swFormat; AVPixelFormat swFormat;
std::vector<AVCodecID> supportedCodecs; std::vector<AVCodecID> supportedCodecs;
...@@ -62,9 +59,10 @@ getFormatCb(AVCodecContext* codecCtx, const AVPixelFormat* formats) ...@@ -62,9 +59,10 @@ getFormatCb(AVCodecContext* codecCtx, const AVPixelFormat* formats)
return fallback; return fallback;
} }
HardwareAccel::HardwareAccel(AVCodecID id, const std::string& name, AVPixelFormat format, AVPixelFormat swFormat, CodecType type) HardwareAccel::HardwareAccel(AVCodecID id, const std::string& name, AVHWDeviceType hwType, AVPixelFormat format, AVPixelFormat swFormat, CodecType type)
: id_(id) : id_(id)
, name_(name) , name_(name)
, hwType_(hwType)
, format_(format) , format_(format)
, swFormat_(swFormat) , swFormat_(swFormat)
, type_(type) , type_(type)
...@@ -158,27 +156,23 @@ bool ...@@ -158,27 +156,23 @@ bool
HardwareAccel::initDevice() HardwareAccel::initDevice()
{ {
int ret = 0; int ret = 0;
auto hwType = av_hwdevice_find_type_by_name(name_.c_str());
if (hwType == AV_HWDEVICE_TYPE_NONE and (name_ == "nvenc" or name_ == "nvdec")) {
hwType = AV_HWDEVICE_TYPE_CUDA;
}
#ifdef HAVE_VAAPI_ACCEL_DRM #ifdef HAVE_VAAPI_ACCEL_DRM
// default DRM device may not work on multi GPU computers, so check all possible values // default DRM device may not work on multi GPU computers, so check all possible values
if (name_ == "vaapi") { if (hwType_ == AV_HWDEVICE_TYPE_VAAPI) {
const std::string path = "/dev/dri/"; const std::string path = "/dev/dri/";
auto files = jami::fileutils::readDirectory(path); auto files = jami::fileutils::readDirectory(path);
// renderD* is preferred over card* // renderD* is preferred over card*
std::sort(files.rbegin(), files.rend()); std::sort(files.rbegin(), files.rend());
for (auto& entry : files) { for (auto& entry : files) {
std::string deviceName = path + entry; std::string deviceName = path + entry;
if ((ret = av_hwdevice_ctx_create(&deviceCtx_, hwType, deviceName.c_str(), nullptr, 0)) >= 0) { if ((ret = av_hwdevice_ctx_create(&deviceCtx_, hwType_, deviceName.c_str(), nullptr, 0)) >= 0) {
return true; return true;
} }
} }
} }
#endif #endif
// default device (nullptr) works for most cases // default device (nullptr) works for most cases
ret = av_hwdevice_ctx_create(&deviceCtx_, hwType, nullptr, nullptr, 0); ret = av_hwdevice_ctx_create(&deviceCtx_, hwType_, nullptr, nullptr, 0);
return ret >= 0; return ret >= 0;
} }
...@@ -261,15 +255,15 @@ std::unique_ptr<HardwareAccel> ...@@ -261,15 +255,15 @@ std::unique_ptr<HardwareAccel>
HardwareAccel::setupDecoder(AVCodecID id, int width, int height) HardwareAccel::setupDecoder(AVCodecID id, int width, int height)
{ {
static const HardwareAPI apiList[] = { static const HardwareAPI apiList[] = {
{ "nvdec", AV_PIX_FMT_CUDA, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_VP8, AV_CODEC_ID_MJPEG } }, { "nvdec", AV_HWDEVICE_TYPE_CUDA, AV_PIX_FMT_CUDA, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_H265, AV_CODEC_ID_VP8, AV_CODEC_ID_MJPEG } },
{ "vaapi", AV_PIX_FMT_VAAPI, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4, AV_CODEC_ID_VP8, AV_CODEC_ID_MJPEG } }, { "vaapi", AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4, AV_CODEC_ID_VP8, AV_CODEC_ID_MJPEG } },
{ "vdpau", AV_PIX_FMT_VDPAU, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4 } }, { "vdpau", AV_HWDEVICE_TYPE_VDPAU, AV_PIX_FMT_VDPAU, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4 } },
{ "videotoolbox", AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4 } }, { "videotoolbox", AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MPEG4 } },
}; };
for (const auto& api : apiList) { for (const auto& api : apiList) {
if (std::find(api.supportedCodecs.begin(), api.supportedCodecs.end(), id) != api.supportedCodecs.end()) { if (std::find(api.supportedCodecs.begin(), api.supportedCodecs.end(), id) != api.supportedCodecs.end()) {
auto accel = std::make_unique<HardwareAccel>(id, api.name, api.format, api.swFormat, CODEC_DECODER); auto accel = std::make_unique<HardwareAccel>(id, api.name, api.hwType, api.format, api.swFormat, CODEC_DECODER);
if (accel->initDevice()) { if (accel->initDevice()) {
// we don't need frame context for videotoolbox // we don't need frame context for videotoolbox
if (api.format == AV_PIX_FMT_VIDEOTOOLBOX || if (api.format == AV_PIX_FMT_VIDEOTOOLBOX ||
...@@ -288,15 +282,15 @@ std::unique_ptr<HardwareAccel> ...@@ -288,15 +282,15 @@ std::unique_ptr<HardwareAccel>
HardwareAccel::setupEncoder(AVCodecID id, int width, int height, AVBufferRef* framesCtx) HardwareAccel::setupEncoder(AVCodecID id, int width, int height, AVBufferRef* framesCtx)
{ {
static const HardwareAPI apiList[] = { static const HardwareAPI apiList[] = {
{ "nvenc", AV_PIX_FMT_CUDA, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_H265 } }, { "nvenc", AV_HWDEVICE_TYPE_CUDA, AV_PIX_FMT_CUDA, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_H265 } },
{ "vaapi", AV_PIX_FMT_VAAPI, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MJPEG, AV_CODEC_ID_VP8 } }, { "vaapi", AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264, AV_CODEC_ID_MJPEG, AV_CODEC_ID_VP8 } },
{ "videotoolbox", AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264 } }, { "videotoolbox", AV_HWDEVICE_TYPE_VIDEOTOOLBOX, AV_PIX_FMT_VIDEOTOOLBOX, AV_PIX_FMT_NV12, { AV_CODEC_ID_H264 } },
}; };
for (auto api : apiList) { for (auto api : apiList) {
const auto& it = std::find(api.supportedCodecs.begin(), api.supportedCodecs.end(), id); const auto& it = std::find(api.supportedCodecs.begin(), api.supportedCodecs.end(), id);
if (it != api.supportedCodecs.end()) { if (it != api.supportedCodecs.end()) {
auto accel = std::make_unique<HardwareAccel>(id, api.name, api.format, api.swFormat, CODEC_ENCODER); auto accel = std::make_unique<HardwareAccel>(id, api.name, api.hwType, api.format, api.swFormat, CODEC_ENCODER);
const auto& codecName = accel->getCodecName(); const auto& codecName = accel->getCodecName();
if (avcodec_find_encoder_by_name(codecName.c_str())) { if (avcodec_find_encoder_by_name(codecName.c_str())) {
if (accel->initDevice()) { if (accel->initDevice()) {
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#include <string> #include <string>
#include <vector> #include <vector>
extern "C" {
#include <libavutil/hwcontext.h>
}
namespace jami { namespace video { namespace jami { namespace video {
/** /**
...@@ -57,7 +61,7 @@ public: ...@@ -57,7 +61,7 @@ public:
/** /**
* Made public so std::unique_ptr can access it. Should not be called. * Made public so std::unique_ptr can access it. Should not be called.
*/ */
HardwareAccel(AVCodecID id, const std::string& name, AVPixelFormat format, AVPixelFormat swFormat, CodecType type); HardwareAccel(AVCodecID id, const std::string& name, AVHWDeviceType hwType, AVPixelFormat format, AVPixelFormat swFormat, CodecType type);
/** /**
* Dereferences hardware contexts. * Dereferences hardware contexts.
...@@ -131,6 +135,7 @@ private: ...@@ -131,6 +135,7 @@ private:
AVCodecID id_ {AV_CODEC_ID_NONE}; AVCodecID id_ {AV_CODEC_ID_NONE};
std::string name_; std::string name_;
AVHWDeviceType hwType_ {AV_HWDEVICE_TYPE_NONE};
AVPixelFormat format_ {AV_PIX_FMT_NONE}; AVPixelFormat format_ {AV_PIX_FMT_NONE};
AVPixelFormat swFormat_ {AV_PIX_FMT_NONE}; AVPixelFormat swFormat_ {AV_PIX_FMT_NONE};
CodecType type_ {CODEC_NONE}; CodecType type_ {CODEC_NONE};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment