webrtcvideocapturer.cc revision 7433a088d2e97993266b66c102b0866aa90b4424
128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// libjingle 228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Copyright 2011 Google Inc. 328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Redistribution and use in source and binary forms, with or without 528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// modification, are permitted provided that the following conditions are met: 628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 1. Redistributions of source code must retain the above copyright notice, 828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// this list of conditions and the following disclaimer. 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 2. Redistributions in binary form must reproduce the above copyright notice, 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// this list of conditions and the following disclaimer in the documentation 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// and/or other materials provided with the distribution. 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 3. The name of the author may not be used to endorse or promote products 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// derived from this software without specific prior written permission. 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Implementation of class WebRtcVideoCapturer. 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 2828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/webrtc/webrtcvideocapturer.h" 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_CONFIG_H 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <config.h> 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#ifdef HAVE_WEBRTC_VIDEO 35f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org#include "talk/base/criticalsection.h" 3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/base/logging.h" 3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/base/thread.h" 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/base/timeutils.h" 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h" 4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/base/win32.h" // Need this to #include the impl files. 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "webrtc/modules/video_capture/include/video_capture_factory.h" 4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket { 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstruct kVideoFourCCEntry { 4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org uint32 fourcc; 4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type; 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This indicates our format preferences and defines a mapping between 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// webrtc::RawVideoType (from video_capture_defines.h) to our FOURCCs. 5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic kVideoFourCCEntry kSupportedFourCCs[] = { 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_I420, webrtc::kVideoI420 }, // 12 bpp, no conversion. 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YV12, webrtc::kVideoYV12 }, // 12 bpp, no conversion. 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_NV12, webrtc::kVideoNV12 }, // 12 bpp, fast conversion. 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_NV21, webrtc::kVideoNV21 }, // 12 bpp, fast conversion. 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YUY2, webrtc::kVideoYUY2 }, // 16 bpp, fast conversion. 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_UYVY, webrtc::kVideoUYVY }, // 16 bpp, fast conversion. 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_MJPG, webrtc::kVideoMJPEG }, // compressed, slow conversion. 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_ARGB, webrtc::kVideoARGB }, // 32 bpp, slow conversion. 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_24BG, webrtc::kVideoRGB24 }, // 24 bpp, slow conversion. 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass WebRtcVcmFactory : public WebRtcVcmFactoryInterface { 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule* Create(int id, const char* device) { 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::Create(id, device); 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) { 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::CreateDeviceInfo(id); 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) { 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete info; 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap, 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* format) { 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org uint32 fourcc = 0; 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].webrtc_type == cap.rawType) { 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = kSupportedFourCCs[i].fourcc; 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (fourcc == 0) { 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->fourcc = fourcc; 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->width = cap.width; 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->height = cap.height; 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->interval = VideoFormat::FpsToInterval(cap.maxFPS); 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool FormatToCapability(const VideoFormat& format, 9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability* cap) { 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown; 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].fourcc == format.fourcc) { 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc_type = kSupportedFourCCs[i].webrtc_type; 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (webrtc_type == webrtc::kVideoUnknown) { 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->width = format.width; 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->height = format.height; 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->maxFPS = VideoFormat::IntervalToFps(format.interval); 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->expectedCaptureDelay = 0; 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->rawType = webrtc_type; 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->codecType = webrtc::kVideoCodecUnknown; 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->interlaced = false; 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Implementation of class WebRtcVideoCapturer 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer() 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(new WebRtcVcmFactory), 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_(NULL), 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org captured_frames_(0) { 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory) 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(factory), 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_(NULL), 13428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org captured_frames_(0) { 13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::~WebRtcVideoCapturer() { 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->Release(); 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(const Device& device) { 14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0); 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!info) { 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Find the desired camera, by name. 15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // In the future, comparing IDs will be more robust. 15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Figure what's needed to allow this. 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int num_cams = info->NumberOfDevices(); 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_id[256] = ""; 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool found = false; 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int index = 0; index < num_cams; ++index) { 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_name[256]; 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org vcm_id, ARRAY_SIZE(vcm_id)) != -1) { 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (device.name == reinterpret_cast<char*>(vcm_name)) { 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org found = true; 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!found) { 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id; 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Enumerate the supported formats. 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Find out why this starts/stops the camera... 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<VideoFormat> supported; 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int32_t num_caps = info->NumberOfCapabilities(vcm_id); 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int32_t i = 0; i < num_caps; ++i) { 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (info->GetCapability(vcm_id, i, cap) != -1) { 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat format; 18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (CapabilityToFormat(cap, &format)) { 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org supported.push_back(format); 18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format " 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << cap.rawType; 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (supported.empty()) { 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id; 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_ = factory_->Create(0, vcm_id); 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id; 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // It is safe to change member attributes now. 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->AddRef(); 20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetId(device.id); 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetSupportedFormats(supported); 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(webrtc::VideoCaptureModule* module) { 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module) { 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid VCM supplied"; 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Set id and formats. 22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org (module_ = module)->AddRef(); 22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 22428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired, 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* best_format) { 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!best_format) { 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) { 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We maybe using a manually injected VCM which doesn't support enum. 23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Use the desired format as the best format. 23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->width = desired.width; 23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->height = desired.height; 23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->fourcc = FOURCC_I420; 23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->interval = desired.interval; 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Failed to find best capture format," 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " fall back to the requested format " 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << best_format->ToString(); 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgCaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) { 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer has not been initialized"; 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_NO_DEVICE; 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(hellner): weird to return failure when it is in fact actually running. 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (IsRunning()) { 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already running"; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(&capture_format); 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!FormatToCapability(capture_format, &cap)) { 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid capture format specified"; 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string camera_id(GetId()); 26628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org uint32 start = talk_base::Time(); 2677433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org module_->RegisterCaptureDataCallback(*this); 2687433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org if (module_->StartCapture(cap) != 0) { 26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Camera '" << camera_id << "' failed to start"; 27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Camera '" << camera_id << "' started with format " 27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << capture_format.ToString() << ", elapsed time " 27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << talk_base::TimeSince(start) << " ms"; 27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org captured_frames_ = 0; 27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureState(CS_RUNNING); 27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_STARTING; 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 282f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Critical section blocks Stop from shutting down during callbacks from capture 283f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// thread to OnIncomingCapturedFrame. Note that the crit is try-locked in 284f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// OnFrameCaptured, as the lock ordering between this and the system component 285f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// controlling the camera is reversed: system frame -> OnIncomingCapturedFrame; 286f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Stop -> system stop camera). 28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::Stop() { 288f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org talk_base::CritScope cs(&critical_section_stopping_); 28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (IsRunning()) { 29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org talk_base::Thread::Current()->Clear(this); 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->StopCapture(); 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->DeRegisterCaptureDataCallback(); 29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Determine if the VCM exposes any drop stats we can use. 29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org double drop_ratio = 0.0; 29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::string camera_id(GetId()); 29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Camera '" << camera_id << "' stopped after capturing " 29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << captured_frames_ << " frames and dropping " 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << drop_ratio << "%"; 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(NULL); 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::IsRunning() { 30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (module_ != NULL && module_->CaptureStarted()); 30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetPreferredFourccs( 30928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<uint32>* fourccs) { 31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!fourccs) { 31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->clear(); 31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->push_back(kSupportedFourCCs[i].fourcc); 31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::OnIncomingCapturedFrame(const int32_t id, 32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::I420VideoFrame& sample) { 323f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // This would be a normal CritScope, except that it's possible that: 324f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // (1) whatever system component producing this frame has taken a lock, and 325f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // (2) Stop() probably calls back into that system component, which may take 326f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // the same lock. Due to the reversed order, we have to try-lock in order to 327f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // avoid a potential deadlock. Besides, if we can't enter because we're 328f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // stopping, we may as well drop the frame. 329f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org talk_base::TryCritScope cs(&critical_section_stopping_); 330f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org if (!cs.locked() || !IsRunning()) { 331f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org // Capturer has been stopped or is in the process of stopping. 332f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org return; 333f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org } 33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 33528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++captured_frames_; 33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Log the size and pixel aspect ratio of the first captured frame. 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (1 == captured_frames_) { 33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Captured frame size " 33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << sample.width() << "x" << sample.height() 34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << ". Expected format " << GetCaptureFormat()->ToString(); 34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Signal down stream components on captured frame. 34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The CapturedFrame class doesn't support planes. We have to ExtractBuffer 34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // to one block for it. 34628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int length = webrtc::CalcBufferSize(webrtc::kI420, 34728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org sample.width(), sample.height()); 34816d6254e8c6c865ca65cc943e03fa635dc5c6a63wu@webrtc.org capture_buffer_.resize(length); 34916d6254e8c6c865ca65cc943e03fa635dc5c6a63wu@webrtc.org // TODO(ronghuawu): Refactor the WebRtcCapturedFrame to avoid memory copy. 35016d6254e8c6c865ca65cc943e03fa635dc5c6a63wu@webrtc.org webrtc::ExtractBuffer(sample, length, &capture_buffer_[0]); 35116d6254e8c6c865ca65cc943e03fa635dc5c6a63wu@webrtc.org WebRtcCapturedFrame frame(sample, &capture_buffer_[0], length); 35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SignalFrameCaptured(this, &frame); 35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id, 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const int32_t delay) { 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Capture delay changed to " << delay << " ms"; 35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WebRtcCapturedFrame 36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::I420VideoFrame& sample, 36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void* buffer, 36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int length) { 36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org width = sample.width(); 36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org height = sample.height(); 36628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = FOURCC_I420; 36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(hellner): Support pixel aspect ratio (for OSX). 36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_width = 1; 36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_height = 1; 37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds). 37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org elapsed_time = sample.render_time_ms() * talk_base::kNumNanosecsPerMillisec; 37228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org time_stamp = elapsed_time; 37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org data_size = length; 37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org data = buffer; 37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace cricket 37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif // HAVE_WEBRTC_VIDEO 380