Panda3D

ffmpegVideoCursor.h

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 &params);
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
 All Classes Functions Variables Enumerations