2013-12-10 18 views
5

Ich versuche, eine YUV420 Daten in die AVFrame Struktur von FFMPEG zu dumpen. Von den folgenden Link:FFMPEG: Dumping YUV Daten in AVFrame Struktur

http://ffmpeg.org/doxygen/trunk/structAVFrame.html, kann ich ableiten, dass ich in meinen Daten setzen müssen

data[AV_NUM_DATA_POINTERS] 

linesize [AV_NUM_DATA_POINTERS]. 

Die YUV-Daten i-Dump bin versucht, mit ist YUV420 und die Bildgröße ist 416x240. Also, wie kann ich diese Yuv-Daten auf AVFrame-Strukturen Variable dump/map? Ich weiß, dass Linesize den Schritt darstellt, d. H. Ich nehme die Breite meines Bildes an, ich habe mit einigen Kombinationen versucht, aber bekomme den Ausgang nicht. Ich bitte Sie freundlich, mir zu helfen, den Puffer zuzuordnen. Danke im Voraus.

Antwort

17

AVFrame kann als AV-Bild interpretiert werden, um die Felder data und linesize zu füllen. Der einfachste Weg, dieses Feld zu füllen, ist die Verwendung der avpicture_fill Funktion.

Um die Y U- und V-Puffer des AVFrame zu füllen, hängt es von Ihren Eingabedaten ab und was Sie mit dem Rahmen machen wollen (möchten Sie in den AVFrame schreiben und die ursprünglichen Daten löschen oder eine Kopie behalten).

Wenn der Puffer groß genug ist (mindestens linesize[0] * height für Y-Daten, linesize[1 or 2] * height/2 für U/V-Daten) können Sie direkt verwenden Eingangspuffer:

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

Wenn Sie wollen/müssen eine Kopie manipulieren Eingabedaten müssen Sie die benötigte Puffergröße berechnen und Eingabedaten darin kopieren.

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

Sobald Sie mit dem AVFrame fertig sind, vergessen Sie nicht, es mit av_frame_free zu befreien (und jeder Puffer von av_malloc zugewiesen).

+0

Einfach genial Erklärung. Danke – Zax

+0

Mehr über Typecasting zwischen '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); 
}