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)