00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
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
00043
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
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
00114 static ReMutex _av_lock;
00115
00116
00117
00118 Mutex _lock;
00119
00120
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
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
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
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