OpenWalnut 1.3.1
WGEScreenCapture.h
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #ifndef WGESCREENCAPTURE_H
00026 #define WGESCREENCAPTURE_H
00027 
00028 #include <limits>
00029 
00030 #include <boost/signals2.hpp>
00031 #include <boost/function.hpp>
00032 
00033 #include <osg/Camera>
00034 #include <osg/Image>
00035 #include <osg/RenderInfo>
00036 
00037 #include "../common/WSharedObject.h"
00038 #include "../common/WCondition.h"
00039 
00040 #include "animation/WGEAnimationFrameTimer.h"
00041 
00042 
00043 
00044 /**
00045  * This class is a screen recorder. It records the frame buffer to files on a per-frame-basis. This class is NOT thread-safe due to performance
00046  * reasons. You should not distribute the instance among multiple threads. It can be applied to <b>ONE</b> camera only by setting it as
00047  * finalDrawCallback (osg::Camera::setFinalDrawCallback). Each camera can only use ONE final draw callback.
00048  *
00049  * This class is abstract. Derive your own class and handle image writing.
00050  *
00051  * \note This class does NOT write the images to disk. Set a callback for this.
00052  *
00053  * \ingroup GE
00054  */
00055 class WGEScreenCapture: public osg::Camera::DrawCallback
00056 {
00057 public:
00058     /**
00059      * Keeps track of several frame-counts.
00060      */
00061     typedef struct
00062     {
00063         size_t m_frames;        //!< current number of frames.
00064         size_t m_framesLeft;    //!< the frames to take until stop.
00065     }
00066     RecordingInformation;
00067 
00068     /**
00069      * The shared access type to the FrameCounting struct.
00070      */
00071     typedef WSharedObject< RecordingInformation > SharedRecordingInformation;
00072 
00073     /**
00074      * Convenience typedef
00075      */
00076     typedef osg::ref_ptr< WGEScreenCapture > RefPtr;
00077 
00078     /**
00079      * Convenience typedef
00080      */
00081     typedef osg::ref_ptr< const WGEScreenCapture > ConstRefPtr;
00082 
00083     /**
00084      * This callback signature is needed to subscribe to the handleImage signal.
00085      */
00086     typedef boost::function< void( size_t, size_t, osg::ref_ptr< osg::Image > ) > HandleImageCallbackType;
00087 
00088     /**
00089      * Creates a screen capture callback.
00090      */
00091     WGEScreenCapture();
00092 
00093     /**
00094      * Destructor. Cleans up.
00095      */
00096     virtual ~WGEScreenCapture();
00097 
00098     /**
00099      * Starts recording. If it already is running, nothing happens.
00100      */
00101     void recordStart();
00102 
00103     /**
00104      * Stops recording. If not recording, nothing happens.
00105      */
00106     void recordStop();
00107 
00108     /**
00109      * Checks if there are frames left for recording.
00110      *
00111      * \return true if yes.
00112      */
00113     bool isRecording();
00114 
00115     /**
00116      * Makes a screenshot with the <b>next</b> frame. This is a shortcut for record( 1 ).
00117      */
00118     void screenshot();
00119 
00120     /**
00121      * Resets the frame-counter to 0.
00122      */
00123     void resetFrameCounter();
00124 
00125     /**
00126      * The draw callback operator. Gets called by OSG in draw traversal.
00127      *
00128      * \param renderInfo the OSG renderinfo
00129      */
00130     virtual void operator()( osg::RenderInfo& renderInfo ) const;   // NOLINT - osg wants this to be a non-const reference
00131 
00132     /**
00133      * The condition returned here is actually the change condition of the frame counter. This can be used to update GUI or something as it
00134      * contains frame-counts, recording information and so on (updated per frame).
00135      *
00136      * \return the condition
00137      */
00138     WCondition::ConstSPtr getRecordCondition() const;
00139 
00140     /**
00141      * Returns the current recording information. Release the lock after you grabbed the info you need.
00142      *
00143      * \return the info struct - read ticket
00144      */
00145     SharedRecordingInformation::ReadTicket getRecordingInformation() const;
00146 
00147     /**
00148      * Returns a timer getting ticked on each recorded frame. This can then be used for animations for example.
00149      *
00150      * \return the timer.
00151      */
00152     WGEAnimationFrameTimer::ConstSPtr getFrameTimer() const;
00153 
00154     /**
00155      * Subscribes a specified function to the new-image-signal. This gets emitted every time a new image was grabbed.
00156      *
00157      * \param callback the callback
00158      *
00159      * \return the connection.
00160      */
00161     boost::signals2::connection subscribeSignal( HandleImageCallbackType callback );
00162 
00163 protected:
00164     /**
00165      * The function handles new images. Implement it.
00166      *
00167      * \param framesLeft how much frames to come
00168      * \param totalFrames the total number of frames until now
00169      * \param image the image
00170      */
00171     virtual void handleImage( size_t framesLeft, size_t totalFrames, osg::ref_ptr< osg::Image > image ) const;
00172 
00173     /**
00174      * Starts recording. If already recording, it continues recording.
00175      *
00176      * \param frames the number of frames to record. 0 means stop, 1 is a single screenshot.
00177      */
00178     void record( size_t frames = std::numeric_limits< size_t >::max() );
00179 
00180 private:
00181     /**
00182      * Counts the frames to take.
00183      */
00184     SharedRecordingInformation m_recordingInformation;
00185 
00186     /**
00187      * The frame timer. Ticket on each recorded frame.
00188      */
00189     WGEAnimationFrameTimer::SPtr m_timer;
00190 
00191     /**
00192      * The type of the signal for handleSignal.
00193      */
00194     typedef boost::signals2::signal< void( size_t, size_t, osg::ref_ptr< osg::Image > ) > HandleImageSignalType;
00195 
00196     /**
00197      * The signal emitted on every new grabbed image.
00198      */
00199     HandleImageSignalType m_signalHandleImage;
00200 };
00201 
00202 #endif  // WGESCREENCAPTURE_H