简体   繁体   中英

Error in RGB to YUV conversion in FFmpeg

I am trying convert a RGB image into YUV. I am loading image using openCV.

I am calling the function as follows:

//I know IplImage is outdated 
IplImage* im = cvLoadImage("1.jpg", 1);
//....
bgr2yuv(im->imageData, dst, im->width, im->height);

the function to convert Color image to yuv image is given below. I am using ffmpeg to do that.

void bgr2yuv(unsigned char *src, unsigned char *dest, int w, int h)
{
  AVFrame *yuvIm = avcodec_alloc_frame();
  AVFrame *rgbIm = avcodec_alloc_frame();
  avpicture_fill(rgbIm, src, PIX_FMT_BGR24, w, h);
  avpicture_fill(yuvIm, dest, PIX_FMT_YUV420P, w, h);
  av_register_all();

  struct SwsContext * imgCtx = sws_getCachedContext(imgCtx,
                                         w, h,(::PixelFormat)PIX_FMT_BGR24,
                                         w, h,(::PixelFormat)PIX_FMT_YUV420P,
                                         SWS_BICUBIC, NULL, NULL, NULL);

  sws_scale(imgCtx, rgbIm->data, rgbIm->linesize,0, h, yuvIm->data, yuvIm->linesize);
  av_free(yuvIm);
  av_free(rgbIm);
}

I am getting wrong output after conversion. I am thinking this is due to padding happening in the IplImage. (My input image width is not multiple of 4).

I updated linesize variable even after that I am not getting correct output. Its working fine when I am using images whose width is multiple of 4.

Can anybody tell what is the problem in the code.

Check IplImage::align or IplImage::widthStep and use these to set AVFrame::linesize . For the RGB frame, for example, you would set:

frame->linesize[0] = img->widthStep;

The layout of the dst array can be whatever you want, it depends on how you're using it afterwards.

We need to do as follows:

rgbIm->linesize[0] = im->widthStep;

But I think output data from sws_scale() is not padded to make it multiple of 4. So when you are copying this data (dest) again to IplImage this will create problem in displaying, saving etc..

So we need to set widthStep=width as follows:

IplImage* yuvImage = cvCreateImageHeader(cvGetSize(im), 8, 1);
yuvImage->widthStep = yuvImage->width;
yuvImage->imageData = dest;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM