Sign in to follow this  

Multi format movie playing

This topic is 3735 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, My first post!! YAY. I've spent the last day googling for different movie libraries that could be used with either OpenGL or SDL on Windows XP. There are a few that standout; mplayer and Fmmpeg. I'd like to write an opengl app that places movies (especially AVI, divx, xvid, mpeg2, mpeg) into rotating cubes/texture. Having looked and played with the mplayer, it looks ideal (handles a lot of formats), but is driven either by command line or via an interactive method of calling. This would be good, but it renders directly to the screen (ie, I can see no way of grabbing frames and painting onto a texture). Has anyone written a tutorial/code that links directly to mplayer and uses its functions as I would like? I'm half tempted to learn some of the code to write my own controller (but that's a lot of code to read!). Any thoughts on this or a better alternative? I'd like to use a library that is o/s independent, but I'm willing to stick to XP (Directx) if I have to... Any response would be appreciated. Regards Sp33dy

Share this post


Link to post
Share on other sites
I am also interested in this topic so maybe we could work something out together?

Somewhere I found some code to render a video to a texture using ffmpeg (mplayer uses ffmpeg too I think).
I will look if I can find it and give you the link


ffmpeg
This should be a good starting point but it is only for playing videos in an sdl window (using ans YUV overlay). So you (we) have to modify this code so that it can render the video to a texture

Share this post


Link to post
Share on other sites
Hi there madRenEGadE,

Yes, I'd read that article. I've also looked at the opengl article from nehe's site:

NeHe Avi tutorial 35

I was impressed with nehe's and the ffmpeg examples. Nehe's is as close to what I want and might be the starting point. Trying to add in additional codec's to it, but that seems a lot of work. The MPlayer is truely great, astonishing compatability and very fast rendering. Why I thought it must be possible to reuse the code, but directly rather than through the command line structure. It's a shame that package doesn't provide an option to return each frame into the opengl/sdl texture that is to be wrapped by a 3d object.

Just my thoughts. Yes, I certainly am going to find sometime to hack around. If you are about, I'd appreciate any updates you find. I'll do the same here.

Regards

Sp33dy

Share this post


Link to post
Share on other sites
Here is a part of my code, you must modify and clean it up to run, but it works. Caution its for OpenGL, but DirectX should be no problem.


if(av_open_input_file(&pFormatCtx, filename.c_str(), NULL, 0, NULL)!=0)
{
MessageBox(NULL,"av_open error","Error",MB_OK); // Couldn't open file
PostQuitMessage(0);
return 0;
}

