BMP to YUV420 to H264 encode problem with odd-sized images

BMP to YUV420 to H264 encode problem with odd-sized images

I am trying to convert some .bmp into h264 to be streamed. Basically a bitmap bytestream is sent over to be encoded.I looked thru the samples/forum and got enough ideas to get started and so far I got some pretty good results.The only problem I have right now is bitmaps with non-even width/height is not encoded correctly - in VLC it's just a green screen. With even-numbered width/height images the h264 file is correct.I tried passing-in the stride of the bitmap (via C# BitmapData.Stride) but still getting the green image.The C/IPP dll:

void ConvertBGRtoYUV420(Ipp8u* rgbData, Ipp8u* yuvData, int imgWidth, int imgHeight, int stride, int frameNumber)


	Ipp8u* yuv[3];

	int yuvStep[3] = {imgWidth, imgWidth/2, imgWidth/2};

	int srcStep = stride;

	IppiSize srcSize = {imgWidth, imgHeight};
	for(int i = 0; i < frameNumber; ++i)


		yuv[0] = yuvData + i * imgWidth * imgHeight * 3/2;

		yuv[1] = yuv[0] + imgWidth * imgHeight;

		yuv[2] = yuv[1] + imgWidth * imgHeight / 4;
		ippiBGRToYCbCr420_8u_C3P3R(rgbData, srcStep, yuv, yuvStep, srcSize);


// bmp is in BGR, not RGB!

int EncodeStream(Ipp8u* inData, int imgWidth, int imgHeight, int frameNumber, Ipp8u* encodedData, int& VideoDataSize, int stride)


	Ipp8u *cYUVData = ippsMalloc_8u(200000000);

	ConvertBGRtoYUV420(inData, cYUVData, imgWidth, imgHeight, stride, frameNumber);

	UMC::Status status;

	UMC::MediaData DataOut;

	UMC::VideoData DataIn;

	int FrameSize;
	UMC::H264EncoderParams Params;

	UMC::H264VideoEncoder H264Encoder;

	Params.B_frame_rate = 0;

	Params.key_interval = 1; = imgHeight; = imgWidth; = 1000000;

	Params.numThreads = 1; 
	// roi = entire img

	IppiSize roi;

	roi.width = imgWidth;

	roi.height = imgHeight;
	if((status = H264Encoder.Init(&Params))!=UMC::UMC_OK)

	  return -1;
   FrameSize = imgWidth * imgHeight * 3/2;



   DataOut.SetBufferPointer(encodedData, 100000000);

   int nEncodedFrames=0;

   while ( nEncodedFrames < frameNumber)


	    status = H264Encoder.GetFrame(&DataIn, &DataOut);

        if (status == UMC::UMC_OK)



               cYUVData += FrameSize;





	return TRUE;

The call from C#:
Image img = new Bitmap(@"C:test.bmp");

            const string fileName = @"C:output.h264";

            BinaryWriter bw = new BinaryWriter(File.Open(fileName, FileMode.Create));
            byte[] data;

            byte[] output;
            var bmd = (img as Bitmap).LockBits(new Rectangle(0, 0, img.Width, img.Height), ImageLockMode.ReadOnly,


            // first row of pixels

            IntPtr ptr = bmd.Scan0;
            int bytes = Math.Abs(bmd.Stride)*img.Height;

            data = new byte[bytes];
            // copy rgb values into array

            Marshal.Copy(ptr, data, 0, bytes);

            output = new byte[bytes];
            int size = 0;

            int ret = ConvertBGRtoYUV420(data, img.Width, img.Height, 100, output, ref size, bmd.Stride);


Any ideas on what I'm doing wrong in handling non-even width/height bitmaps?

3 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

If I am not mistaken, width and height not divisible by 2 are not supported in H.264. The only thing you can do is crop or upscale.

Igor Levicki

I see. Thanks for the insight.

Leave a Comment

Please sign in to add a comment. Not a member? Join today