00001 // This is core/vidl/vidl_dshow_live_istream.h 00002 #ifndef vidl_dshow_live_istream_h_ 00003 #define vidl_dshow_live_istream_h_ 00004 //========================================================================= 00005 //: 00006 // \file 00007 // \brief DirectShow live video input stream support. 00008 // \author Paul Crane 00009 // \author Miguel A. Figueroa-Villanueva (miguelf at ieee dot org) 00010 // 00011 // This file includes experimental support for DirectShow live video input 00012 // in vidl (e.g., from cameras and/or frame grabbers). 00013 // 00014 // \verbatim 00015 // Modifications 00016 // 01/19/2006 - DirectShow code contributed by Paul Crane. (miguelf) 00017 // 03/09/2006 - File imported to vxl repository with some modifications 00018 // and extensions to Paul's code. (miguelf) 00019 // \endverbatim 00020 // 00021 //========================================================================= 00022 00023 #include <vidl/vidl_istream.h> 00024 #include <vidl/vidl_frame.h> 00025 #include <vidl/vidl_frame_sptr.h> 00026 #include <vidl/vidl_pixel_format.h> 00027 00028 #include <vcl_string.h> 00029 #include <vcl_vector.h> 00030 00031 #include <atlbase.h> 00032 #include <dshow.h> 00033 #include <qedit.h> 00034 00035 //------------------------------------------------------------------------- 00036 // ***** probably move this from here??? 00037 //------------------------------------------------------------------------- 00038 class sample_grabber_cb : public ISampleGrabberCB 00039 { 00040 public: 00041 //: Constructor. 00042 sample_grabber_cb(); 00043 00044 // IUnknown interface 00045 STDMETHODIMP_(ULONG) AddRef() { return 1; } // fake ref counting 00046 STDMETHODIMP_(ULONG) Release() { return 2; } // fake ref counting 00047 STDMETHODIMP QueryInterface(REFIID riid, void **target); 00048 00049 // ISampleGrabberCB interface 00050 STDMETHODIMP SampleCB(double time, IMediaSample *sample); 00051 STDMETHODIMP BufferCB(double time, BYTE* buffer, long buffer_size); 00052 00053 // vidl helpers 00054 void advance(); 00055 vidl_frame_sptr current_frame(); 00056 00057 private: 00058 // Internal frame buffer information. 00059 vcl_vector<unsigned char> buffer_[3]; 00060 double buffer_time_[3]; 00061 00062 // Some status checking flags and counters. 00063 unsigned int busy_index_; 00064 unsigned int curr_index_; 00065 unsigned int next_index_; 00066 00067 HANDLE mutex_; 00068 }; 00069 00070 //------------------------------------------------------------------------- 00071 //: DirectShow live video input stream support. 00072 // 00073 // This is still in an experimental stage, but should be usable. It should 00074 // be able to open avi and wmv files as long as the system has the 00075 // available decoder, in the case of compressed video. 00076 // 00077 // DirectShow is very flexible and complex. Therefore we have taken the 00078 // approach to throw an exception or abort in the case where something 00079 // that is not supported fails, rather than try to parse through every 00080 // error and provide an alternative. However, we welcome any feedback on 00081 // desired features to make vidl_dshow_file_istream more usable in the 00082 // VXL context. 00083 //------------------------------------------------------------------------- 00084 template <class ParamsObject> 00085 class vidl_dshow_live_istream : public vidl_istream 00086 { 00087 public: 00088 //: Constructor - default 00089 vidl_dshow_live_istream(); 00090 00091 //: Constructor - from a string containing a device name. 00092 vidl_dshow_live_istream(const vcl_string& device_name); 00093 00094 //: Constructor - from a parameter object. 00095 vidl_dshow_live_istream(const ParamsObject& params); 00096 00097 //: Destructor. 00098 virtual ~vidl_dshow_live_istream() { close(); } 00099 00100 //: Return true if the stream is open for reading. 00101 // ***** if closed, should return false 00102 virtual bool is_open() const { return is_valid_; } 00103 00104 //: Return true if the stream is in a valid state. 00105 virtual bool is_valid() const { return is_valid_; } 00106 00107 //: Return true if the stream support seeking. 00108 virtual bool is_seekable() const { return false; } 00109 00110 //: Return the number of frames if known 00111 // returns -1 for non-seekable streams 00112 virtual int num_frames() const { return -1; } 00113 00114 //: Return the current frame number. 00115 // ***** through exception ?? 00116 virtual unsigned int frame_number() const { return 0; } 00117 00118 //: Return the width of each frame 00119 virtual unsigned int width() const { return buffer_width_; } 00120 00121 //: Return the height of each frame 00122 virtual unsigned int height() const { return buffer_height_; } 00123 00124 //: Return the pixel format 00125 virtual vidl_pixel_format format() const { return buffer_pixel_format_; } 00126 00127 //: Return the frame rate (FPS, 0.0 if unspecified) 00128 // \todo return a framerate if it is constant for a live video 00129 virtual double frame_rate() const { return 0.0; } 00130 00131 //: Return the duration in seconds (0.0 if unknown) 00132 virtual double duration() const { return 0.0; } 00133 00134 //: Close the stream. 00135 virtual void close(); 00136 00137 // ***** did we decide to keep the alias? 00138 00139 //: Advance to the next frame (but don't acquire an image). 00140 virtual bool advance() { return advance_wait(); } 00141 00142 //: Read the next frame from the stream (advance and acquire). 00143 virtual vidl_frame_sptr read_frame(); 00144 00145 //: Return the current frame in the stream. 00146 virtual vidl_frame_sptr current_frame(); 00147 00148 //: Seek to the given frame number. 00149 // ***** throw exception ?? 00150 virtual bool seek_frame(unsigned int frame_number) { return false; } 00151 00152 void run(void); 00153 void pause(void); 00154 void stop(void); 00155 00156 private: 00157 // Disable assignment and copy-construction. 00158 vidl_dshow_live_istream(const vidl_dshow_live_istream&); 00159 vidl_dshow_live_istream& operator=(const vidl_dshow_live_istream&); 00160 00161 //: Parameters that define the input stream process. 00162 ParamsObject params_; 00163 00164 //: Connect to a device using its FriendlyName (in params_ object). 00165 void connect(void); 00166 00167 //: If hr == S_FALSE, wait for the state change to complete. 00168 void wait_for_state_change(HRESULT hr); 00169 00170 //: ***** Callback method... 00171 sample_grabber_cb sample_grabber_callback_; 00172 00173 // Handles to the COM interfaces. 00174 CComPtr<IFilterGraph2> filter_graph_; 00175 CComPtr<IMoniker> moniker_; 00176 CComPtr<IMediaControl> media_control_; 00177 00178 // Internal frame buffer information. 00179 vidl_frame_sptr buffer_; 00180 unsigned int buffer_width_; 00181 unsigned int buffer_height_; 00182 vidl_pixel_format buffer_pixel_format_; 00183 00184 // Some status checking flags and counters. 00185 bool is_valid_; 00186 00187 //: ID in Running Object Table (ROT), for debugging with GraphEdit. 00188 DWORD register_; 00189 00190 // ***** we're considering removing this from API... 00191 00192 //: Initiate advance and wait for completion; synchronous advance. 00193 bool advance_wait(); 00194 //: Initiate advance and return immediately; asynchronous advance. 00195 bool advance_start(); 00196 //: Advance to the next frame (but don't acquire an image). 00197 bool is_frame_available() const; 00198 }; 00199 00200 #endif // vidl_dshow_live_istream_h_