简体   繁体   中英

How do I specify the linesize of a frame when calling av_frame_get_buffer

    int stream_index = find_stream(AVMEDIA_TYPE_VIDEO, input);

    AVStream *s = input->container->streams[stream_index];

    AVFrame *new_frame = av_frame_alloc();

    new_frame->width = s->codecpar->width;
    new_frame->height = s->codecpar->height;
    new_frame->format = s->codecpar->format;

    av_frame_get_buffer(new_frame, 0);

    printf("%i %i %i %i %i %i\n", new_frame->linesize[0], new_frame->linesize[1], new_frame->linesize[2], new_frame->width, new_frame->height, new_frame->format);
    apply_path(input->paths[stream_index], new_frame);

the values from the frame created with av_frame_get_buffer(new_frame, 0); are this:

linesize 0  1080  
linesize 1  540  
linesize 2  540  
width  1080  
height  1080  
format  0 (AV_PIX_FMT_YUV420P)  

The values I want:

linesize 0  1152  
linesize 1  576  
linesize 2  576  
width  1080  
height  1080  
format  0 (AV_PIX_FMT_YUV420P)   

I want to use linesize instead of width and height because when I decode frames from diferent videos they may have different linesizes but same width and height

We may use manual allocation using av_malloc :

AVFrame* new_frame = av_frame_alloc();

int linesize0 = 1152;
int linesize1 = 576;
int linesize2 = 576;
int width = 1080;
int height = 1080;

new_frame->linesize[0] = linesize0;
new_frame->linesize[1] = linesize1;
new_frame->linesize[2] = linesize2;

new_frame->data[0] = (uint8_t*)av_malloc(linesize0 * height);
new_frame->data[1] = (uint8_t*)av_malloc(linesize1 * height/2); //For YUV420 we need to allocate height/2 rows.
new_frame->data[2] = (uint8_t*)av_malloc(linesize2 * height/2);

new_frame->width = s->codecpar->width;
new_frame->height = s->codecpar->height;
new_frame->format = s->codecpar->format;

According to av_malloc documentation (in mem.h ), the function handles the alignment:

Allocate a memory block with alignment suitable for all memory accesses.

It is recommended to av_malloc instead of using new or malloc .


Free allocated buffers at the end:

av_freep(new_frame->data[0]);
av_freep(new_frame->data[1]);
av_freep(new_frame->data[2]);

Note:

It looks like we could also use av_image_alloc .
I tested it, and it's not working as I thought.

/**
 * Allocate an image with size w and h and pixel format pix_fmt, and
 * fill pointers and linesizes accordingly.
 * The allocated image buffer has to be freed by using
 * av_freep(&pointers[0]).
 *
 * @param align the value to use for buffer size alignment
 * @return the size in bytes required for the image buffer, a negative
 * error code in case of failure
 */
int av_image_alloc(uint8_t *pointers[4], int linesizes[4],
                   int w, int h, enum AVPixelFormat pix_fmt, int align);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM