unit USmpeg; interface uses SDL, smpeg, gl, glu, glext, SysUtils, UIni; procedure OpenSmpeg(FileName: string); procedure SkipSmpeg(Time: single); procedure PlaySmpeg; procedure PauseSmpeg; //PauseMod procedure UpdateSmpeg; procedure CloseSmpeg; function glmovie_init(Width : GLuint; Height : GLuint ) : GLenum; procedure glmpeg_update(surface: PSDL_Surface; x: Sint32; y: Sint32; w: Uint32; h: Uint32); cdecl; procedure DrawSmpeg(frame: PGLubyte); procedure glmovie_resize( width : GLuint; height : GLuint ); procedure glmovie_quit; var mpeg: PSMPEG; mpeg_info: TSMPEG_Info; surface: PSDL_Surface; type { Some data is redundant at this stage. } PGLMovieTexture = ^TGLMovieTexture; TGLMovieTexture = record id : GLuint; (* OpenGL texture id. *) poly_width : GLuint; (* Quad width for tile. *) poly_height : GLuint; (* Quad height for tile. *) movie_width : GLuint; (* Width of movie inside tile. *) movie_height : GLuint; (* Height of movie inside tile. *) skip_rows : GLuint; (* Number of rows of movie to skip *) skip_pixels : GLuint; (* Number of columns of movie to skip *) row : GLuint; (* Row number of tile in scheme. *) col : GLuint; (* Column number of tile in scheme. *) end; type TGLuintArray = array of GLuint; PGLuintArray = ^TGLuintArray; TGLMovieTextureArray = array of TGLMovieTexture; PGLMovieTextureArray = ^TGLMovieTextureArray; var (* Our evil maximum texture size. Boo 3Dfxnot *) texture_size : GLuint = 1024;//512; texture_ids : GLuint; textures: TGLMovieTexture; tiled_width : GLuint = 0; tiled_height : GLuint = 0; movie_width : GLuint = 0; movie_height : GLuint = 0; implementation procedure OpenSmpeg(FileName: string); begin mpeg := SMPEG_new(PChar(FileName), @mpeg_info, 0); // audio if ( mpeg = nil ) then begin SDL_Quit; Exit; end; // SMPEG_setvolume(mpeg, 50); SMPEG_enableaudio(mpeg, 0); (* Everything needs to be in RGB for GL, but needs to be 32-bit for SMPEG. *) surface := SDL_AllocSurface( SDL_SWSURFACE, mpeg_info.width, mpeg_info.height, 32, $000000FF, $0000FF00, $00FF0000, $FF000000 ); if ( surface = nil ) then begin SDL_Quit; Exit; end; (* *Initialize* with mpeg size. *) if (glmovie_init( mpeg_info.width, mpeg_info.height ) <> GL_NO_ERROR ) then begin SDL_Quit; Exit; end; SMPEG_setdisplay(mpeg, surface, nil, @glmpeg_update); end; procedure SkipSmpeg(Time: single); begin SMPEG_skip(mpeg, Time); end; procedure PlaySmpeg; begin SMPEG_play(mpeg); end; //Pause Mod procedure PauseSmpeg; begin SMPEG_pause(mpeg); end; procedure UpdateSmpeg; begin // glmpeg_update(surface,0,0,0,0); DrawSmpeg( PGLubyte( surface.pixels ) ); end; procedure CloseSmpeg; begin SMPEG_delete(mpeg); //Fixing the Memory Lag in earlyer Versions (X-Mas Mod, all Official Versions) glmovie_quit; end; function glmovie_init( Width : GLuint; Height : GLuint ) : GLenum; type PGLubyteArray = ^TGLubyteArray; TGLubyteArray = array of GLubyte; var (* Initial black texels. *) pixels : TGLubyteArray; (* Absolute offsets from within tiled frame. *) //offset_x: GLuint; //offset_y: GLuint; skip_rows : GLuint; skip_pixels : GLuint; i, j, current : GLuint; begin skip_rows := 0; current := 0; (* Save original movie dimensions. *) movie_width := width; movie_height := height; (* Get the power of 2 dimensions. *) tiled_width := 1024{512}; tiled_height := 1024{512}; texture_size := 1024{512}; (* Time for fun with data type = record *) glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glEnable(GL_TEXTURE_2D); glEnable(GL_DITHER); glGenTextures(1, @texture_ids); current := 0; (* Setup texture. *) textures.id := texture_ids; textures.poly_width := texture_size; textures.poly_height := texture_size; textures.movie_width := movie_width - 2; textures.movie_height := movie_height - 2; textures.row := i; textures.col := j; textures.skip_pixels := skip_pixels; textures.skip_rows := skip_rows; SetLength( pixels, textures.poly_width * textures.poly_height * 4 ); if ( pixels = nil ) then begin glDeleteTextures(1, @texture_ids); result := GL_OUT_OF_MEMORY; exit; end; //FillChar( pixels^, textures[ current ].poly_width * textures[ current ].poly_height * 4, 0 ); (* Do all of our useful binding. *) glBindTexture(GL_TEXTURE_2D, texture_ids); // glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); (* Specify our 256x256 black texture. *) glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, 1024{512},//textures.poly_width, 1024{512},//textures.poly_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, @pixels[0] ); SetLength( pixels, 0 ); (* Simple state setup at the end. *) result := glGetError( ); end; procedure glmpeg_update( surface : PSDL_Surface; x : Sint32; y : Sint32; w : Uint32; h : Uint32 ); cdecl; var error : GLenum; begin glClear( GL_COLOR_BUFFER_BIT ); glMatrixMode( GL_MODELVIEW ); glLoadIdentity; DrawSmpeg( PGLubyte( surface.pixels ) ); error := glGetError( ); if ( error <> GL_NO_ERROR ) then Exit; SDL_GL_SwapBuffers; end; procedure DrawSmpeg(frame: PGLubyte); var Shift: GLdouble; CropT: real; CropB: real; TexT: real; TexB: real; TexL: real; TexR: real; Wide: boolean; begin (* full screen mpeg *) { CropT := 0; CropB := 600; TexT := 0; TexB := 1; TexL := 0; TexW := 1;} // set movie texture crop Wide := false; if (textures.movie_width = 720-2) and (textures.movie_height = 344-2) then begin TexT := 0; TexB := 342/1024; Wide := true; end; if textures.movie_height = 304-2 then begin TexT := 0; TexB := 304/1024; Wide := true; end; if textures.movie_height = 152-2 then begin TexT := 0; TexB := 152/1024; Wide := true; end; CropT := 110; // (110/800 = 13,75% max crop) CropB := 490; // (110/800 = 13,75% max crop) if (textures.movie_height <> 304-2) and (textures.movie_height <> 152-2) and (textures.movie_height <> 344-2) then begin TexT := 110 / 600 * (textures.movie_height / 1024{512}); TexB := 490 / 600 * (textures.movie_height / 1024{512}); if Ini.MovieSize >= 1 then begin // full screen size CropT := 0; CropB := 600; TexT := 0; TexB := textures.movie_height / 1024{512}; end; end; TexL := {10}0/600 * (textures.movie_width / 1024{512}); TexR := {590}600/600 * (textures.movie_width / 1024{512}); glEnable(GL_TEXTURE_2D); glDisable(GL_BLEND); glColor3f(1, 1, 1); glBindTexture( GL_TEXTURE_2D, texture_ids ); // glPixelStorei( GL_UNPACK_ROW_LENGTH, movie_width ); glPixelStorei( GL_UNPACK_SKIP_ROWS, 0); glPixelStorei( GL_UNPACK_SKIP_PIXELS, 0); glTexSubImage2D( GL_TEXTURE_2D, 0, 0, (* offset_x *) 0, (* offset_y *) textures.movie_width + 2, textures.movie_height + 2, GL_RGBA, GL_UNSIGNED_BYTE, frame ); // draw glBegin( GL_QUADS ); glTexCoord2f(TexL, TexT); glVertex2f(0, CropT); glTexCoord2f(TexL, TexB); glVertex2f(0, CropB); glTexCoord2f(TexR, TexB); glVertex2f(800, CropB); glTexCoord2f(TexR, TexT); glVertex2f(800, CropT); glEnd; glDisable(GL_TEXTURE_2D); end; procedure glmovie_resize( width : GLuint; height : GLuint ); begin glViewport(0, 0, width, height); glMatrixMode(GL_PROJECTION); glLoadIdentity; gluOrtho2D(0, 800, 600, 0); end; procedure glmovie_quit; begin glDeleteTextures(1, @texture_ids); SDL_FreeSurface(surface); end; end.