PDA

View Full Version : OpenGL example code wanted - OpenGL with OObased Video/Imag



cairnswm
16-04-2008, 07:23 PM
System: Windows XP (but would like cross platform)
Compiler/IDE: Delphi 7 - but would like working FPK cross compile Linux/MacOS
Libraries/API: OpenGL (would also accept a working example in DirectX 7 as the solution needs to work on "older" PCs)

Hi All

I am trying very hard to get a rather simple OpenGL example working. I require the folling to be working in my example

1. Open a OpenGL window
2. Using OO have the following components
2a. A video Class (Open AVI, Draw AVI at Location, Close AVI/Free)
2b. A Image/Texture Class (OpenFile, DrawImage at Location, Close File/Free)

I have been trying to modify the following internet examples to achieve this without much luck:

Sulaco OpenGL video example: http://www.sulaco.co.za/opengl_project_AVI_video_textures.htm

Tutorial 35 from Nehe:
http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=35

(Also tried adding the video concepts into other examples such as the Sulaco glWindows example - without any success).

Would some one out there be so kind as to build me a simple project that achieves these few goals. I am planning on building a Cross Platform Open Source, Multimedia Authoring tool. Images, and Video are my very simplest requirements for the application. Once I have these basic requirements working I will start adding the additional functionality such as transitions, buttons, slide show and scripting options.

My thanks to anyone that can help me out.

User137
17-04-2008, 08:43 AM
Are you making it purely 2D in ortho mode? The basic idea behind video rendering is to extract each video frame and load it as a texture to graphics card memory (btw this transfer is very slow). Don't know if buffering 5 or so frames help but it may be possible to use any "idle time" during playback to load as many frames in time allows. Either way, a simple TMediaplayer should greatly outperform a graphics card based videoplayer.

Drawing the frame itself in position, was it 2D or 3D is a trivial task. Using glBegin(GL_QUADS), glTexCoord2f(), glVertex2f(), finally glEnd().

Don't know the best way to loading a 2D image, made functions myself for each format like BMP, JPG, PNG, GIF. But there may be some public libraries available.

cairnswm
17-04-2008, 11:02 AM
I only need 2D

Both sites mentioned above have 2D texture examples, but like I say when I try to include video in the same project I just cant seem to get it right.

User137
17-04-2008, 12:24 PM
Would be fun having such a class too so went and tried
http://www.swissdelphicenter.ch/torry/showcode.php?id=1180

Got as far as showing AVI details, length, framerate etc but when attempting to load frame it fails. Don't know if that VFW.pas is outdated but i rechecked and downloaded all needed codecs for my Test.avi which shows on vlc-player and windows mediaplayer.

I also noticed that nehe example used VFW.

savage
17-04-2008, 06:45 PM
I only need 2D

Both sites mentioned above have 2D texture examples, but like I say when I try to include video in the same project I just cant seem to get it right.

When you say "get it right" what exactly is going wrong? Does it crash, does it draw incorrectly?

Btw, Jan Horn's AVLens demo crashes on my machine. Does it on anyone else's?

savage
17-04-2008, 07:39 PM
Btw, have you seen the SDL/smpeg/OpenGL example here...
http://www.gamedev.net/community/forums/post.asp?method=reply&topic_id=348801

Well this is the class used in there converted...


unit SDLMovie;

interface

uses
sdl,
gl,
glu,
glext,
smpeg;

type
TSDLMovie = class
private
// Surface for the main screen
screen : PSDL_Surface;

// Surface for the movie
movieSurface : PSDL_Surface;

// Holds the movie information
movieInfo : SMPEG_Info;

// Load the movie
movie : PSMPEG;

// The max we can scale by
MaxScaleX, MaxScaleY, MaxScale : integer;

// Locations on screen to draw at
X, Y : integer;

procedure DrawIMG( img : PSDL_Surface; X, Y : integer );

public
constructor Create;


// Free our movie
destructor Destroy; override;


procedure ClearScreen;

// Set's the volume on a scale of 0 - 100
procedure SetVolume( vol : integer );


// Scale the movie by the desired factors
procedure Scale( w, h : integer );


// Scale the movie by the desired factor
procedure ScaleBy( factor : integer );

// Sets the region of the video to be shown
procedure SetDisplayRegion( x, y, w, h : integer );

// Set the position that the movie should be drawn at on the screen

procedure SetPosition( ax, ay : integer );


// Check for any errors

procedure CheckErrors;

