I want to use FFmpeg to convert the input NV12 format to YUV420P.
I tried to use sws_scale conversion, but the colors are all green.
I have successfully converted YUYV422 to 420P using sws, but FAILED to convert NV12 to YUV420.
What should I change?
Here is my code:
QStringList inList = int_put_res.split("x");
m_in_width = inList[0].toInt();
m_in_hieght = inList[1].toInt();
QStringList outList = out_put_res.split("x");
m_out_width = outList[0].toInt();
m_out_hieght = outList[1].toInt();
int VSize = m_in_width * m_in_hieght;
AVPacket *packet;
AVCodecContext *enc_ctx = NULL;
AVFrame *image_inFrame= nullptr;
packet = av_packet_alloc();
int ret = 0;
int base = 0;
image_inFrame = av_frame_alloc();
open_encoder(m_out_width,m_out_hieght, &enc_ctx);
switch (AVPixelFormat(m_fmt_ctx->streams[m_videoindex]->codecpar->format))
{
case AV_PIX_FMT_YUV420P:
m_yuv420p_convert_ctx = initSWS(image_inFrame,NULL,m_in_width,m_in_hieght,AV_PIX_FMT_YUV420P,AV_PIX_FMT_YUV420P);
break;
case AV_PIX_FMT_YUYV422:
m_yuv420p_convert_ctx = initSWS(image_inFrame,NULL,m_in_width,m_in_hieght,AV_PIX_FMT_YUYV422,AV_PIX_FMT_YUV420P);
break;
case AV_PIX_FMT_NV12:
m_yuv420p_convert_ctx = initSWS(image_inFrame,NULL,m_in_width,m_in_hieght,AV_PIX_FMT_NV12,AV_PIX_FMT_YUV420P);
break;
}
m_frame = create_frame(m_out_width, m_out_hieght);
AVPacket *newpkt = av_packet_alloc();
if (!newpkt)
{
spdlog::error("failed to alloc avpacket!");
goto __ERROR;
}
if (!m_fmt_ctx)
{
goto __ERROR;
}
while (m_isStop != true)
{
if(av_read_frame(m_fmt_ctx, packet) != 0) {
goto __ERROR;
}
getSWS(m_yuv420p_convert_ctx,packet,image_inFrame,m_frame);
av_packet_unref(packet);
m_frame->pts = base++;
}
SwsContext *FFSDK::initSWS(AVFrame *scrFrame, AVFrame *dstFrame, int
image_width, int image_height,enum AVPixelFormat scrFmt, enum
AVPixelFormat dstFmt)
if(scrFrame != NULL){
av_image_alloc(scrFrame->data, scrFrame->linesize,image_width, image_height, scrFmt, 1);
}
if(dstFrame != NULL){
av_image_alloc(dstFrame->data, dstFrame->linesize, m_out_width, m_out_hieght, dstFmt, 1);
}
return sws_getContext(image_width,image_height,
scrFmt,
m_out_width, m_out_hieght, dstFmt,
SWS_BICUBIC,
nullptr,
nullptr,
nullptr);
}
void FFSDK::getSWS(SwsContext *context,AVPacket *packet,AVFrame *scrFrame, AVFrame *dstFrame)
{
scrFrame->data[0] = packet->data;
sws_scale(context,
scrFrame->data,
scrFrame->linesize, 0, m_in_hieght, dstFrame->data,
dstFrame->linesize);
}
I can't see the problem from the pieces of code that you have posted.
Green colors are usually result of zero data (all elements of Y, U and V are zeros).
The reason for the zero content is probably because nothing is written to the destination (or source) buffers of the video frame.
I have created a "self contained" code sample that demonstrates the conversion from NV12 to YUV420 using
sws_scale
.Start by building synthetic input frame using FFmpeg (command line tool).
The command creates 320x240 video frame in raw NV12 format:
The next code sample applies the following stages:
sws_scale
).Here is the complete code:
For validating the output:
After executing the code, execute FFmpeg (command line tool).
The following command converts the raw binary frame (in YUV420 format) to PNG (in RGB format).
Sample output (after converting from YUV420 to PNG image file format):

I hope it helps you find the problem...