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