blob: 9f1f32af4fe8bfed81726e7e293f2f7a9c60f0d4 [file] [log] [blame]
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00001/*
2 * libjingle
3 * Copyright 2011 Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
henrike@webrtc.org28e20752013-07-10 00:45:36 +000027
28#include "talk/media/webrtc/webrtcvideocapturer.h"
29
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#ifdef HAVE_WEBRTC_VIDEO
buildbot@webrtc.orga09a9992014-08-13 17:26:08 +000035#include "talk/media/webrtc/webrtcvideoframe.h"
36#include "talk/media/webrtc/webrtcvideoframefactory.h"
tommi@webrtc.orge07710c2015-02-19 17:43:25 +000037#include "webrtc/base/bind.h"
38#include "webrtc/base/checks.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000039#include "webrtc/base/criticalsection.h"
40#include "webrtc/base/logging.h"
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000041#include "webrtc/base/safe_conversions.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000042#include "webrtc/base/thread.h"
43#include "webrtc/base/timeutils.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000044
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000045#include "webrtc/base/win32.h" // Need this to #include the impl files.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046#include "webrtc/modules/video_capture/include/video_capture_factory.h"
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -070047#include "webrtc/system_wrappers/interface/field_trial.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000048
49namespace cricket {
50
51struct kVideoFourCCEntry {
Peter Boström0c4e06b2015-10-07 12:23:21 +020052 uint32_t fourcc;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000053 webrtc::RawVideoType webrtc_type;
54};
55
56// This indicates our format preferences and defines a mapping between
57// webrtc::RawVideoType (from video_capture_defines.h) to our FOURCCs.
58static kVideoFourCCEntry kSupportedFourCCs[] = {
59 { FOURCC_I420, webrtc::kVideoI420 }, // 12 bpp, no conversion.
60 { FOURCC_YV12, webrtc::kVideoYV12 }, // 12 bpp, no conversion.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000061 { FOURCC_YUY2, webrtc::kVideoYUY2 }, // 16 bpp, fast conversion.
62 { FOURCC_UYVY, webrtc::kVideoUYVY }, // 16 bpp, fast conversion.
buildbot@webrtc.orgfa5fcd62014-07-21 21:55:43 +000063 { FOURCC_NV12, webrtc::kVideoNV12 }, // 12 bpp, fast conversion.
64 { FOURCC_NV21, webrtc::kVideoNV21 }, // 12 bpp, fast conversion.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000065 { FOURCC_MJPG, webrtc::kVideoMJPEG }, // compressed, slow conversion.
66 { FOURCC_ARGB, webrtc::kVideoARGB }, // 32 bpp, slow conversion.
67 { FOURCC_24BG, webrtc::kVideoRGB24 }, // 24 bpp, slow conversion.
68};
69
70class WebRtcVcmFactory : public WebRtcVcmFactoryInterface {
71 public:
72 virtual webrtc::VideoCaptureModule* Create(int id, const char* device) {
73 return webrtc::VideoCaptureFactory::Create(id, device);
74 }
75 virtual webrtc::VideoCaptureModule::DeviceInfo* CreateDeviceInfo(int id) {
76 return webrtc::VideoCaptureFactory::CreateDeviceInfo(id);
77 }
78 virtual void DestroyDeviceInfo(webrtc::VideoCaptureModule::DeviceInfo* info) {
79 delete info;
80 }
81};
82
83static bool CapabilityToFormat(const webrtc::VideoCaptureCapability& cap,
84 VideoFormat* format) {
Peter Boström0c4e06b2015-10-07 12:23:21 +020085 uint32_t fourcc = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086 for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
87 if (kSupportedFourCCs[i].webrtc_type == cap.rawType) {
88 fourcc = kSupportedFourCCs[i].fourcc;
89 break;
90 }
91 }
92 if (fourcc == 0) {
93 return false;
94 }
95
96 format->fourcc = fourcc;
97 format->width = cap.width;
98 format->height = cap.height;
99 format->interval = VideoFormat::FpsToInterval(cap.maxFPS);
100 return true;
101}
102
103static bool FormatToCapability(const VideoFormat& format,
104 webrtc::VideoCaptureCapability* cap) {
105 webrtc::RawVideoType webrtc_type = webrtc::kVideoUnknown;
106 for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
107 if (kSupportedFourCCs[i].fourcc == format.fourcc) {
108 webrtc_type = kSupportedFourCCs[i].webrtc_type;
109 break;
110 }
111 }
112 if (webrtc_type == webrtc::kVideoUnknown) {
113 return false;
114 }
115
116 cap->width = format.width;
117 cap->height = format.height;
118 cap->maxFPS = VideoFormat::IntervalToFps(format.interval);
119 cap->expectedCaptureDelay = 0;
120 cap->rawType = webrtc_type;
121 cap->codecType = webrtc::kVideoCodecUnknown;
122 cap->interlaced = false;
123 return true;
124}
125
126///////////////////////////////////////////////////////////////////////////
127// Implementation of class WebRtcVideoCapturer
128///////////////////////////////////////////////////////////////////////////
129
130WebRtcVideoCapturer::WebRtcVideoCapturer()
131 : factory_(new WebRtcVcmFactory),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200132 module_(nullptr),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000133 captured_frames_(0),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200134 start_thread_(nullptr),
135 async_invoker_(nullptr) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000136 set_frame_factory(new WebRtcVideoFrameFactory());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137}
138
139WebRtcVideoCapturer::WebRtcVideoCapturer(WebRtcVcmFactoryInterface* factory)
140 : factory_(factory),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200141 module_(nullptr),
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000142 captured_frames_(0),
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200143 start_thread_(nullptr),
144 async_invoker_(nullptr) {
buildbot@webrtc.org4f0d4012014-08-07 04:47:36 +0000145 set_frame_factory(new WebRtcVideoFrameFactory());
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000146}
147
148WebRtcVideoCapturer::~WebRtcVideoCapturer() {
149 if (module_) {
150 module_->Release();
151 }
152}
153
154bool WebRtcVideoCapturer::Init(const Device& device) {
henrikg91d6ede2015-09-17 00:24:34 -0700155 RTC_DCHECK(!start_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000156 if (module_) {
157 LOG(LS_ERROR) << "The capturer is already initialized";
158 return false;
159 }
160
161 webrtc::VideoCaptureModule::DeviceInfo* info = factory_->CreateDeviceInfo(0);
162 if (!info) {
163 return false;
164 }
165
166 // Find the desired camera, by name.
167 // In the future, comparing IDs will be more robust.
168 // TODO(juberti): Figure what's needed to allow this.
169 int num_cams = info->NumberOfDevices();
170 char vcm_id[256] = "";
171 bool found = false;
172 for (int index = 0; index < num_cams; ++index) {
173 char vcm_name[256];
174 if (info->GetDeviceName(index, vcm_name, ARRAY_SIZE(vcm_name),
175 vcm_id, ARRAY_SIZE(vcm_id)) != -1) {
176 if (device.name == reinterpret_cast<char*>(vcm_name)) {
177 found = true;
178 break;
179 }
180 }
181 }
182 if (!found) {
183 LOG(LS_WARNING) << "Failed to find capturer for id: " << device.id;
184 factory_->DestroyDeviceInfo(info);
185 return false;
186 }
187
188 // Enumerate the supported formats.
189 // TODO(juberti): Find out why this starts/stops the camera...
190 std::vector<VideoFormat> supported;
191 int32_t num_caps = info->NumberOfCapabilities(vcm_id);
192 for (int32_t i = 0; i < num_caps; ++i) {
193 webrtc::VideoCaptureCapability cap;
194 if (info->GetCapability(vcm_id, i, cap) != -1) {
195 VideoFormat format;
196 if (CapabilityToFormat(cap, &format)) {
197 supported.push_back(format);
198 } else {
199 LOG(LS_WARNING) << "Ignoring unsupported WebRTC capture format "
200 << cap.rawType;
201 }
202 }
203 }
204 factory_->DestroyDeviceInfo(info);
Yuriy Shevchuk39f2b0c2015-05-14 14:16:13 -0700205
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000206 if (supported.empty()) {
207 LOG(LS_ERROR) << "Failed to find usable formats for id: " << device.id;
208 return false;
209 }
Yuriy Shevchuk39f2b0c2015-05-14 14:16:13 -0700210
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000211 module_ = factory_->Create(0, vcm_id);
212 if (!module_) {
213 LOG(LS_ERROR) << "Failed to create capturer for id: " << device.id;
214 return false;
215 }
216
217 // It is safe to change member attributes now.
218 module_->AddRef();
219 SetId(device.id);
220 SetSupportedFormats(supported);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000221
222 // Ensure these 2 have the same value.
223 SetApplyRotation(module_->GetApplyRotation());
224
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225 return true;
226}
227
228bool WebRtcVideoCapturer::Init(webrtc::VideoCaptureModule* module) {
henrikg91d6ede2015-09-17 00:24:34 -0700229 RTC_DCHECK(!start_thread_);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230 if (module_) {
231 LOG(LS_ERROR) << "The capturer is already initialized";
232 return false;
233 }
234 if (!module) {
235 LOG(LS_ERROR) << "Invalid VCM supplied";
236 return false;
237 }
238 // TODO(juberti): Set id and formats.
239 (module_ = module)->AddRef();
240 return true;
241}
242
243bool WebRtcVideoCapturer::GetBestCaptureFormat(const VideoFormat& desired,
244 VideoFormat* best_format) {
245 if (!best_format) {
246 return false;
247 }
248
249 if (!VideoCapturer::GetBestCaptureFormat(desired, best_format)) {
250 // We maybe using a manually injected VCM which doesn't support enum.
251 // Use the desired format as the best format.
252 best_format->width = desired.width;
253 best_format->height = desired.height;
254 best_format->fourcc = FOURCC_I420;
255 best_format->interval = desired.interval;
256 LOG(LS_INFO) << "Failed to find best capture format,"
257 << " fall back to the requested format "
258 << best_format->ToString();
259 }
260 return true;
261}
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000262bool WebRtcVideoCapturer::SetApplyRotation(bool enable) {
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700263 // Can't take lock here as this will cause deadlock with
264 // OnIncomingCapturedFrame. In fact, the whole method, including methods it
265 // calls, can't take lock.
henrikg91d6ede2015-09-17 00:24:34 -0700266 RTC_DCHECK(module_);
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000267
jbauchbd384282015-07-16 04:05:52 -0700268 const std::string group_name =
Guo-wei Shieh64c1e8c2015-04-01 15:33:06 -0700269 webrtc::field_trial::FindFullName("WebRTC-CVO");
270
271 if (group_name == "Disabled") {
272 return true;
273 }
274
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000275 if (!VideoCapturer::SetApplyRotation(enable)) {
276 return false;
277 }
278 return module_->SetApplyRotation(enable);
279}
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000280
281CaptureState WebRtcVideoCapturer::Start(const VideoFormat& capture_format) {
282 if (!module_) {
283 LOG(LS_ERROR) << "The capturer has not been initialized";
284 return CS_NO_DEVICE;
285 }
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200286 if (start_thread_) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000287 LOG(LS_ERROR) << "The capturer is already running";
henrikg91d6ede2015-09-17 00:24:34 -0700288 RTC_DCHECK(start_thread_->IsCurrent())
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200289 << "Trying to start capturer on different threads";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000290 return CS_FAILED;
291 }
292
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000293 start_thread_ = rtc::Thread::Current();
henrikg91d6ede2015-09-17 00:24:34 -0700294 RTC_DCHECK(!async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200295 async_invoker_.reset(new rtc::AsyncInvoker());
296 captured_frames_ = 0;
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000297
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000298 SetCaptureFormat(&capture_format);
299
300 webrtc::VideoCaptureCapability cap;
301 if (!FormatToCapability(capture_format, &cap)) {
302 LOG(LS_ERROR) << "Invalid capture format specified";
303 return CS_FAILED;
304 }
305
Peter Boström0c4e06b2015-10-07 12:23:21 +0200306 uint32_t start = rtc::Time();
mallinath@webrtc.org7433a082014-01-29 00:56:02 +0000307 module_->RegisterCaptureDataCallback(*this);
308 if (module_->StartCapture(cap) != 0) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200309 LOG(LS_ERROR) << "Camera '" << GetId() << "' failed to start";
310 module_->DeRegisterCaptureDataCallback();
311 async_invoker_.reset();
312 SetCaptureFormat(nullptr);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000313 start_thread_ = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000314 return CS_FAILED;
315 }
316
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200317 LOG(LS_INFO) << "Camera '" << GetId() << "' started with format "
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000318 << capture_format.ToString() << ", elapsed time "
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000319 << rtc::TimeSince(start) << " ms";
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000321 SetCaptureState(CS_RUNNING);
322 return CS_STARTING;
323}
324
325void WebRtcVideoCapturer::Stop() {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200326 if (!start_thread_) {
327 LOG(LS_ERROR) << "The capturer is already stopped";
328 return;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000329 }
henrikg91d6ede2015-09-17 00:24:34 -0700330 RTC_DCHECK(start_thread_);
331 RTC_DCHECK(start_thread_->IsCurrent());
332 RTC_DCHECK(async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200333 if (IsRunning()) {
334 // The module is responsible for OnIncomingCapturedFrame being called, if
335 // we stop it we will get no further callbacks.
336 module_->StopCapture();
337 }
338 module_->DeRegisterCaptureDataCallback();
339
340 // TODO(juberti): Determine if the VCM exposes any drop stats we can use.
341 double drop_ratio = 0.0;
342 LOG(LS_INFO) << "Camera '" << GetId() << "' stopped after capturing "
343 << captured_frames_ << " frames and dropping "
344 << drop_ratio << "%";
345
346 // Clear any pending async invokes (that OnIncomingCapturedFrame may have
347 // caused).
348 async_invoker_.reset();
349
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350 SetCaptureFormat(NULL);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000351 start_thread_ = nullptr;
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000352}
353
354bool WebRtcVideoCapturer::IsRunning() {
355 return (module_ != NULL && module_->CaptureStarted());
356}
357
Peter Boström0c4e06b2015-10-07 12:23:21 +0200358bool WebRtcVideoCapturer::GetPreferredFourccs(std::vector<uint32_t>* fourccs) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359 if (!fourccs) {
360 return false;
361 }
362
363 fourccs->clear();
364 for (size_t i = 0; i < ARRAY_SIZE(kSupportedFourCCs); ++i) {
365 fourccs->push_back(kSupportedFourCCs[i].fourcc);
366 }
367 return true;
368}
369
perkj@webrtc.orgaf612d52015-03-18 09:51:05 +0000370void WebRtcVideoCapturer::OnIncomingCapturedFrame(
371 const int32_t id,
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700372 const webrtc::VideoFrame& sample) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200373 // This can only happen between Start() and Stop().
henrikg91d6ede2015-09-17 00:24:34 -0700374 RTC_DCHECK(start_thread_);
375 RTC_DCHECK(async_invoker_);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000376 if (start_thread_->IsCurrent()) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200377 SignalFrameCapturedOnStartThread(sample);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000378 } else {
379 // This currently happens on with at least VideoCaptureModuleV4L2 and
380 // possibly other implementations of WebRTC's VideoCaptureModule.
381 // In order to maintain the threading contract with the upper layers and
382 // consistency with other capturers such as in Chrome, we need to do a
383 // thread hop.
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200384 // Note that Stop() can cause the async invoke call to be cancelled.
385 async_invoker_->AsyncInvoke<void>(start_thread_,
386 // Note that this results in a shallow copying of the frame.
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000387 rtc::Bind(&WebRtcVideoCapturer::SignalFrameCapturedOnStartThread,
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200388 this, sample));
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000389 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000390}
391
392void WebRtcVideoCapturer::OnCaptureDelayChanged(const int32_t id,
393 const int32_t delay) {
394 LOG(LS_INFO) << "Capture delay changed to " << delay << " ms";
395}
396
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000397void WebRtcVideoCapturer::SignalFrameCapturedOnStartThread(
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700398 const webrtc::VideoFrame frame) {
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200399 // This can only happen between Start() and Stop().
henrikg91d6ede2015-09-17 00:24:34 -0700400 RTC_DCHECK(start_thread_);
401 RTC_DCHECK(start_thread_->IsCurrent());
402 RTC_DCHECK(async_invoker_);
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200403
404 ++captured_frames_;
405 // Log the size and pixel aspect ratio of the first captured frame.
406 if (1 == captured_frames_) {
407 LOG(LS_INFO) << "Captured frame size "
408 << frame.width() << "x" << frame.height()
409 << ". Expected format " << GetCaptureFormat()->ToString();
410 }
411
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000412 // Signal down stream components on captured frame.
413 // The CapturedFrame class doesn't support planes. We have to ExtractBuffer
414 // to one block for it.
415 size_t length =
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200416 webrtc::CalcBufferSize(webrtc::kI420, frame.width(), frame.height());
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000417 capture_buffer_.resize(length);
418 // TODO(magjed): Refactor the WebRtcCapturedFrame to avoid memory copy or
419 // take over ownership of the buffer held by |frame| if that's possible.
Henrik Boströmcbe408a2015-05-27 10:11:34 +0200420 webrtc::ExtractBuffer(frame, length, &capture_buffer_[0]);
421 WebRtcCapturedFrame webrtc_frame(frame, &capture_buffer_[0], length);
tommi@webrtc.orge07710c2015-02-19 17:43:25 +0000422 SignalFrameCaptured(this, &webrtc_frame);
423}
424
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000425// WebRtcCapturedFrame
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700426WebRtcCapturedFrame::WebRtcCapturedFrame(const webrtc::VideoFrame& sample,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000427 void* buffer,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000428 size_t length) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000429 width = sample.width();
430 height = sample.height();
431 fourcc = FOURCC_I420;
432 // TODO(hellner): Support pixel aspect ratio (for OSX).
433 pixel_width = 1;
434 pixel_height = 1;
435 // Convert units from VideoFrame RenderTimeMs to CapturedFrame (nanoseconds).
magjedb09b6602015-10-01 03:02:44 -0700436 time_stamp = sample.render_time_ms() * rtc::kNumNanosecsPerMillisec;
Peter Boström0c4e06b2015-10-07 12:23:21 +0200437 data_size = rtc::checked_cast<uint32_t>(length);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000438 data = buffer;
guoweis@webrtc.org1226e922015-02-11 18:37:54 +0000439 rotation = sample.rotation();
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000440}
441
442} // namespace cricket
443
444#endif // HAVE_WEBRTC_VIDEO