webrtcvideocapturer.cc revision 39f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81
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 {
5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  uint32 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) {
8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  uint32 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),
13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      module_(NULL),
133e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org      captured_frames_(0),
134e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org      start_thread_(nullptr) {
1354f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org  set_frame_factory(new WebRtcVideoFrameFactory());
13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
13728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory)
13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    : factory_(factory),
14028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      module_(NULL),
141e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org      captured_frames_(0),
142e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org      start_thread_(nullptr) {
1434f0d401faecf5d8a4c82e6e2223651ef13ad8e31buildbot@webrtc.org  set_frame_factory(new WebRtcVideoFrameFactory());
14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
14628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcVideoCapturer::~WebRtcVideoCapturer() {
14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (module_) {
14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    module_->Release();
14928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(const Device& device) {
153e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  DCHECK(!start_thread_);
15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (module_) {
15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "The capturer is already initialized";
15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0);
16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!info) {
16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Find the desired camera, by name.
16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // In the future, comparing IDs will be more robust.
16628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(juberti): Figure what's needed to allow this.
16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int num_cams = info->NumberOfDevices();
16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  char vcm_id[256] = "";
16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  bool found = false;
17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  for (int index = 0; index < num_cams; ++index) {
17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    char vcm_name[256];
17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name),
17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                            vcm_id, ARRAY_SIZE(vcm_id)) != -1) {
17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      if (device.name == reinterpret_cast<char*>(vcm_name)) {
17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        found = true;
17628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        break;
17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      }
17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!found) {
18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    factory_->DestroyDeviceInfo(info);
18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
18428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Enumerate the supported formats.
18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(juberti): Find out why this starts/stops the camera...
18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  std::vector<VideoFormat> supported;
18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  int32_t num_caps = info->NumberOfCapabilities(vcm_id);
19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  for (int32_t i = 0; i < num_caps; ++i) {
19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    webrtc::VideoCaptureCapability cap;
19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    if (info->GetCapability(vcm_id, i, cap) != -1) {
19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      VideoFormat format;
19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      if (CapabilityToFormat(cap, &format)) {
19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        supported.push_back(format);
19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      } else {
19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org        LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format "
19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                        << cap.rawType;
19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org      }
20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    }
20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  factory_->DestroyDeviceInfo(info);
20339f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk
20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (supported.empty()) {
20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id;
20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
20839f2b0c870c59dbc37d4f4d8cdb5fff7a7ae5b81Yuriy Shevchuk
20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  module_ = factory_->Create(0, vcm_id);
21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!module_) {
21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id;
21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // It is safe to change member attributes now.
21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  module_->AddRef();
21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SetId(device.id);
21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SetSupportedFormats(supported);
2191226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org
2201226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  // Ensure these 2 have the same value.
2211226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  SetApplyRotation(module_->GetApplyRotation());
2221226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org
22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
22428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::Init(webrtc::VideoCaptureModule* module) {
227e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  DCHECK(!start_thread_);
22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (module_) {
22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "The capturer is already initialized";
23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!module) {
23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Invalid VCM supplied";
23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(juberti): Set id and formats.
23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  (module_ = module)->AddRef();
23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired,
24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                               VideoFormat* best_format) {
24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!best_format) {
24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) {
24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // We maybe using a manually injected VCM which doesn't support enum.
24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // Use the desired format as the best format.
25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    best_format->width = desired.width;
25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    best_format->height = desired.height;
25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    best_format->fourcc = FOURCC_I420;
25328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    best_format->interval = desired.interval;
25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_INFO) << "Failed to find best capture format,"
25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << " fall back to the requested format "
25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << best_format->ToString();
25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
2601226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.orgbool WebRtcVideoCapturer::SetApplyRotation(bool enable) {
26164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  // Can't take lock here as this will cause deadlock with
26264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  // OnIncomingCapturedFrame. In fact, the whole method, including methods it
26364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  // calls, can't take lock.
264d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(module_);
2651226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org
26664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  const std::string group_name =
26764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      webrtc::field_trial::FindFullName("WebRTC-CVO");
26864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
26964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  if (group_name == "Disabled") {
27064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    return true;
27164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
27264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
2731226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  if (!VideoCapturer::SetApplyRotation(enable)) {
2741226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org    return false;
2751226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  }
2761226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  return module_->SetApplyRotation(enable);
2771226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org}
27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgCaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) {
28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!module_) {
28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "The capturer has not been initialized";
28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return CS_NO_DEVICE;
28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
285d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&critical_section_stopping_);
28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (IsRunning()) {
28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "The capturer is already running";
28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return CS_FAILED;
28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
291e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  DCHECK(!start_thread_);
292e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org
293e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  start_thread_ = rtc::Thread::Current();
294e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org
29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SetCaptureFormat(&capture_format);
29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  webrtc::VideoCaptureCapability cap;
29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!FormatToCapability(capture_format, &cap)) {
29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Invalid capture format specified";
30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return CS_FAILED;
30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
30228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
30328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  std::string camera_id(GetId());
304d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  uint32 start = rtc::Time();
3057433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org  module_->RegisterCaptureDataCallback(*this);
3067433a088d2e97993266b66c102b0866aa90b4424mallinath@webrtc.org  if (module_->StartCapture(cap) != 0) {
30728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_ERROR) << "Camera '" << camera_id << "' failed to start";
308e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    start_thread_ = nullptr;
30928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return CS_FAILED;
31028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
31128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
31228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_INFO) << "Camera '" << camera_id << "' started with format "
31328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org               << capture_format.ToString() << ", elapsed time "
314d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org               << rtc::TimeSince(start) << " ms";
31528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
31628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  captured_frames_ = 0;
31728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SetCaptureState(CS_RUNNING);
31828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return CS_STARTING;
31928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
32028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
321f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Critical section blocks Stop from shutting down during callbacks from capture
322f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// thread to OnIncomingCapturedFrame. Note that the crit is try-locked in
323f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// OnFrameCaptured, as the lock ordering between this and the system component
324f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// controlling the camera is reversed: system frame -> OnIncomingCapturedFrame;
325f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org// Stop -> system stop camera).
32628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::Stop() {
327d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&critical_section_stopping_);
32828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (IsRunning()) {
329e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    DCHECK(start_thread_);
330d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Thread::Current()->Clear(this);
33128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    module_->StopCapture();
33228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    module_->DeRegisterCaptureDataCallback();
33328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
33428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    // TODO(juberti): Determine if the VCM exposes any drop stats we can use.
33528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    double drop_ratio = 0.0;
33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    std::string camera_id(GetId());
33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_INFO) << "Camera '" << camera_id << "' stopped after capturing "
33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << captured_frames_ << " frames and dropping "
33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << drop_ratio << "%";
34028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  SetCaptureFormat(NULL);
342e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  start_thread_ = nullptr;
34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::IsRunning() {
34628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return (module_ != NULL && module_->CaptureStarted());
34728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
34828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool WebRtcVideoCapturer::GetPreferredFourccs(
35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    std::vector<uint32>* fourccs) {
35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (!fourccs) {
35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    return false;
35328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
35428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  fourccs->clear();
35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    fourccs->push_back(kSupportedFourCCs[i].fourcc);
35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
35928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  return true;
36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
362af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.orgvoid WebRtcVideoCapturer::OnIncomingCapturedFrame(
363af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org    const int32_t id,
364af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org    const webrtc::I420VideoFrame& sample) {
365f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // This would be a normal CritScope, except that it's possible that:
366f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // (1) whatever system component producing this frame has taken a lock, and
367f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // (2) Stop() probably calls back into that system component, which may take
368f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // the same lock. Due to the reversed order, we have to try-lock in order to
369f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // avoid a potential deadlock. Besides, if we can't enter because we're
370f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  // stopping, we may as well drop the frame.
371d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::TryCritScope cs(&critical_section_stopping_);
372f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  if (!cs.locked() || !IsRunning()) {
373f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org    // Capturer has been stopped or is in the process of stopping.
374f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org    return;
375f6d6ed0c66457170be3f3b2bc214cd7141e441a4wu@webrtc.org  }
37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  ++captured_frames_;
37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Log the size and pixel aspect ratio of the first captured frame.
37928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  if (1 == captured_frames_) {
38028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org    LOG(LS_INFO) << "Captured frame size "
3812056ee3e3c7683ae4b2c4b12da99c3105c4f46a9magjed@webrtc.org                 << sample.width() << "x" << sample.height()
38228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                 << ". Expected format " << GetCaptureFormat()->ToString();
38328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  }
38428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
385e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  if (start_thread_->IsCurrent()) {
3862056ee3e3c7683ae4b2c4b12da99c3105c4f46a9magjed@webrtc.org    SignalFrameCapturedOnStartThread(&sample);
387e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  } else {
388e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    // This currently happens on with at least VideoCaptureModuleV4L2 and
389e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    // possibly other implementations of WebRTC's VideoCaptureModule.
390e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    // In order to maintain the threading contract with the upper layers and
391e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    // consistency with other capturers such as in Chrome, we need to do a
392e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    // thread hop.
393e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org    start_thread_->Invoke<void>(
394e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org        rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread,
3952056ee3e3c7683ae4b2c4b12da99c3105c4f46a9magjed@webrtc.org                  this, &sample));
396e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  }
39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
39928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id,
40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                                const int32_t delay) {
40128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  LOG(LS_INFO) << "Capture delay changed to " << delay << " ms";
40228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
40328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
404e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.orgvoid WebRtcVideoCapturer::SignalFrameCapturedOnStartThread(
405af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org    const webrtc::I420VideoFrame* frame) {
406e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  DCHECK(start_thread_->IsCurrent());
407e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  // Signal down stream components on captured frame.
408e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  // The CapturedFrame class doesn't support planes. We have to ExtractBuffer
409e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  // to one block for it.
410e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  size_t length =
411e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org      webrtc::CalcBufferSize(webrtc::kI420, frame->width(), frame->height());
412e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  capture_buffer_.resize(length);
413e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  // TODO(magjed): Refactor the WebRtcCapturedFrame to avoid memory copy or
414e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  // take over ownership of the buffer held by |frame| if that's possible.
415e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  webrtc::ExtractBuffer(*frame, length, &capture_buffer_[0]);
416e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  WebRtcCapturedFrame webrtc_frame(*frame, &capture_buffer_[0], length);
417e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org  SignalFrameCaptured(this, &webrtc_frame);
418e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org}
419e07710cc91b3dccd7fea7df3d99c304f419babdatommi@webrtc.org
42028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// WebRtcCapturedFrame
42128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgWebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::I420VideoFrame& sample,
42228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org                                         void* buffer,
4234591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                         size_t length) {
42428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  width = sample.width();
42528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  height = sample.height();
42628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  fourcc = FOURCC_I420;
42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // TODO(hellner): Support pixel aspect ratio (for OSX).
42828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  pixel_width = 1;
42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  pixel_height = 1;
43028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds).
431d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  elapsed_time = sample.render_time_ms() * rtc::kNumNanosecsPerMillisec;
43228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  time_stamp = elapsed_time;
4334591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org  data_size = rtc::checked_cast<uint32>(length);
43428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org  data = buffer;
4351226e926e6104322d9b99026b98f515cb4d40fd4guoweis@webrtc.org  rotation = sample.rotation();
43628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}
43728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
43828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}  // namespace cricket
43928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org
44028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
441