iOS - 自定義視頻播放器 -- (2)

渲染CVPixelBufferRef視頻幀顯示

流程

1歹苦、構(gòu)建OPenGL渲染環(huán)境
2、CVPixelBufferRef生成紋理Texture
2立倍、紋理顯示

構(gòu)建OPenGL渲染環(huán)境

1澜薄、創(chuàng)建EAGLContext上下文

self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    [EAGLContext setCurrentContext:self.context];

2、構(gòu)建設(shè)置CAEAGLLayer屬性

_eaglLayer = (CAEAGLLayer*) self.layer;
_eaglLayer.opaque = YES;
_eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
                                    [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGBA8, kEAGLDrawablePropertyColorFormat, nil];
    _eaglLayer.contentsScale = [[UIScreen mainScreen] scale];

3叉钥、綁定紋理緩沖區(qū)和幀緩沖區(qū)罢缸,并與CAEAGLLayer聯(lián)系

//1.渲染緩存區(qū), 幀緩存區(qū)對象
GLuint renderBuffer;
GLuint frameBuffer;
//2.獲取渲染緩存區(qū)名稱, 綁定渲染緩存區(qū)以及將渲染緩存區(qū)與 layer建立聯(lián)系
glGenRenderbuffers(1, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
[self.context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
//3.獲取幀緩存區(qū)名稱, 綁定幀緩存區(qū)以及渲染緩存區(qū)附著到幀緩存區(qū)上
glGenFramebuffers(1, &frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);

4、初始化紋理著色器和片元著色器投队,生成Program

NSString *fsh = [[self.filterBundle resourcePath] stringByAppendingFormat:@"/%@/%@.fsh",name,name];
    NSString *vsh = [[self.filterBundle resourcePath] stringByAppendingFormat:@"/%@/%@.vsh",name,name];
    GLuint program = [SKGLUtils compileShaders:vsh shaderFragment:fsh isFilePath:YES];

5枫疆、上傳圖片數(shù)據(jù),生成紋理顯示

glUseProgram(rgbaProgram);
glActiveTexture(GL_TEXTURE0);
CVOpenGLESTextureCacheCreateTextureFromImage(……)
……
glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

CVPixelBufferRef生成紋理Texture

CVPixelBufferRef是一種像素圖片類型敷鸦,是一個(gè)C對象息楔,不是一個(gè)類寝贡,對它的操作都是C函數(shù)進(jìn)行操作。有著多種不同的數(shù)據(jù)格式值依,通過CVPixelBufferGetPixelFormatType(pixelBuffer)來獲取圃泡,通常使用RGBA和YUV420比較常見。 由于是C對象愿险,它不受ARC去管理颇蜡,創(chuàng)建出一個(gè)對象,需要手動去釋放拯啦。(Swift語言可以不需要手動澡匪,這個(gè)或許和Swift沒有暴露指針操作有關(guān)系)。其中包含著視頻幀數(shù)據(jù)褒链,也可以理解為圖片數(shù)據(jù)唁情。

通過CVPixelBufferGetBaseAddressOfPlane可以得到每個(gè)平面的數(shù)據(jù)指針(圖片數(shù)據(jù))。在得到 Address之前需要調(diào)用CVPixelBufferLockBaseAddress甫匹,進(jìn)行l(wèi)ock下來實(shí)現(xiàn)地址映射甸鸟,同時(shí)lock也保證了沒有讀寫沖突。

將 CVPixelBufferRef 生成紋理兵迅,有兩種方法:
1抢韭、取出CVPixelBufferRef的圖片數(shù)據(jù),通過glTexImage2D(……)進(jìn)行上傳紋理恍箭,生成紋理ID
2刻恭、使用系統(tǒng)C函數(shù)方法CVOpenGLESTextureCacheCreateTextureFromImage(……)進(jìn)行上傳紋理

 CVReturn err;
 CVOpenGLESTextureRef luminanceTextureRef = NULL;
 CVOpenGLESTextureRef chrominanceTextureRef = NULL;
 
 glActiveTexture(GL_TEXTURE0);
 err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
                                                       videoTextureCache,
                                                       pixelBuffer,
                                                       NULL,
                                                       GL_TEXTURE_2D,
                                                       GL_RED_EXT,
                                                       frameWidth,
                                                       frameHeight,
                                                       GL_RED_EXT,
                                                       GL_UNSIGNED_BYTE,
                                                       0,
                                                       &luminanceTextureRef);
if (err) {
     NSLog(@"Error at CVOpenGLESTextureCacheCreateTextureFromImage %d", err);
    }

顯示紋理

將生成的紋理進(jìn)行啟用和綁定

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, CVOpenGLESTextureGetName(luminanceTextureRef));
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

