Revision control
Copy as Markdown
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#ifndef QFFMPEGTEXTURECONVERTER_P_H
#define QFFMPEGTEXTURECONVERTER_P_H
#include <QtFFmpegMediaPluginImpl/private/qffmpegdefs_p.h>
#include <QtMultimedia/private/qhwvideobuffer_p.h>
#include <memory>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
QT_BEGIN_NAMESPACE
class QRhi;
namespace QFFmpeg {
/**
* @brief The base class for platform-specific implementations of TextureConverter
* One of two virtual methods, createTextures and createTextureHandles, must be overridden.
* If the implementation operates with QRhiTexture under the hood, overriding of
* createTextures is prefferable, otherwise expose texture handles of native textures
* by createTextureHandles.
*/
class TextureConverterBackend : public std::enable_shared_from_this<TextureConverterBackend>
{
public:
TextureConverterBackend(QRhi *rhi) : rhi(rhi) { }
virtual ~TextureConverterBackend();
virtual QVideoFrameTexturesUPtr createTextures(AVFrame * /*hwFrame*/,
QVideoFrameTexturesUPtr & /*oldTextures*/)
{
return nullptr;
}
virtual QVideoFrameTexturesHandlesUPtr
createTextureHandles(AVFrame * /*hwFrame*/, QVideoFrameTexturesHandlesUPtr /*oldHandles*/)
{
return nullptr;
}
/**
* @brief Points to the matching QRhi.
* If the constructor, createTextures, or createTextureHandles get failed without
* chances for recovery, it may set the pointer to nullptr, which will invalidate
* the parent TextureConverter, and textures creation won't be invoked anymore.
*/
QRhi *rhi = nullptr;
};
using TextureConverterBackendPtr = std::shared_ptr<TextureConverterBackend>;
/**
* @brief The TextureConverter class implements conversion of AVFrame hw textures to
* textures for rendering by the specified QRhi. Any instance of TextureConverter
* matches the pair of FFmpeg hw frames context + QRhi.
*/
class TextureConverter
{
public:
/**
* @brief Construct uninitialized texture converter for the specified QRhi
*/
TextureConverter(QRhi &rhi);
/**
* @brief Initializes the instance of the texture converter for the frame context
* associated with the specified frame. The method tries to initialize
* the conversion backend during the first call with the specified frame format.
* If frame format is not changed, the method does nothing even if the first
* attempt failed.
* @return Whether the instance has been initialized.
*/
bool init(AVFrame &hwFrame);
/**
* @brief Creates video frame textures basing on the current hw frame and the previous textures
* from the texture pool. We should strive to reuse oldTextures if we can do so.
* If the method returns null, try createTextureHandles.
*/
QVideoFrameTexturesUPtr createTextures(AVFrame &hwFrame, QVideoFrameTexturesUPtr &oldTextures);
/**
* @brief Creates video frame texture handles basing on the current hw frame and the previous
* texture handles from the pool. We should strive to reuse oldHandles if we can do so.
*/
QVideoFrameTexturesHandlesUPtr createTextureHandles(AVFrame &hwFrame,
QVideoFrameTexturesHandlesUPtr oldHandles);
/**
* @brief Indicates whether the texture converter is not initialized or the initialization
* failed. If hw texture conversion is disabled, it always true.
*/
bool isNull() const { return !m_backend || !m_backend->rhi; }
/**
* @brief Applies platform-specific hw texture conversion presets for a decoder.
* The function is supposed to be invoked for the get_format callback.
*/
static void applyDecoderPreset(AVPixelFormat format, AVCodecContext &codecContext);
/**
* @brief Indicates whether hw texture conversion is enabled for the application.
*/
static bool hwTextureConversionEnabled();
/**
* @brief Indicates whether the matching textute converter backend can be created.
* If isBackendAvailable returns false, instances cannot be initialized with
* the specified frame. If it returns true, init will attempt to create backend,
* but it may fail if something goes wrong in the backend.
*/
static bool isBackendAvailable(AVFrame &hwFrame, QRhi &rhi);
private:
void updateBackend(AVFrame &hwFrame);
private:
QRhi &m_rhi;
AVPixelFormat m_format = AV_PIX_FMT_NONE;
TextureConverterBackendPtr m_backend;
};
} // namespace QFFmpeg
QT_END_NAMESPACE
#endif // QFFMPEGTEXTURECONVERTER_P_H