2013-12-10 54 views
5

我試圖將一個YUV420數據轉儲到FFMPEG的AVFrame結構中。從下面的鏈接:FFMPEG:將YUV數據轉儲到AVFrame結構中

http://ffmpeg.org/doxygen/trunk/structAVFrame.html,我可以得到我需要把我的數據到

data[AV_NUM_DATA_POINTERS] 

使用

linesize [AV_NUM_DATA_POINTERS]. 

的YUV數據我試圖轉儲YUV420和圖片大小是416x240.那麼我怎麼轉儲/映射這個yuv數據到AVFrame結構變量?我知道linesize代表邁步,即我想我的圖片的寬度,我嘗試了一些組合,但沒有得到輸出。我懇請您幫我繪製緩衝區。提前致謝。

回答

17

AVFrame可以解釋爲AVPicture來填充datalinesize字段。填寫這些字段最簡單的方法是使用avpicture_fill函數。要填充AVFrame的Y U和V緩衝區,它取決於您的輸入數據以及您想要對幀執行的操作(是否要寫入AVFrame並擦除初始數據?或保留副本)。

如果緩衝區足夠大(至少linesize[0] * height爲Y數據,linesize[1 or 2] * height/2對於U/V數據),你可以直接使用輸入緩衝器:

// Initialize the AVFrame 
AVFrame* frame = avcodec_alloc_frame(); 
frame->width = width; 
frame->height = height; 
frame->format = AV_PIX_FMT_YUV420P; 

// Initialize frame->linesize 
avpicture_fill((AVPicture*)frame, NULL, frame->format, frame->width, frame->height); 

// Set frame->data pointers manually 
frame->data[0] = inputBufferY; 
frame->data[1] = inputBufferU; 
frame->data[2] = inputBufferV; 

// Or if your Y, U, V buffers are contiguous and have the correct size, simply use: 
// avpicture_fill((AVPicture*)frame, inputBufferYUV, frame->format, frame->width, frame->height); 

如果你想/需要操作的副本輸入數據,您需要計算所需的緩衝區大小,並在其中複製輸入數據。

// Initialize the AVFrame 
AVFrame* frame = avcodec_alloc_frame(); 
frame->width = width; 
frame->height = height; 
frame->format = AV_PIX_FMT_YUV420P; 

// Allocate a buffer large enough for all data 
int size = avpicture_get_size(frame->format, frame->width, frame->height); 
uint8_t* buffer = (uint8_t*)av_malloc(size); 

// Initialize frame->linesize and frame->data pointers 
avpicture_fill((AVPicture*)frame, buffer, frame->format, frame->width, frame->height); 

// Copy data from the 3 input buffers 
memcpy(frame->data[0], inputBufferY, frame->linesize[0] * frame->height); 
memcpy(frame->data[1], inputBufferU, frame->linesize[1] * frame->height/2); 
memcpy(frame->data[2], inputBufferV, frame->linesize[2] * frame->height/2); 

一旦你與AVFrame完成後,不要忘了av_frame_free(和av_malloc分配的任何緩衝區)以釋放它。

+0

只是很棒的解釋。謝謝 – Zax

+0

更多有關'struct *'之間的類型轉換:http://stackoverflow.com/questions/3766229/casting-one-struct-pointer-to-other-c –

1
FF_API int ff_get_format_plane_size(int fmt, int plane, int scanLine, int height) 
{ 
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(fmt); 
    if (desc) 
    { 
      int h = height; 
      if (plane == 1 || plane == 2) 
      { 
       h = FF_CEIL_RSHIFT(height, desc->log2_chroma_h); 
      } 
      return h*scanLine; 
    } 
    else 
     return AVERROR(EINVAL); 
}