Unity渲染iOS中的NV12格式數(shù)據(jù)---(上)

在我們的項目中绰沥,iOS端視頻播放使用的是第三方開源框架ijkplayer,在硬解碼的時候幔崖,解碼出的數(shù)據(jù)格式是NV12碟刺,而Unity只能渲染RGB格式,所以需要做轉(zhuǎn)換除抛。

解決方案:

在iOS端使用ffmpeg的函數(shù)將NV12格式轉(zhuǎn)換為YUV420P格式狮杨,將YUV三個分量分別傳入Unity中,然后在Unity中將YUV420P轉(zhuǎn)換為RGB并渲染到忽。

具體實現(xiàn):
  • NV12轉(zhuǎn)換為YUV420P
//獲取到NV12數(shù)據(jù)的兩個指針橄教,一個指針指向Y數(shù)據(jù),一個指針指向UV數(shù)據(jù)
UInt8 *bufferPtrY = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,0);
UInt8 *bufferPtrUV = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer,1);
if (!bufferPtr || !bufferPtr1) {
    printf("!bufferPtrY || !bufferPtrUV\n");
    return;
}
size_t width = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);
size_t height = CVPixelBufferGetHeightOfPlane(imageBuffer,0);
AVFrame *pFrame=*dest_frame;
if (pFrame == NULL)
{
     pFrame = av_frame_alloc();
     av_image_alloc(pFrame->data, pFrame->linesize, (int)width, (int)height, AV_PIX_FMT_YUV420P,1);
     *dest_frame = pFrame;
}
static int sws_flags =  SWS_FAST_BILINEAR;
    
uint8_t * srcSlice[8] ={bufferPtrY, bufferPtrUV, NULL, NULL,NULL,NULL,NULL,NULL};
int srcStride[8] = {(int)width, (int)width, 0, 0, 0,0,0,0};
    
if (img_convert_ctx == NULL)
{
    img_convert_ctx = sws_getContext(
                                      (int)width,
                                      (int)height,
                                       AV_PIX_FMT_NV12,
                                       (int)width,
                                       overlay->h,
                                       AV_PIX_FMT_YUV420P,
                                       sws_flags,
                                       NULL, NULL, NULL);
}
int ret = sws_scale(
              img_convert_ctx,
              srcSlice,
              srcStride,
              0,
              overlay->h,
              pFrame->data,
              pFrame->linesize);

此時pFrame變量即包含YUV420P格式的圖像數(shù)據(jù)喘漏。

  • 使用OpenGL將數(shù)據(jù)拷貝至顯存
GLuint tex[3];
// 如果tex[0]為0护蝶,那么代表所有tex還沒有初始化
if (0 == tex[0]) {
      // 初始化創(chuàng)建所有紋理
      for (int i = 0; i < 3; i++)
      {
          glGenTextures(1, &tex[i]);
          glBindTexture(GL_TEXTURE_2D, tex[i]);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
          glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
          glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
      }
}
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pData0);
            
glBindTexture(GL_TEXTURE_2D, tex[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w/2, h/2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pData1);
            
glBindTexture(GL_TEXTURE_2D, tex[2]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w/2, h/2, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pData2);

// 通過消息發(fā)送給Unity
UnitySendMessage(VRController::Instance()->GetRenderCallbackGoName(), VRController::Instance()->GetRenderCallbackFuncName(), [[NSString stringWithFormat:@"%ld|%ld|%ld",tex[0], tex[1], tex[2]] UTF8String]);

其中pData0、pData1翩迈、pData2分別對應YUV三個方向的分量持灰。

  • Unity獲取顯存中的圖像數(shù)據(jù)
public void display(string texString) {
    string[] tex = texString.Split ('|');
    IntPtr nativeTex1 = (IntPtr)long.Parse (tex [0]);
    IntPtr nativeTex2 = (IntPtr)long.Parse (tex [1]);
    IntPtr nativeTex3 = (IntPtr)long.Parse (tex [2]);
    if (_videoTextureY == null) {
        _videoTextureY = Texture2D.CreateExternalTexture ((int)videoLineW, (int)videoH, TextureFormat.Alpha8,false, false, (IntPtr)nativeTex1);
        _videoTextureY.filterMode = FilterMode.Bilinear;
        _videoTextureY.wrapMode = TextureWrapMode.Clamp;
    }
    if (_videoTextureU == null) {
        _videoTextureU = Texture2D.CreateExternalTexture ((int)videoLineW / 2, (int)videoH / 2, TextureFormat.Alpha8,false, false, (IntPtr)nativeTex2);
        _videoTextureU.filterMode = FilterMode.Point;
        _videoTextureU.wrapMode = TextureWrapMode.Clamp;
    }
    if (_videoTextureV == null) {
        _videoTextureV = Texture2D.CreateExternalTexture ((int)videoLineW / 2, (int)videoH / 2, TextureFormat.Alpha8,false, false, (IntPtr)nativeTex3);
        _videoTextureV.filterMode = FilterMode.Point;
        _videoTextureV.wrapMode = TextureWrapMode.Clamp;
    }

    _videoTextureY.UpdateExternalTexture ((IntPtr)nativeTex1);
    _videoTextureU.UpdateExternalTexture ((IntPtr)nativeTex2);
    _videoTextureV.UpdateExternalTexture ((IntPtr)nativeTex3);
}
  • 在shader中將YUV格式轉(zhuǎn)換為RGB格式
fixed4 yuv;
yuv.x = tex2D(_MainTexY, i.uv).a;  
yuv.y = tex2D(_MainTexU, i.uv).a - 0.5;  
yuv.z = tex2D(_MainTexV, i.uv).a - 0.5;
c.r = yuv.x + 1.403*yuv.z;
c.g = yuv.x - 0.344*yuv.y - 0.714*yuv.z;
c.b = yuv.x + 1.770*yuv.y;
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市负饲,隨后出現(xiàn)的幾起案子堤魁,更是在濱河造成了極大的恐慌,老刑警劉巖返十,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件妥泉,死亡現(xiàn)場離奇詭異,居然都是意外死亡洞坑,警方通過查閱死者的電腦和手機盲链,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來迟杂,“玉大人刽沾,你說我怎么就攤上這事∨趴剑” “怎么了侧漓?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長攻泼。 經(jīng)常有香客問我火架,道長鉴象,這世上最難降的妖魔是什么忙菠? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任何鸡,我火速辦了婚禮,結(jié)果婚禮上牛欢,老公的妹妹穿的比我還像新娘骡男。我一直安慰自己,他們只是感情好傍睹,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布隔盛。 她就那樣靜靜地躺著,像睡著了一般拾稳。 火紅的嫁衣襯著肌膚如雪吮炕。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天访得,我揣著相機與錄音龙亲,去河邊找鬼。 笑死悍抑,一個胖子當著我的面吹牛鳄炉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搜骡,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拂盯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了记靡?” 一聲冷哼從身側(cè)響起谈竿,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摸吠,沒想到半個月后榕订,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕便,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年劫恒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片轿腺。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡两嘴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出族壳,到底是詐尸還是另有隱情憔辫,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布仿荆,位于F島的核電站贰您,受9級特大地震影響坏平,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锦亦,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一舶替、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧杠园,春花似錦顾瞪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞧甩,卻和暖如春钉跷,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背肚逸。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工爷辙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吼虎。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓犬钢,卻偏偏與公主長得像,于是被迫代替她去往敵國和親思灰。 傳聞我的和親對象是個殘疾皇子玷犹,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355

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