File indexing completed on 2025-01-19 03:57:04
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 "qavhwdevice_mediacodec_p.h" 0009 #include "qavvideobuffer_gpu_p.h" 0010 #include "qavcodec_p.h" 0011 #include "qavandroidsurfacetexture_p.h" 0012 #include <GLES/gl.h> 0013 0014 extern "C" { 0015 #include <libavutil/pixdesc.h> 0016 #include <libavcodec/mediacodec.h> 0017 #include <libavutil/hwcontext_mediacodec.h> 0018 } 0019 0020 QT_BEGIN_NAMESPACE 0021 0022 Q_GLOBAL_STATIC(QAVAndroidSurfaceTexture, androidSurfaceTexture); 0023 0024 class QAVHWDevice_MediaCodecPrivate 0025 { 0026 public: 0027 GLuint texture = 0; 0028 }; 0029 0030 QAVHWDevice_MediaCodec::QAVHWDevice_MediaCodec() 0031 : d_ptr(new QAVHWDevice_MediaCodecPrivate) 0032 { 0033 } 0034 0035 QAVHWDevice_MediaCodec::~QAVHWDevice_MediaCodec() 0036 { 0037 Q_D(QAVHWDevice_MediaCodec); 0038 if (d->texture) 0039 glDeleteTextures(1, &d->texture); 0040 } 0041 0042 void QAVHWDevice_MediaCodec::init(AVCodecContext *avctx) 0043 { 0044 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0045 AVBufferRef *hw_device_ctx = avctx->hw_device_ctx; 0046 if (hw_device_ctx) { 0047 AVHWDeviceContext *deviceContext = reinterpret_cast<AVHWDeviceContext *>(hw_device_ctx->data); 0048 if (deviceContext->hwctx) { 0049 AVMediaCodecDeviceContext *mediaDeviceContext = 0050 reinterpret_cast<AVMediaCodecDeviceContext *>(deviceContext->hwctx); 0051 if (mediaDeviceContext) 0052 mediaDeviceContext->surface = androidSurfaceTexture->surface(); 0053 } 0054 } 0055 #else 0056 Q_UNUSED(avctx); 0057 #endif 0058 } 0059 0060 AVPixelFormat QAVHWDevice_MediaCodec::format() const 0061 { 0062 return AV_PIX_FMT_MEDIACODEC; 0063 } 0064 0065 AVHWDeviceType QAVHWDevice_MediaCodec::type() const 0066 { 0067 return AV_HWDEVICE_TYPE_MEDIACODEC; 0068 } 0069 0070 class VideoBuffer_MediaCodec : public QAVVideoBuffer_GPU 0071 { 0072 public: 0073 VideoBuffer_MediaCodec(QAVHWDevice_MediaCodecPrivate *hw, const QAVVideoFrame &frame) 0074 : QAVVideoBuffer_GPU(frame) 0075 , m_hw(hw) 0076 { 0077 } 0078 0079 QAVVideoFrame::HandleType handleType() const override 0080 { 0081 return QAVVideoFrame::GLTextureHandle; 0082 } 0083 0084 QVariant handle(QRhi */*rhi*/) const override 0085 { 0086 if (!androidSurfaceTexture->isValid()) 0087 return {}; 0088 0089 if (!m_hw->texture) { 0090 androidSurfaceTexture->detachFromGLContext(); 0091 glGenTextures(1, &m_hw->texture); 0092 androidSurfaceTexture->attachToGLContext(m_hw->texture); 0093 } 0094 0095 AVMediaCodecBuffer *buffer = reinterpret_cast<AVMediaCodecBuffer *>(frame().frame()->data[3]); 0096 if (!buffer) { 0097 qWarning() << "Received a frame without AVMediaCodecBuffer."; 0098 } else if (av_mediacodec_release_buffer(buffer, 1) < 0) { 0099 qWarning() << "Failed to render buffer to surface."; 0100 return {}; 0101 } 0102 0103 androidSurfaceTexture->updateTexImage(); 0104 return m_hw->texture; 0105 } 0106 0107 QAVHWDevice_MediaCodecPrivate *m_hw = nullptr; 0108 }; 0109 0110 QAVVideoBuffer *QAVHWDevice_MediaCodec::videoBuffer(const QAVVideoFrame &frame) const 0111 { 0112 return new VideoBuffer_MediaCodec(d_ptr.get(), frame); 0113 } 0114 0115 QT_END_NAMESPACE