blob: a5405510597c47975370cb330471719dd7373e1d [file] [log] [blame]
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00001/*
kjellander1afca732016-02-07 20:46:45 -08002 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 *
kjellander1afca732016-02-07 20:46:45 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00009 */
henrike@webrtc.org28e20752013-07-10 00:45:36 +000010
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010011#include "webrtc/media/engine/webrtcvideocapturer.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000012
tfarina5237aaf2015-11-10 23:44:30 -080013#include "webrtc/base/arraysize.h"
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000014#include "webrtc/base/bind.h"
15#include "webrtc/base/checks.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000016#include "webrtc/base/criticalsection.h"
17#include "webrtc/base/logging.h"
Tommid44c0772016-03-11 17:12:32 -080018#include "webrtc/base/safe_conversions.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000019#include "webrtc/base/thread.h"
20#include "webrtc/base/timeutils.h"
kjellander@webrtc.org5ad12972016-02-12 06:39:40 +010021#include "webrtc/media/engine/webrtcvideoframe.h"
22#include "webrtc/media/engine/webrtcvideoframefactory.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000023
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000024#include "webrtc/base/win32.h" // Need this to #include the impl files.
Henrik Kjellander5dda80a2015-11-12 12:46:09 +010025#include "webrtc/modules/video_capture/video_capture_factory.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010026#include "webrtc/system_wrappers/include/field_trial.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28namespace cricket {
29
30struct kVideoFourCCEntry {
Peter Boström0c4e06b2015-10-07 12:23:21 +020031 uint32_t fourcc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000032 webrtc::RawVideoType webrtc_type;
33};
34
35// This indicates our format preferences and defines a mapping between
36// webrtc::RawVideoType (from video_capture_defines.h) to our FOURCCs.
37static kVideoFourCCEntry kSupportedFourCCs[] = {
38 { FOURCC_I420, webrtc::kVideoI420 }, // 12 bpp, no conversion.
39 { FOURCC_YV12, webrtc::kVideoYV12 }, // 12 bpp, no conversion.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000040 { FOURCC_YUY2, webrtc::kVideoYUY2 }, // 16 bpp, fast conversion.
41 { FOURCC_UYVY, webrtc::kVideoUYVY }, // 16 bpp, fast conversion.
buildbot@webrtc.orgfa5fcd62014-07-21 21:55:43 +000042 { FOURCC_NV12, webrtc::kVideoNV12 }, // 12 bpp, fast conversion.
43 { FOURCC_NV21, webrtc::kVideoNV21 }, // 12 bpp, fast conversion.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044 { FOURCC_MJPG, webrtc::kVideoMJPEG }, // compressed, slow conversion.
45 { FOURCC_ARGB, webrtc::kVideoARGB }, // 32 bpp, slow conversion.
46 { FOURCC_24BG, webrtc::kVideoRGB24 }, // 24 bpp, slow conversion.
47};
48
49class WebRtcVcmFactory : public WebRtcVcmFactoryInterface {
50 public:
Peter Boström09c3a1e2016-03-22 17:17:39 +010051 virtual rtc::scoped_refptr<webrtc::VideoCaptureModule> Create(
52 int id,
53 const char* device) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054 return webrtc::VideoCaptureFactory::Create(id, device);
55 }
56 virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) {
57 return webrtc::VideoCaptureFactory::CreateDeviceInfo(id);
58 }
59 virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) {
60 delete info;
61 }
62};
63
64static bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap,
65 VideoFormat* format) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020066 uint32_t fourcc = 0;
tfarina5237aaf2015-11-10 23:44:30 -080067 for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000068 if (kSupportedFourCCs[i].webrtc_type == cap.rawType) {
69 fourcc = kSupportedFourCCs[i].fourcc;
70 break;
71 }
72 }
73 if (fourcc == 0) {
74 return false;
75 }
76
77 format->fourcc = fourcc;
78 format->width = cap.width;
79 format->height = cap.height;
80 format->interval = VideoFormat::FpsToInterval(cap.maxFPS);
81 return true;
82}
83
84static bool FormatToCapability(const VideoFormat& format,
85 webrtc::VideoCaptureCapability* cap) {
86 webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown;
tfarina5237aaf2015-11-10 23:44:30 -080087 for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000088 if (kSupportedFourCCs[i].fourcc == format.fourcc) {
89 webrtc_type = kSupportedFourCCs[i].webrtc_type;
90 break;
91 }
92 }
93 if (webrtc_type == webrtc::kVideoUnknown) {
94 return false;
95 }
96
97 cap->width = format.width;
98 cap->height = format.height;
99 cap->maxFPS = VideoFormat::IntervalToFps(format.interval);
100 cap->expectedCaptureDelay = 0;
101 cap->rawType = webrtc_type;
102 cap->codecType = webrtc::kVideoCodecUnknown;
103 cap->interlaced = false;
104 return true;
105}
106
107///////////////////////////////////////////////////////////////////////////
108// Implementation of class WebRtcVideoCapturer
109///////////////////////////////////////////////////////////////////////////
110
111WebRtcVideoCapturer::WebRtcVideoCapturer()
112 : factory_(new WebRtcVcmFactory),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200113 module_(nullptr),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000114 captured_frames_(0),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200115 start_thread_(nullptr),
116 async_invoker_(nullptr) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000117 set_frame_factory(new WebRtcVideoFrameFactory());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000118}
119
120WebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory)
121 : factory_(factory),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200122 module_(nullptr),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000123 captured_frames_(0),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200124 start_thread_(nullptr),
125 async_invoker_(nullptr) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000126 set_frame_factory(new WebRtcVideoFrameFactory());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127}
128
Peter Boström09c3a1e2016-03-22 17:17:39 +0100129WebRtcVideoCapturer::~WebRtcVideoCapturer() {}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130
131bool WebRtcVideoCapturer::Init(const Device& device) {
henrikg91d6ede2015-09-17 00:24:34 -0700132 RTC_DCHECK(!start_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 if (module_) {
134 LOG(LS_ERROR) << "The capturer is already initialized";
135 return false;
136 }
137
138 webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0);
139 if (!info) {
140 return false;
141 }
142
143 // Find the desired camera, by name.
144 // In the future, comparing IDs will be more robust.
145 // TODO(juberti): Figure what's needed to allow this.
146 int num_cams = info->NumberOfDevices();
147 char vcm_id[256] = "";
148 bool found = false;
149 for (int index = 0; index < num_cams; ++index) {
150 char vcm_name[256];
tfarina5237aaf2015-11-10 23:44:30 -0800151 if (info->GetDeviceName(index, vcm_name, arraysize(vcm_name), vcm_id,
152 arraysize(vcm_id)) != -1) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153 if (device.name == reinterpret_cast<char*>(vcm_name)) {
154 found = true;
155 break;
156 }
157 }
158 }
159 if (!found) {
160 LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
161 factory_->DestroyDeviceInfo(info);
162 return false;
163 }
164
165 // Enumerate the supported formats.
166 // TODO(juberti): Find out why this starts/stops the camera...
167 std::vector<VideoFormat> supported;
168 int32_t num_caps = info->NumberOfCapabilities(vcm_id);
169 for (int32_t i = 0; i < num_caps; ++i) {
170 webrtc::VideoCaptureCapability cap;
171 if (info->GetCapability(vcm_id, i, cap) != -1) {
172 VideoFormat format;
173 if (CapabilityToFormat(cap, &format)) {
174 supported.push_back(format);
175 } else {
176 LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format "
177 << cap.rawType;
178 }
179 }
180 }
181 factory_->DestroyDeviceInfo(info);
Yuriy Shevchuk39f2b0c2015-05-14 14:16:13 -0700182
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000183 if (supported.empty()) {
184 LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id;
185 return false;
186 }
Yuriy Shevchuk39f2b0c2015-05-14 14:16:13 -0700187
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188 module_ = factory_->Create(0, vcm_id);
189 if (!module_) {
190 LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id;
191 return false;
192 }
193
194 // It is safe to change member attributes now.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000195 SetId(device.id);
196 SetSupportedFormats(supported);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000197
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198 return true;
199}
200
Peter Boström09c3a1e2016-03-22 17:17:39 +0100201bool WebRtcVideoCapturer::Init(
202 const rtc::scoped_refptr<webrtc::VideoCaptureModule>& module) {
henrikg91d6ede2015-09-17 00:24:34 -0700203 RTC_DCHECK(!start_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000204 if (module_) {
205 LOG(LS_ERROR) << "The capturer is already initialized";
206 return false;
207 }
208 if (!module) {
209 LOG(LS_ERROR) << "Invalid VCM supplied";
210 return false;
211 }
212 // TODO(juberti): Set id and formats.
Peter Boström09c3a1e2016-03-22 17:17:39 +0100213 module_ = module;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000214 return true;
215}
216
217bool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired,
218 VideoFormat* best_format) {
219 if (!best_format) {
220 return false;
221 }
222
223 if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) {
224 // We maybe using a manually injected VCM which doesn't support enum.
225 // Use the desired format as the best format.
226 best_format->width = desired.width;
227 best_format->height = desired.height;
228 best_format->fourcc = FOURCC_I420;
229 best_format->interval = desired.interval;
230 LOG(LS_INFO) << "Failed to find best capture format,"
231 << " fall back to the requested format "
232 << best_format->ToString();
233 }
234 return true;
235}
Pera5092412016-02-12 13:30:57 +0100236void WebRtcVideoCapturer::OnSinkWantsChanged(const rtc::VideoSinkWants& wants) {
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700237 // Can't take lock here as this will cause deadlock with
238 // OnIncomingCapturedFrame. In fact, the whole method, including methods it
239 // calls, can't take lock.
henrikg91d6ede2015-09-17 00:24:34 -0700240 RTC_DCHECK(module_);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000241
jbauchbd384282015-07-16 04:05:52 -0700242 const std::string group_name =
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700243 webrtc::field_trial::FindFullName("WebRTC-CVO");
244
245 if (group_name == "Disabled") {
Pera5092412016-02-12 13:30:57 +0100246 return;
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700247 }
248
Pera5092412016-02-12 13:30:57 +0100249 VideoCapturer::OnSinkWantsChanged(wants);
250 bool result = module_->SetApplyRotation(wants.rotation_applied);
251 RTC_CHECK(result);
252
253 return;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000254}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000255
256CaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) {
257 if (!module_) {
258 LOG(LS_ERROR) << "The capturer has not been initialized";
Perfb45d172016-02-29 12:07:35 +0100259 return CS_FAILED;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000260 }
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200261 if (start_thread_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262 LOG(LS_ERROR) << "The capturer is already running";
henrikg91d6ede2015-09-17 00:24:34 -0700263 RTC_DCHECK(start_thread_->IsCurrent())
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200264 << "Trying to start capturer on different threads";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265 return CS_FAILED;
266 }
267
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000268 start_thread_ = rtc::Thread::Current();
henrikg91d6ede2015-09-17 00:24:34 -0700269 RTC_DCHECK(!async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200270 async_invoker_.reset(new rtc::AsyncInvoker());
271 captured_frames_ = 0;
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000272
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000273 SetCaptureFormat(&capture_format);
274
275 webrtc::VideoCaptureCapability cap;
276 if (!FormatToCapability(capture_format, &cap)) {
277 LOG(LS_ERROR) << "Invalid capture format specified";
278 return CS_FAILED;
279 }
280
Peter Boström0c4e06b2015-10-07 12:23:21 +0200281 uint32_t start = rtc::Time();
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000282 module_->RegisterCaptureDataCallback(*this);
283 if (module_->StartCapture(cap) != 0) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200284 LOG(LS_ERROR) << "Camera '" << GetId() << "' failed to start";
285 module_->DeRegisterCaptureDataCallback();
286 async_invoker_.reset();
287 SetCaptureFormat(nullptr);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000288 start_thread_ = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000289 return CS_FAILED;
290 }
291
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200292 LOG(LS_INFO) << "Camera '" << GetId() << "' started with format "
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000293 << capture_format.ToString() << ", elapsed time "
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000294 << rtc::TimeSince(start) << " ms";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000295
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000296 SetCaptureState(CS_RUNNING);
297 return CS_STARTING;
298}
299
300void WebRtcVideoCapturer::Stop() {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200301 if (!start_thread_) {
302 LOG(LS_ERROR) << "The capturer is already stopped";
303 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000304 }
henrikg91d6ede2015-09-17 00:24:34 -0700305 RTC_DCHECK(start_thread_);
306 RTC_DCHECK(start_thread_->IsCurrent());
307 RTC_DCHECK(async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200308 if (IsRunning()) {
309 // The module is responsible for OnIncomingCapturedFrame being called, if
310 // we stop it we will get no further callbacks.
311 module_->StopCapture();
312 }
313 module_->DeRegisterCaptureDataCallback();
314
315 // TODO(juberti): Determine if the VCM exposes any drop stats we can use.
316 double drop_ratio = 0.0;
317 LOG(LS_INFO) << "Camera '" << GetId() << "' stopped after capturing "
318 << captured_frames_ << " frames and dropping "
319 << drop_ratio << "%";
320
321 // Clear any pending async invokes (that OnIncomingCapturedFrame may have
322 // caused).
323 async_invoker_.reset();
324
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000325 SetCaptureFormat(NULL);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000326 start_thread_ = nullptr;
hbos0de97f12015-12-01 02:13:33 -0800327 SetCaptureState(CS_STOPPED);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328}
329
330bool WebRtcVideoCapturer::IsRunning() {
331 return (module_ != NULL && module_->CaptureStarted());
332}
333
Peter Boström0c4e06b2015-10-07 12:23:21 +0200334bool WebRtcVideoCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335 if (!fourccs) {
336 return false;
337 }
338
339 fourccs->clear();
tfarina5237aaf2015-11-10 23:44:30 -0800340 for (size_t i = 0; i < arraysize(kSupportedFourCCs); ++i) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000341 fourccs->push_back(kSupportedFourCCs[i].fourcc);
342 }
343 return true;
344}
345
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000346void WebRtcVideoCapturer::OnIncomingCapturedFrame(
347 const int32_t id,
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700348 const webrtc::VideoFrame& sample) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200349 // This can only happen between Start() and Stop().
henrikg91d6ede2015-09-17 00:24:34 -0700350 RTC_DCHECK(start_thread_);
351 RTC_DCHECK(async_invoker_);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000352 if (start_thread_->IsCurrent()) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200353 SignalFrameCapturedOnStartThread(sample);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000354 } else {
355 // This currently happens on with at least VideoCaptureModuleV4L2 and
356 // possibly other implementations of WebRTC's VideoCaptureModule.
357 // In order to maintain the threading contract with the upper layers and
358 // consistency with other capturers such as in Chrome, we need to do a
359 // thread hop.
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200360 // Note that Stop() can cause the async invoke call to be cancelled.
noahric5d9b92b2015-10-24 11:14:46 -0700361 async_invoker_->AsyncInvoke<void>(
362 start_thread_,
363 // Note that Bind captures by value, so there's an intermediate copy
364 // of sample.
365 rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread, this,
366 sample));
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000367 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368}
369
370void WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id,
371 const int32_t delay) {
372 LOG(LS_INFO) << "Capture delay changed to " << delay << " ms";
373}
374
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000375void WebRtcVideoCapturer::SignalFrameCapturedOnStartThread(
noahric5d9b92b2015-10-24 11:14:46 -0700376 const webrtc::VideoFrame& frame) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200377 // This can only happen between Start() and Stop().
henrikg91d6ede2015-09-17 00:24:34 -0700378 RTC_DCHECK(start_thread_);
379 RTC_DCHECK(start_thread_->IsCurrent());
380 RTC_DCHECK(async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200381
382 ++captured_frames_;
383 // Log the size and pixel aspect ratio of the first captured frame.
384 if (1 == captured_frames_) {
385 LOG(LS_INFO) << "Captured frame size "
386 << frame.width() << "x" << frame.height()
387 << ". Expected format " << GetCaptureFormat()->ToString();
388 }
389
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000390 // Signal down stream components on captured frame.
391 // The CapturedFrame class doesn't support planes. We have to ExtractBuffer
392 // to one block for it.
393 size_t length =
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200394 webrtc::CalcBufferSize(webrtc::kI420, frame.width(), frame.height());
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000395 capture_buffer_.resize(length);
396 // TODO(magjed): Refactor the WebRtcCapturedFrame to avoid memory copy or
397 // take over ownership of the buffer held by |frame| if that's possible.
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200398 webrtc::ExtractBuffer(frame, length, &capture_buffer_[0]);
399 WebRtcCapturedFrame webrtc_frame(frame, &capture_buffer_[0], length);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000400 SignalFrameCaptured(this, &webrtc_frame);
401}
402
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000403// WebRtcCapturedFrame
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700404WebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::VideoFrame& sample,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000405 void* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000406 size_t length) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000407 width = sample.width();
408 height = sample.height();
409 fourcc = FOURCC_I420;
410 // TODO(hellner): Support pixel aspect ratio (for OSX).
411 pixel_width = 1;
412 pixel_height = 1;
413 // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds).
magjedb09b6602015-10-01 03:02:44 -0700414 time_stamp = sample.render_time_ms() * rtc::kNumNanosecsPerMillisec;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200415 data_size = rtc::checked_cast<uint32_t>(length);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416 data = buffer;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000417 rotation = sample.rotation();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000418}
419
420} // namespace cricket