if(av_find_stream_info(pFormatCtx)<0)
{
MessageBox(NULL,"No streams","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

unsigned int i;
videoStream = -1;

for(i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
{
videoStream=i;
break;
}
if(videoStream==-1)
{
MessageBox(NULL,"No video streams","Error",MB_OK);
PostQuitMessage(0);
return 0;
}
}

pCodecCtx=pFormatCtx->streams[videoStream]->codec;

AVCodec *pCodec;

pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
MessageBox(NULL,"No codec availaible","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

if(avcodec_open(pCodecCtx, pCodec)<0)
{
MessageBox(NULL,"Codec could not be opened","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

pFrameRGB=avcodec_alloc_frame();
pFrame=avcodec_alloc_frame();

numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
buffer=new uint8_t[numBytes];

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24,
pCodecCtx->width, pCodecCtx->height);
pSWSCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);




And here how to copy it ot the texture:


if(av_read_frame(pFormatCtx, &packet)>=0)
{
if(packet.stream_index==videoStream)
{
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);

if(frameFinished)
{
//sws_scale((AVPicture *)pFrameRGB, PIX_FMT_RGB24, (AVPicture*)pFrame, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);
sws_scale(pSWSCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
}
}
}
else
curr_frame = 0;

av_free_packet(&packet);




I hope it helps a bit. If you have questions, ask.

EDIT: Oops, forgot to post the texture update function, sorry.


glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,vid->GetWidth(),vid->GetHeight(),GL_RGB,GL_UNSIGNED_BYTE,(char*)pFrameRGB->data[0]);

Share this post


Link to post
Share on other sites
Thanks Red_falcon,

Very kind of you. I'll give it a play later. I'm tempted with either SDL or OpenGL (haven't got a concrete choice yet, although I'm aware SDL is over the top of OpenGL).

I hadn't thought of searching these here forums for ffmpeg, low and behold, another good thread:

ffmpeg on these forums

Starting to get some valid options to chase. I actually assumed ffmpeg was for mpeg only!!! Doh...

Regards

Sp33dy

Share this post


Link to post
Share on other sites
Right,

Well based on that, FFMpeg is the choice to try.

Now the question is (probably not for here, but you obviously have an opinion). Is it better to work with OpenGL (there are a good set of NeHe tutorials) or SDL. I know SDL is another wrapper. Just wondered if it makes it easier to move to another platform. Initially I'm developing for XP, but am considering a new Linux Box too....

Regards

Sp33dy

P.S. I'm a professional Java developer/Architect. Been a while since I coded in C/C++, but it won't take me long. Hence why these basic questions are coming out. Before I invest in the time, it's nice to have opinions of others..

Share this post


Link to post
Share on other sites
I have never used any wrappers, only native OpenGL and a couple of supporting libs. But if you want it to be portable then you can try SDL or something equal. I can't speak for Linux, cause i never tried to program for it.

Share this post


Link to post
Share on other sites
Why not use SDL AND OpenGL? I want to use ffmpeg for video playback in my game engine and
so I am using sdl for window creation and event handling and opengl for rendering.
It is very easy to port to other platforms.

Share this post


Link to post
Share on other sites
Ah ok,

The way I read it was that you either use OpenGL or SDL (which is another abstraction layer over OpenGL). If you use both, then I guess that is great.

So, my next step's:

1. Use the link above for other forum post to get to the link for how to compile FFMpeg etc.

2. Take a look again at NeHe's tutorial.

3. Take a look at the code kindly provided by Red_falcon.

4. See if I can get 2 & 3 working together.

I'm sure that is a good plan. Probably take a day or two as the wife is now home and I've signed off from work. Depends on how much blagging I can do to sit down with machine tonight.

I'll keep you posted.

Regards

Sp33dy

Share this post


Link to post
Share on other sites
No need to compile yourself, I had enough pain trying it, and failing of course;)

here you get ready compiled dll's and libs: http://arrozcru.no-ip.org/ffmpeg/
and they have a forum for ffmpeg.

Share this post


Link to post
Share on other sites
Red_falcon,

You there? Things have moved on nicely this morning. I've taken MeHe's tutorial 6 (rotating cube) and mashed it with your code (with help from the ffmpeg tutorial page above and details from MeHe 35 Tutorial).

I now have some code that runs a silent movie in a rotating cube (all sides). I'll chase the audio later, but I guess its a simliar technique (easy to figure out).

My problems?? :

1. GL_TEXTURE_RECTANGLE_ARB for


glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB,0,0,0,vid-&gt;GetWidth(),vid-&gt;GetHeight(),GL_RGB,GL_UNSIGNED_BYTE,(char*)pFrameRGB-&gt;data[0]);



It won't compile. I get "error C2065: 'GL_TEXTURE_RECTANGLE_ARB' : undeclared identifier". I've googled and can't find a suitable answer. Is it card related (not sure how the compiler knows about my card) or is it a missing LIB (I've got Visual Studio 2007, ffmpeg installed with stdin.h/inttypes.h extras etc). No other special libraries included.

2. I changed GL_TEXTURE_RECTANGLE_ARB to GL_TEXTURE_2D and have got things working. However, it's a miracle how its working!!! Why, because the movie is being played over the top of the texture that was being loaded by MeHe tutorial. If I remove any reference to the Texture, it all stops working. I can't figure out how to use the pFrameRGB->data copy (ie how to link it to its own texture). Any hints?

Thanks,

Sp33dy

