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" 375237aaf243d29732f59557361b7a993c0a18cf0etfarina#include "webrtc/base/arraysize.h" 38e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org#include "webrtc/base/bind.h" 39e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org#include "webrtc/base/checks.h" 40d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/criticalsection.h" 41d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/logging.h" 424591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org#include "webrtc/base/safe_conversions.h" 43d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/thread.h" 44d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/timeutils.h" 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 46d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org#include "webrtc/base/win32.h" // Need this to #include the impl files. 475dda80abea311731144b1d544aff61c408412f12Henrik Kjellander#include "webrtc/modules/video_capture/video_capture_factory.h" 4898f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/field_trial.h" 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace cricket { 5128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstruct kVideoFourCCEntry { 530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t fourcc; 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type; 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This indicates our format preferences and defines a mapping between 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// webrtc::RawVideoType (from video_capture_defines.h) to our FOURCCs. 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic kVideoFourCCEntry kSupportedFourCCs[] = { 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_I420, webrtc::kVideoI420 }, // 12 bpp, no conversion. 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YV12, webrtc::kVideoYV12 }, // 12 bpp, no conversion. 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_YUY2, webrtc::kVideoYUY2 }, // 16 bpp, fast conversion. 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_UYVY, webrtc::kVideoUYVY }, // 16 bpp, fast conversion. 64fa5fcd671de2f6db6249c3cdd2908f4fc39d84a0buildbot@webrtc.org { FOURCC_NV12, webrtc::kVideoNV12 }, // 12 bpp, fast conversion. 65fa5fcd671de2f6db6249c3cdd2908f4fc39d84a0buildbot@webrtc.org { FOURCC_NV21, webrtc::kVideoNV21 }, // 12 bpp, fast conversion. 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_MJPG, webrtc::kVideoMJPEG }, // compressed, slow conversion. 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_ARGB, webrtc::kVideoARGB }, // 32 bpp, slow conversion. 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org { FOURCC_24BG, webrtc::kVideoRGB24 }, // 24 bpp, slow conversion. 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgclass WebRtcVcmFactory : public WebRtcVcmFactoryInterface { 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org public: 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule* Create(int id, const char* device) { 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::Create(id, device); 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) { 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return webrtc::VideoCaptureFactory::CreateDeviceInfo(id); 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) { 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org delete info; 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap, 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* format) { 860c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t fourcc = 0; 875237aaf243d29732f59557361b7a993c0a18cf0etfarina for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) { 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].webrtc_type == cap.rawType) { 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = kSupportedFourCCs[i].fourcc; 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (fourcc == 0) { 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 9628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->fourcc = fourcc; 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->width = cap.width; 9928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->height = cap.height; 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format->interval = VideoFormat::FpsToInterval(cap.maxFPS); 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic bool FormatToCapability(const VideoFormat& format, 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability* cap) { 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown; 1075237aaf243d29732f59557361b7a993c0a18cf0etfarina for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) { 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (kSupportedFourCCs[i].fourcc == format.fourcc) { 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc_type = kSupportedFourCCs[i].webrtc_type; 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (webrtc_type == webrtc::kVideoUnknown) { 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->width = format.width; 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->height = format.height; 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->maxFPS = VideoFormat::IntervalToFps(format.interval); 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->expectedCaptureDelay = 0; 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->rawType = webrtc_type; 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->codecType = webrtc::kVideoCodecUnknown; 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cap->interlaced = false; 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Implementation of class WebRtcVideoCapturer 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/////////////////////////////////////////////////////////////////////////// 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer() 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(new WebRtcVcmFactory), 133cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_(nullptr), 134e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org captured_frames_(0), 135cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström start_thread_(nullptr), 136cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_(nullptr) { 1374f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org set_frame_factory(new WebRtcVideoFrameFactory()); 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory) 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : factory_(factory), 142cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_(nullptr), 143e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org captured_frames_(0), 144cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström start_thread_(nullptr), 145cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_(nullptr) { 1464f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org set_frame_factory(new WebRtcVideoFrameFactory()); 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::~WebRtcVideoCapturer() { 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->Release(); 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(const Device& device) { 15691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!start_thread_); 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0); 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!info) { 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Find the desired camera, by name. 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // In the future, comparing IDs will be more robust. 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Figure what's needed to allow this. 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int num_cams = info->NumberOfDevices(); 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_id[256] = ""; 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool found = false; 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int index = 0; index < num_cams; ++index) { 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org char vcm_name[256]; 1755237aaf243d29732f59557361b7a993c0a18cf0etfarina if (info->GetDeviceName(index, vcm_name, arraysize(vcm_name), vcm_id, 1765237aaf243d29732f59557361b7a993c0a18cf0etfarina arraysize(vcm_id)) != -1) { 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (device.name == reinterpret_cast<char*>(vcm_name)) { 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org found = true; 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org break; 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!found) { 18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id; 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Enumerate the supported formats. 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Find out why this starts/stops the camera... 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<VideoFormat> supported; 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int32_t num_caps = info->NumberOfCapabilities(vcm_id); 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int32_t i = 0; i < num_caps; ++i) { 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (info->GetCapability(vcm_id, i, cap) != -1) { 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat format; 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (CapabilityToFormat(cap, &format)) { 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org supported.push_back(format); 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format " 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << cap.rawType; 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org factory_->DestroyDeviceInfo(info); 20639f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (supported.empty()) { 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id; 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21139f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_ = factory_->Create(0, vcm_id); 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id; 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // It is safe to change member attributes now. 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->AddRef(); 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetId(device.id); 22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetSupportedFormats(supported); 2221226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 2231226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org // Ensure these 2 have the same value. 2241226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org SetApplyRotation(module_->GetApplyRotation()); 2251226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(webrtc::VideoCaptureModule* module) { 23091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!start_thread_); 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (module_) { 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already initialized"; 23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module) { 23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid VCM supplied"; 23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(juberti): Set id and formats. 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org (module_ = module)->AddRef(); 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired, 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org VideoFormat* best_format) { 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!best_format) { 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) { 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We maybe using a manually injected VCM which doesn't support enum. 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Use the desired format as the best format. 25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->width = desired.width; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->height = desired.height; 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->fourcc = FOURCC_I420; 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_format->interval = desired.interval; 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Failed to find best capture format," 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << " fall back to the requested format " 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << best_format->ToString(); 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 2631226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.orgbool WebRtcVideoCapturer::SetApplyRotation(bool enable) { 26464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // Can't take lock here as this will cause deadlock with 26564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // OnIncomingCapturedFrame. In fact, the whole method, including methods it 26664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh // calls, can't take lock. 26791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(module_); 2681226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org 269bd3842808996dbb85007242214352f1e6ebd3d17jbauch const std::string group_name = 27064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh webrtc::field_trial::FindFullName("WebRTC-CVO"); 27164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh 27264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh if (group_name == "Disabled") { 27364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh return true; 27464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh } 27564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh 2761226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org if (!VideoCapturer::SetApplyRotation(enable)) { 2771226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org return false; 2781226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org } 2791226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org return module_->SetApplyRotation(enable); 2801226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org} 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgCaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) { 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!module_) { 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer has not been initialized"; 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_NO_DEVICE; 28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 287cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (start_thread_) { 28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "The capturer is already running"; 28991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()) 290cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << "Trying to start capturer on different threads"; 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 294e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = rtc::Thread::Current(); 29591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(!async_invoker_); 296cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(new rtc::AsyncInvoker()); 297cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström captured_frames_ = 0; 298e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(&capture_format); 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org webrtc::VideoCaptureCapability cap; 30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!FormatToCapability(capture_format, &cap)) { 30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_ERROR) << "Invalid capture format specified"; 30428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 30528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 30628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3070c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström uint32_t start = rtc::Time(); 3087433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org module_->RegisterCaptureDataCallback(*this); 3097433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org if (module_->StartCapture(cap) != 0) { 310cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_ERROR) << "Camera '" << GetId() << "' failed to start"; 311cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_->DeRegisterCaptureDataCallback(); 312cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(); 313cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström SetCaptureFormat(nullptr); 314e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = nullptr; 31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_FAILED; 31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 318cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Camera '" << GetId() << "' started with format " 31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << capture_format.ToString() << ", elapsed time " 320d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org << rtc::TimeSince(start) << " ms"; 32128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureState(CS_RUNNING); 32328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return CS_STARTING; 32428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 32528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::Stop() { 327cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (!start_thread_) { 328cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_ERROR) << "The capturer is already stopped"; 329cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström return; 330cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström } 33191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 33291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()); 33391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (IsRunning()) { 335cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // The module is responsible for OnIncomingCapturedFrame being called, if 336cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // we stop it we will get no further callbacks. 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org module_->StopCapture(); 33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 339cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström module_->DeRegisterCaptureDataCallback(); 340cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 341cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // TODO(juberti): Determine if the VCM exposes any drop stats we can use. 342cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström double drop_ratio = 0.0; 343cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Camera '" << GetId() << "' stopped after capturing " 344cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << captured_frames_ << " frames and dropping " 345cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << drop_ratio << "%"; 346cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 347cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Clear any pending async invokes (that OnIncomingCapturedFrame may have 348cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // caused). 349cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström async_invoker_.reset(); 350cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetCaptureFormat(NULL); 352e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org start_thread_ = nullptr; 3530de97f1b748d8238fe3a7ad8d7afb2b6cb456a3ehbos SetCaptureState(CS_STOPPED); 35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::IsRunning() { 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (module_ != NULL && module_->CaptureStarted()); 35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3600c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) { 36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!fourccs) { 36228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->clear(); 3665237aaf243d29732f59557361b7a993c0a18cf0etfarina for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) { 36728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourccs->push_back(kSupportedFourCCs[i].fourcc); 36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 372af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.orgvoid WebRtcVideoCapturer::OnIncomingCapturedFrame( 373af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org const int32_t id, 3744765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez const webrtc::VideoFrame& sample) { 375cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // This can only happen between Start() and Stop(). 37691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 37791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 378e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org if (start_thread_->IsCurrent()) { 379cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström SignalFrameCapturedOnStartThread(sample); 380e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org } else { 381e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // This currently happens on with at least VideoCaptureModuleV4L2 and 382e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // possibly other implementations of WebRTC's VideoCaptureModule. 383e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // In order to maintain the threading contract with the upper layers and 384e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // consistency with other capturers such as in Chrome, we need to do a 385e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // thread hop. 386cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Note that Stop() can cause the async invoke call to be cancelled. 3875d9b92b53daf4db78fd090be4e210e07f786120dnoahric async_invoker_->AsyncInvoke<void>( 3885d9b92b53daf4db78fd090be4e210e07f786120dnoahric start_thread_, 3895d9b92b53daf4db78fd090be4e210e07f786120dnoahric // Note that Bind captures by value, so there's an intermediate copy 3905d9b92b53daf4db78fd090be4e210e07f786120dnoahric // of sample. 3915d9b92b53daf4db78fd090be4e210e07f786120dnoahric rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, this, 3925d9b92b53daf4db78fd090be4e210e07f786120dnoahric sample)); 393e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org } 39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id, 39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const int32_t delay) { 39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_INFO) << "Capture delay changed to " << delay << " ms"; 39928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 401e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.orgvoid WebRtcVideoCapturer::SignalFrameCapturedOnStartThread( 4025d9b92b53daf4db78fd090be4e210e07f786120dnoahric const webrtc::VideoFrame& frame) { 403cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // This can only happen between Start() and Stop(). 40491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_); 40591d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(start_thread_->IsCurrent()); 40691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg RTC_DCHECK(async_invoker_); 407cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 408cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström ++captured_frames_; 409cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström // Log the size and pixel aspect ratio of the first captured frame. 410cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström if (1 == captured_frames_) { 411cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström LOG(LS_INFO) << "Captured frame size " 412cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << frame.width() << "x" << frame.height() 413cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström << ". Expected format " << GetCaptureFormat()->ToString(); 414cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström } 415cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström 416e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // Signal down stream components on captured frame. 417e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // The CapturedFrame class doesn't support planes. We have to ExtractBuffer 418e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // to one block for it. 419e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org size_t length = 420cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström webrtc::CalcBufferSize(webrtc::kI420, frame.width(), frame.height()); 421e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org capture_buffer_.resize(length); 422e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // TODO(magjed): Refactor the WebRtcCapturedFrame to avoid memory copy or 423e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org // take over ownership of the buffer held by |frame| if that's possible. 424cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström webrtc::ExtractBuffer(frame, length, &capture_buffer_[0]); 425cbe408aa118e46e1f1dd28d201378968f00b60eaHenrik Boström WebRtcCapturedFrame webrtc_frame(frame, &capture_buffer_[0], length); 426e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org SignalFrameCaptured(this, &webrtc_frame); 427e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org} 428e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org 42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WebRtcCapturedFrame 4304765070b8d6f024509c717c04d9b708750666927Miguel Casas-SanchezWebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::VideoFrame& sample, 43128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org void* buffer, 4324591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org size_t length) { 43328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org width = sample.width(); 43428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org height = sample.height(); 43528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org fourcc = FOURCC_I420; 43628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(hellner): Support pixel aspect ratio (for OSX). 43728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_width = 1; 43828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org pixel_height = 1; 43928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds). 440b09b660c53ff2c499d149e05e5c435f5057273fcmagjed time_stamp = sample.render_time_ms() * rtc::kNumNanosecsPerMillisec; 4410c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström data_size = rtc::checked_cast<uint32_t>(length); 44228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org data = buffer; 4431226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org rotation = sample.rotation(); 44428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 44528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 44628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace cricket 44728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 44828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif // HAVE_WEBRTC_VIDEO 449