15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows specific implementation of VideoCaptureDevice.
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DirectShow is used for capturing. DirectShow provide its own threads
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for capturing.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Avoid including strsafe.h via dshow as it will cause build warnings.
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NO_DSHOW_STRSAFE
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <dshow.h>
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_comptr.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_device.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/video_capture_types.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/video/capture/win/capability_list_win.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/win/sink_filter_win.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "media/video/capture/win/sink_input_pin_win.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace media {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All the methods in the class can only be run on a COM initialized thread.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class VideoCaptureDeviceWin
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::NonThreadSafe,
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      public VideoCaptureDevice,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public SinkFilterObserver {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // A utility class that wraps the AM_MEDIA_TYPE type and guarantees that
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // we free the structure when exiting the scope.  DCHECKing is also done to
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // avoid memory leaks.
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  class ScopedMediaType {
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   public:
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ScopedMediaType() : media_type_(NULL) {}
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ~ScopedMediaType() { Free(); }
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AM_MEDIA_TYPE* operator->() { return media_type_; }
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AM_MEDIA_TYPE* get() { return media_type_; }
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void Free();
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AM_MEDIA_TYPE** Receive();
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)   private:
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void FreeMediaType(AM_MEDIA_TYPE* mt);
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void DeleteMediaType(AM_MEDIA_TYPE* mt);
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    AM_MEDIA_TYPE* media_type_;
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  };
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  static HRESULT GetDeviceFilter(const std::string& device_id,
571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 const CLSID device_class_id,
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 IBaseFilter** filter);
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static base::win::ScopedComPtr<IPin> GetPin(IBaseFilter* filter,
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              PIN_DIRECTION pin_dir,
611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              REFGUID category,
621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                              REFGUID major_type);
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  static VideoPixelFormat TranslateMediaSubtypeToPixelFormat(
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      const GUID& sub_type);
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit VideoCaptureDeviceWin(const Name& device_name);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~VideoCaptureDeviceWin();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Opens the device driver for this device.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool Init();
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // VideoCaptureDevice implementation.
720529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  virtual void AllocateAndStart(
730529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      const VideoCaptureParams& params,
740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      scoped_ptr<VideoCaptureDevice::Client> client) OVERRIDE;
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void StopAndDeAllocate() OVERRIDE;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  enum InternalState {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kIdle,  // The device driver is opened but camera is not in use.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kCapturing,  // Video is being captured.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    kError  // Error accessing HW functions.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // User needs to recover by destroying the object.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Implements SinkFilterObserver.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void FrameReceived(const uint8* buffer, int length);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool CreateCapabilityMap();
890529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  void SetAntiFlickerInCaptureFilter();
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  HRESULT InstantiateWDMFiltersAndPins();
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  HRESULT AddWDMCrossbarFilterToGraphAndConnect();
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetErrorState(const std::string& reason);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Name device_name_;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InternalState state_;
964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<VideoCaptureDevice::Client> client_;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IBaseFilter> capture_filter_;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IGraphBuilder> graph_builder_;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IMediaControl> media_control_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IPin> input_sink_pin_;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IPin> output_capture_pin_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used when using a MJPEG decoder.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IBaseFilter> mjpg_filter_;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IPin> input_mjpg_pin_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedComPtr<IPin> output_mjpg_pin_;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Used for WDM devices as specified by |device_name_|. These devices need a
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // WDM Crossbar Filter upstream from the Capture filter.
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::win::ScopedComPtr<IBaseFilter> crossbar_filter_;
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::win::ScopedComPtr<IPin> crossbar_video_output_pin_;
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::win::ScopedComPtr<IPin> analog_video_input_pin_;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SinkFilter> sink_filter_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Map of all capabilities this device support.
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CapabilityList capabilities_;
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  VideoCaptureFormat capture_format_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_IMPLICIT_CONSTRUCTORS(VideoCaptureDeviceWin);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace media
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // MEDIA_VIDEO_CAPTURE_WIN_VIDEO_CAPTURE_DEVICE_WIN_H_
125