videorecorder.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002  *                                                                         *
00003  *   This program is free software; you can redistribute it and/or modify  *
00004  *   it under the terms of the GNU General Public License as published by  *
00005  *   the Free Software Foundation; either version 2 of the License, or     *
00006  *   (at your option) any later version.                                   *
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; //<! counts all frames that where send to the videorecorder
00030      int frameCounterIn;  //<! counts all frames that where passed to the video encoder
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     // Initiate encoding
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    if ( surf->pitch == surf->w*4 && surf->format->BytesPerPixel == 4 ) {
00086       if ( surf->format->Rshift == 0 && surf->format->Gshift == 8 && surf->format->Bshift == 16 ) {
00087          frame.pixelFormat = REVEL_PF_RGBA;
00088          directScreenRender = true;
00089       }
00090       
00091       if ( surf->format->Rshift == 24 && surf->format->Gshift == 16 && surf->format->Bshift == 8 ) {
00092          frame.pixelFormat = REVEL_PF_ABGR;
00093          directScreenRender = true;
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    // we are limited the video to our framerate
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

Generated on Mon Jan 5 01:28:27 2009 for Advanced Strategic Command by  doxygen 1.5.1