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