GpuFormats.hpp
1 #pragma once
2 #include <Media/Libav.hpp>
3 
4 #if SCORE_HAS_LIBAV
5 extern "C" {
6 #include <libavformat/avformat.h>
7 #include <libavutil/pixdesc.h>
8 #include <libavutil/version.h>
9 #if __has_include(<libavutil/hwcontext.h>)
10 #include <libavutil/hwcontext.h>
11 #endif
12 struct AVCodecContext;
13 }
14 
15 namespace Video
16 {
17 
18 inline bool hardwareDecoderIsAvailable(AVPixelFormat p) noexcept
19 {
20  switch(p)
21  {
22 #if defined(__linux__)
23  case AV_PIX_FMT_DRM_PRIME: {
24  static const bool ok = avcodec_find_decoder_by_name("h264_v4l2m2m");
25  return ok;
26  }
27  case AV_PIX_FMT_VAAPI: {
28  static const bool ok = avcodec_find_decoder_by_name("mjpeg_vaapi");
29  return ok;
30  }
31  case AV_PIX_FMT_VDPAU: {
32  static const bool ok = avcodec_find_decoder_by_name("h264_vdpau");
33  return ok;
34  }
35 #endif
36 #if defined(_WIN32)
37  case AV_PIX_FMT_DXVA2_VLD:
38  return true;
39  case AV_PIX_FMT_D3D11:
40  return true;
41 #endif
42 #if defined(__APPLE__)
43  case AV_PIX_FMT_VIDEOTOOLBOX:
44  return true;
45 #endif
46  // Cross-platform pix formats
47  case AV_PIX_FMT_CUDA: {
48  static const bool ok = avcodec_find_decoder_by_name("mjpeg_cuvid")
49  || avcodec_find_decoder_by_name("h264_cuvid");
50  return ok;
51  }
52  case AV_PIX_FMT_QSV: {
53  static const bool ok = avcodec_find_decoder_by_name("mjpeg_qsv")
54  || avcodec_find_decoder_by_name("h264_qsv");
55  return ok;
56  }
57  default:
58  return false;
59  }
60 }
61 
62 inline constexpr bool formatIsHardwareDecoded(AVPixelFormat fmt) noexcept
63 {
64 #if LIBAVUTIL_VERSION_MAJOR < 57
65  return false;
66 #else
67  switch(fmt)
68  {
69  case AV_PIX_FMT_VAAPI:
70  case AV_PIX_FMT_VDPAU:
71  case AV_PIX_FMT_DXVA2_VLD:
72  case AV_PIX_FMT_D3D11:
73  case AV_PIX_FMT_CUDA:
74  case AV_PIX_FMT_QSV:
75  case AV_PIX_FMT_VIDEOTOOLBOX:
76  case AV_PIX_FMT_DRM_PRIME:
77  return true;
78  default:
79  return false;
80  }
81 #endif
82 }
83 
84 inline constexpr bool formatNeedsDecoding(AVPixelFormat fmt) noexcept
85 {
86  // They all get translated to some NV12 or something like that
87  if(formatIsHardwareDecoded(fmt))
88  return false;
89 
90  switch(fmt)
91  {
92  case AV_PIX_FMT_YUV420P:
93  case AV_PIX_FMT_RGB24:
94  case AV_PIX_FMT_BGR24:
95  case AV_PIX_FMT_NV12:
96  case AV_PIX_FMT_NV21:
97  case AV_PIX_FMT_YUVJ420P:
98  case AV_PIX_FMT_YUVJ422P:
99  case AV_PIX_FMT_YUV422P:
100  case AV_PIX_FMT_UYVY422:
101  case AV_PIX_FMT_YUYV422:
102  case AV_PIX_FMT_RGB0:
103  case AV_PIX_FMT_RGBA:
104  case AV_PIX_FMT_BGR0:
105  case AV_PIX_FMT_BGRA:
106  case AV_PIX_FMT_ARGB:
107  case AV_PIX_FMT_ABGR:
108 
109 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 19, 100)
110  case AV_PIX_FMT_YUV420P10LE:
111  case AV_PIX_FMT_YUV420P12LE:
112  case AV_PIX_FMT_YUV422P10LE:
113  case AV_PIX_FMT_YUV422P12LE:
114  case AV_PIX_FMT_GBRPF32LE:
115  case AV_PIX_FMT_GBRAPF32LE:
116  case AV_PIX_FMT_GRAYF32LE:
117  case AV_PIX_FMT_GRAYF32BE:
118 #endif
119  case AV_PIX_FMT_GRAY8:
120  case AV_PIX_FMT_GRAY16:
121  return false;
122 
123  // Other formats get rgb'd
124  default:
125  return true;
126  }
127 }
128 
129 #if LIBAVUTIL_VERSION_MAJOR >= 57
130 // Get hardware pix format
131 struct HWAccelFormats
132 {
133  AVPixelFormat format{AV_PIX_FMT_NONE};
134  AVHWDeviceType device{AV_HWDEVICE_TYPE_NONE};
135 };
136 
137 inline constexpr HWAccelFormats ffmpegHardwareDecodingFormats(AVPixelFormat p) noexcept
138 {
139  switch(p)
140  {
141 #if defined(__linux__)
142  case AV_PIX_FMT_DRM_PRIME:
143  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DRM_PRIME))
144  return {};
145  return {AV_PIX_FMT_DRM_PRIME, AV_HWDEVICE_TYPE_DRM};
146  case AV_PIX_FMT_VAAPI:
147  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VAAPI))
148  return {};
149  return {AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI};
150  case AV_PIX_FMT_VDPAU:
151  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VDPAU))
152  return {};
153  return {AV_PIX_FMT_VDPAU, AV_HWDEVICE_TYPE_VDPAU};
154 #endif
155 #if defined(_WIN32)
156  case AV_PIX_FMT_DXVA2_VLD:
157  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DXVA2_VLD))
158  return {};
159  return {AV_PIX_FMT_DXVA2_VLD, AV_HWDEVICE_TYPE_DXVA2};
160  case AV_PIX_FMT_D3D11:
161  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_D3D11))
162  return {};
163  return {AV_PIX_FMT_D3D11, AV_HWDEVICE_TYPE_D3D11VA};
164 #endif
165 #if defined(__APPLE__)
166  case AV_PIX_FMT_VIDEOTOOLBOX:
167  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VIDEOTOOLBOX))
168  return {};
169  return {AV_PIX_FMT_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VIDEOTOOLBOX};
170 #endif
171  // Cross-platform pix formats
172  case AV_PIX_FMT_CUDA:
173  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_CUDA))
174  return {};
175  return {AV_PIX_FMT_CUDA, AV_HWDEVICE_TYPE_CUDA};
176  case AV_PIX_FMT_QSV:
177  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_QSV))
178  return {};
179  return {AV_PIX_FMT_QSV, AV_HWDEVICE_TYPE_QSV};
180  // case AV_PIX_FMT_VULKAN:
181  // return {AV_PIX_FMT_VULKAN, AV_HWDEVICE_TYPE_VULKAN};
182  // case AV_PIX_FMT_OPENCL:
183  // return {AV_PIX_FMT_OPENCL, AV_HWDEVICE_TYPE_OPENCL};
184  default:
185  return {};
186  }
187 }
188 
189 inline constexpr bool ffmpegCanDoHardwareDecoding(AVCodecID id) noexcept
190 {
191  switch(id)
192  {
193  case AV_CODEC_ID_AV1:
194  case AV_CODEC_ID_H264:
195  case AV_CODEC_ID_HEVC:
196  case AV_CODEC_ID_MJPEG:
197  case AV_CODEC_ID_MPEG1VIDEO:
198  case AV_CODEC_ID_MPEG2VIDEO:
199  case AV_CODEC_ID_MPEG4:
200  case AV_CODEC_ID_VC1:
201  case AV_CODEC_ID_VP8:
202  case AV_CODEC_ID_VP9:
203  case AV_CODEC_ID_WMV1:
204  case AV_CODEC_ID_WMV2:
205  case AV_CODEC_ID_WMV3:
206  return true;
207  default:
208  return false;
209  }
210 }
211 #endif
212 }
213 
214 #endif