I am trying to convert an input RGB8 image into NV12 using libav, but sws_scale raises a reading access violation. I must have the planes or the stride wrong, but I can't see why.
At this point I believe I'd benefit from a fresh pair of eyes. What am I missing?
void convertRGB2NV12(unsigned char *rgb_in, width, height) {
struct SwsContext* sws_context = nullptr;
const int in_linesize[1] = {3 * width}; // RGB stride
int out_linesize[2] = {width, width}; // NV12 stride
// NV12 data is separated in two
// planes, one for the intensity (Y) and another one for
// the colours(UV) interleaved, both with
// the same width as the frame but the UV plane with
// half of its height.
uint8_t* out_planes[2];
out_planes[0] = new uint8_t[width * height];
out_planes[1] = new uint8_t[width * height/2];
sws_context = sws_getCachedContext(sws_context, width, height,
AV_PIX_FMT_RGB8, width, height,
AV_PIX_FMT_NV12, 0, 0, 0, 0);
sws_scale(sws_context, (const uint8_t* const*)rgb_in, in_linesize,
0, height, out_planes, out_linesize);
// (.....)
}
There are two main issues:
Replace
AV_PIX_FMT_RGB8
withAV_PIX_FMT_RGB24
.rgb_in
should be "wrapped" with array of pointers:Testing:
Use FFmpeg command line tool for creating binary input in RGB24 pixel format:
Read the input image using C code:
Execute
convertRGB2NV12(rgb_in, width, height);
.Before the end of the function, add temporary code for writing the output to binary file:
Convert nv12_image.bin as gray scale input to PNG image file (for viewing the result):
Complete code sample:
Input (RGB):

Output (NV12 displayed as gray scale):

Converting NV12 to RGB:
Result:
