Jump to content

  • Log In with Google      Sign In   
  • Create Account


Playing Video FIles with SMPEG


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • This topic is locked This topic is locked
9 replies to this topic

#1 Drew_Benton   Crossbones+   -  Reputation: 1713

Like
1Likes
Like

Posted 01 October 2005 - 04:30 AM

Ok since I've always seen this question come up quite a lot of the past year, and no one has been able to find out how to do this on the Windows platform, I've written a complete tutorial for all you guys and gals that need to play MPEG files with SDL. Online Tutorial Word Document Fairly straight forward, I tried to explain everything for even a beginner at SDL. It is assumed though you do have expeirence with SDL and C++. If anyone runs into any troubles with it, let me know of what I can fix. Just be aware of the license SMPEG uses before you use it and distribute it. Enjoy! Screenshots: Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us Free Image Hosting at www.ImageShack.us BTW - the quality shown is of the actual trailer itself, it was made to look that way, so don't think the quiality for all are bad. It's actually really good, and if you got a different file to use, you'll see what I mean. Oh and I made a mistake I will fix, it's HitMan 4, not 3 that I used.
Quote:
Original post by Eitsch nice - amazing!!! your complete package is not available but it does nto matter.
Thanks for pointing that out, I will be working on updating everything soon, so for the time being, you can get the complete package here 12-20-05: Links fixed in both documents now [Edited by - Drew_Benton on December 20, 2005 8:17:30 PM]

Sponsor:

#2 Rob Loach   Moderators   -  Reputation: 1500

Like
0Likes
Like

Posted 01 October 2005 - 08:18 AM

Nicely done! Maybe one day you should put up a little link to it on your website, haha. Also, get a screenshot up there! You can't have enough screenshots in an online tutorial [wink]. Well done, Drew.

Rob Loach [Website] [Projects] [Contact]

#3 Drew_Benton   Crossbones+   -  Reputation: 1713

Like
0Likes
Like

Posted 01 October 2005 - 08:37 AM

[smile] Oh yea, well I do need to add it to my *real webpage*. Actually the only reason I didn't put it up there yet was not to eat bandwith, might as well let my University handle that [wink]. But I did not think about adding screen shots, thanks for that suggestion. I'll get those made and uploaded right away. Thanks! I'll also fix the content on the tutorial as well.

"But I, being poor, have only my dreams. I have spread my dreams under your feet; tread softly, because you tread on my dreams." - William Butler Yeats

#4 Silent Angel   Members   -  Reputation: 136

Like
0Likes
Like

Posted 03 November 2005 - 08:38 AM

Very nice tutorial, congratulations!

It helped me a lot :-D

#5 __win__   Members   -  Reputation: 188

Like
0Likes
Like

Posted 03 December 2005 - 07:58 PM

nice - amazing!!! your complete package is not available but it does nto matter.

[Edited by - Eitsch on December 4, 2005 2:58:25 AM]

#6 WillPash   Members   -  Reputation: 211

Like
0Likes
Like

Posted 06 December 2005 - 07:56 AM

Hi I was just wondering if anybody knows how to render the video onto a OpenGL texture using SDL and SMPEG, just like Nehe Lesson 35, the AVI video rendering version. How do you load it in SDL through to a OpenGL context, and all the messy GL bits...? Im a newie to SDL...


#7 Drew_Benton   Crossbones+   -  Reputation: 1713

Like
0Likes
Like

Posted 02 January 2006 - 10:38 AM

Ok I've already talked to Will about doing that, but I'll go ahead and post it here if anyone else was interested.

Referring back to this thread which has a SDL_Movie wrapper made, I added in the OpenGL specifics. The key thing to note is that when you convert the SDL_Surface to the texture, you cannot use Steinsoft's as is. It took me 30 minutes to figure out that when you are working with these movie files, you have to instead use: gluBuild2DMipmaps(GL_TEXTURE_2D,4,bmpFile->w, bmpFile->h,GL_BGRA_EXT, GL_UNSIGNED_BYTE,bmpFile->pixels); Note the 4 and the GL_BGRA! Otherwise the movie is distorted and does not work correctly. Here is the complete code example, you can refer to other thread on this if you want the tutorial and the movie for it.


// Header files for SDL
#include "SDL.h"
#include "sdl_opengl.h"

// This is the header file for the library
#include "smpeg.h"

// Link in the needed libraries
#pragma comment( lib, "sdlmain.lib")
#pragma comment( lib, "sdl.lib")
#pragma comment(lib, "opengl32.lib")
#pragma comment(lib, "glu32.lib")
#pragma comment( lib, "smpeg.lib")

