videoCapture.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _VIDEOCAPTURE_H_
  23. #define _VIDEOCAPTURE_H_
  24. #ifndef _TSINGLETON_H_
  25. #include "core/util/tSingleton.h"
  26. #endif
  27. #ifndef _TVECTOR_H_
  28. #include "core/util/tVector.h"
  29. #endif
  30. #ifndef _TORQUE_STRING_H_
  31. #include "core/util/str.h"
  32. #endif
  33. #ifndef _GFXTEXTUREHANDLE_H_
  34. #include "gfx/gfxTextureHandle.h"
  35. #endif
  36. #ifndef _MPOINT2_H_
  37. #include "math/mPoint2.h"
  38. #endif
  39. #ifndef _THREADSAFEDEQUE_H_
  40. #include "platform/threads/threadSafeDeque.h"
  41. #endif
  42. class GuiCanvas;
  43. class VideoFrameGrabber;
  44. class VideoEncoder;
  45. class GBitmap;
  46. typedef VideoEncoder* (*VideoEncoderFactoryFn)();
  47. /// Abstract frame grabber class
  48. /// implementation and initalization depends on video device
  49. class VideoFrameGrabber
  50. {
  51. friend class VideoCapture;
  52. protected:
  53. Point2I mResolution; // The resolution used to capture the back buffer (scaling will be used)
  54. Vector<GBitmap*> mBitmapList; //List of bitmaps created from backbuffer captures
  55. /// Sets the output frame resolution
  56. void setOutResolution( const Point2I& res ) { mResolution = res; }
  57. /// Pushes a fresh bitmap into our list
  58. void pushNewBitmap( GBitmap* bitmap ) { mBitmapList.push_back(bitmap); }
  59. /// Returns one captured bitmap. Returns NULL if there are no more bitmaps.
  60. GBitmap* fetchBitmap();
  61. /// Texture event callback
  62. void _onTextureEvent(GFXTexCallbackCode code);
  63. /// Captures the current backbuffer. If the last capture wasn't made into a bitmap, it will be overriden.
  64. virtual void captureBackBuffer() = 0;
  65. /// Starts converting the last backbuffer capture to a bitmap
  66. /// Depending on the VideoFrameGrabber implementation, this may not produce a bitmap right away.
  67. virtual void makeBitmap() = 0;
  68. /// Releases internal textures
  69. virtual void releaseTextures() {};
  70. public:
  71. VideoFrameGrabber();
  72. virtual ~VideoFrameGrabber();
  73. };
  74. /// Video capture interface class
  75. class VideoCapture
  76. {
  77. private:
  78. struct EncoderFactory {
  79. const char* name;
  80. VideoEncoderFactoryFn factory;
  81. };
  82. /// List of encoder factory functions
  83. static Vector<EncoderFactory> mEncoderFactoryFnList;
  84. // The frame position of the latest backbuffer capture
  85. F32 mCapturedFramePos;
  86. /// Our current video encoder
  87. VideoEncoder* mEncoder;
  88. /// Our video frame grabber
  89. VideoFrameGrabber* mFrameGrabber;
  90. /// The canvas we're recording from
  91. GuiCanvas* mCanvas;
  92. /// True if we're recording
  93. bool mIsRecording;
  94. /// Time when we captured the previous frame
  95. U32 mVideoCaptureStartTime;
  96. /// Frame to be captured next
  97. F32 mNextFramePosition;
  98. /// The framerate we'll use to record
  99. F32 mFrameRate;
  100. /// The per-frame time (in milliseconds)
  101. F32 mMsPerFrame;
  102. /// Accumulated error when converting the per-frame-time to integer
  103. /// this is used to dither the value and keep overall time advancing
  104. /// correct
  105. F32 mMsPerFrameError;
  106. /// Name of the encoder we'll be using
  107. String mEncoderName;
  108. /// The video output resolution
  109. Point2I mResolution;
  110. /// Output filename
  111. String mFileName;
  112. /// Tur if we're waiting for a canvas to bre created before capturing
  113. bool mWaitingForCanvas;
  114. /// Vector with bitmaps to delete
  115. Vector< GBitmap* > mBitmapDeleteList;
  116. /// Initializes our encoder
  117. bool initEncoder( const char* name );
  118. /// Deletes processed bitmaps
  119. void deleteProcessedBitmaps();
  120. public:
  121. VideoCapture();
  122. /// Start a video capture session
  123. void begin( GuiCanvas* canvas );
  124. /// Captures a new frame
  125. void capture();
  126. /// Ends a video capture
  127. void end();
  128. /// Sets the output filename
  129. void setFilename( const char* filename ) { mFileName = filename; }
  130. /// Sets the encoder we'll use
  131. void setEncoderName( const char* encoder ) { mEncoderName = encoder; }
  132. /// Sets the framerate
  133. void setFramerate( F32 fps ) { mFrameRate = fps; }
  134. /// Sets the video output resolution
  135. void setResolution(const Point2I& res) { mResolution = res; }
  136. /// Returns true if we're capturing
  137. bool isRecording() { return mIsRecording; }
  138. /// Returns the number of milliseconds per frame
  139. S32 getMsPerFrame();
  140. /// Sets the video farme grabber (cannot record without one).
  141. void setFrameGrabber( VideoFrameGrabber* grabber ) { mFrameGrabber = grabber; }
  142. /// This will make the video capture begin capturing
  143. /// as soon as a GuiCanvas is created
  144. void waitForCanvas() { mWaitingForCanvas = true; }
  145. bool isWaitingForCanvas() { return mWaitingForCanvas; }
  146. /// Registers an encoder
  147. static void registerEncoder( const char* name, VideoEncoderFactoryFn factoryFn );
  148. // For ManagedSingleton.
  149. static const char* getSingletonName() { return "VideoCapture"; }
  150. };
  151. /// Abstract video encoder class
  152. class VideoEncoder
  153. {
  154. protected:
  155. // Video output file path
  156. String mPath;
  157. // Video framerate
  158. F32 mFramerate;
  159. // Video resolution
  160. Point2I mResolution;
  161. // List with bitmaps which are done encoding
  162. ThreadSafeDeque< GBitmap* > mProcessedBitmaps;
  163. public:
  164. virtual ~VideoEncoder() { }
  165. // Stores an encoded bitmap to be dealt with later
  166. void pushProcessedBitmap( GBitmap* bitmap );
  167. public:
  168. /// Sets the file the encoder will write to
  169. void setFile( const char* path );
  170. /// Sets the framerate (and fixes it if its invalid)
  171. virtual void setFramerate( F32* framerate ) { mFramerate = *framerate; }
  172. /// Sets the output resolution (and fixes it if its invalid)
  173. virtual void setResolution( Point2I* resolution ) { mResolution = *resolution; }
  174. /// Begins accepting frames for encoding
  175. virtual bool begin() = 0;
  176. /// Pushes a new frame into the video stream
  177. virtual bool pushFrame( GBitmap * bitmap ) = 0;
  178. /// Finishes the encoding and closes the video
  179. virtual bool end() = 0;
  180. /// Returns an already encoded bitmap. Video capture will get these and manage their deletion
  181. GBitmap* getProcessedBitmap();
  182. };
  183. /// Returns the VideoCapture singleton.
  184. #define VIDCAP ManagedSingleton<VideoCapture>::instance()
  185. //-----------------------------------------
  186. /// VIDEO ENCODER REGISTRATION MACRO
  187. #define REGISTER_VIDEO_ENCODER(ClassName, EncoderName) \
  188. VideoEncoder* EncoderFactory##EncoderName() { return new ClassName(); } \
  189. struct __VidEncReg##EncoderName { __VidEncReg##EncoderName() { VideoCapture::registerEncoder( #EncoderName, &EncoderFactory##EncoderName ); } }; \
  190. static __VidEncReg##EncoderName _gEncoderRegistration;
  191. #endif // !_VIDEOCAPTURE_H_