2013-12-10 41 views
5

Próbuję zrzucić dane YUV420 do struktury FFMPEG w postaci AVFrame. Z linku poniżej:FFMPEG: Przesyłanie danych YUV do struktury AVFrame

http://ffmpeg.org/doxygen/trunk/structAVFrame.html, mogę czerpać że muszę umieścić swoje dane w

data[AV_NUM_DATA_POINTERS] 

wykorzystaniem

linesize [AV_NUM_DATA_POINTERS]. 

Dane YUV próbuję zrzucić to yuv420 i rozmiar obrazu to 416x240. Jak więc zrzucić/odwzorować te dane yuv na zmienną struktury AVFrame? Wiem, że lineize reprezentuje krok, tj. Przypuszczam, że szerokość mojego obrazu, próbowałem z pewnymi kombinacjami, ale nie otrzymuję wyjścia. Uprzejmie proszę o pomoc w mapowaniu bufora. Z góry dziękuję.

Odpowiedz

17

AVFrame może być interpretowany jako AVPicture w celu wypełnienia pól data i linesize. Najprostszym sposobem wypełnienia tych pól jest użycie funkcji avpicture_fill.

Aby wypełnić bufory Y U i V AVFrame, zależy to od danych wejściowych i od tego, co chcesz zrobić z ramką (chcesz zapisać do ramki AVFrame i usunąć początkowe dane lub zachować kopię).

Jeśli bufor jest wystarczająco duży (przynajmniej linesize[0] * height danych Y, linesize[1 or 2] * height/2 dla U/V danych), można korzystać bezpośrednio bufory wejściowe:

// 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); 

Jeśli chcesz/potrzeby manipulowania kopię dane wejściowe, musisz obliczyć potrzebny rozmiar bufora i skopiować dane wejściowe w nim.

// 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); 

Gdy skończysz z AVFrame, nie zapomnij, aby uwolnić ją z av_frame_free (i dowolnego bufora przydzielonego przez av_malloc).

+0

Po prostu niesamowite wyjaśnienie. Dzięki – Zax

+0

Więcej informacji na temat typowania tekstu między '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); 
}