CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 9 of 9
  1. #1
    Join Date
    Jun 2012
    Posts
    8

    Video player in vc++ (each frame being shown in a new window)

    I am trying to show all the frames of a video sequence in the same window. But currently it is showing each frame in a different window. e.g. once it shows first frame, I need to close that window and then another window pops up and it shows next frame and then I need to close that one and then next window pops up...and so on.

    i am using createwindow function to create a window and I associate HINSTANCE of a frame to HWND using CreateWindow function. If I do createwindow only once it just shows first frame in a window and once I close it nothing happens..

    can anybody help me out with this???

    Here is the part of code related to it:-

    Code:
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       hInst = hInstance; // Store instance handle in our global variable
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
    
    
       if (!hWnd)
       {
          return FALSE;
       }
    
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);
    
       return TRUE;
    }
    So when I call it in loop, each time it creates a new window for each frame. But if I call CreateWindow only once, then it doesn't update frame. If I am right its happening that way coz it doesn't associate new hInstance with window as hInstance is being updated with each frame.
    Is there a way to associate/update hInstance to a hWnd without calling CreateWindow function? Or am I thinking in wrong direction? Can someone clarify please.
    Last edited by Marc G; July 2nd, 2012 at 01:46 AM. Reason: Added code tags

  2. #2
    Join Date
    Nov 2003
    Location
    Belgium
    Posts
    8,150

    Re: Video player in vc++ (each frame being shown in a new window)

    We need to see more of your code to be able to help you.
    For starters, InitInstance should be called only once. It's meant to initialize your instance of your program.
    If you only want 1 window, then you only call CreateWindow once.
    You can update your existing window by implementing a proper window procedure function, and handle WM_PAINT messages to paint your window.
    Marc Gregoire - NuonSoft (http://www.nuonsoft.com)
    My Blog
    Wallpaper Cycler 3.5.0.97

    Author of Professional C++, 4th Edition by Wiley/Wrox (includes C++17 features)
    ISBN: 978-1-119-42130-6
    [ http://www.facebook.com/professionalcpp ]

  3. #3
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Video player in vc++ (each frame being shown in a new window)

    I am trying to show all the frames of a video sequence in the same window.
    What does that "show" mean? You extract frames somehow (how?), and your problem is just drawing image? Or your window embeds video player that gets positioned to appropriate frame time? Depending on the answer there could be few totally different resolution approaches.

    i am using createwindow function to create a window and I associate HINSTANCE of a frame to HWND using CreateWindow function.
    it doesn't associate new hInstance with window as hInstance is being updated with each frame.
    This sounds senseless. HINSTANCE is a base address of a binary module (.exe or .dll), therefore, it has nothing to do with a frame. You need to explain, which way frames are obtained in your program, and why you do think they have an "association" with module instance.
    Best regards,
    Igor

  4. #4
    Join Date
    Jun 2012
    Posts
    8

    Re: Video player in vc++ (each frame being shown in a new window)

    I am pasting my complete code here :-

    "Image.h" :-

    Code:
    #if !defined(AFX_IMAGE_H__E34B6FBB_5FED_457A_B3D1_D4844DCD4951__INCLUDED_)
    #define AFX_IMAGE_H__E34B6FBB_5FED_457A_B3D1_D4844DCD4951__INCLUDED_
    
    #if _MSC_VER > 1000
    #pragma once
    #endif // _MSC_VER > 1000
    
    #include "resource.h"
    #include "stdafx.h"
    #include "resource.h"
    #include <stdio.h>
    
    // Class structure of Image 
    class MyImage 
    {
    
    private:
    	int		Width;
    	int		Height;
    	char	ImagePath[_MAX_PATH];
    	unsigned char*	Data;
    	unsigned char*	NewData;
    	
    public:
    	int playFlag;	// 0 = pause and 1 = play
    	int stopFlag;	// set 1 when user hits stop, equal to 0 rest of the time
    
    	int channelNum;	// 0->All to be displayed, 1->Y, 2->U, 3->V
    
    	MyImage() {playFlag=1; stopFlag=0;channelNum=0;};
    	~MyImage() { if(Data) delete Data; };
    	void	setWidth(int w)  { Width = w; }; 
    	void	setHeight(int h) { Height = h; }; 
    	void	setImageData(unsigned char *img ) { Data = img; };
    	void	setImagePath(char *path) { strcpy(ImagePath, path); }
    	int		getWidth() { return Width; };
    	int		getHeight() { return Height; };
    	unsigned char*	getImageData() { return NewData; };
    	char*	getImagePath() { return ImagePath; }
    	void	ReadImage();
    	void	ConvertYUVtoRGB();
    
    };
    
    #endif // !defined(AFX_IMAGE_H__E34B6FBB_5FED_457A_B3D1_D4844DCD4951__INCLUDED_)
    AND "Image.cpp" :-

    Code:
    // Image.cpp : Defines the entry point for the application.
    //
    
    #include "Image.h"
    
    MyImage myImage;
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    HINSTANCE hInst;								// current instance
    TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text
    
    // Foward declarations of functions included in this code module:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    FILE *IN_FILE;
    int flag;
    HWND hWnd;
    
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
     	// TODO: Place code here.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	int w, h;
    	char ImagePath[_MAX_PATH];
    	sscanf(lpCmdLine, "%s", &ImagePath);
    	//ImagePath = {"M:\\MediaPlayer\\data\\yuv\\image1.rgb"};
    	w = 352;
    	h = 288;
    	myImage.setWidth(w);
    	myImage.setHeight(h);
    	myImage.setImagePath(ImagePath);
    
    	flag = 0;
    
    	while(1)
    	{
    
    		if(myImage.playFlag==1)
    		{
    			myImage.ReadImage();
    			myImage.ConvertYUVtoRGB();
    		}
    
    	// Initialize global strings
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_IMAGE, szWindowClass, MAX_LOADSTRING);
    	
    
    	MyRegisterClass(hInstance);
    
    	// Perform application initialization:
    
    	if (!InitInstance (hInstance, nCmdShow)) 
    	{
    		return FALSE;
    	}	
    
    	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_IMAGE);
    
    	// Main message loop:
    	/*while (GetMessage(&msg, NULL, 0, 0)) 
    	{
    		if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) 
    		{
    			TranslateMessage(&msg);
    			DispatchMessage(&msg);
    		}
    	}*/
    	
    
    	}
    	return msg.wParam;
    }
    
    
    
    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    //  COMMENTS:
    //
    //    This function and its usage is only necessary if you want this code
    //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
    //    function that was added to Windows 95. It is important to call this function
    //    so that the application will get 'well formed' small icons associated
    //    with it.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    	WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX); 
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= (WNDPROC)WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_IMAGE);
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= (LPCSTR)IDC_IMAGE;
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNCTION: InitInstance(HANDLE, int)
    //
    //   PURPOSE: Saves instance handle and creates main window
    //
    //   COMMENTS:
    //
    //        In this function, we save the instance handle in a global variable and
    //        create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       //HWND hWnd;
    
       hInst = hInstance; // Store instance handle in our global variable
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
       
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
      
       UpdateWindow(hWnd);   
      
       return TRUE;
    }
    
    //
    //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
    //
    //  PURPOSE:  Processes messages for the main window.
    //
    //  WM_COMMAND	- process the application menu
    //  WM_PAINT	- Paint the main window
    //  WM_DESTROY	- post a quit message and return
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    	TCHAR szHello[MAX_LOADSTRING];
    	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
    
    	switch (message) 
    	{
    		case WM_COMMAND:
    			wmId    = LOWORD(wParam); 
    			wmEvent = HIWORD(wParam); 
    			// Parse the menu selections:
    			switch (wmId)
    			{
    				case IDM_ABOUT:
    				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
    				   break;
    				case IDM_EXIT:
    				   DestroyWindow(hWnd);
    				   break;
    				case IDM_PLAY:
    					myImage.playFlag = 1;
    					myImage.stopFlag = 0;
    					break;
    				case IDM_PAUSE:
    					myImage.playFlag = 0;
    					break;
    				case IDM_STOP:
    					myImage.playFlag = 1;
    					myImage.stopFlag = 1;					
    					break;
    				case ID_CHANNEL_ALL:
    					myImage.channelNum = 0;					
    					break;
    				case ID_CHANNEL_Y:
    					myImage.channelNum = 1;
    					break;
    				case ID_CHANNEL_U:
    					myImage.channelNum = 2;
    					break;
    				case ID_CHANNEL_V:
    					myImage.channelNum = 3;
    					break;
    				default:
    				   return DefWindowProc(hWnd, message, wParam, lParam);
    			}
    			break;
    		case WM_PAINT:
    			{
    				hdc = BeginPaint(hWnd, &ps);
    				// TODO: Add any drawing code here...
    				RECT rt;
    				GetClientRect(hWnd, &rt);
    				char text[1000];
    				
    				BITMAPINFO bmi;
    				CBitmap bitmap;
    				memset(&bmi,0,sizeof(bmi));
    				bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
    				bmi.bmiHeader.biWidth = myImage.getWidth();
    				bmi.bmiHeader.biHeight = -myImage.getHeight();  // Use negative height.  DIB is top-down.
    				bmi.bmiHeader.biPlanes = 1;
    				bmi.bmiHeader.biBitCount = 24;
    				bmi.bmiHeader.biCompression = BI_RGB;
    				bmi.bmiHeader.biSizeImage = myImage.getWidth()*myImage.getHeight();
    
    				
    				SetDIBitsToDevice(hdc,
    								  myImage.getWidth()+50,100,myImage.getWidth(),myImage.getHeight(),
    								  0,0,0,myImage.getHeight(),
    								  myImage.getImageData(),&bmi,DIB_RGB_COLORS);
    
    
    				EndPaint(hWnd, &ps);
    			}
    			break;
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
       }
       return 0;
    }
    
    // Mesage handler for about box.
    LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch (message)
    	{
    		case WM_INITDIALOG:
    				return TRUE;
    
    		case WM_COMMAND:
    			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
    			{
    				EndDialog(hDlg, LOWORD(wParam));
    				return TRUE;
    			}
    			break;
    	}
        return FALSE;
    }
    
    // clipper function for range 0 to 255
    
    double ClipRGB(double num)
    {
    	if(num < 0.0)
    		num = 0.0;
    	if(num > 255.0)
    		num = 255.0;
    	return num;
    }
    
    // MyImage functions defined here
    
    void MyImage::ConvertYUVtoRGB()
    {
    	int i;
    	double iY,iU,iV;
    	double iR,iG,iB;
    	NewData = new unsigned char[Width*Height*3];
    
    	for(i=0; i<Height*Width; i++)
    	{
    		iY = (double) Data[3*i];
    		iU = (double) Data[3*i+1];
    		iV = (double) Data[3*i+2];
    
    		if(myImage.channelNum == 0)				// All channels to be displayed
    		{
    			iR = iY + 1.4075*(iV-128.0);		/* softpixel.com formula (http://softpixel.com/~cwright/progra...olorspace/yuv/) */
    			iG = iY - 0.3455*(iU-128.0) - 0.7169*(iV-128.0);
    			iB = iY + 1.7790*(iU-128.0);
    		}
    		else if(myImage.channelNum == 1)		// Y channel to be displayed
    		{
    			/*iR = iY;
    			iG = iY;
    			iB = iY;*/
    			iR = iY + 1.4075*(128.0-128.0);
    			iG = iY - 0.3455*(128.0-128.0) - 0.7169*(128.0-128.0);
    			iB = iY + 1.7790*(128.0-128.0);
    		}
    		else if(myImage.channelNum == 2)		// U channel to be displayed
    		{
    			/*iR = 0.0;
    			iG = 0.3455*(iU-128.0);
    			iB = 1.7790*(iU-128.0);*/
    			iR = iY + 1.4075*(128.0-128.0);
    			iG = iY - 0.3455*(iU-128.0) - 0.7169*(128.0-128.0);
    			iB = iY + 1.7790*(iU-128.0);
    		}
    		else if(myImage.channelNum == 3)		// V channel to be displayed
    		{
    			/*iR = 1.4075*(iV-128.0);
    			iG = 0.0 - 0.7169*(iV-128.0);
    			iB = 0.0;*/
    			iR = iY + 1.4075*(iV-128.0);
    			iG = iY - 0.3455*(128.0-128.0) - 0.7169*(iV-128.0);
    			iB = iY + 1.7790*(128.0-128.0);
    		}
    
    		iR = ClipRGB(iR);		// Clipping of RGB values
    		iG = ClipRGB(iG);
    		iB = ClipRGB(iB);
    
    		NewData[3*i]	= (unsigned char) iB;
    		NewData[3*i+1]	= (unsigned char) iG;
    		NewData[3*i+2]	= (unsigned char) iR;
    	}
    }
    
    void MyImage::ReadImage()
    {	
    	int i,j,ctr;
    	char *Ybuf = new char[Height*Width]; 
    	char *Ubuf = new char[Height*Width/4];
    	char *Vbuf = new char[Height*Width/4];
    	char *IUbuf = new char[Height*Width/2];
    	char *IVbuf = new char[Height*Width/2];
    	char *NewUbuf = new char[Height*Width];
    	char *NewVbuf = new char[Height*Width];
    
    	if(myImage.stopFlag == 1)
    	{
    		fclose(IN_FILE);
    		IN_FILE = fopen(ImagePath, "rb");
    		if (IN_FILE == NULL)
    		{
    			fprintf(stderr, "Error");
    			exit(0);
    		}
    		myImage.playFlag = 0;
    	}
    	if(flag == 0)
    	{		
    		IN_FILE = fopen(ImagePath, "rb");
    		if (IN_FILE == NULL)
    		{
    			fprintf(stderr, "Error");
    			exit(0);
    		}
    		flag = 1;
    	}
    
    	for (i = 0; i < Width*Height; i++)
    	{
    		Ybuf[i] = fgetc(IN_FILE);
    	}
    	for (i = 0; i < Width*Height/4; i++)
    	{
    		Ubuf[i] = fgetc(IN_FILE);
    	}
    	for (i = 0; i < Width*Height/4; i++)
    	{
    		Vbuf[i] = fgetc(IN_FILE);
    	}
    	
    	ctr = 0;
    	for (i = 0; i < Height/2; i++)
    	{
    		for (j = 0; j < Width/2; j++)
    		{
    			IUbuf[ctr]			= Ubuf[i*Width/2+j];
    			IUbuf[ctr+Width/2]	= Ubuf[i*Width/2+j];
    			IVbuf[ctr]			= Vbuf[i*Width/2+j];
    			IVbuf[ctr+Width/2]	= Vbuf[i*Width/2+j];
    			ctr++;
    		}
    		ctr = ctr + Width/2;
    	}
    
    	ctr = 0;
    	for (i = 0; i < Width*Height; i+=2)
    	{
    		NewUbuf[i]		= IUbuf[ctr];
    		NewUbuf[i+1]	= IUbuf[ctr];
    		NewVbuf[i]		= IVbuf[ctr];
    		NewVbuf[i+1]	= IVbuf[ctr];
    		ctr++;
    	}
    
    	FILE *OUT_FILE;
    	OUT_FILE = fopen("M:\\uval.txt","w");
    	char ch= ' ',nl='\n';
    	
    	for (i = 0; i < Width*Height; i++)
    	{
    		fputc( NewUbuf[i], OUT_FILE);
    		fputc( ch, OUT_FILE);
    
    		if( ((i+1)%Width) == 0)
    		{
    			fputc( nl, OUT_FILE);			
    		}
    	}
    
    	Data = new unsigned char[Width*Height*3];
    
    	for (i = 0; i < Height*Width; i++)
    	{
    		Data[3*i]	= Ybuf[i];
    		Data[3*i+1]	= NewUbuf[i];
    		Data[3*i+2]	= NewVbuf[i];
    
    		/*Data[3*i+1]	= (unsigned char) 0;
    		Data[3*i+2]	= (unsigned char) 0;*/
    	}	
    
    	delete [] Ybuf;
    	delete [] Ubuf;
    	delete [] Vbuf;
    	//fclose(IN_FILE);
    }
    I am extracting frames from a .YUV file (video frames in sequence in YUV format) from memory. And I want to play the video in a window instance.

    I hope my question would be more clear now.
    Last edited by Marc G; July 3rd, 2012 at 01:56 AM. Reason: Added code tags

  5. #5
    Join Date
    Jun 2012
    Posts
    8

    Re: Video player in vc++ (each frame being shown in a new window)

    I think this version of "Image.cpp" will make more sense :-
    Code:
    // Image.cpp : Defines the entry point for the application.
    //
    
    #include "Image.h"
    
    MyImage myImage;
    
    #define MAX_LOADSTRING 100
    
    // Global Variables:
    HINSTANCE hInst;								// current instance
    TCHAR szTitle[MAX_LOADSTRING];								// The title bar text
    TCHAR szWindowClass[MAX_LOADSTRING];								// The title bar text
    
    // Foward declarations of functions included in this code module:
    ATOM				MyRegisterClass(HINSTANCE hInstance);
    BOOL				InitInstance(HINSTANCE, int);
    LRESULT CALLBACK	WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK	About(HWND, UINT, WPARAM, LPARAM);
    
    FILE *IN_FILE;
    int flag;
    HWND hWnd;
    WNDCLASSEX wcex;
    
    
    int APIENTRY WinMain(HINSTANCE hInstance,
                         HINSTANCE hPrevInstance,
                         LPSTR     lpCmdLine,
                         int       nCmdShow)
    {
     	// TODO: Place code here.
    	MSG msg;
    	HACCEL hAccelTable;
    
    	int w, h;
    	char ImagePath[_MAX_PATH];
    	sscanf(lpCmdLine, "%s", &ImagePath);
    	//ImagePath = {"M:\\MediaPlayer\\data\\yuv\\image1.rgb"};
    	w = 352;
    	h = 288;
    	myImage.setWidth(w);
    	myImage.setHeight(h);
    	myImage.setImagePath(ImagePath);
    
    	flag = 0;
    
    	
    
    	// Initialize global strings
    	LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
    	LoadString(hInstance, IDC_IMAGE, szWindowClass, MAX_LOADSTRING);
    	
    
    	MyRegisterClass(hInstance);
    
    	// Perform application initialization:
    
    	if (!InitInstance (hInstance, nCmdShow)) 
    	{
    		return FALSE;
    	}
    
    	hAccelTable = LoadAccelerators(hInstance, (LPCTSTR)IDC_IMAGE);
    
    	while(1)
    	{
    
    		if(myImage.playFlag==1)
    		{
    			myImage.ReadImage();
    			myImage.ConvertYUVtoRGB();
    		}
    
    		// Code to update the window to be added here. How to use WndProc for updating?
    	}
    	
    }
    
    
    
    //
    //  FUNCTION: MyRegisterClass()
    //
    //  PURPOSE: Registers the window class.
    //
    //  COMMENTS:
    //
    //    This function and its usage is only necessary if you want this code
    //    to be compatible with Win32 systems prior to the 'RegisterClassEx'
    //    function that was added to Windows 95. It is important to call this function
    //    so that the application will get 'well formed' small icons associated
    //    with it.
    //
    ATOM MyRegisterClass(HINSTANCE hInstance)
    {
    	//WNDCLASSEX wcex;
    
    	wcex.cbSize = sizeof(WNDCLASSEX); 
    
    	wcex.style			= CS_HREDRAW | CS_VREDRAW;
    	wcex.lpfnWndProc	= (WNDPROC)WndProc;
    	wcex.cbClsExtra		= 0;
    	wcex.cbWndExtra		= 0;
    	wcex.hInstance		= hInstance;
    	wcex.hIcon			= LoadIcon(hInstance, (LPCTSTR)IDI_IMAGE);
    	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);
    	wcex.hbrBackground	= (HBRUSH)(COLOR_WINDOW+1);
    	wcex.lpszMenuName	= (LPCSTR)IDC_IMAGE;
    	wcex.lpszClassName	= szWindowClass;
    	wcex.hIconSm		= LoadIcon(wcex.hInstance, (LPCTSTR)IDI_SMALL);
    
    	return RegisterClassEx(&wcex);
    }
    
    //
    //   FUNCTION: InitInstance(HANDLE, int)
    //
    //   PURPOSE: Saves instance handle and creates main window
    //
    //   COMMENTS:
    //
    //        In this function, we save the instance handle in a global variable and
    //        create and display the main program window.
    //
    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
       //HWND hWnd;
    
       hInst = hInstance; // Store instance handle in our global variable
    
       hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
         
       if (!hWnd)
       {
          return FALSE;
       }
    
       ShowWindow(hWnd, nCmdShow);
       UpdateWindow(hWnd);   
    
       return TRUE;
    }
    
    //
    //  FUNCTION: WndProc(HWND, unsigned, WORD, LONG)
    //
    //  PURPOSE:  Processes messages for the main window.
    //
    //  WM_COMMAND	- process the application menu
    //  WM_PAINT	- Paint the main window
    //  WM_DESTROY	- post a quit message and return
    //
    //
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	int wmId, wmEvent;
    	PAINTSTRUCT ps;
    	HDC hdc;
    	TCHAR szHello[MAX_LOADSTRING];
    	LoadString(hInst, IDS_HELLO, szHello, MAX_LOADSTRING);
    
    	switch (message) 
    	{
    		case WM_COMMAND:
    			wmId    = LOWORD(wParam); 
    			wmEvent = HIWORD(wParam); 
    			// Parse the menu selections:
    			switch (wmId)
    			{
    				case IDM_ABOUT:
    				   DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
    				   break;
    				case IDM_EXIT:
    				   DestroyWindow(hWnd);
    				   break;
    				case IDM_PLAY:
    					myImage.playFlag = 1;
    					myImage.stopFlag = 0;
    					break;
    				case IDM_PAUSE:
    					myImage.playFlag = 0;
    					break;
    				case IDM_STOP:
    					myImage.playFlag = 1;
    					myImage.stopFlag = 1;					
    					break;
    				case ID_CHANNEL_ALL:
    					myImage.channelNum = 0;					
    					break;
    				case ID_CHANNEL_Y:
    					myImage.channelNum = 1;
    					break;
    				case ID_CHANNEL_U:
    					myImage.channelNum = 2;
    					break;
    				case ID_CHANNEL_V:
    					myImage.channelNum = 3;
    					break;
    				default:
    				   return DefWindowProc(hWnd, message, wParam, lParam);
    			}
    			break;
    		case WM_PAINT:
    			{
    				hdc = BeginPaint(hWnd, &ps);
    				// TODO: Add any drawing code here...
    				RECT rt;
    				GetClientRect(hWnd, &rt);
    				char text[1000];
    				
    				BITMAPINFO bmi;
    				CBitmap bitmap;
    				memset(&bmi,0,sizeof(bmi));
    				bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
    				bmi.bmiHeader.biWidth = myImage.getWidth();
    				bmi.bmiHeader.biHeight = -myImage.getHeight();  // Use negative height.  DIB is top-down.
    				bmi.bmiHeader.biPlanes = 1;
    				bmi.bmiHeader.biBitCount = 24;
    				bmi.bmiHeader.biCompression = BI_RGB;
    				bmi.bmiHeader.biSizeImage = myImage.getWidth()*myImage.getHeight();
    
    				
    				SetDIBitsToDevice(hdc,
    								  myImage.getWidth()+50,100,myImage.getWidth(),myImage.getHeight(),
    								  0,0,0,myImage.getHeight(),
    								  myImage.getImageData(),&bmi,DIB_RGB_COLORS);
    
    
    				EndPaint(hWnd, &ps);
    			}
    			break;
    		case WM_DESTROY:
    			PostQuitMessage(0);
    			break;
    		default:
    			return DefWindowProc(hWnd, message, wParam, lParam);
       }
       return 0;
    }
    
    // Mesage handler for about box.
    LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	switch (message)
    	{
    		case WM_INITDIALOG:
    				return TRUE;
    
    		case WM_COMMAND:
    			if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) 
    			{
    				EndDialog(hDlg, LOWORD(wParam));
    				return TRUE;
    			}
    			break;
    	}
        return FALSE;
    }
    
    // clipper function for range 0 to 255
    
    double ClipRGB(double num)
    {
    	if(num < 0.0)
    		num = 0.0;
    	if(num > 255.0)
    		num = 255.0;
    	return num;
    }
    
    // MyImage functions defined here
    
    void MyImage::ConvertYUVtoRGB()
    {
    	int i;
    	double iY,iU,iV;
    	double iR,iG,iB;
    	NewData = new unsigned char[Width*Height*3];
    
    	for(i=0; i<Height*Width; i++)
    	{
    		iY = (double) Data[3*i];
    		iU = (double) Data[3*i+1];
    		iV = (double) Data[3*i+2];
    
    		if(myImage.channelNum == 0)				// All channels to be displayed
    		{
    			iR = iY + 1.4075*(iV-128.0);		/* softpixel.com formula (http://softpixel.com/~cwright/progra...olorspace/yuv/) */
    			iG = iY - 0.3455*(iU-128.0) - 0.7169*(iV-128.0);
    			iB = iY + 1.7790*(iU-128.0);
    		}
    		else if(myImage.channelNum == 1)		// Y channel to be displayed
    		{
    			/*iR = iY;
    			iG = iY;
    			iB = iY;*/
    			iR = iY + 1.4075*(128.0-128.0);
    			iG = iY - 0.3455*(128.0-128.0) - 0.7169*(128.0-128.0);
    			iB = iY + 1.7790*(128.0-128.0);
    		}
    		else if(myImage.channelNum == 2)		// U channel to be displayed
    		{
    			/*iR = 0.0;
    			iG = 0.3455*(iU-128.0);
    			iB = 1.7790*(iU-128.0);*/
    			iR = iY + 1.4075*(128.0-128.0);
    			iG = iY - 0.3455*(iU-128.0) - 0.7169*(128.0-128.0);
    			iB = iY + 1.7790*(iU-128.0);
    		}
    		else if(myImage.channelNum == 3)		// V channel to be displayed
    		{
    			/*iR = 1.4075*(iV-128.0);
    			iG = 0.0 - 0.7169*(iV-128.0);
    			iB = 0.0;*/
    			iR = iY + 1.4075*(iV-128.0);
    			iG = iY - 0.3455*(128.0-128.0) - 0.7169*(iV-128.0);
    			iB = iY + 1.7790*(128.0-128.0);
    		}
    
    		iR = ClipRGB(iR);		// Clipping of RGB values
    		iG = ClipRGB(iG);
    		iB = ClipRGB(iB);
    
    		NewData[3*i]	= (unsigned char) iB;
    		NewData[3*i+1]	= (unsigned char) iG;
    		NewData[3*i+2]	= (unsigned char) iR;
    	}
    }
    
    void MyImage::ReadImage()
    {	
    	int i,j,ctr;
    	char *Ybuf = new char[Height*Width]; 
    	char *Ubuf = new char[Height*Width/4];
    	char *Vbuf = new char[Height*Width/4];
    	char *IUbuf = new char[Height*Width/2];
    	char *IVbuf = new char[Height*Width/2];
    	char *NewUbuf = new char[Height*Width];
    	char *NewVbuf = new char[Height*Width];
    
    	if(myImage.stopFlag == 1)
    	{
    		fclose(IN_FILE);
    		IN_FILE = fopen(ImagePath, "rb");
    		if (IN_FILE == NULL)
    		{
    			fprintf(stderr, "Error");
    			exit(0);
    		}
    		myImage.playFlag = 0;
    	}
    	if(flag == 0)
    	{		
    		IN_FILE = fopen(ImagePath, "rb");
    		if (IN_FILE == NULL)
    		{
    			fprintf(stderr, "Error");
    			exit(0);
    		}
    		flag = 1;
    	}
    
    	for (i = 0; i < Width*Height; i++)
    	{
    		Ybuf[i] = fgetc(IN_FILE);
    	}
    	for (i = 0; i < Width*Height/4; i++)
    	{
    		Ubuf[i] = fgetc(IN_FILE);
    	}
    	for (i = 0; i < Width*Height/4; i++)
    	{
    		Vbuf[i] = fgetc(IN_FILE);
    	}
    	
    	ctr = 0;
    	for (i = 0; i < Height/2; i++)
    	{
    		for (j = 0; j < Width/2; j++)
    		{
    			IUbuf[ctr]			= Ubuf[i*Width/2+j];
    			IUbuf[ctr+Width/2]	= Ubuf[i*Width/2+j];
    			IVbuf[ctr]			= Vbuf[i*Width/2+j];
    			IVbuf[ctr+Width/2]	= Vbuf[i*Width/2+j];
    			ctr++;
    		}
    		ctr = ctr + Width/2;
    	}
    
    	ctr = 0;
    	for (i = 0; i < Width*Height; i+=2)
    	{
    		NewUbuf[i]		= IUbuf[ctr];
    		NewUbuf[i+1]	= IUbuf[ctr];
    		NewVbuf[i]		= IVbuf[ctr];
    		NewVbuf[i+1]	= IVbuf[ctr];
    		ctr++;
    	}
    
    	FILE *OUT_FILE;
    	OUT_FILE = fopen("M:\\uval.txt","w");
    	char ch= ' ',nl='\n';
    	
    	for (i = 0; i < Width*Height; i++)
    	{
    		fputc( NewUbuf[i], OUT_FILE);
    		fputc( ch, OUT_FILE);
    
    		if( ((i+1)%Width) == 0)
    		{
    			fputc( nl, OUT_FILE);			
    		}
    	}
    
    	Data = new unsigned char[Width*Height*3];
    
    	for (i = 0; i < Height*Width; i++)
    	{
    		Data[3*i]	= Ybuf[i];
    		Data[3*i+1]	= NewUbuf[i];
    		Data[3*i+2]	= NewVbuf[i];
    
    		/*Data[3*i+1]	= (unsigned char) 0;
    		Data[3*i+2]	= (unsigned char) 0;*/
    	}	
    
    	delete [] Ybuf;
    	delete [] Ubuf;
    	delete [] Vbuf;
    	//fclose(IN_FILE);
    }
    In this case whats happening is that InitInstance is being called once and a window is created but I don't know how to update the window with frames. I have WndProc function in my code. How exactly shall I call that function? As in with what parameters? And I shall do that in my while loop just after converting the frame to RGB format right?
    Last edited by Marc G; July 3rd, 2012 at 01:57 AM. Reason: Added code tags

  6. #6
    Join Date
    Nov 2003
    Location
    Belgium
    Posts
    8,150

    Re: Video player in vc++ (each frame being shown in a new window)

    Please, use code tags. Do you really expect anyone to read/understand the code like you've posted it?
    I have added the code tags for you now, but in the future, please use them [ code ] ... [ /code ] (without the spaces).

    Regarding your problem, I don't see a message loop. Every windows application needs a message loop. For example, see http://msdn.microsoft.com/en-us/libr...(v=vs.85).aspx
    Marc Gregoire - NuonSoft (http://www.nuonsoft.com)
    My Blog
    Wallpaper Cycler 3.5.0.97

    Author of Professional C++, 4th Edition by Wiley/Wrox (includes C++17 features)
    ISBN: 978-1-119-42130-6
    [ http://www.facebook.com/professionalcpp ]

  7. #7
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Video player in vc++ (each frame being shown in a new window)

    Quote Originally Posted by hellSigma View Post
    I think this version of "Image.cpp" will make more sense :-
    Actually not much in the light of what you said above.

    First of all, this is not video player. It's rather image renderer, as I can see ReadImage reads from separate files, converts between color spaces and saves data for future rendering.

    Second, your window becomes dead immediately after first UpdateWindow call. Due to UpdateWindow the window procedure receives single WM_PAINT message, which creates first draw occurrence. And what's next? To react to user input events, message pump must exist, exactly what Marc already pointed out. Okay, imagine you have the pump. What is your plan for animating your view?

    Code:
    	while(1)
    	{
    
    		if(myImage.playFlag==1)
    		{
    			myImage.ReadImage();
    			myImage.ConvertYUVtoRGB();
    		}
    
    		// Code to update the window to be added here. How to use WndProc for updating?
    	}
    Again, imagine you solved window update issue. Look what your while loop does: it reads image, prepares it for rendering and renders one, doing all this without any timing, as fast as hard drive can read, CPU can calculate and video card can blit. Your movie is gonna end in a few moments. This is definitely not what you would expect, isn't it?

    So, what is your plan about animation?

    In this case whats happening is that InitInstance is being called once and a window is created but I don't know how to update the window with frames. I have WndProc function in my code. How exactly shall I call that function? As in with what parameters? And I shall do that in my while loop just after converting the frame to RGB format right?
    You never call window procedure directly. Never. Instead, you let Windows do that for you when message queu gets processed. To spin up the message queue processing you need to create Message Loop in your program and start dispatching messages coming to your program.

    Next step would be implementing some mechanism for processing images in timely fashion. The simplest approach would be window timer. You create timer with 100ms timeout (to play 10 frames per second), and on every timer event you synthesize the next image path, read the imape, prepare it for RGB colorspace, store data and invalidate your window. This invalidation results in Windows sending WM_PAINT message where you render the stored data. So all the process appears driven by timer events. It's important to understand that your program code execution must relinquish to let Windows properly do its part behind the scene.
    Best regards,
    Igor

  8. #8
    Join Date
    Jun 2012
    Posts
    8

    Re: Video player in vc++ (each frame being shown in a new window)

    ok!!!
    Last edited by hellSigma; July 25th, 2012 at 06:57 PM.

  9. #9
    Join Date
    Nov 2000
    Location
    Voronezh, Russia
    Posts
    6,633

    Re: Video player in vc++ (each frame being shown in a new window)

    You really need to get rid of your current idea of reading/rendering images inside your message loop (which looks scary now ). Instead, you need a classic message loop, and your image stuff moved to timer handler.
    Best regards,
    Igor

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured