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.key_frame_controls.method=1;

	Params.B_frame_rate = 0;

	Params.key_interval = 1;

	Params.info.clip_info.height = imgHeight;

	Params.info.clip_info.width = imgWidth;

	Params.info.bitrate = 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;

   DataIn.Init(imgWidth,imgHeight,UMC::YUV420,8);

   DataIn.SetBufferPointer(inData,FrameSize);

   DataIn.SetDataSize(FrameSize);
   DataOut.SetBufferPointer(encodedData, 100000000);
   VideoDataSize=0;

   int nEncodedFrames=0;

   while ( nEncodedFrames < frameNumber)

   {

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

        if (status == UMC::UMC_OK)

        {

               nEncodedFrames++;
               VideoDataSize+=DataOut.GetDataSize();

	           DataOut.MoveDataPointer(DataOut.GetDataSize());
               cYUVData += FrameSize;

	           DataIn.SetBufferPointer(cYUVData,FrameSize);

	           DataIn.SetDataSize(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,

                                     PixelFormat.Format24bppRgb);

            // 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);

            bw.Write(output);

            bw.Close();
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.

Regards,
Igor Levicki

I see. Thanks for the insight.

Leave a Comment

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