21AVFVideoBuffer::AVFVideoBuffer(AVFVideoSinkInterface *sink, QCFType<CVImageBufferRef> buffer)
22 : QHwVideoBuffer(sink->rhi() ? QVideoFrame::RhiTextureHandle : QVideoFrame::NoHandle,
25 m_buffer(std::move(buffer))
29 const bool rhiIsOpenGL = sink && sink->rhi() && sink->rhi()->backend() == QRhi::OpenGLES2;
30 m_format = QAVFHelpers::videoFormatForImageBuffer(m_buffer, rhiIsOpenGL);
32 if (m_rhi && m_rhi->backend() == QRhi::Metal)
33 metalCache = CVMetalTextureCacheRef(CFRetain(sink->cvMetalTextureCache));
45 if (m_mode == QVideoFrame::NotMapped) {
46 CVPixelBufferLockBaseAddress(m_buffer, mode == QVideoFrame::ReadOnly
47 ? kCVPixelBufferLock_ReadOnly
52 mapData.planeCount = CVPixelBufferGetPlaneCount(m_buffer);
53 Q_ASSERT(mapData.planeCount <= 3);
55 if (!mapData.planeCount) {
57 mapData.bytesPerLine[0] = CVPixelBufferGetBytesPerRow(m_buffer);
58 mapData.data[0] =
static_cast<uchar*>(CVPixelBufferGetBaseAddress(m_buffer));
59 mapData.dataSize[0] = CVPixelBufferGetDataSize(m_buffer);
60 mapData.planeCount = mapData.data[0] ? 1 : 0;
65 for (
int i = 0; i < mapData.planeCount; ++i) {
66 mapData.bytesPerLine[i] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, i);
67 mapData.dataSize[i] = mapData.bytesPerLine[i]*CVPixelBufferGetHeightOfPlane(m_buffer, i);
68 mapData.data[i] =
static_cast<uchar*>(CVPixelBufferGetBaseAddressOfPlane(m_buffer, i));
88 case QRhiTexture::UnknownFormat:
89 return MTLPixelFormatInvalid;
90 case QRhiTexture::RGBA8:
91 return MTLPixelFormatRGBA8Unorm;
92 case QRhiTexture::BGRA8:
93 return MTLPixelFormatBGRA8Unorm;
95 case QRhiTexture::RED_OR_ALPHA8:
96 return MTLPixelFormatR8Unorm;
97 case QRhiTexture::RG8:
98 return MTLPixelFormatRG8Unorm;
99 case QRhiTexture::R16:
100 return MTLPixelFormatR16Unorm;
101 case QRhiTexture::RG16:
102 return MTLPixelFormatRG16Unorm;
103 case QRhiTexture::RGBA16F:
104 return MTLPixelFormatRGBA16Float;
105 case QRhiTexture::RGBA32F:
106 return MTLPixelFormatRGBA32Float;
107 case QRhiTexture::R16F:
108 return MTLPixelFormatR16Float;
109 case QRhiTexture::R32F:
110 return MTLPixelFormatR32Float;
117 auto *textureDescription = QVideoTextureHelper::textureDescription(m_format.pixelFormat());
118 int bufferPlanes = CVPixelBufferGetPlaneCount(m_buffer);
120 if (plane > 0 && plane >= bufferPlanes)
124 if (m_rhi->backend() == QRhi::Metal) {
125 if (!cvMetalTexture[plane]) {
126 size_t width = CVPixelBufferGetWidth(m_buffer);
127 size_t height = CVPixelBufferGetHeight(m_buffer);
128 QSize planeSize = textureDescription->rhiPlaneSize(QSize(width, height), plane, m_rhi);
131 qWarning(
"cannot create texture, Metal texture cache was released?");
136 const auto pixelFormat = rhiTextureFormatToMetalFormat(textureDescription->rhiTextureFormat(plane, m_rhi));
137 if (pixelFormat != MTLPixelFormatInvalid) {
140 auto ret = CVMetalTextureCacheCreateTextureFromImage(
145 planeSize.width(), planeSize.height(),
147 &cvMetalTexture[plane]);
149 if (ret != kCVReturnSuccess)
150 qCWarning(qLcVideoBuffer) <<
"texture creation failed" << ret;
152 qCWarning(qLcVideoBuffer) <<
"requested invalid pixel format:"
153 << textureDescription->rhiTextureFormat(plane, m_rhi);
157 return cvMetalTexture[plane] ? quint64(CVMetalTextureGetTexture(cvMetalTexture[plane])) : 0;
158 }
else if (m_rhi->backend() == QRhi::OpenGLES2) {
161 CVOpenGLTextureCacheFlush(sink->cvOpenGLTextureCache, 0);
163 const CVReturn cvret = CVOpenGLTextureCacheCreateTextureFromImage(
165 sink->cvOpenGLTextureCache,
169 if (cvret != kCVReturnSuccess)
170 qWarning() <<
"OpenGL texture creation failed" << cvret;
172 Q_ASSERT(CVOpenGLTextureGetTarget(cvOpenGLTexture) == GL_TEXTURE_RECTANGLE);
174 return CVOpenGLTextureGetName(cvOpenGLTexture);
177 CVOpenGLESTextureCacheFlush(sink->cvOpenGLESTextureCache, 0);
179 const CVReturn cvret = CVOpenGLESTextureCacheCreateTextureFromImage(
181 sink->cvOpenGLESTextureCache,
186 CVPixelBufferGetWidth(m_buffer),
187 CVPixelBufferGetHeight(m_buffer),
192 if (cvret != kCVReturnSuccess)
193 qWarning() <<
"OpenGL ES texture creation failed" << cvret;
196 return CVOpenGLESTextureGetName(cvOpenGLESTexture);