2016-02-27 55 views
1

我想獲得一個幀的像素數據。我發現這個(原始版本是舊代碼)並改變了一些東西。C++ videoplayer ffmpeg:獲取像素數據?

我有這樣的代碼:

AVFormatContext *pFormatCtx; 
pFormatCtx = avformat_alloc_context(); 
// Open file 
if (int err = avformat_open_input(&pFormatCtx, file, NULL, 0) != 0) 
{ 
    exit(2); 
} 
// Get infromation about streams 
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) 
{ 
    exit(2); 
} 

// # video stream 
int videoStreamIndex = -1; 
AVCodecContext *pVideoCodecCtx; 
AVCodec *pVideoCodec; 
int res = 0; 
int width = 0; 
int height = 0; 
for (unsigned int i = 0; i < pFormatCtx->nb_streams; i++) 
{ 
    if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
    { 
     videoStreamIndex = i; 
     pVideoCodecCtx = pFormatCtx->streams[i]->codec; 
     // Find decoder 
     pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id); 
     if (pVideoCodec) 
     { 
      // Open decoder 
      res = !(avcodec_open2(pVideoCodecCtx, pVideoCodec, NULL) < 0); 
      width = pVideoCodecCtx->coded_width; 
      height = pVideoCodecCtx->coded_height; 
     } 
     break; 
    } 
} 
// Frame width 
width = pFormatCtx->streams[videoStreamIndex]->codec->width; 
// Frame height 
height = pFormatCtx->streams[videoStreamIndex]->codec->height; 


AVPacket packet; 
int got_picture_ptr; 
AVPacket *avpkt; 
AVFrame * pOutFrame; 
pOutFrame = av_frame_alloc(); 
AVFrame * rgbOutFrame = av_frame_alloc(); 

if (!pOutFrame) { 
    fprintf(stderr, "Could not allocate video frame\n"); 
    exit(1); 
} 

while (av_read_frame(pFormatCtx, &packet) >= 0) 
{ 
    if (packet.stream_index == videoStreamIndex) 
    { 
     // Decode packeg to frame. 
     int videoFrameBytes = avcodec_decode_video2(pVideoCodecCtx, pOutFrame, 
      &got_picture_ptr, &packet); 

     // Create context 
     SwsContext* pImgConvertCtx = sws_getContext(pVideoCodecCtx->width, 
      pVideoCodecCtx->height, 
      pVideoCodecCtx->pix_fmt, 
      pVideoCodecCtx->width, pVideoCodecCtx->height, 
      AV_PIX_FMT_YUV420P, 
      SWS_BICUBIC, NULL, NULL, NULL); 
     // Convert frame 
     sws_scale(pImgConvertCtx, pOutFrame->data, pOutFrame->linesize, 
      width, height, rgbOutFrame->data, rgbOutFrame->linesize); 
    } 

} 

我知道,從SwsContextsws_scale代碼是錯誤的,但我不知道,我在哪裏可以找到我的幀的像素數據...(以及以何種格式它被存儲)。

有人可以幫我嗎?

回答

2

像素數據存儲在數據字段中。

根據文檔:

uint8_t * AVFrame ::數據[AV_NUM_DATA_POINTERS]

指針圖象/信道平面。

查看here瞭解更多信息。

一般來說,你的代碼有點誤導性,而且有些問題。我可以指出一些缺點:

1)您不需要在每個傳入視頻數據包上創建新的SwsContext。只需在while週期之前創建一次。

2)其次,你有一個rgbOutFrame,但是對於縮放到YUV420像素格式創建SwsContext。它看起來很奇怪。

3)此外,avcodec_decode_video2被調用,但您從不檢查返回值,也不檢查got_picture_ptr標誌。這種做法實際上是容易出錯。

等等......

希望它會幫助你提高你的程序,並得到必要的結果。

+0

感謝您的快速回答,但我仍然有一些問題:什麼是圖片平面?我應該怎麼做才能獲得像素值? – 3DExtended

+0

我試圖使用類似於frame-> data [0] [i]的值作爲位置i的值,但它是一個uint8_t(我認爲rgba)。但是當我使用它像rgba時,只有alpha值有一個不爲零的值...請幫助:/ – 3DExtended

+0

@ 3DExtended嘗試更改'sws_getContext'以轉換爲'rgb',而不是'yuv420' –