CopyResult copyFrame(const VideoFrame &videoFrame, Field field) override { Q_UNUSED(field) { QMutexLocker locker(&m_buffersMutex); const int idx = m_buffers.indexOf(videoFrame.surfaceId); if (idx < 0) return CopyNotReady; m_buffers.removeAt(idx); while (m_buffers.size() > 5) CVPixelBufferRelease((CVPixelBufferRef)m_buffers.takeFirst()); } CVPixelBufferRef pixelBuffer = (CVPixelBufferRef)videoFrame.surfaceId; CGLContextObj glCtx = CGLGetCurrentContext(); IOSurfaceRef surface = CVPixelBufferGetIOSurface(pixelBuffer); const OSType pixelFormat = IOSurfaceGetPixelFormat(surface); if (pixelFormat != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) { CVPixelBufferRelease(pixelBuffer); return CopyError; } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_glTextures[0]); if (CGLTexImageIOSurface2D(glCtx, GL_TEXTURE_RECTANGLE_ARB, GL_R8, videoFrame.size.getWidth(0), videoFrame.size.getHeight(0), GL_RED, GL_UNSIGNED_BYTE, surface, 0) != kCGLNoError) { CVPixelBufferRelease(pixelBuffer); return CopyError; } glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_glTextures[1]); if (CGLTexImageIOSurface2D(glCtx, GL_TEXTURE_RECTANGLE_ARB, GL_RG8, videoFrame.size.getWidth(1), videoFrame.size.getHeight(1), GL_RG, GL_UNSIGNED_BYTE, surface, 1) != kCGLNoError) { CVPixelBufferRelease(pixelBuffer); return CopyError; } CVPixelBufferRelease(m_pixelBufferToRelease); m_pixelBufferToRelease = pixelBuffer; return CopyOk; }
bool CRendererVTB::UploadTexture(int index) { YUVBUFFER &buf = m_buffers[index]; YUVPLANE (&planes)[YuvImage::MAX_PLANES] = m_buffers[index].fields[0]; VTB::CVideoBufferVTB *vb = dynamic_cast<VTB::CVideoBufferVTB*>(buf.videoBuffer); if (!vb) { return false; } CVImageBufferRef cvBufferRef = vb->GetPB(); glEnable(m_textureTarget); // It is the fastest way to render a CVPixelBuffer backed // with an IOSurface as there is no CPU -> GPU upload. CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj(); IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef); OSType format_type = IOSurfaceGetPixelFormat(surface); if (format_type != kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange) { return false; } GLsizei surfplanes = IOSurfaceGetPlaneCount(surface); if (surfplanes != 2) { return false; } GLsizei widthY = IOSurfaceGetWidthOfPlane(surface, 0); GLsizei widthUV = IOSurfaceGetWidthOfPlane(surface, 1); GLsizei heightY = IOSurfaceGetHeightOfPlane(surface, 0); GLsizei heightUV = IOSurfaceGetHeightOfPlane(surface, 1); glBindTexture(m_textureTarget, planes[0].id); CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_LUMINANCE, widthY, heightY, GL_LUMINANCE, GL_UNSIGNED_BYTE, surface, 0); glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(m_textureTarget, planes[1].id); CGLTexImageIOSurface2D(cgl_ctx, m_textureTarget, GL_LUMINANCE_ALPHA, widthUV, heightUV, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, surface, 1); glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glBindTexture(m_textureTarget, 0); glDisable(m_textureTarget); CalculateTextureSourceRects(index, 3); return true; }