| 1 | // Copyright (C) 2024 The Qt Company Ltd. | 
|---|
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | 
|---|
| 3 |  | 
|---|
| 4 | #ifndef QFFMPEGTEXTURECONVERTER_P_H | 
|---|
| 5 | #define QFFMPEGTEXTURECONVERTER_P_H | 
|---|
| 6 |  | 
|---|
| 7 | #include <QtFFmpegMediaPluginImpl/private/qffmpegdefs_p.h> | 
|---|
| 8 | #include <QtMultimedia/private/qhwvideobuffer_p.h> | 
|---|
| 9 |  | 
|---|
| 10 | #include <memory> | 
|---|
| 11 |  | 
|---|
| 12 | // | 
|---|
| 13 | //  W A R N I N G | 
|---|
| 14 | //  ------------- | 
|---|
| 15 | // | 
|---|
| 16 | // This file is not part of the Qt API.  It exists purely as an | 
|---|
| 17 | // implementation detail.  This header file may change from version to | 
|---|
| 18 | // version without notice, or even be removed. | 
|---|
| 19 | // | 
|---|
| 20 | // We mean it. | 
|---|
| 21 | // | 
|---|
| 22 |  | 
|---|
| 23 | QT_BEGIN_NAMESPACE | 
|---|
| 24 |  | 
|---|
| 25 | class QRhi; | 
|---|
| 26 |  | 
|---|
| 27 | namespace QFFmpeg { | 
|---|
| 28 |  | 
|---|
| 29 | /** | 
|---|
| 30 | * @brief The base class for platform-specific implementations of TextureConverter | 
|---|
| 31 | *        One of two virtual methods, createTextures and createTextureHandles, must be overridden. | 
|---|
| 32 | *        If the implementation operates with QRhiTexture under the hood, overriding of | 
|---|
| 33 | *        createTextures is prefferable, otherwise expose texture handles of native textures | 
|---|
| 34 | *        by createTextureHandles. | 
|---|
| 35 | */ | 
|---|
| 36 | class TextureConverterBackend : public std::enable_shared_from_this<TextureConverterBackend> | 
|---|
| 37 | { | 
|---|
| 38 | public: | 
|---|
| 39 | TextureConverterBackend(QRhi *rhi) : rhi(rhi) { } | 
|---|
| 40 |  | 
|---|
| 41 | virtual ~TextureConverterBackend(); | 
|---|
| 42 |  | 
|---|
| 43 | virtual QVideoFrameTexturesUPtr createTextures(AVFrame * /*hwFrame*/, | 
|---|
| 44 | QVideoFrameTexturesUPtr & /*oldTextures*/) | 
|---|
| 45 | { | 
|---|
| 46 | return nullptr; | 
|---|
| 47 | } | 
|---|
| 48 |  | 
|---|
| 49 | virtual QVideoFrameTexturesHandlesUPtr | 
|---|
| 50 | createTextureHandles(AVFrame * /*hwFrame*/, QVideoFrameTexturesHandlesUPtr /*oldHandles*/) | 
|---|
| 51 | { | 
|---|
| 52 | return nullptr; | 
|---|
| 53 | } | 
|---|
| 54 |  | 
|---|
| 55 | /** | 
|---|
| 56 | * @brief Points to the matching QRhi. | 
|---|
| 57 | *        If the constructor, createTextures, or createTextureHandles get failed without | 
|---|
| 58 | *        chances for recovery, it may set the pointer to nullptr, which will invalidate | 
|---|
| 59 | *        the parent TextureConverter, and textures creation won't be invoked anymore. | 
|---|
| 60 | */ | 
|---|
| 61 | QRhi *rhi = nullptr; | 
|---|
| 62 | }; | 
|---|
| 63 | using TextureConverterBackendPtr = std::shared_ptr<TextureConverterBackend>; | 
|---|
| 64 |  | 
|---|
| 65 | /** | 
|---|
| 66 | * @brief The TextureConverter class implements conversion of AVFrame hw textures to | 
|---|
| 67 | *        textures for rendering by the specified QRhi. Any instance of TextureConverter | 
|---|
| 68 | *        matches the pair of FFmpeg hw frames context + QRhi. | 
|---|
| 69 | */ | 
|---|
| 70 | class TextureConverter | 
|---|
| 71 | { | 
|---|
| 72 | public: | 
|---|
| 73 | /** | 
|---|
| 74 | * @brief Construct uninitialized texture converter for the specified QRhi | 
|---|
| 75 | */ | 
|---|
| 76 | TextureConverter(QRhi &rhi); | 
|---|
| 77 |  | 
|---|
| 78 | /** | 
|---|
| 79 | * @brief Initializes the instance of the texture converter for the frame context | 
|---|
| 80 | *        associated with the specified frame. The method tries to initialize | 
|---|
| 81 | *        the conversion backend during the first call with the specified frame format. | 
|---|
| 82 | *        If frame format is not changed, the method does nothing even if the first | 
|---|
| 83 | *        attempt failed. | 
|---|
| 84 | * @return Whether the instance has been initialized. | 
|---|
| 85 | */ | 
|---|
| 86 | bool init(AVFrame &hwFrame); | 
|---|
| 87 |  | 
|---|
| 88 | /** | 
|---|
| 89 | * @brief Creates video frame textures basing on the current hw frame and the previous textures | 
|---|
| 90 | *        from the texture pool. We should strive to reuse oldTextures if we can do so. | 
|---|
| 91 | *        If the method returns null, try createTextureHandles. | 
|---|
| 92 | */ | 
|---|
| 93 | QVideoFrameTexturesUPtr createTextures(AVFrame &hwFrame, QVideoFrameTexturesUPtr &oldTextures); | 
|---|
| 94 |  | 
|---|
| 95 | /** | 
|---|
| 96 | * @brief Creates video frame texture handles basing on the current hw frame and the previous | 
|---|
| 97 | *        texture handles from the pool. We should strive to reuse oldHandles if we can do so. | 
|---|
| 98 | */ | 
|---|
| 99 | QVideoFrameTexturesHandlesUPtr createTextureHandles(AVFrame &hwFrame, | 
|---|
| 100 | QVideoFrameTexturesHandlesUPtr oldHandles); | 
|---|
| 101 |  | 
|---|
| 102 | /** | 
|---|
| 103 | * @brief Indicates whether the texture converter is not initialized or the initialization | 
|---|
| 104 | * failed. If hw texture conversion is disabled, it always true. | 
|---|
| 105 | */ | 
|---|
| 106 | bool isNull() const { return !m_backend || !m_backend->rhi; } | 
|---|
| 107 |  | 
|---|
| 108 | /** | 
|---|
| 109 | * @brief Applies platform-specific hw texture conversion presets for a decoder. | 
|---|
| 110 | *        The function is supposed to be invoked for the get_format callback. | 
|---|
| 111 | */ | 
|---|
| 112 | static void applyDecoderPreset(AVPixelFormat format, AVCodecContext &codecContext); | 
|---|
| 113 |  | 
|---|
| 114 | /** | 
|---|
| 115 | * @brief Indicates whether hw texture conversion is enabled for the application. | 
|---|
| 116 | */ | 
|---|
| 117 | static bool hwTextureConversionEnabled(); | 
|---|
| 118 |  | 
|---|
| 119 | /** | 
|---|
| 120 | * @brief Indicates whether the matching textute converter backend can be created. | 
|---|
| 121 | *        If isBackendAvailable returns false, instances cannot be initialized with | 
|---|
| 122 | *        the specified frame. If it returns true, init will attempt to create backend, | 
|---|
| 123 | *        but it may fail if something goes wrong in the backend. | 
|---|
| 124 | */ | 
|---|
| 125 | static bool isBackendAvailable(AVFrame &hwFrame); | 
|---|
| 126 |  | 
|---|
| 127 | private: | 
|---|
| 128 | void updateBackend(AVPixelFormat format); | 
|---|
| 129 |  | 
|---|
| 130 | private: | 
|---|
| 131 | QRhi &m_rhi; | 
|---|
| 132 | AVPixelFormat m_format = AV_PIX_FMT_NONE; | 
|---|
| 133 | TextureConverterBackendPtr m_backend; | 
|---|
| 134 | }; | 
|---|
| 135 |  | 
|---|
| 136 | } // namespace QFFmpeg | 
|---|
| 137 |  | 
|---|
| 138 | QT_END_NAMESPACE | 
|---|
| 139 |  | 
|---|
| 140 | #endif // QFFMPEGTEXTURECONVERTER_P_H | 
|---|
| 141 |  | 
|---|