// Load the movie
procedure Load( const fileName : string; s : PSDL_Surface; maxscalex : integer = 1; maxscaley : integer = 1 );

// Set the looping of hte movie

procedure SetLoop( val : integer );

// Play the movie

procedure Play;

// Pause the movie

procedure Pause;

// Stops the movie, but keeps current position

procedure Stop;

// Rewind the movie back to 0:00:00

procedure Rewind;

// Seek a number of bytes into the movie

procedure Seek( bytes : integer );

// Skip a number of seconds

procedure Skip( seconds : single );


// Render some frame of the movie

procedure RenderFrame( frame : integer );


// Render the final frame of the movie

procedure RenderFinal;


// Draw the movie surface to the main screen at x, y

procedure DisplayAt( x, y : integer );

// Draw the movie surface to the main screen at x, y

procedure Display;


// Return the current info for the movie
function GetInfo : SMPEG_Info;

// Get the current status of the movie, can be SMPEG_ERROR = -1, SMPEG_STOPPED, SMPEG_PLAYING
function GetStatus : SMPEGstatus;
end;

implementation

{ TSDLMovie }

procedure TSDLMovie.CheckErrors;
begin
// Maybe out put to logger
{ char* error = SMPEG_error( movie );
if( error )
printf( "Error: %s\n", error ); }
end;

procedure TSDLMovie.ClearScreen;
begin
SDL_FillRect( movieSurface, 0, 0 );
end;

constructor TSDLMovie.Create;
begin
MaxScaleX := 1;
MaxScaleY := 1;
MaxScale := 1;

screen := nil;
movieSurface := nil;
movie := nil;
X := 0;
Y := 0;
end;

destructor TSDLMovie.Destroy;
begin
Stop;
SMPEG_delete( movie );
movie := nil;
SDL_FreeSurface( movieSurface );
movieSurface := nil;
inherited;
end;

procedure TSDLMovie.Display;
begin
DrawIMG( movieSurface, X, Y );
end;

procedure TSDLMovie.DisplayAt( x, y : integer );
begin
DrawIMG( movieSurface, x, y );
end;

procedure TSDLMovie.DrawIMG( img : PSDL_Surface; X, Y : integer );
var
bmpFile : PSDL_Surface;
texture : GLuint;
begin
//SDL_Surface* bmpFile = MirrorSurfaceX(img);
bmpFile := img;

// Standard OpenGL texture creation code
// glPixelStorei( GL_UNPACK_ALIGNMENT, 4 );

glGenTextures( 1, @texture );
glBindTexture( GL_TEXTURE_2D, texture );

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 0 );
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 0 );

gluBuild2DMipmaps( GL_TEXTURE_2D, 4, bmpFile.w, bmpFile.h, GL_BGRA_EXT, GL_UNSIGNED_BYTE, bmpFile.pixels );

//Free surface after using it
SDL_FreeSurface( bmpFile );

glBindTexture( GL_TEXTURE_2D, texture );
glPushMatrix;
glTranslatef( 0.0, 0.0, -5.0 );
glBegin( GL_QUADS );
glTexCoord2f( 0.0, 0.0 ); glVertex3f( -1.0, -1.0, 1.0 );
glTexCoord2f( 1.0, 0.0 ); glVertex3f( 1.0, -1.0, 1.0 );
glTexCoord2f( 1.0, 1.0 ); glVertex3f( 1.0, 1.0, 1.0 );
glTexCoord2f( 0.0, 1.0 ); glVertex3f( -1.0, 1.0, 1.0 );
glEnd;
glPopMatrix;
glDeleteTextures( 1, @texture );
end;

function TSDLMovie.GetInfo : SMPEG_Info;
begin
SMPEG_getinfo( movie, @movieInfo );
result := movieInfo;
end;

function TSDLMovie.GetStatus : SMPEGstatus;
begin
result := SMPEG_status( movie );
end;

procedure TSDLMovie.Load( const fileName : string; s : PSDL_Surface;
maxscalex, maxscaley : integer );
var
tempSurface2 : PSDL_Surface;
begin
MaxScaleX := maxscalex;
MaxScaleY := maxscaley;

// Limit how much we can scale by
if ( maxscalex > maxscaley ) then
MaxScale := maxscaley
else
MaxScale := maxscalex;

// Assign the screen surface
screen := s;

// Load the movie and store the information about it
movie := SMPEG_new( PChar( fileName ), @movieInfo, 0 );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}