最后進(jìn)行顯示紋理

glClearColor(0.1f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

注意事項(xiàng)

1、生成的紋理在使用結(jié)束時(shí)候進(jìn)行釋放CFRelease(luminanceTextureRef);
2扯夭、使用CVOpenGLESTextureCacheCreateTextureFromImage()videoTextureCache對象只需要創(chuàng)建一次鳍贾,不需要多此創(chuàng)建,不用時(shí)刪除
3交洗、渲染或者釋放時(shí)候骑科,注意在渲染線程中做操作。否則可能線程不同步問題构拳,造成野指針
4咆爽、APP在退出到后臺時(shí)候呢岗,應(yīng)該停止渲染OPenGL的操作物延。iOS不支持在后臺做OPenGL的執(zhí)行掂林,會有野指針閃退問題

Git Code

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末谊却,一起剝皮案震驚了整個(gè)濱河市惫霸,隨后出現(xiàn)的幾起案子洽胶,更是在濱河造成了極大的恐慌屈梁,老刑警劉巖惕味,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盐碱,死亡現(xiàn)場離奇詭異把兔,居然都是意外死亡沪伙,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進(jìn)店門县好,熙熙樓的掌柜王于貴愁眉苦臉地迎上來围橡,“玉大人,你說我怎么就攤上這事缕贡∥淌冢” “怎么了?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵晾咪,是天一觀的道長收擦。 經(jīng)常有香客問我,道長谍倦,這世上最難降的妖魔是什么塞赂? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮昼蛀,結(jié)果婚禮上宴猾,老公的妹妹穿的比我還像新娘。我一直安慰自己叼旋,他們只是感情好仇哆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夫植,像睡著了一般讹剔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上详民,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天延欠,我揣著相機(jī)與錄音,去河邊找鬼阐斜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛诀紊,可吹牛的內(nèi)容都是我干的谒出。 我是一名探鬼主播,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼邻奠,長吁一口氣:“原來是場噩夢啊……” “哼笤喳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碌宴,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤杀狡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后贰镣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呜象,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膳凝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了恭陡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹬音。...
    茶點(diǎn)故事閱讀 40,102評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖休玩,靈堂內(nèi)的尸體忽然破棺而出著淆,到底是詐尸還是另有隱情,我是刑警寧澤拴疤,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布永部,位于F島的核電站,受9級特大地震影響呐矾,放射性物質(zhì)發(fā)生泄漏苔埋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一凫佛、第九天 我趴在偏房一處隱蔽的房頂上張望讲坎。 院中可真熱鬧,春花似錦愧薛、人聲如沸晨炕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓮栗。三九已至,卻和暖如春瞄勾,著一層夾襖步出監(jiān)牢的瞬間费奸,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工进陡, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留愿阐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓趾疚,卻偏偏與公主長得像缨历,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子糙麦,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 背景需求 如何將視頻添加上自定義的渲染效果辛孵,并顯示? 大致流程 1赡磅、解碼視頻2魄缚、獲取視頻幀3、渲染視頻幀4焚廊、顯示渲...
    燒烤有點(diǎn)辣閱讀 1,749評論 0 1
  • 對OpenGL ES學(xué)習(xí)了一段時(shí)間冶匹,今天實(shí)現(xiàn)一個(gè)360度的全景視頻播放器习劫。本博客的代碼可在我的github倉庫下載...
    wosicuanqi閱讀 5,656評論 3 18
  • 一.不采用GLKBaseEffect,使用編譯連接自定義頂點(diǎn)/片元著色器(shader)徙硅,用簡單的glsl語言來實(shí)...
    楓紫_6174閱讀 764評論 0 0
  • 久違的晴天榜聂,家長會。 家長大會開好到教室時(shí)嗓蘑,離放學(xué)已經(jīng)沒多少時(shí)間了须肆。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,523評論 16 22
  • 創(chuàng)業(yè)是很多人的夢想桩皿,多少人為了理想和不甘選擇了創(chuàng)業(yè)來實(shí)現(xiàn)自我價(jià)值豌汇,我就是其中一個(gè)。 創(chuàng)業(yè)后泄隔,我由女人變成了超人拒贱,什...
    亦寶寶閱讀 1,812評論 4 1