webrtcvideocapturer.cc revision 5d9b92b53daf4db78fd090be4e210e07f786120d
15f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org/* 25f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * libjingle 35f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Copyright 2011 Google Inc. 45f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 55f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * Redistribution and use in source and binary forms, with or without 65f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * modification, are permitted provided that the following conditions are met: 75f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 85f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 95f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * this list of conditions and the following disclaimer. 105f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 115f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * this list of conditions and the following disclaimer in the documentation 125f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * and/or other materials provided with the distribution. 135f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 3. The name of the author may not be used to endorse or promote products 145f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * derived from this software without specific prior written permission. 155f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * 165f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 175f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 185f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 195f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 205f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 215f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 225f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 235f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 245f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 255f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 265f93d0a140515e3b8cdd1b9a4c6f5871144e5deejlmiller@webrtc.org */ 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 35a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h" 36a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "talk/media/webrtc/webrtcvideoframefactory.h" 37e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org#include "webrtc/base/bind.h" 38e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org#include "webrtc/base/checks.h" 39d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/criticalsection.h" 40d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/logging.h" 414591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org#include "webrtc/base/safe_conversions.h" 42d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/thread.h" 43d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/timeutils.h" 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 45d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/win32.h" // Need this to #include the impl files. 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "webrtc/modules/video_capture/include/video_capture_factory.h" 4764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh#include "webrtc/system_wrappers/interface/field_trial.h" 4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket { 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstruct kVideoFourCCEntry { 520c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t fourcc; 5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type; 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This indicates our format preferences and defines a mapping between 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// webrtc::RawVideoType (from video_capture_defines.h) to our FOURCCs. 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic kVideoFourCCEntry kSupportedFourCCs[] = { 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_I420, webrtc::kVideoI420 }, // 12 bpp, no conversion. 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YV12, webrtc::kVideoYV12 }, // 12 bpp, no conversion. 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YUY2, webrtc::kVideoYUY2 }, // 16 bpp, fast conversion. 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_UYVY, webrtc::kVideoUYVY }, // 16 bpp, fast conversion. 63fa5fcd671de2f6db6249c3cdd2908f4fc39d84a0buildbot@webrtc.org { FOURCC_NV12, webrtc::kVideoNV12 }, // 12 bpp, fast conversion. 64fa5fcd671de2f6db6249c3cdd2908f4fc39d84a0buildbot@webrtc.org { FOURCC_NV21, webrtc::kVideoNV21 }, // 12 bpp, fast conversion. 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_MJPG, webrtc::kVideoMJPEG }, // compressed, slow conversion. 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_ARGB, webrtc::kVideoARGB }, // 32 bpp, slow conversion. 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_24BG, webrtc::kVideoRGB24 }, // 24 bpp, slow conversion. 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass WebRtcVcmFactory : public WebRtcVcmFactoryInterface { 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule* Create(int id, const char* device) { 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::Create(id, device); 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) { 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::CreateDeviceInfo(id); 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) { 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete info; 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap, 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* format) { 850c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t fourcc = 0; 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].webrtc_type == cap.rawType) { 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = kSupportedFourCCs[i].fourcc; 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (fourcc == 0) { 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->fourcc = fourcc; 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->width = cap.width; 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->height = cap.height; 9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->interval = VideoFormat::FpsToInterval(cap.maxFPS); 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool FormatToCapability(const VideoFormat& format, 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability* cap) { 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown; 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].fourcc == format.fourcc) { 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc_type = kSupportedFourCCs[i].webrtc_type; 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (webrtc_type == webrtc::kVideoUnknown) { 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->width = format.width; 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->height = format.height; 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->maxFPS = VideoFormat::IntervalToFps(format.interval); 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->expectedCaptureDelay = 0; 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->rawType = webrtc_type; 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->codecType = webrtc::kVideoCodecUnknown; 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->interlaced = false; 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Implementation of class WebRtcVideoCapturer 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer() 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(new WebRtcVcmFactory), 132cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_(nullptr), 133e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org captured_frames_(0), 134cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström start_thread_(nullptr), 135cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_(nullptr) { 1364f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org set_frame_factory(new WebRtcVideoFrameFactory()); 13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory) 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(factory), 141cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_(nullptr), 142e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org captured_frames_(0), 143cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström start_thread_(nullptr), 144cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_(nullptr) { 1454f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org set_frame_factory(new WebRtcVideoFrameFactory()); 14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::~WebRtcVideoCapturer() { 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->Release(); 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(const Device& device) { 15591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!start_thread_); 15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0); 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!info) { 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Find the desired camera, by name. 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // In the future, comparing IDs will be more robust. 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Figure what's needed to allow this. 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int num_cams = info->NumberOfDevices(); 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_id[256] = ""; 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool found = false; 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int index = 0; index < num_cams; ++index) { 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_name[256]; 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name), 17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org vcm_id, ARRAY_SIZE(vcm_id)) != -1) { 17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (device.name == reinterpret_cast<char*>(vcm_name)) { 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org found = true; 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!found) { 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id; 18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Enumerate the supported formats. 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Find out why this starts/stops the camera... 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<VideoFormat> supported; 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int32_t num_caps = info->NumberOfCapabilities(vcm_id); 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int32_t i = 0; i < num_caps; ++i) { 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (info->GetCapability(vcm_id, i, cap) != -1) { 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat format; 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (CapabilityToFormat(cap, &format)) { 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org supported.push_back(format); 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format " 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << cap.rawType; 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 20539f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk 20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (supported.empty()) { 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id; 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21039f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk 21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_ = factory_->Create(0, vcm_id); 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id; 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // It is safe to change member attributes now. 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->AddRef(); 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetId(device.id); 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetSupportedFormats(supported); 2211226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 2221226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org // Ensure these 2 have the same value. 2231226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org SetApplyRotation(module_->GetApplyRotation()); 2241226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(webrtc::VideoCaptureModule* module) { 22991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!start_thread_); 23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module) { 23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid VCM supplied"; 23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Set id and formats. 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org (module_ = module)->AddRef(); 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired, 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* best_format) { 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!best_format) { 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) { 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We maybe using a manually injected VCM which doesn't support enum. 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Use the desired format as the best format. 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->width = desired.width; 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->height = desired.height; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->fourcc = FOURCC_I420; 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->interval = desired.interval; 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Failed to find best capture format," 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " fall back to the requested format " 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << best_format->ToString(); 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 2621226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.orgbool WebRtcVideoCapturer::SetApplyRotation(bool enable) { 26364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // Can't take lock here as this will cause deadlock with 26464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // OnIncomingCapturedFrame. In fact, the whole method, including methods it 26564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // calls, can't take lock. 26691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(module_); 2671226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 268bd3842808996dbb85007242214352f1e6ebd3d17jbauch const std::string group_name = 26964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh webrtc::field_trial::FindFullName("WebRTC-CVO"); 27064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh 27164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh if (group_name == "Disabled") { 27264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh return true; 27364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh } 27464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh 2751226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org if (!VideoCapturer::SetApplyRotation(enable)) { 2761226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org return false; 2771226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org } 2781226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org return module_->SetApplyRotation(enable); 2791226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org} 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgCaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) { 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer has not been initialized"; 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_NO_DEVICE; 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 286cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (start_thread_) { 28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already running"; 28891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()) 289cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << "Trying to start capturer on different threads"; 29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 293e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = rtc::Thread::Current(); 29491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!async_invoker_); 295cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(new rtc::AsyncInvoker()); 296cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström captured_frames_ = 0; 297e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org 29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(&capture_format); 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!FormatToCapability(capture_format, &cap)) { 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid capture format specified"; 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3060c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t start = rtc::Time(); 3077433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org module_->RegisterCaptureDataCallback(*this); 3087433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org if (module_->StartCapture(cap) != 0) { 309cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_ERROR) << "Camera '" << GetId() << "' failed to start"; 310cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_->DeRegisterCaptureDataCallback(); 311cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(); 312cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström SetCaptureFormat(nullptr); 313e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = nullptr; 31428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 317cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Camera '" << GetId() << "' started with format " 31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << capture_format.ToString() << ", elapsed time " 319d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org << rtc::TimeSince(start) << " ms"; 32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureState(CS_RUNNING); 32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_STARTING; 32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::Stop() { 326cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (!start_thread_) { 327cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_ERROR) << "The capturer is already stopped"; 328cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström return; 329cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström } 33091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 33191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()); 33291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 33328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (IsRunning()) { 334cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // The module is responsible for OnIncomingCapturedFrame being called, if 335cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // we stop it we will get no further callbacks. 33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->StopCapture(); 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 338cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_->DeRegisterCaptureDataCallback(); 339cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 340cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // TODO(juberti): Determine if the VCM exposes any drop stats we can use. 341cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström double drop_ratio = 0.0; 342cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Camera '" << GetId() << "' stopped after capturing " 343cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << captured_frames_ << " frames and dropping " 344cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << drop_ratio << "%"; 345cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 346cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Clear any pending async invokes (that OnIncomingCapturedFrame may have 347cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // caused). 348cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(); 349cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(NULL); 351e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = nullptr; 35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::IsRunning() { 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (module_ != NULL && module_->CaptureStarted()); 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3580c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) { 35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!fourccs) { 36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->clear(); 36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) { 36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->push_back(kSupportedFourCCs[i].fourcc); 36628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 370af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.orgvoid WebRtcVideoCapturer::OnIncomingCapturedFrame( 371af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org const int32_t id, 3724765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez const webrtc::VideoFrame& sample) { 373cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // This can only happen between Start() and Stop(). 37491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 37591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 376e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org if (start_thread_->IsCurrent()) { 377cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström SignalFrameCapturedOnStartThread(sample); 378e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org } else { 379e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // This currently happens on with at least VideoCaptureModuleV4L2 and 380e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // possibly other implementations of WebRTC's VideoCaptureModule. 381e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // In order to maintain the threading contract with the upper layers and 382e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // consistency with other capturers such as in Chrome, we need to do a 383e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // thread hop. 384cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Note that Stop() can cause the async invoke call to be cancelled. 3855d9b92b53daf4db78fd090be4e210e07f786120dnoahric async_invoker_->AsyncInvoke<void>( 3865d9b92b53daf4db78fd090be4e210e07f786120dnoahric start_thread_, 3875d9b92b53daf4db78fd090be4e210e07f786120dnoahric // Note that Bind captures by value, so there's an intermediate copy 3885d9b92b53daf4db78fd090be4e210e07f786120dnoahric // of sample. 3895d9b92b53daf4db78fd090be4e210e07f786120dnoahric rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, this, 3905d9b92b53daf4db78fd090be4e210e07f786120dnoahric sample)); 391e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org } 39228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 39328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id, 39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const int32_t delay) { 39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Capture delay changed to " << delay << " ms"; 39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 399e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.orgvoid WebRtcVideoCapturer::SignalFrameCapturedOnStartThread( 4005d9b92b53daf4db78fd090be4e210e07f786120dnoahric const webrtc::VideoFrame& frame) { 401cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // This can only happen between Start() and Stop(). 40291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 40391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()); 40491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 405cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 406cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström ++captured_frames_; 407cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Log the size and pixel aspect ratio of the first captured frame. 408cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (1 == captured_frames_) { 409cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Captured frame size " 410cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << frame.width() << "x" << frame.height() 411cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << ". Expected format " << GetCaptureFormat()->ToString(); 412cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström } 413cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 414e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // Signal down stream components on captured frame. 415e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // The CapturedFrame class doesn't support planes. We have to ExtractBuffer 416e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // to one block for it. 417e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org size_t length = 418cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström webrtc::CalcBufferSize(webrtc::kI420, frame.width(), frame.height()); 419e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org capture_buffer_.resize(length); 420e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // TODO(magjed): Refactor the WebRtcCapturedFrame to avoid memory copy or 421e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // take over ownership of the buffer held by |frame| if that's possible. 422cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström webrtc::ExtractBuffer(frame, length, &capture_buffer_[0]); 423cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström WebRtcCapturedFrame webrtc_frame(frame, &capture_buffer_[0], length); 424e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org SignalFrameCaptured(this, &webrtc_frame); 425e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org} 426e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org 42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WebRtcCapturedFrame 4284765070b8d6f024509c717c04d9b708750666927Miguel Casas-SanchezWebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::VideoFrame& sample, 42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void* buffer, 4304591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t length) { 43128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org width = sample.width(); 43228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org height = sample.height(); 43328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = FOURCC_I420; 43428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(hellner): Support pixel aspect ratio (for OSX). 43528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_width = 1; 43628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_height = 1; 43728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds). 438b09b660c53ff2c499d149e05e5c435f5057273fcmagjed time_stamp = sample.render_time_ms() * rtc::kNumNanosecsPerMillisec; 4390c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström data_size = rtc::checked_cast<uint32_t>(length); 44028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org data = buffer; 4411226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org rotation = sample.rotation(); 44228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 44328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 44428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace cricket 44528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 44628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif // HAVE_WEBRTC_VIDEO 447