2#include <Media/Libav.hpp>
9#include <libavcodec/avcodec.h>
10#include <libavformat/avformat.h>
11#include <libavutil/pixdesc.h>
12#include <libavutil/version.h>
13#if __has_include(<libavutil/hwcontext.h>)
14#include <libavutil/hwcontext.h>
22inline bool hardwareDecoderIsAvailable(AVPixelFormat p)
noexcept
27 case AV_PIX_FMT_DRM_PRIME: {
28 static const bool ok = avcodec_find_decoder_by_name(
"h264_v4l2m2m");
31 case AV_PIX_FMT_VAAPI: {
35 static const bool ok = avcodec_find_decoder_by_name(
"mjpeg_vaapi")
36 || av_hwdevice_find_type_by_name(
"vaapi") != AV_HWDEVICE_TYPE_NONE;
39 case AV_PIX_FMT_VDPAU: {
40 static const bool ok = avcodec_find_decoder_by_name(
"h264_vdpau");
45 case AV_PIX_FMT_DXVA2_VLD:
47 case AV_PIX_FMT_D3D11:
49#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
50 case AV_PIX_FMT_D3D12:
55 case AV_PIX_FMT_VIDEOTOOLBOX:
59 case AV_PIX_FMT_CUDA: {
60 static const bool ok = avcodec_find_decoder_by_name(
"mjpeg_cuvid")
61 || avcodec_find_decoder_by_name(
"h264_cuvid");
64 case AV_PIX_FMT_QSV: {
65 static const bool ok = avcodec_find_decoder_by_name(
"mjpeg_qsv")
66 || avcodec_find_decoder_by_name(
"h264_qsv");
69 case AV_PIX_FMT_VULKAN: {
71 = av_hwdevice_find_type_by_name(
"vulkan") != AV_HWDEVICE_TYPE_NONE;
79inline constexpr bool formatIsHardwareDecoded(AVPixelFormat fmt)
noexcept
81#if LIBAVUTIL_VERSION_MAJOR < 57
86 case AV_PIX_FMT_VAAPI:
87 case AV_PIX_FMT_VDPAU:
88 case AV_PIX_FMT_DXVA2_VLD:
89 case AV_PIX_FMT_D3D11:
90#if defined(_WIN32) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
91 case AV_PIX_FMT_D3D12:
95 case AV_PIX_FMT_VIDEOTOOLBOX:
96 case AV_PIX_FMT_DRM_PRIME:
97 case AV_PIX_FMT_VULKAN:
105inline constexpr bool formatNeedsDecoding(AVPixelFormat fmt)
noexcept
108 if(formatIsHardwareDecoded(fmt))
113 case AV_PIX_FMT_YUV420P:
114 case AV_PIX_FMT_RGB24:
115 case AV_PIX_FMT_BGR24:
116 case AV_PIX_FMT_RGB48LE:
117 case AV_PIX_FMT_BGR48LE:
118 case AV_PIX_FMT_NV12:
119 case AV_PIX_FMT_NV21:
120 case AV_PIX_FMT_NV16:
121 case AV_PIX_FMT_P010LE:
122 case AV_PIX_FMT_P016LE:
123 case AV_PIX_FMT_YUVJ420P:
124 case AV_PIX_FMT_YUVJ422P:
125 case AV_PIX_FMT_YUVJ440P:
126 case AV_PIX_FMT_YUV422P:
127 case AV_PIX_FMT_YUV440P:
128 case AV_PIX_FMT_YUV444P:
129 case AV_PIX_FMT_YUVJ444P:
130 case AV_PIX_FMT_YUVA420P:
131 case AV_PIX_FMT_YUVA444P:
132 case AV_PIX_FMT_UYVY422:
133 case AV_PIX_FMT_YUYV422:
134 case AV_PIX_FMT_RGB0:
135 case AV_PIX_FMT_RGBA:
136 case AV_PIX_FMT_BGR0:
137 case AV_PIX_FMT_BGRA:
138 case AV_PIX_FMT_ARGB:
139 case AV_PIX_FMT_ABGR:
140 case AV_PIX_FMT_RGBA64LE:
141 case AV_PIX_FMT_BGRA64LE:
142 case AV_PIX_FMT_X2RGB10LE:
143 case AV_PIX_FMT_GBRP:
144 case AV_PIX_FMT_GBRAP:
146 case AV_PIX_FMT_YA16LE:
148#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 19, 100)
149 case AV_PIX_FMT_YUV420P10LE:
150 case AV_PIX_FMT_YUV420P12LE:
151 case AV_PIX_FMT_YUV422P10LE:
152 case AV_PIX_FMT_YUV422P12LE:
153 case AV_PIX_FMT_YUV444P10LE:
154 case AV_PIX_FMT_YUV444P12LE:
155 case AV_PIX_FMT_YUVA444P10LE:
156 case AV_PIX_FMT_YUVA444P12LE:
157 case AV_PIX_FMT_GBRP10LE:
158 case AV_PIX_FMT_GBRP12LE:
159 case AV_PIX_FMT_GBRP16LE:
160 case AV_PIX_FMT_GBRAP10LE:
161 case AV_PIX_FMT_GBRAP12LE:
162 case AV_PIX_FMT_GBRAP16LE:
163 case AV_PIX_FMT_GBRPF32LE:
164 case AV_PIX_FMT_GBRAPF32LE:
165 case AV_PIX_FMT_GRAYF32LE:
166 case AV_PIX_FMT_GRAYF32BE:
167 case AV_PIX_FMT_NV24:
168 case AV_PIX_FMT_NV42:
169 case AV_PIX_FMT_Y210LE:
172#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(57, 17, 100)
173 case AV_PIX_FMT_X2BGR10LE:
174 case AV_PIX_FMT_P210LE:
175 case AV_PIX_FMT_P410LE:
178#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(60, 8, 100)
179 case AV_PIX_FMT_RGBAF32LE:
180 case AV_PIX_FMT_VUYA:
181 case AV_PIX_FMT_VUYX:
182 case AV_PIX_FMT_GRAYF16LE:
183 case AV_PIX_FMT_GRAYF16BE:
186 case AV_PIX_FMT_GRAY8:
187 case AV_PIX_FMT_GRAY16:
196#if LIBAVUTIL_VERSION_MAJOR >= 57
200 AVPixelFormat format{AV_PIX_FMT_NONE};
201 AVHWDeviceType device{AV_HWDEVICE_TYPE_NONE};
204inline constexpr HWAccelFormats ffmpegHardwareDecodingFormats(AVPixelFormat p)
noexcept
208#if defined(__linux__)
209 case AV_PIX_FMT_DRM_PRIME:
210 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DRM_PRIME))
212 return {AV_PIX_FMT_DRM_PRIME, AV_HWDEVICE_TYPE_DRM};
213 case AV_PIX_FMT_VAAPI:
214 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VAAPI))
216 return {AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI};
217 case AV_PIX_FMT_VDPAU:
218 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VDPAU))
220 return {AV_PIX_FMT_VDPAU, AV_HWDEVICE_TYPE_VDPAU};
223 case AV_PIX_FMT_DXVA2_VLD:
224 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DXVA2_VLD))
226 return {AV_PIX_FMT_DXVA2_VLD, AV_HWDEVICE_TYPE_DXVA2};
227 case AV_PIX_FMT_D3D11:
228 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_D3D11))
230 return {AV_PIX_FMT_D3D11, AV_HWDEVICE_TYPE_D3D11VA};
231#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
232 case AV_PIX_FMT_D3D12:
233 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_D3D12))
235 return {AV_PIX_FMT_D3D12, AV_HWDEVICE_TYPE_D3D12VA};
238#if defined(__APPLE__)
239 case AV_PIX_FMT_VIDEOTOOLBOX:
240 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VIDEOTOOLBOX))
242 return {AV_PIX_FMT_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VIDEOTOOLBOX};
245 case AV_PIX_FMT_CUDA:
246 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_CUDA))
248 return {AV_PIX_FMT_CUDA, AV_HWDEVICE_TYPE_CUDA};
250 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_QSV))
252 return {AV_PIX_FMT_QSV, AV_HWDEVICE_TYPE_QSV};
253 case AV_PIX_FMT_VULKAN:
254 if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VULKAN))
256 return {AV_PIX_FMT_VULKAN, AV_HWDEVICE_TYPE_VULKAN};
264inline constexpr bool ffmpegCanDoHardwareDecoding(AVCodecID
id)
noexcept
268 case AV_CODEC_ID_AV1:
269 case AV_CODEC_ID_H264:
270 case AV_CODEC_ID_HEVC:
271 case AV_CODEC_ID_MJPEG:
272 case AV_CODEC_ID_MPEG1VIDEO:
273 case AV_CODEC_ID_MPEG2VIDEO:
274 case AV_CODEC_ID_MPEG4:
275 case AV_CODEC_ID_VC1:
276 case AV_CODEC_ID_VP8:
277 case AV_CODEC_ID_VP9:
278 case AV_CODEC_ID_WMV1:
279 case AV_CODEC_ID_WMV2:
280 case AV_CODEC_ID_WMV3:
281 case AV_CODEC_ID_PRORES:
288inline std::string
hwCodecName(
const char* codec_name, AVHWDeviceType device)
290 std::string name{codec_name};
293 case AV_HWDEVICE_TYPE_CUDA:
294 return name +
"_cuvid";
295 case AV_HWDEVICE_TYPE_QSV:
296 return name +
"_qsv";
297 case AV_HWDEVICE_TYPE_VDPAU:
298 return name +
"_vdpau";
299 case AV_HWDEVICE_TYPE_VAAPI:
301 case AV_HWDEVICE_TYPE_DRM:
302 return name +
"_v4l2m2m";
303 case AV_HWDEVICE_TYPE_DXVA2:
304 case AV_HWDEVICE_TYPE_D3D11VA:
305#if defined(_WIN32) && LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
306 case AV_HWDEVICE_TYPE_D3D12VA:
308 case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
309 case AV_HWDEVICE_TYPE_VULKAN:
318inline bool isVulkanComputeCodec(AVCodecID
id)
322 case AV_CODEC_ID_PRORES:
323 case AV_CODEC_ID_FFV1:
332 AVCodecID codec_id, AVPixelFormat pix_fmt, uint32_t gpuVendorId = 0)
336 auto hwInfo = ffmpegHardwareDecodingFormats(pix_fmt);
337 if(hwInfo.device == AV_HWDEVICE_TYPE_NONE)
340 const AVCodec* codec = avcodec_find_decoder(codec_id);
344 auto dedicated =
hwCodecName(codec->name, hwInfo.device);
345 if(!dedicated.empty() && dedicated != codec->name)
347 if(avcodec_find_decoder_by_name(dedicated.c_str()))
354 const AVCodecHWConfig* config = avcodec_get_hw_config(codec, i);
357 if(config->pix_fmt == pix_fmt
358 && (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX))
367inline constexpr uint32_t NVIDIA = 0x10DE;
368inline constexpr uint32_t Intel = 0x8086;
369inline constexpr uint32_t AMD = 0x1002;
370inline constexpr uint32_t Apple = 0x106B;
371inline constexpr uint32_t Broadcom = 0x14E4;
372inline constexpr uint32_t ARM = 0x13B5;
373inline constexpr uint32_t Qualcomm = 0x5143;
374inline constexpr uint32_t Samsung = 0x144D;
381inline std::vector<AVPixelFormat> selectHardwareAccelerations(
382 int graphicsApi, AVCodecID codec_id, uint32_t gpuVendorId = 0)
384 struct Candidate { AVPixelFormat fmt; };
385 std::vector<Candidate> candidates;
391 candidates = {{AV_PIX_FMT_D3D11}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
394#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
395 candidates = {{AV_PIX_FMT_D3D12}, {AV_PIX_FMT_D3D11}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
397 candidates = {{AV_PIX_FMT_D3D11}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
401#if defined(__APPLE__)
403 candidates = {{AV_PIX_FMT_VIDEOTOOLBOX}};
408#if defined(__linux__)
409 if(gpuVendorId == GpuVendor::NVIDIA)
411 candidates = {{AV_PIX_FMT_VULKAN}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_QSV}};
413 else if(gpuVendorId == GpuVendor::Intel)
415 candidates = {{AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_VULKAN}, {AV_PIX_FMT_QSV}};
417 else if(gpuVendorId == GpuVendor::AMD)
419 candidates = {{AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_VULKAN}};
421 else if(gpuVendorId == GpuVendor::Broadcom
422 || gpuVendorId == GpuVendor::ARM
423 || gpuVendorId == GpuVendor::Qualcomm)
425 candidates = {{AV_PIX_FMT_DRM_PRIME}, {AV_PIX_FMT_VULKAN}};
429 candidates = {{AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_VULKAN}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
433 {AV_PIX_FMT_VULKAN}, {AV_PIX_FMT_D3D11},
434#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(58, 29, 100)
437 {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
438#elif defined(__APPLE__)
439 candidates = {{AV_PIX_FMT_VIDEOTOOLBOX}};
441 candidates = {{AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
447#if defined(__linux__)
448 if(gpuVendorId == GpuVendor::Broadcom
449 || gpuVendorId == GpuVendor::ARM
450 || gpuVendorId == GpuVendor::Qualcomm)
452 candidates = {{AV_PIX_FMT_DRM_PRIME}};
456 candidates = {{AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
459 candidates = {{AV_PIX_FMT_D3D11}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
460#elif defined(__APPLE__)
461 candidates = {{AV_PIX_FMT_VIDEOTOOLBOX}};
467#if defined(__linux__)
468#if defined(__arm__) || defined(__aarch64__)
469 candidates = {{AV_PIX_FMT_DRM_PRIME}, {AV_PIX_FMT_VAAPI}};
471 candidates = {{AV_PIX_FMT_VAAPI}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
474 candidates = {{AV_PIX_FMT_D3D11}, {AV_PIX_FMT_CUDA}, {AV_PIX_FMT_QSV}};
475#elif defined(__APPLE__)
476 candidates = {{AV_PIX_FMT_VIDEOTOOLBOX}};
482 std::vector<AVPixelFormat> result;
483 for(
auto& c : candidates)
485 if(hardwareDecoderIsAvailable(c.fmt)
487 result.push_back(c.fmt);
494 int graphicsApi, AVCodecID codec_id, uint32_t gpuVendorId = 0)
496 auto fmts = selectHardwareAccelerations(graphicsApi, codec_id, gpuVendorId);
497 return fmts.empty() ? AV_PIX_FMT_NONE : fmts.front();
AVPixelFormat selectHardwareAcceleration(score::gfx::GraphicsApi api, AVCodecID codec_id, QRhi *rhi)
Picks the best HW accel for the given API/codec, using QRhi for vendor detection.
Definition HWAccelSetup.cpp:36
std::string hwCodecName(const char *codec_name, AVHWDeviceType device)
Delegates to Video::hwCodecName (score-plugin-gfx wrapper)
Definition HWAccelSetup.cpp:18
bool codecSupportsHWPixelFormat(AVCodecID codec_id, AVPixelFormat pix_fmt)
Delegates to Video::codecSupportsHWPixelFormat (score-plugin-gfx wrapper)
Definition HWAccelSetup.cpp:27