Jump to content


Decoding i420 using VFW


3 replies to this topic

#1 hifive

    New Member

  • Members
  • PipPip
  • 10 posts

Posted 22 August 2009 - 04:26 AM

Hi I am trying to decode using VFW a video stream from my webcam that is in the i420 format to stream to a texture in opengl.

Using ICOpen etc to decompress the i420 stream into plain RGB but for some reason it fails on the call to ICDecompress.

I'm not sure if I need to load a specific decompressor somehow? But ICOpen doesn't fail just ICDecompress call? But it's my first time playing with this stuff.

My work in progress code is:

int cameraSize[2] = { 128, 128 };
HWND cameraWindow = 0;
GLuint webcamTexture = 0;
HIC decompressor = 0;
BITMAPINFO bitmapInfo[2];
BYTE* imageData;


LRESULT WINAPI webcam_callback(HWND window, LPVIDEOHDR video_hdr)
{
	DWORD error = ICDecompress(decompressor, 0, &bitmapInfo[0].bmiHeader, video_hdr->lpData, &bitmapInfo[1].bmiHeader, imageData);


	if(error != ICERR_OK)
		_asm int 3;

/*
	glBindTexture(TEXRECT, webcamTexture);
    glTexSubImage2D(TEXRECT, 0, 0, 0, cameraSize[0], cameraSize[1], GL_BGR_EXT, GL_UNSIGNED_BYTE, imageData);
*/

	return true;
};


bool webcam_init(HWND window)
{
	CAPDRIVERCAPS driverCaps;

 
    for(int driverIndex = 0; driverIndex < 10; ++driverIndex) 
    {
		wchar_t deviceVersion[80];
		wchar_t deviceName[80];


        if(capGetDriverDescription(	driverIndex,
									deviceName, 
									sizeof(deviceName), deviceVersion, 
									sizeof(deviceVersion))) 
        {
			int a = 3;
        }
    }


	cameraWindow = capCreateCaptureWindow(	L"CamDemo",
											WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
											0, 0,
											1, 1,
											window,
											0);

	if(!cameraWindow)
		return false;

	if(!capDriverConnect(cameraWindow, 0))
		return false;

	capDriverGetCaps(cameraWindow, &driverCaps, sizeof(driverCaps));
	capSetCallbackOnFrame(cameraWindow, webcam_callback);

	capPreviewScale(cameraWindow, FALSE);
	capPreviewRate(cameraWindow, 400);	//ms
	capPreview(cameraWindow, true);
	

/*
		CAPTUREPARMS p;
        capCaptureGetSetup(cameraWindow, &p, sizeof(CAPTUREPARMS));
        //p.dwRequestMicroSecPerFrame = 66667/2;
        //capCaptureSetSetup(cameraWindow, &p, sizeof(CAPTUREPARMS));
*/

    memset(&bitmapInfo[0], 0, sizeof(bitmapInfo[0]));
	bitmapInfo[0].bmiHeader.biSize = sizeof(bitmapInfo[0].bmiHeader);
    capGetVideoFormat(cameraWindow, &bitmapInfo[0], sizeof(bitmapInfo[0]));


	cameraSize[0] = bitmapInfo[0].bmiHeader.biWidth;
	cameraSize[1] = bitmapInfo[0].bmiHeader.biHeight;


	decompressor = ICOpen(MAKEFOURCC('V','I','D','C'), bitmapInfo[0].bmiHeader.biCompression, ICMODE_FASTDECOMPRESS);
    
	if(!decompressor)
		_asm int 3;


	memset(&bitmapInfo[1], 0, sizeof(bitmapInfo[1]));
	bitmapInfo[1].bmiHeader.biSize = sizeof(bitmapInfo[1].bmiHeader);
	bitmapInfo[1].bmiHeader.biWidth = cameraSize[0];
	bitmapInfo[1].bmiHeader.biHeight = cameraSize[1];
	bitmapInfo[1].bmiHeader.biCompression = BI_RGB;
	bitmapInfo[1].bmiHeader.biBitCount = 24;
	bitmapInfo[1].bmiHeader.biPlanes = 1;
	bitmapInfo[1].bmiHeader.biSizeImage = cameraSize[0]*cameraSize[1]*3;



	if(ICDecompressBegin(decompressor, &bitmapInfo[0], &bitmapInfo[1]) != ICERR_OK)
		_asm int 3;



	BYTE* imageData = new BYTE[cameraSize[0]*cameraSize[1]*3];
/*
	glGenTextures(1, &webcamTexture);
	glBindTexture(TEXRECT, webcamTexture);
	glTexImage2D(TEXRECT, 0, 3, cameraSize[0], cameraSize[1], 0, GL_BGR_EXT, GL_UNSIGNED_BYTE, imageData);
	

	glTexParameteri(TEXRECT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(TEXRECT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexParameterf(TEXRECT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameterf(TEXRECT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
*/

	return true;
}


void webcam_destroy()
{ 
	delete[] imageData;

	ICDecompressEnd(decompressor);
    ICClose(decompressor);

    capSetCallbackOnFrame(cameraWindow, 0);
	capDriverDisconnect(cameraWindow);
    DestroyWindow(cameraWindow);
}


#2 Reedbeta

    DevMaster Staff

  • Administrators
  • 5340 posts
  • LocationSanta Clara, CA

Posted 22 August 2009 - 04:34 AM

Please use the [code]...[/code] tags when posting code on the forum.
reedbeta.com - developer blog, OpenGL demos, and other projects

#3 hifive

    New Member

  • Members
  • PipPip
  • 10 posts

Posted 22 August 2009 - 05:05 AM

Ah Thank's I didn't know how to do that :)


I have also just tried using:


decompressor = ICLocate(MAKEFOURCC('V','I','D','C'), bitmapInfo[0].bmiHeader.biCompression, &bitmapInfo[0].bmiHeader, &bitmapInfo[1].bmiHeader, ICMODE_FASTDECOMPRESS);


Instead of ICOpen which doesn't fail but still I have the same problem in ICDecompress.

I guess I could write something to directly decode the i420 format to RGB myself but I thought this should be a standard codec to deal with this? Also my webcam supports YUY2 format too. But I don't know what are the most common formats for webcams as I want it to work easily across different machines.

#4 hifive

    New Member

  • Members
  • PipPip
  • 10 posts

Posted 22 August 2009 - 07:52 PM

I also have tested

ICINFO ICInfo; 
ICGetInfo(decompressor, &ICInfo, sizeof(ICInfo));

and I get:

- ICInfo {dwSize=568 fccType=1667524982 fccHandler=808596553 ...} ICINFO
dwSize 568 unsigned long
fccType 1667524982 unsigned long
fccHandler 808596553 unsigned long
dwFlags 0 unsigned long
dwVersion 9002 unsigned long
dwVersionICM 260 unsigned long
+ szName 0x0012f504 "MS H.263" wchar_t [16]
+ szDescription 0x0012f524 "Intel 4:2:0 Video V2.50" wchar_t [128]
+ szDriver 0x0012f624 "C:\WINDOWS\system32\msh263.drv" wchar_t [128]



I am trying to decode the web cam stream at 640x480 resolution and I can't find any decent working example of anyone doing similar?





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users