How do you resize an AVFrame?

2019-02-16 03:06发布

问题:

How do you resize an AVFrame? I

Here's what I'm currently doing:

AVFrame* frame = /*...*/;

int width = 600, height = 400;
AVFrame* resizedFrame = av_frame_alloc();

auto format = AVPixelFormat(frame->format);

auto buffer = av_malloc(avpicture_get_size(format, width, height) * sizeof(uint8_t));

avpicture_fill((AVPicture *)resizedFrame, (uint8_t*)buffer, format, width, height);

struct SwsContext* swsContext = sws_getContext(frame->width, frame->height, format,
                                               width,         height,         format,
                                               SWS_BILINEAR,  nullptr,        nullptr,        nullptr);

sws_scale(swsContext, frame->data, frame->linesize, 0, frame->height, resizedFrame->data, resizedFrame->linesize);

But after this resizedFrames->widthand height are still 0, the contents of the AVFrame look like garbage, and I get an warning that data is unaligned when I call sws_scale. Note: I don't want to change the pixel format, and I don't want to hard code what it is.

回答1:

So, there's a few things going on.

  • avpicture_fill() does not set frame->width/height/format. You have to set these values yourself.
  • avpicture_get_size() and avpicture_fill() do not guarantee alignment. The underlying functions called in these wrappers (e.g. av_image_get_buffer_size() or av_image_fill_arrays()) are called with align=1, so there's no buffer alignment between lines. If you want alignment (you do), you either have to call the underlying functions directly with a different align setting, or call avcodec_align_dimensions2() on the width/height and provide aligned width/height to the avpicture_*() functions. If you do that, you can also consider using avpicture_alloc() instead of avpicture_get_size() + av_malloc() + avpicture_fill().

I think if you follow these two suggestions, you'll find that the rescaling works as expected, gives no warnings and has correct output. The quality may not be great because you're trying to do bilinear scaling. Most people use bicubic scaling (SWS_BICUBIC).



标签: c++ c ffmpeg