Reputation: 41
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
Upvotes: 0
Views: 508
Reputation: 32114
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);
Upvotes: 1