FFMPEG: volcado de datos YUV en la estructura de AVFrame
(2)
Estoy tratando de volcar datos de YUV420
en la estructura AVFrame
de FFMPEG. Desde el siguiente enlace:
http://ffmpeg.org/doxygen/trunk/structAVFrame.html , puedo deducir que necesito poner mis datos en
data[AV_NUM_DATA_POINTERS]
utilizando
linesize [AV_NUM_DATA_POINTERS].
Los datos de YUV que trato de volcar son YUV420 y el tamaño de la imagen es 416x240.
Entonces, ¿cómo puedo volcar / mapear estos datos yuv a la variable de estructuras AVFrame? Me doy cuenta de que linesize representa la zancada, es decir, supongo que el ancho de mi imagen, lo he intentado con algunas combinaciones pero no obtengo el resultado. Le solicito amablemente que me ayude a mapear el búfer. Gracias por adelantado.
AVFrame se puede interpretar como una imagen AV para rellenar los campos de data
y de linesize
. La forma más fácil de llenar estos campos es usar la función avpicture_fill .
Para rellenar los buffers YU y V del AVFrame, depende de los datos de entrada y de lo que quiera hacer con el fotograma (¿desea escribir en el AVFrame y borrar los datos iniciales? O conservar una copia).
Si el búfer es lo suficientemente grande (al menos linesize[0] * height
para datos Y, linesize[1 or 2] * height/2
para datos U / V), puede usar directamente búferes de entrada:
// 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);
Si desea / necesita manipular una copia de datos de entrada, necesita calcular el tamaño de búfer necesario y copiar datos de entrada en él.
// 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);
Una vez que haya terminado con el AVFrame, no olvide liberarlo con av_frame_free
(y cualquier búfer asignado por av_malloc
).
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);
}