12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/*
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  Use of this source code is governed by a BSD-style license
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  that can be found in the LICENSE file in the root of the source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  tree. An additional intellectual property rights grant can be found
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  in the file PATENTS.  All contributing project authors may
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *  be found in the AUTHORS file in the root of the source tree.
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/video_engine/vie_capturer.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/common_video/interface/texture_video_frame.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "webrtc/modules/interface/module_common_types.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webrtc/modules/utility/interface/process_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/modules/video_capture/include/video_capture_factory.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/modules/video_processing/main/interface/video_processing.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/modules/video_render/include/video_render_defines.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "webrtc/system_wrappers/interface/clock.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "webrtc/system_wrappers/interface/event_wrapper.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/system_wrappers/interface/logging.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/system_wrappers/interface/thread_wrapper.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/system_wrappers/interface/trace_event.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/video_engine/include/vie_image_process.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/video_engine/overuse_frame_detector.h"
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "webrtc/video_engine/vie_defines.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "webrtc/video_engine/vie_encoder.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace webrtc {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kThreadWaitTimeMs = 100;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ViECapturer::ViECapturer(int capture_id,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int engine_id,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const Config& config,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         ProcessThread& module_process_thread)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ViEFrameProviderBase(capture_id, engine_id),
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_cs_(CriticalSectionWrapper::CreateCriticalSection()),
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      deliver_cs_(CriticalSectionWrapper::CreateCriticalSection()),
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_module_(NULL),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      external_capture_module_(NULL),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      module_process_thread_(module_process_thread),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_id_(capture_id),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      incoming_frame_cs_(CriticalSectionWrapper::CreateCriticalSection()),
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_thread_(*ThreadWrapper::CreateThread(ViECaptureThreadFunction,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   this, kHighPriority,
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                   "ViECaptureThread")),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture_event_(*EventWrapper::Create()),
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deliver_event_(*EventWrapper::Create()),
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      effect_filter_(NULL),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_proc_module_(NULL),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_proc_module_ref_counter_(0),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      deflicker_frame_stats_(NULL),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      brightness_frame_stats_(NULL),
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      current_brightness_level_(Normal),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reported_brightness_level_(Normal),
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_cs_(CriticalSectionWrapper::CreateCriticalSection()),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      observer_(NULL),
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overuse_detector_(new OveruseFrameDetector(Clock::GetRealTimeClock())) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned int t_id = 0;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!capture_thread_.Start(t_id)) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(false);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_process_thread_.RegisterModule(overuse_detector_.get());
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViECapturer::~ViECapturer() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  module_process_thread_.DeRegisterModule(overuse_detector_.get());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Stop the thread.
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  deliver_cs_->Enter();
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  capture_cs_->Enter();
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  capture_thread_.SetNotAlive();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_event_.Set();
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_cs_->Leave();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deliver_cs_->Leave();
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Stop the camera input.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (capture_module_) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    module_process_thread_.DeRegisterModule(capture_module_);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_->DeRegisterCaptureDataCallback();
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_->Release();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_ = NULL;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (capture_thread_.Stop()) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Thread stopped.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete &capture_thread_;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete &capture_event_;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete &deliver_event_;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(false);
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image_proc_module_) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoProcessingModule::Destroy(image_proc_module_);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (deflicker_frame_stats_) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete deflicker_frame_stats_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deflicker_frame_stats_ = NULL;
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete brightness_frame_stats_;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViECapturer* ViECapturer::CreateViECapture(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int capture_id,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int engine_id,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Config& config,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoCaptureModule* capture_module,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessThread& module_process_thread) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViECapturer* capture = new ViECapturer(capture_id, engine_id, config,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         module_process_thread);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!capture || capture->Init(capture_module) != 0) {
115d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete capture;
116d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    capture = NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return capture;
119d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::Init(VideoCaptureModule* capture_module) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(capture_module_ == NULL);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_ = capture_module;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->RegisterCaptureDataCallback(*this);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->AddRef();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return 0;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ViECapturer* ViECapturer::CreateViECapture(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int capture_id,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int engine_id,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Config& config,
137d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const char* device_unique_idUTF8,
138d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const uint32_t device_unique_idUTF8Length,
139d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    ProcessThread& module_process_thread) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViECapturer* capture = new ViECapturer(capture_id, engine_id, config,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         module_process_thread);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!capture ||
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      capture->Init(device_unique_idUTF8, device_unique_idUTF8Length) != 0) {
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete capture;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture = NULL;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return capture;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::Init(const char* device_unique_idUTF8,
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          uint32_t device_unique_idUTF8Length) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(capture_module_ == NULL);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_unique_idUTF8 == NULL) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_  = VideoCaptureFactory::Create(
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ViEModuleId(engine_id_, capture_id_), external_capture_module_);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_ = VideoCaptureFactory::Create(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!capture_module_) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->AddRef();
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->RegisterCaptureDataCallback(*this);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (module_process_thread_.RegisterModule(capture_module_) != 0) {
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
169d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return 0;
170d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ViECapturer::FrameCallbackChanged() {
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (Started() && !CaptureCapabilityFixed()) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reconfigure the camera if a new size is required and the capture device
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // does not provide encoded frames.
176d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int best_width;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int best_height;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int best_frame_rate;
179d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    VideoCaptureCapability capture_settings;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capture_module_->CaptureSettings(capture_settings);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetBestFormat(&best_width, &best_height, &best_frame_rate);
182d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (best_width != 0 && best_height != 0 && best_frame_rate != 0) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (best_width != capture_settings.width ||
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          best_height != capture_settings.height ||
185d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          best_frame_rate != capture_settings.maxFPS ||
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          capture_settings.codecType != kVideoCodecUnknown) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Stop();
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Start(requested_capability_);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::Start(const CaptureCapability& capture_capability) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int width;
197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  int height;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int frame_rate;
199d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  VideoCaptureCapability capability;
200d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  requested_capability_ = capture_capability;
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!CaptureCapabilityFixed()) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ask the observers for best size.
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GetBestFormat(&width, &height, &frame_rate);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (width == 0) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      width = kViECaptureDefaultWidth;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (height == 0) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      height = kViECaptureDefaultHeight;
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (frame_rate == 0) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      frame_rate = kViECaptureDefaultFramerate;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.height = height;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    capability.width = width;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.maxFPS = frame_rate;
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.rawType = kVideoI420;
218d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    capability.codecType = kVideoCodecUnknown;
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Width, height and type specified with call to Start, not set by
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // observers.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.width = requested_capability_.width;
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    capability.height = requested_capability_.height;
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.maxFPS = requested_capability_.maxFPS;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.rawType = requested_capability_.rawType;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    capability.interlaced = requested_capability_.interlaced;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
228d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return capture_module_->StartCapture(capability);
229d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::Stop() {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  requested_capability_ = CaptureCapability();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return capture_module_->StopCapture();
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::Started() {
237d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return capture_module_->CaptureStarted();
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* ViECapturer::CurrentDeviceName() const {
241d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return capture_module_->CurrentDeviceName();
242d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::RegisterCpuOveruseObserver(CpuOveruseObserver* observer) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overuse_detector_->SetObserver(observer);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
248d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ViECapturer::SetCpuOveruseOptions(const CpuOveruseOptions& options) {
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  overuse_detector_->SetOptions(options);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overuse_detector_->GetCpuOveruseMetrics(metrics);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::SetCaptureDelay(int32_t delay_ms) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->SetCaptureDelay(delay_ms);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
259d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::SetRotateCapturedFrames(
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const RotateCapturedFrame rotation) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VideoCaptureRotation converted_rotation = kCameraRotate0;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (rotation) {
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RotateCapturedFrame_0:
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converted_rotation = kCameraRotate0;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RotateCapturedFrame_90:
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converted_rotation = kCameraRotate90;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RotateCapturedFrame_180:
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converted_rotation = kCameraRotate180;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case RotateCapturedFrame_270:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      converted_rotation = kCameraRotate270;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return capture_module_->SetCaptureRotation(converted_rotation);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int ViECapturer::IncomingFrame(unsigned char* video_frame,
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               unsigned int video_frame_length,
283cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               uint16_t width,
284cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               uint16_t height,
285cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                               RawVideoType video_type,
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                               unsigned long long capture_time) {  // NOLINT
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!external_capture_module_) {
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return -1;
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  VideoCaptureCapability capability;
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  capability.width = width;
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  capability.height = height;
293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  capability.rawType = video_type;
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return external_capture_module_->IncomingFrame(video_frame,
295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 video_frame_length,
296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                 capability, capture_time);
297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)int ViECapturer::IncomingFrameI420(const ViEVideoFrameI420& video_frame,
300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   unsigned long long capture_time) {  // NOLINT
301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!external_capture_module_) {
302cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return -1;
303cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int size_y = video_frame.height * video_frame.y_pitch;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2);
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CriticalSectionScoped cs(incoming_frame_cs_.get());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ret = incoming_frame_.CreateFrame(size_y,
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.y_plane,
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_u,
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.u_plane,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       size_v,
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.v_plane,
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                       video_frame.width,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.height,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.y_pitch,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.u_pitch,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       video_frame.v_pitch);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ret < 0) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG_F(LS_ERROR) << "Could not create I420Frame.";
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return external_capture_module_->IncomingI420VideoFrame(&incoming_frame_,
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                          capture_time);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void ViECapturer::SwapFrame(I420VideoFrame* frame) {
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  external_capture_module_->IncomingI420VideoFrame(frame,
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                                   frame->render_time_ms());
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  frame->set_timestamp(0);
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  frame->set_ntp_time_ms(0);
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  frame->set_render_time_ms(0);
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ViECapturer::OnIncomingCapturedFrame(const int32_t capture_id,
339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          I420VideoFrame& video_frame) {
340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CriticalSectionScoped cs(capture_cs_.get());
341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Make sure we render this frame earlier since we know the render time set
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // is slightly off since it's being set when the frame has been received from
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the camera, and not when the camera actually captured the frame.
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  video_frame.set_render_time_ms(video_frame.render_time_ms() - FrameDelay());
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
346d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", video_frame.render_time_ms(),
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           "render_time", video_frame.render_time_ms());
348d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (video_frame.native_handle() != NULL) {
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    captured_frame_.reset(video_frame.CloneFrame());
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (captured_frame_ == NULL || captured_frame_->native_handle() != NULL)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      captured_frame_.reset(new I420VideoFrame());
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    captured_frame_->SwapFrame(&video_frame);
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_event_.Set();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overuse_detector_->FrameCaptured(captured_frame_->width(),
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   captured_frame_->height());
359d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::OnCaptureDelayChanged(const int32_t id,
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const int32_t delay) {
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(LS_INFO) << "Capture delayed change to " << delay
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << " for device " << id;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deliver the network delay to all registered callbacks.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViEFrameProviderBase::SetFrameDelay(delay);
368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::RegisterEffectFilter(
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ViEEffectFilter* effect_filter) {
372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CriticalSectionScoped cs(deliver_cs_.get());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (effect_filter != NULL && effect_filter_ != NULL) {
375d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LOG_F(LS_ERROR) << "Effect filter already registered.";
376d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return -1;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  effect_filter_ = effect_filter;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int32_t ViECapturer::IncImageProcRefCount() {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!image_proc_module_) {
384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    assert(image_proc_module_ref_counter_ == 0);
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    image_proc_module_ = VideoProcessingModule::Create(
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        ViEModuleId(engine_id_, capture_id_));
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (!image_proc_module_) {
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      LOG_F(LS_ERROR) << "Could not create video processing module.";
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      return -1;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
392d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  image_proc_module_ref_counter_++;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
396d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)int32_t ViECapturer::DecImageProcRefCount() {
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  image_proc_module_ref_counter_--;
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (image_proc_module_ref_counter_ == 0) {
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Destroy module.
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VideoProcessingModule::Destroy(image_proc_module_);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    image_proc_module_ = NULL;
402d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::EnableDeflickering(bool enable) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(deliver_cs_.get());
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable) {
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (deflicker_frame_stats_) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (IncImageProcRefCount() != 0) {
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return -1;
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    deflicker_frame_stats_ = new VideoProcessingModule::FrameStats();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
417d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (deflicker_frame_stats_ == NULL) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecImageProcRefCount();
421d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    delete deflicker_frame_stats_;
422d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    deflicker_frame_stats_ = NULL;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int32_t ViECapturer::EnableBrightnessAlarm(bool enable) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(deliver_cs_.get());
4294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (enable) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (brightness_frame_stats_) {
4314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return -1;
4324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
4334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (IncImageProcRefCount() != 0) {
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return -1;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    brightness_frame_stats_ = new VideoProcessingModule::FrameStats();
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DecImageProcRefCount();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (brightness_frame_stats_ == NULL) {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete brightness_frame_stats_;
443d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    brightness_frame_stats_ = NULL;
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
448d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)bool ViECapturer::ViECaptureThreadFunction(void* obj) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return static_cast<ViECapturer*>(obj)->ViECaptureProcess();
450d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
451d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::ViECaptureProcess() {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (capture_event_.Wait(kThreadWaitTimeMs) == kEventSignaled) {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overuse_detector_->FrameProcessingStarted();
455d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int64_t encode_start_time = -1;
456d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    deliver_cs_->Enter();
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SwapCapturedAndDeliverFrameIfAvailable()) {
458d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds();
459d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      DeliverI420Frame(deliver_frame_.get());
460d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (deliver_frame_->native_handle() != NULL)
461d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        deliver_frame_.reset();  // Release the texture so it can be reused.
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deliver_cs_->Leave();
464d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (current_brightness_level_ != reported_brightness_level_) {
465d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      CriticalSectionScoped cs(observer_cs_.get());
466d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      if (observer_) {
467d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        observer_->BrightnessAlarm(id_, current_brightness_level_);
468d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        reported_brightness_level_ = current_brightness_level_;
469116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update the overuse detector with the duration.
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (encode_start_time != -1) {
473d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      overuse_detector_->FrameEncoded(
474d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          Clock::GetRealTimeClock()->TimeInMilliseconds() - encode_start_time);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're done!
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::DeliverI420Frame(I420VideoFrame* video_frame) {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (video_frame->native_handle() != NULL) {
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ViEFrameProviderBase::DeliverFrame(video_frame);
484d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Apply image enhancement and effect filter.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (deflicker_frame_stats_) {
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image_proc_module_->GetFrameStats(deflicker_frame_stats_,
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          *video_frame) == 0) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      image_proc_module_->Deflickering(video_frame, deflicker_frame_stats_);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      LOG_F(LS_ERROR) << "Could not get frame stats.";
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (brightness_frame_stats_) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (image_proc_module_->GetFrameStats(brightness_frame_stats_,
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          *video_frame) == 0) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int32_t brightness = image_proc_module_->BrightnessDetection(
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *video_frame, *brightness_frame_stats_);
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      switch (brightness) {
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case VideoProcessingModule::kNoWarning:
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        current_brightness_level_ = Normal;
5054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case VideoProcessingModule::kDarkWarning:
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        current_brightness_level_ = Dark;
508868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        break;
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case VideoProcessingModule::kBrightWarning:
5104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        current_brightness_level_ = Bright;
511d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
513d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)        break;
5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
517d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (effect_filter_) {
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unsigned int length = CalcBufferSize(kI420,
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         video_frame->width(),
5204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         video_frame->height());
521d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExtractBuffer(*video_frame, length, video_buffer.get());
523d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    effect_filter_->Transform(length,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              video_buffer.get(),
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              video_frame->ntp_time_ms(),
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              video_frame->timestamp(),
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              video_frame->width(),
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              video_frame->height());
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deliver the captured frame to all observers (channels, renderer or file).
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ViEFrameProviderBase::DeliverFrame(video_frame);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ViECapturer::DeregisterFrameCallback(
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ViEFrameCallback* callbackObject) {
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ViEFrameProviderBase::DeregisterFrameCallback(callbackObject);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::IsFrameCallbackRegistered(
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ViEFrameCallback* callbackObject) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(provider_cs_.get());
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ViEFrameProviderBase::IsFrameCallbackRegistered(callbackObject);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::CaptureCapabilityFixed() {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return requested_capability_.width != 0 &&
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      requested_capability_.height != 0 &&
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      requested_capability_.maxFPS != 0;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int32_t ViECapturer::RegisterObserver(ViECaptureObserver* observer) {
5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CriticalSectionScoped cs(observer_cs_.get());
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (observer_) {
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LOG_F(LS_ERROR) << "Observer already registered.";
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return -1;
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_ = observer;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->RegisterCaptureCallback(*this);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->EnableFrameRateCallback(true);
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->EnableNoPictureAlarm(true);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int32_t ViECapturer::DeRegisterObserver() {
567d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  capture_module_->EnableFrameRateCallback(false);
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  capture_module_->EnableNoPictureAlarm(false);
569d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  capture_module_->DeRegisterCaptureCallback();
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
571d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CriticalSectionScoped cs(observer_cs_.get());
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_ = NULL;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::IsObserverRegistered() {
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(observer_cs_.get());
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return observer_ != NULL;
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::OnCaptureFrameRate(const int32_t id,
582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)                                     const uint32_t frame_rate) {
583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CriticalSectionScoped cs(observer_cs_.get());
584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  observer_->CapturedFrameRate(id_, static_cast<uint8_t>(frame_rate));
585d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ViECapturer::OnNoPictureAlarm(const int32_t id,
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   const VideoCaptureAlarm alarm) {
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(LS_WARNING) << "OnNoPictureAlarm " << id;
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CriticalSectionScoped cs(observer_cs_.get());
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CaptureAlarm vie_alarm = (alarm == Raised) ? AlarmRaised : AlarmCleared;
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer_->NoPictureAlarm(id, vie_alarm);
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ViECapturer::SwapCapturedAndDeliverFrameIfAvailable() {
597d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  CriticalSectionScoped cs(capture_cs_.get());
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (captured_frame_ == NULL)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (captured_frame_->native_handle() != NULL) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deliver_frame_.reset(captured_frame_.release());
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
606d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (captured_frame_->IsZeroSize())
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (deliver_frame_ == NULL)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deliver_frame_.reset(new I420VideoFrame());
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deliver_frame_->SwapFrame(captured_frame_.get());
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  captured_frame_->ResetSize();
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace webrtc
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)