File indexing completed on 2025-01-19 03:57:06
0001 /********************************************************* 0002 * Copyright (C) 2020, Val Doroshchuk <valbok@gmail.com> * 0003 * * 0004 * This file is part of QtAVPlayer. * 0005 * Free Qt Media Player based on FFmpeg. * 0006 *********************************************************/ 0007 0008 #include "qavvideocodec_p.h" 0009 #include "qavhwdevice_p.h" 0010 #include "qavcodec_p_p.h" 0011 #include "qavpacket_p.h" 0012 #include "qavframe.h" 0013 #include "qavvideoframe.h" 0014 #include <QDebug> 0015 0016 extern "C" { 0017 #include <libavutil/pixdesc.h> 0018 #include <libavcodec/avcodec.h> 0019 } 0020 0021 QT_BEGIN_NAMESPACE 0022 0023 class QAVVideoCodecPrivate : public QAVCodecPrivate 0024 { 0025 public: 0026 QSharedPointer<QAVHWDevice> hw_device; 0027 }; 0028 0029 static bool isSoftwarePixelFormat(AVPixelFormat from) 0030 { 0031 switch (from) { 0032 case AV_PIX_FMT_VAAPI: 0033 case AV_PIX_FMT_VDPAU: 0034 case AV_PIX_FMT_MEDIACODEC: 0035 case AV_PIX_FMT_VIDEOTOOLBOX: 0036 case AV_PIX_FMT_D3D11: 0037 case AV_PIX_FMT_D3D11VA_VLD: 0038 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 0, 0) 0039 case AV_PIX_FMT_OPENCL: 0040 #endif 0041 case AV_PIX_FMT_CUDA: 0042 case AV_PIX_FMT_DXVA2_VLD: 0043 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(52, 58, 101) 0044 case AV_PIX_FMT_XVMC: 0045 #endif 0046 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 134, 0) 0047 case AV_PIX_FMT_VULKAN: 0048 #endif 0049 case AV_PIX_FMT_DRM_PRIME: 0050 case AV_PIX_FMT_MMAL: 0051 case AV_PIX_FMT_QSV: 0052 return false; 0053 default: 0054 return true; 0055 } 0056 } 0057 0058 static AVPixelFormat negotiate_pixel_format(AVCodecContext *c, const AVPixelFormat *f) 0059 { 0060 auto d = reinterpret_cast<QAVVideoCodecPrivate *>(c->opaque); 0061 0062 QList<AVHWDeviceType> supported; 0063 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(58, 0, 0) 0064 for (int i = 0;; ++i) { 0065 const AVCodecHWConfig *config = avcodec_get_hw_config(c->codec, i); 0066 if (!config) 0067 break; 0068 0069 if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX) 0070 supported.append(config->device_type); 0071 } 0072 0073 if (!supported.isEmpty()) { 0074 qDebug() << c->codec->name << ": supported hardware device contexts:"; 0075 for (auto a: supported) 0076 qDebug() << " " << av_hwdevice_get_type_name(a); 0077 } else { 0078 qWarning() << "None of the hardware accelerations are supported"; 0079 } 0080 #endif 0081 0082 QList<AVPixelFormat> softwareFormats; 0083 QList<AVPixelFormat> hardwareFormats; 0084 for (int i = 0; f[i] != AV_PIX_FMT_NONE; ++i) { 0085 if (!isSoftwarePixelFormat(f[i])) { 0086 hardwareFormats.append(f[i]); 0087 continue; 0088 } 0089 softwareFormats.append(f[i]); 0090 } 0091 0092 qDebug() << "Available pixel formats:"; 0093 for (auto a : softwareFormats) { 0094 auto dsc = av_pix_fmt_desc_get(a); 0095 qDebug() << " " << dsc->name << ": AVPixelFormat(" << a << ")"; 0096 } 0097 0098 for (auto a : hardwareFormats) { 0099 auto dsc = av_pix_fmt_desc_get(a); 0100 qDebug() << " " << dsc->name << ": AVPixelFormat(" << a << ")"; 0101 } 0102 0103 AVPixelFormat pf = !softwareFormats.isEmpty() ? softwareFormats[0] : AV_PIX_FMT_NONE; 0104 const char *decStr = "software"; 0105 if (d->hw_device) { 0106 for (auto f : hardwareFormats) { 0107 if (f == d->hw_device->format()) { 0108 d->hw_device->init(c); 0109 pf = d->hw_device->format(); 0110 decStr = "hardware"; 0111 break; 0112 } 0113 } 0114 } 0115 0116 auto dsc = av_pix_fmt_desc_get(pf); 0117 if (dsc) 0118 qDebug() << "Using" << decStr << "decoding in" << dsc->name; 0119 else 0120 qDebug() << "None of the pixel formats"; 0121 0122 return pf; 0123 } 0124 0125 QAVVideoCodec::QAVVideoCodec() 0126 : QAVFrameCodec(*new QAVVideoCodecPrivate) 0127 { 0128 d_ptr->avctx->opaque = d_ptr.get(); 0129 d_ptr->avctx->get_format = negotiate_pixel_format; 0130 } 0131 0132 QAVVideoCodec::~QAVVideoCodec() 0133 { 0134 av_buffer_unref(&avctx()->hw_device_ctx); 0135 } 0136 0137 void QAVVideoCodec::setDevice(const QSharedPointer<QAVHWDevice> &d) 0138 { 0139 d_func()->hw_device = d; 0140 } 0141 0142 QAVHWDevice *QAVVideoCodec::device() const 0143 { 0144 return d_func()->hw_device.data(); 0145 } 0146 0147 QT_END_NAMESPACE