- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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:
[cpp]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;
}[/cpp]
The call from C#:
[bash]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();[/bash][bash]Any ideas on what I'm doing wrong in handling non-even width/height bitmaps?[/bash]
Link Copied
2 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I see. Thanks for the insight.
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page