123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #ifndef _VIDEOCAPTURE_H_
- #define _VIDEOCAPTURE_H_
- #ifndef _TSINGLETON_H_
- #include "core/util/tSingleton.h"
- #endif
- #ifndef _TVECTOR_H_
- #include "core/util/tVector.h"
- #endif
- #ifndef _TORQUE_STRING_H_
- #include "core/util/str.h"
- #endif
- #ifndef _GFXTEXTUREHANDLE_H_
- #include "gfx/gfxTextureHandle.h"
- #endif
- #ifndef _MPOINT2_H_
- #include "math/mPoint2.h"
- #endif
- #ifndef _THREADSAFEDEQUE_H_
- #include "platform/threads/threadSafeDeque.h"
- #endif
- class GuiCanvas;
- class VideoFrameGrabber;
- class VideoEncoder;
- class GBitmap;
- typedef VideoEncoder* (*VideoEncoderFactoryFn)();
- /// Abstract frame grabber class
- /// implementation and initalization depends on video device
- class VideoFrameGrabber
- {
- friend class VideoCapture;
- protected:
- Point2I mResolution; // The resolution used to capture the back buffer (scaling will be used)
- Vector<GBitmap*> mBitmapList; //List of bitmaps created from backbuffer captures
- /// Sets the output frame resolution
- void setOutResolution( const Point2I& res ) { mResolution = res; }
- /// Pushes a fresh bitmap into our list
- void pushNewBitmap( GBitmap* bitmap ) { mBitmapList.push_back(bitmap); }
- /// Returns one captured bitmap. Returns NULL if there are no more bitmaps.
- GBitmap* fetchBitmap();
- /// Texture event callback
- void _onTextureEvent(GFXTexCallbackCode code);
-
- /// Captures the current backbuffer. If the last capture wasn't made into a bitmap, it will be overriden.
- virtual void captureBackBuffer() = 0;
- /// Starts converting the last backbuffer capture to a bitmap
- /// Depending on the VideoFrameGrabber implementation, this may not produce a bitmap right away.
- virtual void makeBitmap() = 0;
- /// Releases internal textures
- virtual void releaseTextures() {};
- public:
- VideoFrameGrabber();
- virtual ~VideoFrameGrabber();
- };
- /// Video capture interface class
- class VideoCapture
- {
- private:
- struct EncoderFactory {
- const char* name;
- VideoEncoderFactoryFn factory;
- };
- /// List of encoder factory functions
- static Vector<EncoderFactory> mEncoderFactoryFnList;
- // The frame position of the latest backbuffer capture
- F32 mCapturedFramePos;
- /// Our current video encoder
- VideoEncoder* mEncoder;
- /// Our video frame grabber
- VideoFrameGrabber* mFrameGrabber;
- /// The canvas we're recording from
- GuiCanvas* mCanvas;
- /// True if we're recording
- bool mIsRecording;
- /// Time when we captured the previous frame
- U32 mVideoCaptureStartTime;
- /// Frame to be captured next
- F32 mNextFramePosition;
- /// The framerate we'll use to record
- F32 mFrameRate;
- /// The per-frame time (in milliseconds)
- F32 mMsPerFrame;
- /// Accumulated error when converting the per-frame-time to integer
- /// this is used to dither the value and keep overall time advancing
- /// correct
- F32 mMsPerFrameError;
- /// Name of the encoder we'll be using
- String mEncoderName;
- /// The video output resolution
- Point2I mResolution;
- /// Output filename
- String mFileName;
- /// Tur if we're waiting for a canvas to bre created before capturing
- bool mWaitingForCanvas;
- /// Vector with bitmaps to delete
- Vector< GBitmap* > mBitmapDeleteList;
- /// Initializes our encoder
- bool initEncoder( const char* name );
- /// Deletes processed bitmaps
- void deleteProcessedBitmaps();
-
- public:
- VideoCapture();
-
- /// Start a video capture session
- void begin( GuiCanvas* canvas );
- /// Captures a new frame
- void capture();
-
- /// Ends a video capture
- void end();
- /// Sets the output filename
- void setFilename( const char* filename ) { mFileName = filename; }
- /// Sets the encoder we'll use
- void setEncoderName( const char* encoder ) { mEncoderName = encoder; }
- /// Sets the framerate
- void setFramerate( F32 fps ) { mFrameRate = fps; }
- /// Sets the video output resolution
- void setResolution(const Point2I& res) { mResolution = res; }
- /// Returns true if we're capturing
- bool isRecording() { return mIsRecording; }
- /// Returns the number of milliseconds per frame
- S32 getMsPerFrame();
- /// Sets the video farme grabber (cannot record without one).
- void setFrameGrabber( VideoFrameGrabber* grabber ) { mFrameGrabber = grabber; }
- /// This will make the video capture begin capturing
- /// as soon as a GuiCanvas is created
- void waitForCanvas() { mWaitingForCanvas = true; }
- bool isWaitingForCanvas() { return mWaitingForCanvas; }
- /// Registers an encoder
- static void registerEncoder( const char* name, VideoEncoderFactoryFn factoryFn );
- // For ManagedSingleton.
- static const char* getSingletonName() { return "VideoCapture"; }
- };
- /// Abstract video encoder class
- class VideoEncoder
- {
- protected:
- // Video output file path
- String mPath;
- // Video framerate
- F32 mFramerate;
- // Video resolution
- Point2I mResolution;
- // List with bitmaps which are done encoding
- ThreadSafeDeque< GBitmap* > mProcessedBitmaps;
- public:
- virtual ~VideoEncoder() { }
- // Stores an encoded bitmap to be dealt with later
- void pushProcessedBitmap( GBitmap* bitmap );
-
- public:
- /// Sets the file the encoder will write to
- void setFile( const char* path );
- /// Sets the framerate (and fixes it if its invalid)
- virtual void setFramerate( F32* framerate ) { mFramerate = *framerate; }
- /// Sets the output resolution (and fixes it if its invalid)
- virtual void setResolution( Point2I* resolution ) { mResolution = *resolution; }
- /// Begins accepting frames for encoding
- virtual bool begin() = 0;
- /// Pushes a new frame into the video stream
- virtual bool pushFrame( GBitmap * bitmap ) = 0;
- /// Finishes the encoding and closes the video
- virtual bool end() = 0;
- /// Returns an already encoded bitmap. Video capture will get these and manage their deletion
- GBitmap* getProcessedBitmap();
- };
- /// Returns the VideoCapture singleton.
- #define VIDCAP ManagedSingleton<VideoCapture>::instance()
- //-----------------------------------------
- /// VIDEO ENCODER REGISTRATION MACRO
- #define REGISTER_VIDEO_ENCODER(ClassName, EncoderName) \
- VideoEncoder* EncoderFactory##EncoderName() { return new ClassName(); } \
- struct __VidEncReg##EncoderName { __VidEncReg##EncoderName() { VideoCapture::registerEncoder( #EncoderName, &EncoderFactory##EncoderName ); } }; \
- static __VidEncReg##EncoderName _gEncoderRegistration;
- #endif // !_VIDEOCAPTURE_H_
|