// Create a temporary surface to render the movie to
tempSurface2 := SDL_CreateRGBSurface( SDL_SWSURFACE, movieInfo.width * MaxScaleX, movieInfo.height * MaxScaleY, 32, screen.format.Rmask, screen.format.Gmask, screen.format.Bmask, screen.format.Amask );

// Now make a surface optimized for the main screen
movieSurface := SDL_DisplayFormat( tempSurface2 );

// Free the temporary surface
SDL_FreeSurface( tempSurface2 );

// Set the surface to draw to
SMPEG_setdisplay( movie, movieSurface, nil, nil );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}

// Set the display region
SMPEG_setdisplayregion( movie, 0, 0, movieInfo.width, movieInfo.height );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Pause;
begin
SMPEG_pause( movie );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Play;
begin
SMPEG_play( movie );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.RenderFinal;
begin
SMPEG_renderFinal( movie, movieSurface, 0, 0 );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.RenderFrame( frame : integer );
begin
SMPEG_renderFrame( movie, frame );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Rewind;
begin
SMPEG_rewind( movie );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Scale( w, h : integer );
begin
// Prevent a divide by 0
if ( w = 0 ) then
w := 1;
if ( h = 0 ) then
h := 1;

SMPEG_scaleXY( movie, w, h );
{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.ScaleBy( factor : integer );
begin
// Prevent a divide by 0
if ( factor = 0 ) then
factor := 1;
// Make sure we don't scale larger than the surface size
if ( factor > MaxScale ) then
factor := MaxScale;

SMPEG_scale( movie, factor );
{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Seek( bytes : integer );
begin
SMPEG_seek( movie, bytes );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.SetDisplayRegion( x, y, w, h : integer );
begin
SMPEG_setdisplayregion( movie, x, y, w, h );
{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}

end;

procedure TSDLMovie.SetLoop( val : integer );
begin
SMPEG_loop( movie, val );
{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.SetPosition( ax, ay : integer );
begin
X := ax;
Y := ay;
end;

procedure TSDLMovie.SetVolume( vol : integer );
begin
SMPEG_setvolume( movie, vol );
end;

procedure TSDLMovie.Skip( seconds : single );
begin
SMPEG_skip( movie, seconds );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

procedure TSDLMovie.Stop;
begin
SMPEG_stop( movie );

{$IFDEF _DEBUG}
CheckErrors;
{$ENDIF}
end;

end.


It's not tested, but it does compile.

grudzio
17-04-2008, 07:46 PM
Btw, Jan Horn's AVLens demo crashes on my machine. Does it on anyone else's?
It crashes on mine.



I am planning on building a Cross Platform Open Source, Multimedia Authoring tool.

If it is going to be cross platform You probably should use smpeg (or other cross platform video library).
There is a demo how to use smpeg with OpenGL in the JEDI_SDL package.

EDIT: Sorry, I didn't noticed it was already pointed out by Savage

savage
17-04-2008, 08:05 PM
There is a demo how to use smpeg with OpenGL in the JEDI_SDL package.

EDIT: Sorry, I didn't noticed it was already pointed out by Savage

Damn, I totally forgot that I had ported the glmovie example :o).

cairnswm
18-04-2008, 05:18 AM
Thanks guys

I first tried to do the whole concept in SDL, and had it working (except video but did play with the video samples) but due to the scaling etc that is needed I decided that the SDL only version wasn't going to work for this need.

Another problem with SDL is the number of DLLs that need to be distributed.

So that made me decide to try for a native OpenGL option but I cant get it working.

The problem for me with the demos from Sulaco is this line:
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, AviInfo.dwWidth, AviInfo.dwHeight, GL_RGB, GL_UNSIGNED_BYTE, Framedata);

Whenever I move it into a TVideo class it hangs the program. If I leave it as
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, Video.AviInfo.dwWidth, Video.AviInfo.dwHeight, GL_RGB, GL_UNSIGNED_BYTE, Video.Framedata);
(ie calling the objects inside the object instead of being inside the object Video being an existing instance of TVideo)
it works fine. As you know I don't like fiddling with Game Engine type stuff (I'm not clever enough :) ) so I just want it working :).

PS. If the demos dont work try changing this (or similar) line in GetAVIFrame
if AVIElapsedTime > AVILength then
to
if AVIElapsedTime >= AVILength then
Seemed to work for me in both demos that errored. (but I think the last frame in each video is then missing)


Maybe I should try add the smpeg with opengl option to my S2DL libraries and then use that for the Authoring Software. (Currently S2DL works with JEDI-SDL and OpenGL or with Phoenix2D lib as base renderer)


Cheers