6#include <QtCore/qdebug.h>
7#include <QtCore/qloggingcategory.h>
8#include <QtCore/qscopeguard.h>
11#include <libavutil/pixdesc.h>
12#include <libavutil/samplefmt.h>
13#include <libavutil/error.h>
16#include <libavutil/hwcontext_videotoolbox.h>
21namespace ranges = QtMultimediaPrivate::ranges;
29 if (codec.type() == AVMEDIA_TYPE_VIDEO) {
30 auto checkFormat = [format](AVPixelFormat f) {
return f == format; };
31 return findAVPixelFormat(codec, checkFormat).has_value();
34 if (codec.type() == AVMEDIA_TYPE_AUDIO) {
35 const auto sampleFormats = codec.sampleFormats();
36 return hasValue(sampleFormats, AVSampleFormat(format));
44 const auto desc = av_pix_fmt_desc_get(format);
45 return desc && (desc->flags & AV_PIX_FMT_FLAG_HWACCEL) != 0;
50 if (codec.isExperimental()) {
51 qCWarning(qLcFFmpegUtils) <<
"Applying the option 'strict -2' for the experimental codec"
52 << codec.name() <<
". it's unlikely to work properly";
53 av_dict_set(opts,
"strict",
"-2", 0);
60 case AV_HWDEVICE_TYPE_VIDEOTOOLBOX:
61 return AV_PIX_FMT_VIDEOTOOLBOX;
62 case AV_HWDEVICE_TYPE_VAAPI:
63 return AV_PIX_FMT_VAAPI;
64 case AV_HWDEVICE_TYPE_MEDIACODEC:
65 return AV_PIX_FMT_MEDIACODEC;
66 case AV_HWDEVICE_TYPE_CUDA:
67 return AV_PIX_FMT_CUDA;
68 case AV_HWDEVICE_TYPE_VDPAU:
69 return AV_PIX_FMT_VDPAU;
70 case AV_HWDEVICE_TYPE_OPENCL:
71 return AV_PIX_FMT_OPENCL;
72 case AV_HWDEVICE_TYPE_QSV:
73 return AV_PIX_FMT_QSV;
74 case AV_HWDEVICE_TYPE_D3D11VA:
75 return AV_PIX_FMT_D3D11;
76#if QT_FFMPEG_HAS_D3D12VA
77 case AV_HWDEVICE_TYPE_D3D12VA:
78 return AV_PIX_FMT_D3D12;
80 case AV_HWDEVICE_TYPE_DXVA2:
81 return AV_PIX_FMT_DXVA2_VLD;
82 case AV_HWDEVICE_TYPE_DRM:
83 return AV_PIX_FMT_DRM_PRIME;
84#if QT_FFMPEG_HAS_VULKAN
85 case AV_HWDEVICE_TYPE_VULKAN:
86 return AV_PIX_FMT_VULKAN;
89 return AV_PIX_FMT_NONE;
95 QScopeGuard freeData([&sideData]() { av_free(sideData.data); });
96#if QT_FFMPEG_STREAM_SIDE_DATA_DEPRECATED
97 AVPacketSideData *result = av_packet_side_data_add(
98 &stream->codecpar->coded_side_data,
99 &stream->codecpar->nb_coded_side_data,
113 qWarning() <<
"Adding stream side data is not supported for FFmpeg < 6.1";
123#if QT_FFMPEG_STREAM_SIDE_DATA_DEPRECATED
124 return av_packet_side_data_get(stream->codecpar->coded_side_data,
125 stream->codecpar->nb_coded_side_data, type);
127 auto checkType = [type](
const auto &item) {
return item.type == type; };
128 const auto end = stream->side_data + stream->nb_side_data;
129 const auto found = ranges::find_if(stream->side_data, end, checkType);
130 return found == end ?
nullptr : found;
135 const AVAudioFormat &outputFormat)
137 SwrContext *resampler =
nullptr;
138#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
140#if QT_FFMPEG_SWR_CONST_CH_LAYOUT
141 using AVChannelLayoutPrm =
const AVChannelLayout*;
143 using AVChannelLayoutPrm = AVChannelLayout*;
146 swr_alloc_set_opts2(&resampler,
147 const_cast<AVChannelLayoutPrm>(&outputFormat.channelLayout),
148 outputFormat.sampleFormat,
149 outputFormat.sampleRate,
150 const_cast<AVChannelLayoutPrm>(&inputFormat.channelLayout),
151 inputFormat.sampleFormat,
152 inputFormat.sampleRate,
158 resampler = swr_alloc_set_opts(
nullptr,
159 outputFormat.channelLayoutMask,
160 outputFormat.sampleFormat,
161 outputFormat.sampleRate,
162 inputFormat.channelLayoutMask,
163 inputFormat.sampleFormat,
164 inputFormat.sampleRate,
174 qCWarning(qLcFFmpegUtils) <<
"Failed to initialize audio resampler:" << error;
177 return SwrContextUPtr(resampler);
182 case AVCOL_TRC_BT709:
184 case AVCOL_TRC_BT1361_ECG:
185 case AVCOL_TRC_BT2020_10:
186 case AVCOL_TRC_BT2020_12:
187 case AVCOL_TRC_SMPTE240M:
188 return QVideoFrameFormat::ColorTransfer_BT709;
189 case AVCOL_TRC_GAMMA22:
190 case AVCOL_TRC_SMPTE428:
191 case AVCOL_TRC_IEC61966_2_1:
192 case AVCOL_TRC_IEC61966_2_4:
193 return QVideoFrameFormat::ColorTransfer_Gamma22;
194 case AVCOL_TRC_GAMMA28:
195 return QVideoFrameFormat::ColorTransfer_Gamma28;
196 case AVCOL_TRC_SMPTE170M:
197 return QVideoFrameFormat::ColorTransfer_BT601;
198 case AVCOL_TRC_LINEAR:
199 return QVideoFrameFormat::ColorTransfer_Linear;
200 case AVCOL_TRC_SMPTE2084:
201 return QVideoFrameFormat::ColorTransfer_ST2084;
202 case AVCOL_TRC_ARIB_STD_B67:
203 return QVideoFrameFormat::ColorTransfer_STD_B67;
207 return QVideoFrameFormat::ColorTransfer_Unknown;
213 case QVideoFrameFormat::ColorTransfer_BT709:
214 return AVCOL_TRC_BT709;
215 case QVideoFrameFormat::ColorTransfer_BT601:
216 return AVCOL_TRC_BT709;
217 case QVideoFrameFormat::ColorTransfer_Linear:
218 return AVCOL_TRC_SMPTE2084;
219 case QVideoFrameFormat::ColorTransfer_Gamma22:
220 return AVCOL_TRC_GAMMA22;
221 case QVideoFrameFormat::ColorTransfer_Gamma28:
222 return AVCOL_TRC_GAMMA28;
223 case QVideoFrameFormat::ColorTransfer_ST2084:
224 return AVCOL_TRC_SMPTE2084;
225 case QVideoFrameFormat::ColorTransfer_STD_B67:
226 return AVCOL_TRC_ARIB_STD_B67;
228 return AVCOL_TRC_UNSPECIFIED;
234 switch (colorSpace) {
236 case AVCOL_SPC_UNSPECIFIED:
237 case AVCOL_SPC_RESERVED:
239 case AVCOL_SPC_SMPTE240M:
240 case AVCOL_SPC_YCGCO:
241 case AVCOL_SPC_SMPTE2085:
242 case AVCOL_SPC_CHROMA_DERIVED_NCL:
243 case AVCOL_SPC_CHROMA_DERIVED_CL:
244 case AVCOL_SPC_ICTCP:
245 return QVideoFrameFormat::ColorSpace_Undefined;
247 return QVideoFrameFormat::ColorSpace_AdobeRgb;
248 case AVCOL_SPC_BT709:
249 return QVideoFrameFormat::ColorSpace_BT709;
250 case AVCOL_SPC_BT470BG:
251 case AVCOL_SPC_SMPTE170M:
252 return QVideoFrameFormat::ColorSpace_BT601;
253 case AVCOL_SPC_BT2020_NCL:
254 case AVCOL_SPC_BT2020_CL:
255 return QVideoFrameFormat::ColorSpace_BT2020;
261 switch (colorSpace) {
262 case QVideoFrameFormat::ColorSpace_BT601:
263 return AVCOL_SPC_BT470BG;
264 case QVideoFrameFormat::ColorSpace_BT709:
265 return AVCOL_SPC_BT709;
266 case QVideoFrameFormat::ColorSpace_AdobeRgb:
267 return AVCOL_SPC_RGB;
268 case QVideoFrameFormat::ColorSpace_BT2020:
269 return AVCOL_SPC_BT2020_CL;
271 return AVCOL_SPC_UNSPECIFIED;
277 switch (colorRange) {
278 case AVCOL_RANGE_MPEG:
279 return QVideoFrameFormat::ColorRange_Video;
280 case AVCOL_RANGE_JPEG:
281 return QVideoFrameFormat::ColorRange_Full;
283 return QVideoFrameFormat::ColorRange_Unknown;
289 switch (colorRange) {
290 case QVideoFrameFormat::ColorRange_Video:
291 return AVCOL_RANGE_MPEG;
292 case QVideoFrameFormat::ColorRange_Full:
293 return AVCOL_RANGE_JPEG;
295 return AVCOL_RANGE_UNSPECIFIED;
302 if (!frame->hw_frames_ctx)
305 const auto *frameCtx =
reinterpret_cast<AVHWFramesContext *>(frame->hw_frames_ctx->data);
309 return frameCtx->device_ctx;
313 AVPixelFormat dstPixFmt, SwsFlags conversionType)
317 sws_getContext(srcSize.width(), srcSize.height(), srcPixFmt, dstSize.width(),
318 dstSize.height(), dstPixFmt, conversionType,
nullptr,
nullptr,
nullptr);
321 qCWarning(qLcFFmpegUtils) <<
"Cannot create sws context for:\n"
322 <<
"srcSize:" << srcSize
323 <<
"srcPixFmt:" << srcPixFmt
324 <<
"dstSize:" << dstSize
325 <<
"dstPixFmt:" << dstPixFmt
326 <<
"conversionType:" << conversionType;
328 return SwsContextUPtr(result);
349 dbg << value.num <<
"/" << value.den;
356 auto freeBuffer = QScopeGuard([&] {
360 int status = av_dict_get_string(&dict, &buffer,
'=',
',');
361 if (status < 0 || !buffer)
362 return dbg <<
"Failed to print AVDictionary";
370 const AVDictionary *rawDict = dict.opts;
372 return dbg << *rawDict;
374 return dbg <<
"Empty AVDictionaryHolder";
384 char errBuf[AV_ERROR_MAX_STRING_SIZE];
385 dbg << av_make_error_string(errBuf, AV_ERROR_MAX_STRING_SIZE, qToUnderlying(error));
389#if QT_FFMPEG_HAS_AV_CHANNEL_LAYOUT
390QDebug operator<<(QDebug dbg,
const AVChannelLayout &layout)
393 dbg <<
"nb_channels:" << layout.nb_channels;
394 dbg <<
", order:" << layout.order;
396 if (layout.order == AV_CHANNEL_ORDER_NATIVE || layout.order == AV_CHANNEL_ORDER_AMBISONIC)
397 dbg <<
", mask:" << Qt::bin << layout.u.mask << Qt::dec;
398 else if (layout.order == AV_CHANNEL_ORDER_CUSTOM && layout.u.map)
399 dbg <<
", id: " << layout.u.map->id;
407#if QT_FFMPEG_HAS_AVCODEC_GET_SUPPORTED_CONFIG
408QDebug operator<<(QDebug dbg,
const AVCodecConfig value)
411 case AV_CODEC_CONFIG_CHANNEL_LAYOUT:
412 dbg <<
"AV_CODEC_CONFIG_CHANNEL_LAYOUT";
414 case AV_CODEC_CONFIG_COLOR_RANGE:
415 dbg <<
"AV_CODEC_CONFIG_COLOR_RANGE";
417 case AV_CODEC_CONFIG_COLOR_SPACE:
418 dbg <<
"AV_CODEC_CONFIG_COLOR_SPACE";
420 case AV_CODEC_CONFIG_FRAME_RATE:
421 dbg <<
"AV_CODEC_CONFIG_FRAME_RATE";
423 case AV_CODEC_CONFIG_PIX_FORMAT:
424 dbg <<
"AV_CODEC_CONFIG_PIX_FORMAT";
426 case AV_CODEC_CONFIG_SAMPLE_FORMAT:
427 dbg <<
"AV_CODEC_CONFIG_SAMPLE_FORMAT";
429 case AV_CODEC_CONFIG_SAMPLE_RATE:
430 dbg <<
"AV_CODEC_CONFIG_SAMPLE_RATE";
433 dbg <<
"<UNKNOWN_CODEC_CONFIG>";
AVColorSpace toAvColorSpace(QVideoFrameFormat::ColorSpace colorSpace)
SwsContextUPtr createSwsContext(const QSize &srcSize, AVPixelFormat srcPixFmt, const QSize &dstSize, AVPixelFormat dstPixFmt, SwsFlags conversionType)
void applyExperimentalCodecOptions(const Codec &codec, AVDictionary **opts)
bool isHwPixelFormat(AVPixelFormat format)
AVPacketSideData * addStreamSideData(AVStream *stream, AVPacketSideData sideData)
AVHWDeviceContext * avFrameDeviceContext(const AVFrame *frame)
AVColorTransferCharacteristic toAvColorTransfer(QVideoFrameFormat::ColorTransfer colorTrc)
std::conditional_t< QT_FFMPEG_AVIO_WRITE_CONST, const uint8_t *, uint8_t * > AvioWriteBufferType
QVideoFrameFormat::ColorSpace fromAvColorSpace(AVColorSpace colorSpace)
bool isAVFormatSupported(const Codec &codec, PixelOrSampleFormat format)
QVideoFrameFormat::ColorTransfer fromAvColorTransfer(AVColorTransferCharacteristic colorTrc)
QVideoFrameFormat::ColorRange fromAvColorRange(AVColorRange colorRange)
SwrContextUPtr createResampleContext(const AVAudioFormat &inputFormat, const AVAudioFormat &outputFormat)
AVPixelFormat pixelFormatForHwDevice(AVHWDeviceType deviceType)
const AVPacketSideData * streamSideData(const AVStream *stream, AVPacketSideDataType type)
AVColorRange toAvColorRange(QVideoFrameFormat::ColorRange colorRange)
QDebug operator<<(QDebug dbg, const QFFmpeg::AVDictionaryHolder &dict)
QDebug operator<<(QDebug dbg, QFFmpeg::AVError error)
QDebug operator<<(QDebug dbg, const QFileInfo &fi)
QT_BEGIN_NAMESPACE Q_STATIC_LOGGING_CATEGORY(lcSynthesizedIterableAccess, "qt.iterable.synthesized", QtWarningMsg)