P.S. I might solve before you get back to me.. Just rebooting machine :-(

P.P.S I will post code when it is running (although the code will not be neat).

[Edited by - sp33dy on September 20, 2007 10:44:10 AM]

Share this post


Link to post
Share on other sites
madRenEGadE/Red_falcon,

Ok, here is the very rough (take it at face value. I've left lots of junk in it and not cleaned up any memory leaks).

If you create a 1024x512.bmp and run with an avi (or any other supported movies) of 640x480 resolution, it works very well! In fact, its great to see all sides of the cube animated. I've learnt a lot from this experiment and I now need to learn how to scale the movie correctly, etc.

Thanks for the heads up!! It's exactly what I needed. I hope you find this useful.

NOTE: I did say previously this is a mash of MeHe's tutorial 6, 35 and the FFMpeg Tutorial. If anyone feel's this shouldn't be posted here. Please let me know and I'll remove.

Edit: Removed source, see next post..


[Edited by - sp33dy on September 20, 2007 2:17:53 PM]

Share this post


Link to post
Share on other sites
Guys, you there?

Here is the latest version. I've got rid of the loadBMP function and created a CreateEmptyTexture function which is called from init. Movie is loaded and displayed in the centre of each cube face.

However, HELP! Any thoughts? I've run out of time for today:

1. I set the Texture to 1024x1024 (I figure most movies will be 640x480). The next power of 2 is obviously 1024. I've tried to scale up with Sws_scale and have failed to find a way to scale up the movie. If I make the texture 512x512, I'm unable to scale down. Should I be able to?? Any thoughts.

Please note that some sizes are hardcoded in the code for now. I'd appreciate any thoughts. I was to deal with scaling first and then add sound (which I figure will be easier).


/*
* This Code Was Created By Jeff Molofee 2000
* A HUGE Thanks To Fredric Echols For Cleaning Up
* And Optimizing The Base Code, Making It More Flexible!
* If You've Found This Code Useful, Please Let Me Know.
* Visit My Site At nehe.gamedev.net
*/


#include <windows.h> // Header File For Windows
#include <stdio.h> // Header File For Standard Input/Output
#include <gl\gl.h> // Header File For The OpenGL32 Library
#include <gl\glu.h> // Header File For The GLu32 Library

//libs in : C:\Program Files\Microsoft SDKs\Windows\v6.0\Lib
//downloaded special stdint.h and intypes.h
//Added extern "c"

extern "C" {
#include <ffmpeg\avcodec.h>
#include <ffmpeg\avformat.h>
#include <ffmpeg\swscale.h>
}

HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application

bool keys[256]; // Array Used For The Keyboard Routine
bool active=TRUE; // Window Active Flag Set To TRUE By Default
bool fullscreen=TRUE; // Fullscreen Flag Set To Fullscreen Mode By Default

AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVFrame *pFrame;
AVFrame *pFrameRGB;

GLuint movieTexture;

GLfloat xrot; // X Rotation ( NEW )
GLfloat yrot; // Y Rotation ( NEW )
GLfloat zrot; // Z Rotation ( NEW )

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // Declaration For WndProc

GLuint CreateEmptyTexture(int width, int height) // Create An Empty Texture
{
GLuint txtnumber; // Texture ID
unsigned int* data; // Stored Data

data = (unsigned int*)new GLuint[((width * height)* 4 * sizeof(unsigned int))];
ZeroMemory(data,((width * height)* 4 * sizeof(unsigned int))); // Clear Storage Memory

glGenTextures(1, &txtnumber); // Create 1 Texture
glBindTexture(GL_TEXTURE_2D, txtnumber); // Bind The Texture
glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); // Build Texture Using Information In data
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

delete [] data; // Release data

return txtnumber; // Return The Texture ID
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0) // Prevent A Divide By Zero By
{
height=1; // Making Height Equal One
}

glViewport(0,0,width,height); // Reset The Current Viewport

glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
glLoadIdentity(); // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
glLoadIdentity(); // Reset The Modelview Matrix
}

int InitGL(GLvoid) // All Setup For OpenGL Goes Here
{
// movieTexture=CreateEmptyTexture(pCodecCtx->width,pCodecCtx->height);
movieTexture=CreateEmptyTexture(1024,1024);

glBindTexture(GL_TEXTURE_2D, movieTexture);

glEnable(GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
return TRUE; // Initialization Went OK
}

int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f);

