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_NV12:
94  case AV_PIX_FMT_NV21:
95  case AV_PIX_FMT_YUVJ420P:
96  case AV_PIX_FMT_YUVJ422P:
97  case AV_PIX_FMT_YUV422P:
98  case AV_PIX_FMT_UYVY422:
99  case AV_PIX_FMT_YUYV422:
100  case AV_PIX_FMT_RGB0:
101  case AV_PIX_FMT_RGBA:
102  case AV_PIX_FMT_BGR0:
103  case AV_PIX_FMT_BGRA:
104  case AV_PIX_FMT_ARGB:
105  case AV_PIX_FMT_ABGR:
106 
107 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 19, 100)
108  case AV_PIX_FMT_YUV420P10LE:
109  case AV_PIX_FMT_YUV420P12LE:
110  case AV_PIX_FMT_YUV422P10LE:
111  case AV_PIX_FMT_YUV422P12LE:
112  case AV_PIX_FMT_GBRPF32LE:
113  case AV_PIX_FMT_GBRAPF32LE:
114  case AV_PIX_FMT_GRAYF32LE:
115  case AV_PIX_FMT_GRAYF32BE:
116 #endif
117  case AV_PIX_FMT_GRAY8:
118  case AV_PIX_FMT_GRAY16:
119  return false;
120 
121  // Other formats get rgb'd
122  default:
123  return true;
124  }
125 }
126 
127 #if LIBAVUTIL_VERSION_MAJOR >= 57
128 // Get hardware pix format
129 struct HWAccelFormats
130 {
131  AVPixelFormat format{AV_PIX_FMT_NONE};
132  AVHWDeviceType device{AV_HWDEVICE_TYPE_NONE};
133 };
134 
135 inline constexpr HWAccelFormats ffmpegHardwareDecodingFormats(AVPixelFormat p) noexcept
136 {
137  switch(p)
138  {
139 #if defined(__linux__)
140  case AV_PIX_FMT_DRM_PRIME:
141  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DRM_PRIME))
142  return {};
143  return {AV_PIX_FMT_DRM_PRIME, AV_HWDEVICE_TYPE_DRM};
144  case AV_PIX_FMT_VAAPI:
145  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VAAPI))
146  return {};
147  return {AV_PIX_FMT_VAAPI, AV_HWDEVICE_TYPE_VAAPI};
148  case AV_PIX_FMT_VDPAU:
149  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VDPAU))
150  return {};
151  return {AV_PIX_FMT_VDPAU, AV_HWDEVICE_TYPE_VDPAU};
152 #endif
153 #if defined(_WIN32)
154  case AV_PIX_FMT_DXVA2_VLD:
155  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_DXVA2_VLD))
156  return {};
157  return {AV_PIX_FMT_DXVA2_VLD, AV_HWDEVICE_TYPE_DXVA2};
158  case AV_PIX_FMT_D3D11:
159  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_D3D11))
160  return {};
161  return {AV_PIX_FMT_D3D11, AV_HWDEVICE_TYPE_D3D11VA};
162 #endif
163 #if defined(__APPLE__)
164  case AV_PIX_FMT_VIDEOTOOLBOX:
165  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_VIDEOTOOLBOX))
166  return {};
167  return {AV_PIX_FMT_VIDEOTOOLBOX, AV_HWDEVICE_TYPE_VIDEOTOOLBOX};
168 #endif
169  // Cross-platform pix formats
170  case AV_PIX_FMT_CUDA:
171  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_CUDA))
172  return {};
173  return {AV_PIX_FMT_CUDA, AV_HWDEVICE_TYPE_CUDA};
174  case AV_PIX_FMT_QSV:
175  if(!hardwareDecoderIsAvailable(AV_PIX_FMT_QSV))
176  return {};
177  return {AV_PIX_FMT_QSV, AV_HWDEVICE_TYPE_QSV};
178  // case AV_PIX_FMT_VULKAN:
179  // return {AV_PIX_FMT_VULKAN, AV_HWDEVICE_TYPE_VULKAN};
180  // case AV_PIX_FMT_OPENCL:
181  // return {AV_PIX_FMT_OPENCL, AV_HWDEVICE_TYPE_OPENCL};
182  default:
183  return {};
184  }
185 }
186 
187 inline constexpr bool ffmpegCanDoHardwareDecoding(AVCodecID id) noexcept
188 {
189  switch(id)
190  {
191  case AV_CODEC_ID_AV1:
192  case AV_CODEC_ID_H264:
193  case AV_CODEC_ID_HEVC:
194  case AV_CODEC_ID_MJPEG:
195  case AV_CODEC_ID_MPEG1VIDEO:
196  case AV_CODEC_ID_MPEG2VIDEO:
197  case AV_CODEC_ID_MPEG4:
198  case AV_CODEC_ID_VC1:
199  case AV_CODEC_ID_VP8:
200  case AV_CODEC_ID_VP9:
201  case AV_CODEC_ID_WMV1:
202  case AV_CODEC_ID_WMV2:
203  case AV_CODEC_ID_WMV3:
204  return true;
205  default:
206  return false;
207  }
208 }
209 #endif
210 }
211 
212 #endif