2012-06-05 99 views
1

我試圖從使用FFmpeg的視頻轉換爲jni中的OpenGL ES紋理,但是我得到的所有圖像都是黑色紋理。我輸出了帶有glGetError()的OpenGL,但沒有錯誤。將FFmpeg幀轉換爲OpenGL ES紋理

這裏是我的代碼:

void* pixels; 
int err; 
int i; 
int frameFinished = 0; 
AVPacket packet; 
static struct SwsContext *img_convert_ctx; 
static struct SwsContext *scale_context = NULL; 
int64_t seek_target; 

int target_width = 320; 
int target_height = 240; 
GLenum error = GL_NO_ERROR; 
sws_freeContext(img_convert_ctx); 

i = 0; 
while((i==0) && (av_read_frame(pFormatCtx, &packet)>=0)) { 
     if(packet.stream_index==videoStream) { 
     avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet); 

     if(frameFinished) { 
      LOGI("packet pts %llu", packet.pts); 
      img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, 
        pCodecCtx->pix_fmt, 
        target_width, target_height, PIX_FMT_RGB24, SWS_BICUBIC, 
        NULL, NULL, NULL); 
      if(img_convert_ctx == NULL) { 
       LOGE("could not initialize conversion context\n"); 
       return; 
      } 
       sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); 
       LOGI("sws_scale"); 

       videoTextures = new Texture*[1]; 
       videoTextures[0]->mWidth = 256; //(unsigned)pCodecCtx->width; 
       videoTextures[0]->mHeight = 256; //(unsigned)pCodecCtx->height; 
       videoTextures[0]->mData = pFrameRGB->data[0]; 

       glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 

       glGenTextures(1, &(videoTextures[0]->mTextureID)); 
       glBindTexture(GL_TEXTURE_2D, videoTextures[0]->mTextureID); 
       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
       glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 

       if(0 == got_texture) 
       { 
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, videoTextures[0]->mWidth, videoTextures[0]->mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData); 

        glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, videoTextures[0]->mWidth, videoTextures[0]->mHeight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData); 
       }else 
       { 
        glTexSubImage2D(GL_TEXTURE_2D, 0, 0,0, videoTextures[0]->mWidth, videoTextures[0]->mHeight, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid *)videoTextures[0]->mData); 

       } 

       i = 1; 
       error = glGetError(); 
       if(error != GL_NO_ERROR) { 
        LOGE("couldn't create texture!!"); 
         switch (error) { 
         case GL_INVALID_ENUM: 
         LOGE("GL Error: Enum argument is out of range"); 
         break; 
         case GL_INVALID_VALUE: 
          LOGE("GL Error: Numeric value is out of range"); 
         break; 
         case GL_INVALID_OPERATION: 
          LOGE("GL Error: Operation illegal in current state"); 
         break; 
         case GL_OUT_OF_MEMORY: 
          LOGE("GL Error: Not enough memory to execute command"); 
         break; 
         default: 
          break; 
         } 
       } 
     } 
    } 
    av_free_packet(&packet); 
} 

我已經成功地改變了pFrameRGB中到Java位,但我只是想將其更改爲在C代碼的紋理。

編輯1我輸出了紋理ID,它是0;紋理ID可能爲零?我更改了我的代碼 ,但它始終爲零。

編輯2 紋理顯示,但它是一團糟。

回答

0

嘗試在傳遞給解碼器之前將16個零字節附加到每個數據包。

中avcodec.h一些評論:

/* 
* @warning The input buffer must be FF_INPUT_BUFFER_PADDING_SIZE larger than 
* the actual read bytes because some optimized bitstream readers read 32 or 64 
* bits at once and could read over the end. 
* @warning The end of the input buffer buf should be set to 0 to ensure that 
* no overreading happens for damaged MPEG streams. 
    */ 
2

不習慣GLES,但GL。在那裏,320,240的值不等於512,256,否則你需要使用tex_reords不是0-1而是0-w/h的紋理擴展。至於上傳紋理數據,glTexImage(...)需要第一次使用(即使數據爲0),然後glTexSubImage就足夠了,我認爲大小等初始化與第一次,第二次只是發送肉。

關於ffmpeg的使用,也許是版本的問題,但img_context更接近被重命名爲sws_getContext,只有一次初始化,如果CPU使用率是一個問題,使用SWS_LINEAR代替SWS_CUBIC,也是我認爲pFrameRGB中已經正確avcodec_alloc_frame() 'ed,如果你打算使用GL_RGBA你應該使用PIX_FMT_RGBA,PIX_FMT_RGB24將用於GL_RGB紋理管道,最後你沒有數據包堆棧,所以你可以事先閱讀以保持顯示的同步而不是遲。

我讀過一些關於解壓縮對齊的註釋,我不需要(並且看到在該領域有疑問的成功)來實現ffmpeg到OpenGL/OpenAL媒體庫(http://code.google .com/p/openmedialibrary),很好的音頻位也被提取到Openf loader的ffmpeg(http://code.google.com/p/openalextensions)。有一些不錯的功能,目前我正在嘗試使用紋理壓縮來查看它是否可以執行得更好。考慮這些教程甚至可以使用gpl代碼。

希望能夠對ffmpeg對OpenGL/AL整合的晦澀(缺乏)藝術給予啓發。