Metal Camera開(kāi)發(fā)1:讀取渲染結(jié)果生成UIImage第5節(jié):讀取Metal渲染結(jié)果并生成UIImage介紹了讀取屏幕(MTLTexture的數(shù)據(jù))并由Core Graphics創(chuàng)建UIImage,類(lèi)似于OpenGL ES,這一過(guò)程按我理解是存在多余的內(nèi)存拷貝操作(GPU管理的內(nèi)存塊拷貝到CPU管理的內(nèi)存塊)春畔。為提高性能與簡(jiǎn)化視頻編碼步驟,本文檔介紹Metal渲染到CVPixelBuffer的實(shí)現(xiàn)城须。
文檔結(jié)構(gòu):
- OpenGL ES渲染到CVPixelBuffer實(shí)現(xiàn)代碼
- Metal渲染到CVPixelBuffer實(shí)現(xiàn)代碼
- 參考資料
- 致謝
1. OpenGL ES渲染到CVPixelBuffer實(shí)現(xiàn)代碼
1.1. 創(chuàng)建GL_TEXTURE_2D及glFramebufferTexture2D
GPUImage使用了此方式,基于我之前的代碼測(cè)試可正常運(yùn)行米苹。最關(guān)鍵的地方是創(chuàng)建CVPixelBuffer需指定kCVPixelBufferIOSurfacePropertiesKey屬性為空字典糕伐。基于OpenGL ES 3.0的實(shí)現(xiàn)代碼如下所示蘸嘶。
CVReturn status = CVOpenGLESTextureCacheCreate(
NULL,
NULL,
context,
NULL,
&textureCache);
NSDictionary *pixelBufferAttributes = @{(__bridge NSString*)kCVPixelBufferIOSurfacePropertiesKey: @{}};
status = CVPixelBufferCreate(
NULL,
renderbufferWidth,
renderbufferHeight,
kCVPixelFormatType_32BGRA,
(__bridge CFDictionaryRef)pixelBufferAttributes,
&offlinePixelBuffer);
status = CVOpenGLESTextureCacheCreateTextureFromImage(
NULL,
textureCache,
offlinePixelBuffer,
NULL, // texture attributes
GL_TEXTURE_2D,
GL_RGBA, // OpenGL format
renderbufferWidth,
renderbufferHeight,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
&offlineTexture);
glFramebufferTexture2D(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D,
CVOpenGLESTextureGetName(offlineTexture),
0);
有趣的是良瞧,format
參數(shù)設(shè)置為GL_RGBA也可以正常創(chuàng)建CVOpenGLESTextureRef對(duì)象陪汽。無(wú)論format
參數(shù)設(shè)置為什么值,使用時(shí)都得通過(guò)glFramebufferTexture2D將offlineTexture綁定到幀緩沖區(qū)褥蚯。
1.2. 創(chuàng)建GL_RENDERBUFFER及glFramebufferRenderbuffer
這里嘗試了使用CVOpenGLESTextureCacheCreateTextureFromImage創(chuàng)建成GL_RENDERBUFFER挚冤,配合glFramebufferRenderbuffer可正常工作。創(chuàng)建成GL_RENDERBUFFER必須將format
參數(shù)設(shè)置為GL_BGRA赞庶,否則創(chuàng)建失敗并報(bào)錯(cuò)Failed to create IOSurface image (texture)
训挡。另外,官方給的internalFormat
為GL_RGBA8歧强,這是OpenGL ES 1.0的宏定義澜薄,基于OpenGL ES 3.0開(kāi)發(fā)時(shí),換成GL_RGBA即可摊册。參考代碼如下肤京。
status = CVOpenGLESTextureCacheCreateTextureFromImage(
NULL,
textureCache,
offlinePixelBuffer,
NULL, // texture attributes
GL_RENDERBUFFER,
GL_RGBA8, // OpenGL format
renderbufferWidth,
renderbufferHeight,
GL_BGRA, // native iOS format
GL_UNSIGNED_BYTE,
0,
&offlineTexture);
glFramebufferRenderbuffer(
GL_FRAMEBUFFER,
GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER,
CVOpenGLESTextureGetName(offlineTexture));
1.3. 關(guān)于GL_TEXTURE_2D與GL_RENDERBUFFER
關(guān)于應(yīng)該使用GL_TEXTURE_2D還是GL_RENDERBUFFER,@紅豬和我討論了一段時(shí)間茅特。建議直接參考官方文檔Drawing to Other Rendering Destinations忘分。
2. Metal渲染到CVPixelBuffer實(shí)現(xiàn)代碼
參考OpenGL ES渲染到CVPixelBuffer的實(shí)現(xiàn),很容易模仿出Metal版本白修,如下代碼已通過(guò)驗(yàn)證饭庞。
CVMetalTextureCacheCreate(
kCFAllocatorDefault,
nil,
device!,
nil,
&textureCache)
let pixelBufferAttri = [kCVPixelBufferIOSurfacePropertiesKey as NSObject: [:] as CFDictionary] as CFDictionary
let s = CVPixelBufferCreate(
kCFAllocatorDefault,
1080,
1920,
kCVPixelFormatType_32BGRA,
pixelBufferAttri,
&offlinePixelBuffer)
let result = CVMetalTextureCacheCreateTextureFromImage(
kCFAllocatorDefault,
textureCache!,
offlinePixelBuffer!,
nil,
self.colorPixelFormat,
1080,
1920,
0,
&offlineTexture)
3. 參考資料
- Rendering to a texture with iOS 5 texture cache api. GPUImage在源碼中標(biāo)明了它參考此鏈接,目前來(lái)看熬荆,所有的實(shí)現(xiàn)都源自于此鏈接,似乎是因?yàn)閃WDC Session 419主講人沒(méi)分享代碼給大家绸狐,而此博主寫(xiě)了一份可行的示例代碼卤恳,所以大家都用他的代碼的。
- Capturing from the Camera using AV Foundation on iOS 5 蘋(píng)果官方講座描述了OpenGL ES渲染到CVPixelBuffer的細(xì)節(jié)寒矿。
4. 致謝
感謝@紅豬和我一起討論OpenGL ES渲染到CVPixelBuffer細(xì)節(jié)突琳。