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