bool CRendererVTB::UploadTexture(int index) { CRenderBuffer &renderBuf = m_vtbBuffers[index]; YUVBUFFER &buf = m_buffers[index]; YUVPLANE (&planes)[YuvImage::MAX_PLANES] = m_buffers[index].fields[0]; YuvImage &im = m_buffers[index].image; VTB::CVideoBufferVTB *vb = dynamic_cast<VTB::CVideoBufferVTB*>(buf.videoBuffer); if (!vb) { return false; } CVOpenGLESTextureCacheFlush(m_textureCache, 0); if (renderBuf.m_textureY) CFRelease(renderBuf.m_textureY); renderBuf.m_textureY = nullptr; if (renderBuf.m_textureUV) CFRelease(renderBuf.m_textureUV); renderBuf.m_textureUV = nullptr; CVReturn ret; ret = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_textureCache, vb->GetPB(), nullptr, GL_TEXTURE_2D, GL_LUMINANCE, im.width, im.height, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0, &renderBuf.m_textureY); if (ret != kCVReturnSuccess) { CLog::Log(LOGERROR, "CRendererVTB::UploadTexture - Error uploading texture Y (err: %d)", ret); return false; } ret = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, m_textureCache, vb->GetPB(), nullptr, GL_TEXTURE_2D, GL_LUMINANCE_ALPHA, im.width/2, im.height/2, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 1, &renderBuf.m_textureUV); if (ret != kCVReturnSuccess) { CLog::Log(LOGERROR, "CRendererVTB::UploadTexture - Error uploading texture UV (err: %d)", ret); return false; } // set textures planes[0].id = CVOpenGLESTextureGetName(renderBuf.m_textureY); planes[1].id = CVOpenGLESTextureGetName(renderBuf.m_textureUV); planes[2].id = CVOpenGLESTextureGetName(renderBuf.m_textureUV); glEnable(m_textureTarget); for (int p=0; p<2; p++) { glBindTexture(m_textureTarget, planes[p].id); 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); VerifyGLState(); } CalculateTextureSourceRects(index, 3); return true; }
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; }