[Libav-user] sws_scale has weird behavior when not resizing
Alexandre Millette
amillett at matrox.com
Thu Jul 12 17:29:38 CEST 2012
Hello all.
I'm working on a C++ video player using libav.
Upon testing with various video formats and files, I've encountered a
problem with a small MPEG4/mp4v file (190x240).
The issue is that a small green band (6 px in width) will appear on the
right side of the frames.
This is what I've gathered so far:
- The YUV420 frame read in the stream is ok.
- The RGB32 frame output by sws_scale (there is no resize, the function
is used only for conversion purpose) has the green band, so the problem
comes from sws_scale.
- The green color comes from the original allocation of the YUV frame
(data to 0 equals to a green shade).
- If sws_scale is used also as a resizing device (say converting YUV420
190x240 to RGB32 191x240), there is no colored band, but the frame is of
course 1 pixel wider than intended (frame accuracy is an important
feature of the project, so this is not acceptable).
- When trying a sws_scale resize&convert on only the first frame, the
other frames will still have a band to the right, but it will be the
pixels from the first frame, not green. I can only assume that it is
because the RGB32 frame is not entirely overwritten by the function.
After all this exposition, my question:
Why is sws_scale behavior different when not resizing? What should be
changed in order to produce the same result but without the resizing?
As a precision, resizing up and down each frame is not a viable solution
since performance is an issue (besides it would seem wrong).
Here's some very simplified code to help:
AVCodecContext* mpCodecCtx;
AVFrame* lpFrame;
AVFrame* lpFrameRGB;
static struct SwsContext* img_convert_ctx = 0;
// ...
// mpCodecCtx is opened normally
// lpFrame is allocated and returned by avcodec_decode_video2
// lpFrameRGB is allocated and filled by avpicture_fill
int w = mpCodecCtx->width;
int h = mpCodecCtx->height;
img_convert_ctx = sws_getContext(w, h, PIX_FMT_YUV420P,
w, h, PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);
int ret = sws_scale(img_convert_ctx, lpFrame->data,
lpFrame->linesize, 0, h,
lpFrameRGB->data, lpFrameRGB->linesize);
// Here lpFrameRGB contains the green bar
// This can be prevented by changing the fourth
// parameter of sws_getContext to w+1
Thank you,
Alex M
More information about the Libav-user
mailing list