Panda3D
|
00001 // Filename: ffmpegVideoCursor.h 00002 // Created by: jyelon (01Aug2007) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 #ifndef FFMPEGVIDEOCURSOR_H 00016 #define FFMPEGVIDEOCURSOR_H 00017 00018 #include "pandabase.h" 00019 00020 #ifdef HAVE_FFMPEG 00021 00022 #include "movieVideoCursor.h" 00023 #include "texture.h" 00024 #include "pointerTo.h" 00025 #include "ffmpegVirtualFile.h" 00026 #include "genericThread.h" 00027 #include "threadPriority.h" 00028 #include "pmutex.h" 00029 #include "reMutex.h" 00030 #include "conditionVar.h" 00031 #include "pdeque.h" 00032 00033 class FfmpegVideo; 00034 struct AVFormatContext; 00035 struct AVCodecContext; 00036 struct AVStream; 00037 struct AVPacket; 00038 struct AVFrame; 00039 struct SwsContext; 00040 00041 //////////////////////////////////////////////////////////////////// 00042 // Class : FfmpegVideoCursor 00043 // Description : 00044 //////////////////////////////////////////////////////////////////// 00045 class EXPCL_PANDA_MOVIES FfmpegVideoCursor : public MovieVideoCursor { 00046 private: 00047 FfmpegVideoCursor(); 00048 void init_from(FfmpegVideo *src); 00049 00050 PUBLISHED: 00051 FfmpegVideoCursor(FfmpegVideo *src); 00052 virtual ~FfmpegVideoCursor(); 00053 00054 void set_max_readahead_frames(int max_readahead_frames); 00055 int get_max_readahead_frames() const; 00056 00057 void set_thread_priority(ThreadPriority thread_priority); 00058 ThreadPriority get_thread_priority() const; 00059 00060 void start_thread(); 00061 BLOCKING void stop_thread(); 00062 bool is_thread_started() const; 00063 00064 public: 00065 virtual bool set_time(double timestamp, int loop_count); 00066 virtual PT(Buffer) fetch_buffer(); 00067 00068 public: 00069 // Nested class must be public for PT(FfmpegBuffer) to work correctly. 00070 class EXPCL_PANDA_MOVIES FfmpegBuffer : public Buffer { 00071 public: 00072 ALLOC_DELETED_CHAIN(FfmpegBuffer); 00073 INLINE FfmpegBuffer(size_t block_size, double video_timebase); 00074 virtual int compare_timestamp(const Buffer *other) const; 00075 virtual double get_timestamp() const; 00076 00077 int _begin_frame; 00078 int _end_frame; 00079 double _video_timebase; 00080 00081 public: 00082 static TypeHandle get_class_type() { 00083 return _type_handle; 00084 } 00085 static void init_type() { 00086 Buffer::init_type(); 00087 register_type(_type_handle, "FfmpegVideoCursor::FfmpegBuffer", 00088 Buffer::get_class_type()); 00089 } 00090 virtual TypeHandle get_type() const { 00091 return get_class_type(); 00092 } 00093 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00094 00095 private: 00096 static TypeHandle _type_handle; 00097 }; 00098 00099 protected: 00100 virtual PT(Buffer) make_new_buffer(); 00101 00102 private: 00103 bool open_stream(); 00104 void close_stream(); 00105 void cleanup(); 00106 00107 Filename _filename; 00108 string _sync_name; 00109 int _max_readahead_frames; 00110 ThreadPriority _thread_priority; 00111 PT(GenericThread) _thread; 00112 00113 // This global Mutex protects calls to avcodec_open/close/etc. 00114 static ReMutex _av_lock; 00115 00116 // Protects _readahead_frames and all the immediately following 00117 // members. 00118 Mutex _lock; 00119 00120 // Condition: the thread has something to do. 00121 ConditionVar _action_cvar; 00122 00123 typedef pdeque<PT(FfmpegBuffer) > Buffers; 00124 Buffers _readahead_frames; 00125 enum ThreadStatus { 00126 TS_stopped, 00127 TS_wait, 00128 TS_readahead, 00129 TS_seek, 00130 TS_seeking, 00131 TS_shutdown, 00132 }; 00133 ThreadStatus _thread_status; 00134 int _seek_frame; 00135 00136 int _current_frame; 00137 PT(FfmpegBuffer) _current_frame_buffer; 00138 00139 private: 00140 // The following functions will be called in the sub-thread. 00141 static void st_thread_main(void *self); 00142 void thread_main(); 00143 bool do_poll(); 00144 00145 PT(FfmpegBuffer) do_alloc_frame(); 00146 void do_clear_all_frames(); 00147 00148 bool fetch_packet(int default_frame); 00149 bool do_fetch_packet(int default_frame); 00150 void fetch_frame(int frame); 00151 void decode_frame(int &finished); 00152 void do_decode_frame(int &finished); 00153 void seek(int frame, bool backward); 00154 void do_seek(int frame, bool backward); 00155 int binary_seek(int min_frame, int max_frame, int target_frame, int num_iterations); 00156 void advance_to_frame(int frame); 00157 void reset_stream(); 00158 void export_frame(FfmpegBuffer *buffer); 00159 00160 // The following data members will be accessed by the sub-thread. 00161 AVPacket *_packet; 00162 int _packet_frame; 00163 AVFormatContext *_format_ctx; 00164 AVCodecContext *_video_ctx; 00165 SwsContext *_convert_ctx; 00166 00167 FfmpegVirtualFile _ffvfile; 00168 int _video_index; 00169 double _video_timebase; 00170 AVFrame *_frame; 00171 AVFrame *_frame_out; 00172 int _initial_dts; 00173 double _min_fseek; 00174 int _begin_frame; 00175 int _end_frame; 00176 bool _frame_ready; 00177 bool _eof_known; 00178 int _eof_frame; 00179 00180 // PStat collectors. 00181 static PStatCollector _fetch_buffer_pcollector; 00182 static PStatCollector _seek_pcollector; 00183 static PStatCollector _export_frame_pcollector; 00184 00185 public: 00186 static void register_with_read_factory(); 00187 virtual void write_datagram(BamWriter *manager, Datagram &dg); 00188 00189 virtual void finalize(BamReader *manager); 00190 00191 protected: 00192 static TypedWritable *make_from_bam(const FactoryParams ¶ms); 00193 void fillin(DatagramIterator &scan, BamReader *manager); 00194 00195 public: 00196 static TypeHandle get_class_type() { 00197 return _type_handle; 00198 } 00199 static void init_type() { 00200 MovieVideoCursor::init_type(); 00201 register_type(_type_handle, "FfmpegVideoCursor", 00202 MovieVideoCursor::get_class_type()); 00203 FfmpegBuffer::init_type(); 00204 } 00205 virtual TypeHandle get_type() const { 00206 return get_class_type(); 00207 } 00208 virtual TypeHandle force_init_type() {init_type(); return get_class_type();} 00209 00210 private: 00211 static TypeHandle _type_handle; 00212 00213 friend class FfmpegVideo; 00214 }; 00215 00216 #include "ffmpegVideoCursor.I" 00217 00218 #endif // HAVE_FFMPEG 00219 #endif // FFMPEGVIDEO_H