core/vidl/vidl_dshow_live_istream.h
Go to the documentation of this file.
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_