SDL_Surface *MirrorSurfaceY( SDL_Surface *screen );
SDL_Surface *MirrorSurfaceX( SDL_Surface *screen );

class SDL_Movie
{
private:
// Surface for the main screen
SDL_Surface *screen;

// Surface for the movie
SDL_Surface *movieSurface;

// Holds the movie information
SMPEG_Info movieInfo;

// Load the movie
SMPEG *movie;

// The max we can scale by
int MaxScaleX;
int MaxScaleY;
int MaxScale;

// Locations on screen to draw at
int X, Y;

void DrawIMG(SDL_Surface *img, int x, int y)
{
SDL_Surface* bmpFile = MirrorSurfaceX(img);
GLuint texture;

/* 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.0f,0.0f,-5.0f);
glBegin(GL_QUADS);
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();
glPopMatrix();
glDeleteTextures(1, &texture);
}

public:
SDL_Movie()
{
MaxScaleX = MaxScaleY = MaxScale = 1;

screen = 0;
movieSurface = 0;
movie = 0;
X = Y = 0;
}

// Free our movie
~SDL_Movie()
{
Stop();
SMPEG_delete( movie );
movie = 0;
SDL_FreeSurface( movieSurface );
movieSurface = 0;
}

void ClearScreen()
{
SDL_FillRect( movieSurface, 0, 0 );
}

// Set's the volume on a scale of 0 - 100
void SetVolume( int vol )
{
SMPEG_setvolume( movie, vol );
}

// Scale the movie by the desired factors
void Scale( int w, int h )
{
// Prevent a divide by 0
if( w == 0 )
w = 1;
if( h == 0 )
h = 1;

SMPEG_scaleXY( movie, w, h );
#ifdef _DEBUG
CheckErrors();
#endif
}

// Scale the movie by the desired factor
void ScaleBy( int factor )
{
// Prevent a divide by 0
if( factor == 0 )
factor = 1;
// Make sure we don't scale larger than the surface size
if( factor > MaxScale )
factor = MaxScale;

SMPEG_scale( movie, factor );
#ifdef _DEBUG
CheckErrors();
#endif
}

// Sets the region of the video to be shown
void SetDisplayRegion( int x, int y, int w, int h )
{
SMPEG_setdisplayregion( movie, x, y, w, h );
#ifdef _DEBUG
CheckErrors();
#endif
}

// Set the position that the movie should be drawn at on the screen
void SetPosition( int x, int y )
{
X = x;
Y = y;
}

// Check for any errors
void CheckErrors()
{
char* error = SMPEG_error( movie );
if( error )
printf( "Error: %s\n", error );
}

// Load the movie
void Load( const char* fileName, SDL_Surface* s, int maxscalex = 1, int maxscaley = 1 )
{
MaxScaleX = maxscalex;
MaxScaleY = maxscaley;

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

// Assign the screen surface
screen = s;

// Load the movie and store the information about it
movie = SMPEG_new( fileName, &movieInfo, true );

#ifdef _DEBUG
CheckErrors();
#endif

// Create a temporary surface to render the movie to
SDL_Surface *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, 0, 0 );

#ifdef _DEBUG
CheckErrors();
#endif

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

#ifdef _DEBUG
CheckErrors();
#endif
}

// Set the looping of hte movie
void SetLoop( int val )
{
SMPEG_loop( movie, val );
#ifdef _DEBUG
CheckErrors();
#endif
}

// Play the movie
void Play()
{
SMPEG_play( movie );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Pause the movie
void Pause()
{
SMPEG_pause( movie );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Stops the movie, but keeps current position
void Stop()
{
SMPEG_stop( movie );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Rewind the movie back to 0:00:00
void Rewind()
{
SMPEG_rewind( movie );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Seek a number of bytes into the movie
void Seek( int bytes )
{
SMPEG_seek( movie, bytes );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Skip a number of seconds
void Skip( float seconds )
{
SMPEG_skip( movie, seconds );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Render some frame of the movie
void RenderFrame( int frame )
{
SMPEG_renderFrame( movie, frame );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Render the final frame of the movie
void RenderFinal()
{
SMPEG_renderFinal( movie, movieSurface, 0, 0 );

#ifdef _DEBUG
CheckErrors();
#endif
}

// Draw the movie surface to the main screen at x, y
void DisplayAt( int x, int y )
{
DrawIMG( movieSurface, x, y );
}

// Draw the movie surface to the main screen at x, y
void Display()
{
DrawIMG( movieSurface, X, Y );
}

// Return the current info for the movie
SMPEG_Info GetInfo()
{
SMPEG_getinfo( movie, &movieInfo );
return movieInfo;
}

// Get the current status of the movie, can be SMPEG_ERROR = -1, SMPEG_STOPPED, SMPEG_PLAYING
SMPEGstatus GetStatus()
{
return SMPEG_status(movie);
}
};

int main( int argc, char *argv[] )
{
if ( SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0 )
{
printf("Unable to init SDL: %s\n", SDL_GetError());
return -1;
}
atexit(SDL_Quit);

SDL_Surface* screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL );
if ( screen == NULL )
{
printf("Unable to set 640x480 video: %s\n", SDL_GetError());
return -1;
}

// OpenGL settings
glEnable(GL_TEXTURE_2D);
glClearColor(0, 0, 0, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);

// 3D view in OpenGL
glViewport(0, 0, 640, 480);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)640/(GLfloat)480, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// The movie variable
SDL_Movie mov1;

// Load the specified file and draw it to the 'screen' surface
// In this case, we are allowed to scale the X and Y dimensions by 2 maximually
mov1.Load( "demo.mpg", screen, 2, 2 );

// Set the display at
//mov1.SetPosition( 100, 100 );

// Scale the movie by 2
mov1.ScaleBy( 2 );

// Event variable
SDL_Event event;

// Loop flag
int done = 0;

// Key structure
Uint8* keys;

while(done == 0)
{
// Simple event loop
while ( SDL_PollEvent(&event) )
{
if ( event.type == SDL_QUIT ) { done = 1; }

if ( event.type == SDL_KEYDOWN )
{
if ( event.key.keysym.sym == SDLK_ESCAPE ) { done = 1; }
}
}

// Update key states
keys = SDL_GetKeyState( 0 );

// Play
if( keys[SDLK_p] )
{
mov1.Play();
keys[SDLK_p] = 0;
}

// Pause
if( keys[SDLK_a] )
{
mov1.Pause();
keys[SDLK_a] = 0;
}

// Stop
if( keys[SDLK_s] )
{
mov1.Stop();

// If we stop, we want to start from the beginning again
mov1.Rewind();

// Clear the movie surface so it's no longer showing the last frame
mov1.ClearScreen();

keys[SDLK_s] = 0;
}

// Rewind
if( keys[SDLK_r] )
{
mov1.Rewind();
keys[SDLK_r] = 0;
}

// NOTE: DOES NOT WORK
if( keys[SDLK_LEFT] )
{
// Still trying to figure this one out, how to go backwards
mov1.Skip( -.5 );
keys[SDLK_LEFT] = 0;
}

// Skip forward .5 seconds in the movie
if( keys[SDLK_RIGHT] )
{
mov1.Skip( .5 );
keys[SDLK_RIGHT] = 0;
}

// Clear the main screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();

// Display the movie at the internal location (setposition)
//if( mov1.GetStatus() == SMPEG_PLAYING )
mov1.Display();

// Display the movie at a specified location
//mov1.DisplayAt( 0, 0 );

// Flip the main screen
glFlush();
SDL_GL_SwapBuffers();
}

return 0;
}

// Created from Docs/Cone3D's code
void SetPixelU32(SDL_Surface *screen, int x, int y, Uint32 newcolor)
{
Uint8 *ubuff8;
Uint16 *ubuff16;
Uint32 *ubuff32;
Uint32 color = newcolor;
char c1, c2, c3;

/* Lock the screen, if needed */
if(SDL_MUSTLOCK(screen))
{
if(SDL_LockSurface(screen) < 0)
return;
}

/* How we draw the pixel depends on the bitdepth */
switch(screen->format->BytesPerPixel)
{
case 1:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + x;
*ubuff8 = (Uint8) color;
break;

case 2:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + (x*2);
ubuff16 = (Uint16*) ubuff8;
*ubuff16 = (Uint16) color;
break;

case 3:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y * screen->pitch) + (x*3);

if(SDL_BYTEORDER == SDL_LIL_ENDIAN)
{

c1 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c3 = (color & 0x0000FF);
}
else
{
c3 = (color & 0xFF0000) >> 16;
c2 = (color & 0x00FF00) >> 8;
c1 = (color & 0x0000FF);
}

ubuff8[0] = c3;
ubuff8[1] = c2;
ubuff8[2] = c1;
break;

case 4:
ubuff8 = (Uint8*) screen->pixels;
ubuff8 += (y*screen->pitch) + (x*4);
ubuff32 = (Uint32*)ubuff8;
*ubuff32 = color;
break;

default:
fprintf(stderr, "Error: Unknown bitdepth!\n");
}

/* Unlock the screen if needed */
if(SDL_MUSTLOCK(screen))
{
SDL_UnlockSurface(screen);
}
}

