00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "videorecorder.h"
00012
00013 #ifdef XVIDEXPORT
00014
00015 #include "../libs/revel/revel.h"
00016 #include "../events.h"
00017 #include "../gameoptions.h"
00018
00019 class VideoRecorderInternals {
00020 public:
00021 VideoRecorderInternals() : open(false), frameCounterOut(0), frameCounterIn(0), lastFrame(NULL) {};
00022 ~VideoRecorderInternals() { if ( lastFrame ) delete[] lastFrame; };
00023 int encoderHandle;
00024 Revel_Params revParams;
00025 bool open;
00026 int framerate;
00027 int ascFramerateLimit;
00028 long lastTick;
00029 ASCString filename;
00030 int frameCounterOut;
00031 int frameCounterIn;
00032 int* lastFrame;
00033 };
00034
00035
00036 void checkErrors( const Revel_Error& err )
00037 {
00038 if (err != REVEL_ERR_NONE)
00039 {
00040 printf("Revel Error : %d\n", err);
00041 }
00042 }
00043
00044
00045 VideoRecorder::VideoRecorder( const ASCString& filename, const SDL_Surface* surf, int framerate, int ascFramerateLimit, int quality )
00046 {
00047 data = new VideoRecorderInternals();
00048 data->framerate = framerate;
00049 data->lastTick = getTicker();
00050 data->filename = filename;
00051 data->ascFramerateLimit = ascFramerateLimit;
00052
00053 Revel_Error revError = Revel_CreateEncoder(&data->encoderHandle);
00054 checkErrors( revError );
00055
00056 Revel_InitializeParams(&data->revParams);
00057 data->revParams.width = surf->w;
00058 data->revParams.height = surf->h;
00059 data->revParams.frameRate = data->framerate;
00060 float q = quality;
00061 q /= 100.0f;
00062 data->revParams.quality = q;
00063 data->revParams.codec = REVEL_CD_XVID;
00064
00065 data->revParams.hasAudio = 0;
00066
00067
00068 revError = Revel_EncodeStart(data->encoderHandle, filename.c_str(), &data->revParams);
00069 data->open = true;
00070 }
00071
00072 void VideoRecorder::storeFrame( const SDL_Surface* surf )
00073 {
00074 if ( !surf )
00075 surf = SDL_GetVideoSurface();
00076
00077 if ( !surf )
00078 return;
00079
00080 Revel_VideoFrame frame;
00081 frame.width = surf->w;
00082 frame.height = surf->h;
00083 frame.bytesPerPixel = 4;
00084
00085 bool directScreenRender = false;
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 if ( directScreenRender ) {
00102 int frameSize;
00103 frame.pixels = surf->pixels;
00104 Revel_Error revError = Revel_EncodeFrame(data->encoderHandle, &frame, &frameSize);
00105 checkErrors( revError);
00106 } else {
00107 frame.pixelFormat = REVEL_PF_RGBA;
00108 int* buf;
00109 frame.pixels = buf = new int[frame.width*frame.height];
00110
00111 Uint32* pix = (Uint32*)frame.pixels;
00112
00113 bool diff = false;
00114 int* lastBuf = data->lastFrame;
00115 if ( !data->lastFrame )
00116 diff = true;
00117
00118 for ( int y = 0; y < surf->h; ++y ) {
00119 Uint32* src = ((Uint32*) surf->pixels) + (surf->pitch/4*y);
00120 for ( int x = 0 ; x < surf->w; ++x ) {
00121 Uint8 r,g,b,a;
00122 SDL_GetRGBA( *src, surf->format, &r,&g,&b,&a);
00123 *pix = r + (g<<8) + (b<<16) + (a<<24);
00124 if ( lastBuf ) {
00125 if ( *pix != *lastBuf )
00126 diff = true;
00127 ++lastBuf;
00128 }
00129 ++pix;
00130 ++src;
00131 }
00132 }
00133 if ( diff || 1 ) {
00134 int frameSize;
00135 Revel_Error revError = Revel_EncodeFrame(data->encoderHandle, &frame, &frameSize);
00136 checkErrors( revError);
00137 ++data->frameCounterIn;
00138 }
00139 if ( data->lastFrame )
00140 delete[] data->lastFrame;
00141 data->lastFrame = buf;
00142 }
00143
00144 ++data->frameCounterOut;
00145
00146
00147 while ( getTicker() < data->lastTick + 100/data->ascFramerateLimit )
00148 releasetimeslice();
00149
00150 data->lastTick = getTicker();
00151 }
00152
00153 void VideoRecorder::close()
00154 {
00155 if ( data->open ) {
00156 int totalSize;
00157 Revel_Error revError = Revel_EncodeEnd(data->encoderHandle, &totalSize);
00158 checkErrors( revError );
00159 Revel_DestroyEncoder(data->encoderHandle);
00160 }
00161 printf("recorded %d / %d frames\n", data->frameCounterOut, data->frameCounterIn );
00162 }
00163
00164 const ASCString VideoRecorder::getFilename()
00165 {
00166 return data->filename;
00167 }
00168
00169
00170 VideoRecorder::~VideoRecorder()
00171 {
00172 close();
00173 delete data;
00174 }
00175
00176 #else
00177
00178 VideoRecorder::VideoRecorder( const ASCString& filename, const SDL_Surface* surf, int framerate, int ascFramerateLimit, int quality ) {}
00179 const ASCString VideoRecorder::getFilename() { return ""; }
00180 void VideoRecorder::storeFrame( const SDL_Surface* surf ) {}
00181 void VideoRecorder::close() {}
00182 VideoRecorder::~VideoRecorder() {}
00183
00184 #endif