21AVFVideoBuffer::AVFVideoBuffer(AVFVideoSinkInterface *sink, QCFType<CVImageBufferRef> buffer)
22 : QHwVideoBuffer(sink->rhi() ? QVideoFrame::RhiTextureHandle : QVideoFrame::NoHandle),
26 m_buffer(std::move(buffer))
28 const bool rhiIsOpenGL = sink && sink->rhi() && sink->rhi()->backend() == QRhi::OpenGLES2;
29 m_format = QAVFHelpers::videoFormatForImageBuffer(m_buffer, rhiIsOpenGL);
31 if (sink && sink->rhi() && sink->rhi()->backend() == QRhi::Metal)
32 metalCache = sink->cvMetalTextureCache;
44 if (m_mode == QVideoFrame::NotMapped) {
45 CVPixelBufferLockBaseAddress(m_buffer, mode == QVideoFrame::ReadOnly
46 ? kCVPixelBufferLock_ReadOnly
51 mapData.planeCount = CVPixelBufferGetPlaneCount(m_buffer);
52 Q_ASSERT(mapData.planeCount <= 3);
54 if (!mapData.planeCount) {
56 mapData.bytesPerLine[0] = CVPixelBufferGetBytesPerRow(m_buffer);
57 mapData.data[0] =
static_cast<uchar*>(CVPixelBufferGetBaseAddress(m_buffer));
58 mapData.dataSize[0] = CVPixelBufferGetDataSize(m_buffer);
59 mapData.planeCount = mapData.data[0] ? 1 : 0;
64 for (
int i = 0; i < mapData.planeCount; ++i) {
65 mapData.bytesPerLine[i] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, i);
66 mapData.dataSize[i] = mapData.bytesPerLine[i]*CVPixelBufferGetHeightOfPlane(m_buffer, i);
67 mapData.data[i] =
static_cast<uchar*>(CVPixelBufferGetBaseAddressOfPlane(m_buffer, i));
87 case QRhiTexture::UnknownFormat:
88 return MTLPixelFormatInvalid;
89 case QRhiTexture::RGBA8:
90 return MTLPixelFormatRGBA8Unorm;
91 case QRhiTexture::BGRA8:
92 return MTLPixelFormatBGRA8Unorm;
94 case QRhiTexture::RED_OR_ALPHA8:
95 return MTLPixelFormatR8Unorm;
96 case QRhiTexture::RG8:
97 return MTLPixelFormatRG8Unorm;
98 case QRhiTexture::R16:
99 return MTLPixelFormatR16Unorm;
100 case QRhiTexture::RG16:
101 return MTLPixelFormatRG16Unorm;
102 case QRhiTexture::RGBA16F:
103 return MTLPixelFormatRGBA16Float;
104 case QRhiTexture::RGBA32F:
105 return MTLPixelFormatRGBA32Float;
106 case QRhiTexture::R16F:
107 return MTLPixelFormatR16Float;
108 case QRhiTexture::R32F:
109 return MTLPixelFormatR32Float;
116 auto *textureDescription = QVideoTextureHelper::textureDescription(m_format.pixelFormat());
117 int bufferPlanes = CVPixelBufferGetPlaneCount(m_buffer);
118 if (plane > 0 && plane >= bufferPlanes)
121 if (rhi.backend() == QRhi::Metal) {
122 if (!cvMetalTexture[plane]) {
123 size_t width = CVPixelBufferGetWidth(m_buffer);
124 size_t height = CVPixelBufferGetHeight(m_buffer);
125 QSize planeSize = textureDescription->rhiPlaneSize(QSize(width, height), plane, &rhi);
128 qWarning(
"cannot create texture, Metal texture cache was released?");
133 const auto pixelFormat = rhiTextureFormatToMetalFormat(textureDescription->rhiTextureFormat(plane, &rhi));
134 if (pixelFormat != MTLPixelFormatInvalid) {
137 auto ret = CVMetalTextureCacheCreateTextureFromImage(
142 planeSize.width(), planeSize.height(),
144 &cvMetalTexture[plane]);
146 if (ret != kCVReturnSuccess)
147 qCWarning(qLcVideoBuffer) <<
"texture creation failed" << ret;
149 qCWarning(qLcVideoBuffer) <<
"requested invalid pixel format:"
150 << textureDescription->rhiTextureFormat(plane, &rhi);
154 return cvMetalTexture[plane] ? quint64(CVMetalTextureGetTexture(cvMetalTexture[plane])) : 0;
155 }
else if (rhi.backend() == QRhi::OpenGLES2) {
158 CVOpenGLTextureCacheFlush(sink->cvOpenGLTextureCache, 0);
160 const CVReturn cvret = CVOpenGLTextureCacheCreateTextureFromImage(
162 sink->cvOpenGLTextureCache,
166 if (cvret != kCVReturnSuccess)
167 qCWarning(qLcVideoBuffer) <<
"OpenGL texture creation failed" << cvret;
169 Q_ASSERT(CVOpenGLTextureGetTarget(cvOpenGLTexture) == GL_TEXTURE_RECTANGLE);
171 return CVOpenGLTextureGetName(cvOpenGLTexture);
174 CVOpenGLESTextureCacheFlush(sink->cvOpenGLESTextureCache, 0);
176 const CVReturn cvret = CVOpenGLESTextureCacheCreateTextureFromImage(
178 sink->cvOpenGLESTextureCache,
183 CVPixelBufferGetWidth(m_buffer),
184 CVPixelBufferGetHeight(m_buffer),
189 if (cvret != kCVReturnSuccess)
190 qCWarning(qLcVideoBuffer) <<
"OpenGL ES texture creation failed" << cvret;
193 return CVOpenGLESTextureGetName(cvOpenGLESTexture);