Uint32 GetPixelU32(SDL_Surface* surface, int x, int y)
{
int bpp = surface->format->BytesPerPixel;
Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
switch(bpp)
{
case 1:
return *p;
case 2:
return *(Uint16 *)p;
case 3:
if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
return p[0] << 16 | p[1] << 8 | p[2];
else
return p[0] | p[1] << 8 | p[2] << 16;
case 4:
return *(Uint32 *)p;
default:
return 0;
}
}

SDL_Surface *MirrorSurfaceX( SDL_Surface *screen )
{
SDL_Surface* newimg = SDL_CreateRGBSurface( SDL_HWSURFACE, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);

for( int y = 0; y < screen->h; y++ )
{
for( int x = 0; x < screen->w; x++ )
{
SetPixelU32( newimg, x, y, GetPixelU32( screen, x, screen->h - y - 1 ) );
}
}

return newimg;
}

SDL_Surface *MirrorSurfaceY( SDL_Surface *screen )
{
SDL_Surface* newimg = SDL_CreateRGBSurface( SDL_HWSURFACE, screen->w, screen->h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);

for( int y = 0; y < screen->h; y++ )
{
for( int x = 0; x < screen->w; x++ )
{
SetPixelU32( newimg, x, y, GetPixelU32( screen, screen->w - x - 1, y ) );
}
}

return newimg;
}