glRotatef(xrot,1.0f,0.0f,0.0f);
glRotatef(yrot,0.0f,1.0f,0.0f);
glRotatef(zrot,0.0f,0.0f,1.0f);

glBindTexture(GL_TEXTURE_2D, movieTexture); // Select Our Texture
glTexSubImage2D(GL_TEXTURE_2D,0,(pCodecCtx->width)/2,(pCodecCtx->height)/2,pCodecCtx->width,pCodecCtx->height,GL_RGB,GL_UNSIGNED_BYTE,(char*)pFrameRGB->data[0]);

glBegin(GL_QUADS);
// Front Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
// Back Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Top Face
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Right face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();

xrot+=0.3f;
yrot+=0.2f;
zrot+=0.4f;
return TRUE; // Keep Going
}

GLvoid KillGLWindow(GLvoid) // Properly Kill The Window
{
if (fullscreen) // Are We In Fullscreen Mode?
{
ChangeDisplaySettings(NULL,0); // If So Switch Back To The Desktop
ShowCursor(TRUE); // Show Mouse Pointer
}

if (hRC) // Do We Have A Rendering Context?
{
if (!wglMakeCurrent(NULL,NULL)) // Are We Able To Release The DC And RC Contexts?
{
MessageBox(NULL,"Release Of DC And RC Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}

if (!wglDeleteContext(hRC)) // Are We Able To Delete The RC?
{
MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
}
hRC=NULL; // Set RC To NULL
}

if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC
{
MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hDC=NULL; // Set DC To NULL
}

if (hWnd && !DestroyWindow(hWnd)) // Are We Able To Destroy The Window?
{
MessageBox(NULL,"Could Not Release hWnd.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hWnd=NULL; // Set hWnd To NULL
}

if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class
{
MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);
hInstance=NULL; // Set hInstance To NULL
}
}

/* This Code Creates Our OpenGL Window. Parameters Are: *
* title - Title To Appear At The Top Of The Window *
* width - Width Of The GL Window Or Fullscreen Mode *
* height - Height Of The GL Window Or Fullscreen Mode *
* bits - Number Of Bits To Use For Color (8/16/24/32) *
* fullscreenflag - Use Fullscreen Mode (TRUE) Or Windowed Mode (FALSE) */


BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; // Holds The Results After Searching For A Match
WNDCLASS wc; // Windows Class Structure
DWORD dwExStyle; // Window Extended Style
DWORD dwStyle; // Window Style
RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values
WindowRect.left=(long)0; // Set Left Value To 0
WindowRect.right=(long)width; // Set Right Value To Requested Width
WindowRect.top=(long)0; // Set Top Value To 0
WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window.
wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc Handles Messages
wc.cbClsExtra = 0; // No Extra Window Data
wc.cbWndExtra = 0; // No Extra Window Data
wc.hInstance = hInstance; // Set The Instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer
wc.hbrBackground = NULL; // No Background Required For GL
wc.lpszMenuName = NULL; // We Don't Want A Menu
wc.lpszClassName = "OpenGL"; // Set The Class Name

if (!RegisterClass(&wc)) // Attempt To Register The Window Class
{
MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (fullscreen) // Attempt Fullscreen Mode?
{
DEVMODE dmScreenSettings; // Device Mode
memset(&dmScreenSettings,0,sizeof(dmScreenSettings)); // Makes Sure Memory's Cleared
dmScreenSettings.dmSize=sizeof(dmScreenSettings); // Size Of The Devmode Structure
dmScreenSettings.dmPelsWidth = width; // Selected Screen Width
dmScreenSettings.dmPelsHeight = height; // Selected Screen Height
dmScreenSettings.dmBitsPerPel = bits; // Selected Bits Per Pixel
dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;

// Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar.
if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
{
// If The Mode Fails, Offer Two Options. Quit Or Use Windowed Mode.
if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
{
fullscreen=FALSE; // Windowed Mode Selected. Fullscreen = FALSE
}
else
{
// Pop Up A Message Box Letting User Know The Program Is Closing.
MessageBox(NULL,"Program Will Now Close.","ERROR",MB_OK|MB_ICONSTOP);
return FALSE; // Return FALSE
}
}
}

if (fullscreen) // Are We Still In Fullscreen Mode?
{
dwExStyle=WS_EX_APPWINDOW; // Window Extended Style
dwStyle=WS_POPUP; // Windows Style
ShowCursor(FALSE); // Hide Mouse Pointer
}
else
{
dwExStyle=WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; // Window Extended Style
dwStyle=WS_OVERLAPPEDWINDOW; // Windows Style
}

AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle); // Adjust Window To True Requested Size

// Create The Window
if (!(hWnd=CreateWindowEx( dwExStyle, // Extended Style For The Window
"OpenGL", // Class Name
title, // Window Title
dwStyle | // Defined Window Style
WS_CLIPSIBLINGS | // Required Window Style
WS_CLIPCHILDREN, // Required Window Style
0, 0, // Window Position
WindowRect.right-WindowRect.left, // Calculate Window Width
WindowRect.bottom-WindowRect.top, // Calculate Window Height
NULL, // No Parent Window
NULL, // No Menu
hInstance, // Instance
NULL))) // Dont Pass Anything To WM_CREATE
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Window Creation Error.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be
{
sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor
1, // Version Number
PFD_DRAW_TO_WINDOW | // Format Must Support Window
PFD_SUPPORT_OPENGL | // Format Must Support OpenGL
PFD_DOUBLEBUFFER, // Must Support Double Buffering
PFD_TYPE_RGBA, // Request An RGBA Format
bits, // Select Our Color Depth
0, 0, 0, 0, 0, 0, // Color Bits Ignored
0, // No Alpha Buffer
0, // Shift Bit Ignored
0, // No Accumulation Buffer
0, 0, 0, 0, // Accumulation Bits Ignored
16, // 16Bit Z-Buffer (Depth Buffer)
0, // No Stencil Buffer
0, // No Auxiliary Buffer
PFD_MAIN_PLANE, // Main Drawing Layer
0, // Reserved
0, 0, 0 // Layer Masks Ignored
};

if (!(hDC=GetDC(hWnd))) // Did We Get A Device Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Device Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(PixelFormat=ChoosePixelFormat(hDC,&pfd))) // Did Windows Find A Matching Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Find A Suitable PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!SetPixelFormat(hDC,PixelFormat,&pfd)) // Are We Able To Set The Pixel Format?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Set The PixelFormat.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if (!(hRC=wglCreateContext(hDC))) // Are We Able To Get A Rendering Context?
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Create A GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

if(!wglMakeCurrent(hDC,hRC)) // Try To Activate The Rendering Context
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Can't Activate The GL Rendering Context.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

ShowWindow(hWnd,SW_SHOW); // Show The Window
SetForegroundWindow(hWnd); // Slightly Higher Priority
SetFocus(hWnd); // Sets Keyboard Focus To The Window
ReSizeGLScene(width, height); // Set Up Our Perspective GL Screen

if (!InitGL()) // Initialize Our Newly Created GL Window
{
KillGLWindow(); // Reset The Display
MessageBox(NULL,"Initialization Failed.","ERROR",MB_OK|MB_ICONEXCLAMATION);
return FALSE; // Return FALSE
}

return TRUE; // Success
}

LRESULT CALLBACK WndProc( HWND hWnd, // Handle For This Window
UINT uMsg, // Message For This Window
WPARAM wParam, // Additional Message Information
LPARAM lParam) // Additional Message Information
{
switch (uMsg) // Check For Windows Messages
{
case WM_ACTIVATE: // Watch For Window Activate Message
{
if (!HIWORD(wParam)) // Check Minimization State
{
active=TRUE; // Program Is Active
}
else
{
active=FALSE; // Program Is No Longer Active
}

return 0; // Return To The Message Loop
}

case WM_SYSCOMMAND: // Intercept System Commands
{
switch (wParam) // Check System Calls
{
case SC_SCREENSAVE: // Screensaver Trying To Start?
case SC_MONITORPOWER: // Monitor Trying To Enter Powersave?
return 0; // Prevent From Happening
}
break; // Exit
}

case WM_CLOSE: // Did We Receive A Close Message?
{
PostQuitMessage(0); // Send A Quit Message
return 0; // Jump Back
}

case WM_KEYDOWN: // Is A Key Being Held Down?
{
keys[wParam] = TRUE; // If So, Mark It As TRUE
return 0; // Jump Back
}

case WM_KEYUP: // Has A Key Been Released?
{
keys[wParam] = FALSE; // If So, Mark It As FALSE
return 0; // Jump Back
}

case WM_SIZE: // Resize The OpenGL Window
{
ReSizeGLScene(LOWORD(lParam),HIWORD(lParam)); // LoWord=Width, HiWord=Height
return 0; // Jump Back
}
}

// Pass All Unhandled Messages To DefWindowProc
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}

int WINAPI WinMain( HINSTANCE hInstance, // Instance
HINSTANCE hPrevInstance, // Previous Instance
LPSTR lpCmdLine, // Command Line Parameters
int nCmdShow) // Window Show State
{
av_register_all();

if(av_open_input_file(&pFormatCtx, "c:\\aburner.avi", NULL, 0, NULL)!=0)
{
MessageBox(NULL,"av_open error","Error",MB_OK); // Couldn't open file
PostQuitMessage(0);
return 0;
}

if(av_find_stream_info(pFormatCtx)<0)
{
MessageBox(NULL,"No streams","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

unsigned int i;
int videoStream = -1;

for(i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO)
{
videoStream=i;
break;
}
if(videoStream==-1)
{
MessageBox(NULL,"No video streams","Error",MB_OK);
PostQuitMessage(0);
return 0;
}
}

pCodecCtx=pFormatCtx->streams[videoStream]->codec;

AVCodec *pCodec;

pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
MessageBox(NULL,"No codec availaible","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

if(avcodec_open(pCodecCtx, pCodec)<0)
{
MessageBox(NULL,"Codec could not be opened","Error",MB_OK);
PostQuitMessage(0);
return 0;
}

pFrameRGB=avcodec_alloc_frame();
pFrame=avcodec_alloc_frame();

int numBytes=avpicture_get_size(PIX_FMT_RGB24, pCodecCtx->width,pCodecCtx->height);
uint8_t *buffer=new uint8_t[numBytes];

avpicture_fill((AVPicture *)pFrameRGB, buffer, PIX_FMT_RGB24, pCodecCtx->width, pCodecCtx->height);
SwsContext *pSWSCtx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_RGB24, SWS_FAST_BILINEAR, NULL, NULL, NULL);

MSG msg; // Windows Message Structure
BOOL done=FALSE; // Bool Variable To Exit Loop

// Ask The User Which Screen Mode They Prefer
if (MessageBox(NULL,"Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",MB_YESNO|MB_ICONQUESTION)==IDNO)
{
fullscreen=FALSE; // Windowed Mode
}

// Create Our OpenGL Window
if (!CreateGLWindow("NeHe's Texture Mapping Tutorial",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}

while(!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message==WM_QUIT) // Have We Received A Quit Message?
{
done=TRUE; // If So done=TRUE
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
else // If There Are No Messages
{
AVPacket packet;
int frameFinished;
int curr_frame;

if(av_read_frame(pFormatCtx, &packet)>=0)
{
if(packet.stream_index==videoStream)
{
avcodec_decode_video(pCodecCtx, pFrame, &frameFinished,packet.data, packet.size);

if(frameFinished)
{
sws_scale(pSWSCtx, pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
}
}
}
else curr_frame = 0;

av_free_packet(&packet);

// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done=TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}

if (keys[VK_F1]) // Is F1 Being Pressed?
{
keys[VK_F1]=FALSE; // If So Make Key FALSE
KillGLWindow(); // Kill Our Current Window
fullscreen=!fullscreen; // Toggle Fullscreen / Windowed Mode
// Recreate Our OpenGL Window
if (!CreateGLWindow("NeHe's Texture Mapping Tutorial",640,480,16,fullscreen))
{
return 0; // Quit If Window Was Not Created
}
}
}
}

// Shutdown
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program

// Free movie texture
glDeleteTextures(1,&movieTexture);

// Free sws context
av_free(pSWSCtx);

// Free the RGB image
av_free(buffer);
av_free(pFrameRGB);

// Free the YUV frame
av_free(pFrame);

// Close the codec
avcodec_close(pCodecCtx);

// Close the video file
av_close_input_file(pFormatCtx);
}

Share this post


Link to post
Share on other sites
Hi. Sorry had not much time cause i'm working on a project at the moment(the code i posted is from it :)). I use ARB_TEXTURE_RECTANGLE extension to display videos. The size of the videos is 1280x720, converted form MPEG-2 Transport Stream to Quicktime format.

Share this post


Link to post
Share on other sites
Hi sp33dy,

You do not need to create textures that are sqared (like 1024x1024).
Yust create one that fits your video size.
On old hardware it was a problem to use non-square textures but it should not be
a problem nowadays.

Should not your code to create an empty texture be something like this:


GLuint CreateEmptyTexture(int width, int height)
{
GLuint txtnumber;
unsigned char* data; // unsigned char instead of unsigned int

data = new unsigned char[((width * height)* 3 * sizeof(unsigned char))];
// 3 instead of 4 components cause you do not need alpha for videos I think
ZeroMemory(data,((width * height)* 3 * sizeof(unsigned char))); // Clear Storage Memory

glGenTextures(1, &txtnumber); // Create 1 Texture
glBindTexture(GL_TEXTURE_2D, txtnumber); // Bind The Texture
glTexImage2D(GL_TEXTURE_2D, 0, 3, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data); // Build Texture Using Information In data
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);

delete [] data; // Release data

return txtnumber; // Return The Texture ID
}

Share this post


Link to post
Share on other sites
There is one little error in your code. GL_TEXTURE_2D should be GL_TEXTURE_RECTANGLE_ARB(I hope i remember the sentence right).

EDIT: I suggest to take GLEW or GLEE for extensions, it takes a lot of work off you.

Share this post


Link to post
Share on other sites
Thats my original function:

void CreateEmptyTexture(unsigned int id, int bpp, int width, int height)
{
glEnable(GL_TEXTURE_RECTANGLE_ARB);

glBindTexture(GL_TEXTURE_RECTANGLE_ARB,id);

glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
//glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
//gluBuild2DMipmaps(GL_TEXTURE_2D, bpp, h, v, f, GL_UNSIGNED_BYTE, texdata);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB/*bpp*/, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

glBindTexture(GL_TEXTURE_RECTANGLE_ARB,NULL);
glDisable(GL_TEXTURE_RECTANGLE_ARB);
}

Share this post


Link to post
Share on other sites
Thanks for the updates guys. Been a very busy weekend for me.

I downloaded the Glee library and accessed the RECTANGLE_ARG function (which my card supports). I just don't get a video out, just a white cube.

I'm going to ship the code to another machine today to see if it is the machine or not. If it continues to be white then I'm going to cleanup the code and see if I can output a simple loaded BMP with that function.

Thanks for the help so far and i'll keep you posted.

Regards

Sp33dy

Share this post


Link to post
Share on other sites
Cool guys, I just have some questions and then I might try to get this to work in my own application.

What kind of codecs does it support? Does it support "every" codec that is installed on the computer? Does it support divx/xvid codecs? I guess there's no sound support in this code, right?

Share this post


Link to post
Share on other sites
Yeah there is no sound support in this code your are right.
But here it is described how you can
add sound support.

I do not know really what formats are supported but there are many (about 100 video and audio formats on my machine).

Maybe you can find something at their homepage
or you can run ffmpeg in a console with "-formats" as argument.

Share this post


Link to post
Share on other sites
>madRenEGadE,

That's interesting. You get a white box too.. Mmm. I tried running code on another server and get the same issue. I'm going to have a play with the options when I get a chance (not likely for a couple of days).

>BauerGL,

I've played Divx, XVid, Avi, Mpeg2 and mpeg so far. There is no sound support in the current code attached. However, I'm sure it wont be difficult to extract audio stream and pipe it out somehow. Just haven't got round to it yet. I want to make sure I have the movie playing well first.

Good luck and keep us updated..

Regards

Sp33dy

Share this post


Link to post
Share on other sites

This topic is 3735 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this