Now that should all work, but as you will see when you run it, it is very slow. The reason is because (from my PM):
Quote:

First, you can take a look at this link for the general approach to converting a SDL_Surface* to a Opengl texture. That works for the most part, but the image ends up flipped and mirrored. You can take a look at my post here to see how you can easily fix that, but here lies the problem. If each frame, you load a SDL_Surface from a movie file, which takes A time, then you have to flip those pixels, which will take B time, then you have to convert that surface to an OpenGL texture, which takes C time, to which afterwards you still have to bind the texture and draw it, which takes D time, and you're still not done because you have to free that texture, which takes E time, you have quite a lot of overhead for this process. Needless to say, if you have a larger movie to render, then your frame rate will probabally roll over and die! If you have a smaller movie file it could be do-able, but maybe not to the best of your interests for your program.


So using SMPEG though SDL to get to OpenGL is definitly not the way to go! I have a rather above average computer, and it was running rather 'unnatural' for me as well. Your best bet is to opt for something that can be used natively with OpenGL. On one of those threads, another mention was made to another library, but I've never used it yet, but chances are you'd get better results with that over this.

"But I, being poor, have only my dreams. I have spread my dreams under your feet; tread softly, because you tread on my dreams." - William Butler Yeats

#8 mangshe0   Members   -  Reputation: 122

Like
0Likes
Like

Posted 26 October 2008 - 06:56 PM

i want to ask a quesetion, this time i did some program use SDL,and i want use it to play video, i find must to use smpeg, so i down load some file, it include .cpp .dll and so on,but donot have .lib,
i work in windows, i cannot untie package about liunx ,
so is smpeg must on liunx? and the smpeg.lib live on liunx?
or is i donot find right?
please tell me thank you very much, thanks a lot.
if you know the smpeg.lib down load address(internet),can you pass it to me?
or send the file to me.
my email:mangshe0@163.com
thankyou very much
and i am sorry my english......谢谢



#9 MidiWaffle   Members   -  Reputation: 96

Like
-1Likes
Like

Posted 02 March 2012 - 08:25 PM

The online tutorial doesn't exist anymore, and the word document just links to a bunch of other files that don't exist. Why didn't you just copy the text of the tutorial into the document instead of adding all these useless forms and links. This tutorial is utterly useless until you fix this.

#10 Hodgman   Moderators   -  Reputation: 28522

Like
0Likes
Like

Posted 04 March 2012 - 11:44 PM

The online tutorial doesn't exist anymore, and the word document just links to a bunch of other files that don't exist. Why didn't you just copy the text of the tutorial into the document instead of adding all these useless forms and links. This tutorial is utterly useless until you fix this.

You're about six years too late.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS