1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/* 2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * 4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * Use of this source code is governed by a BSD-style license 5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * that can be found in the LICENSE file in the root of the source 6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * tree. An additional intellectual property rights grant can be found 7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * in the file PATENTS. All contributing project authors may 8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org * be found in the AUTHORS file in the root of the source tree. 9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */ 10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 11281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_frame_provider_base.h" 12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 13b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#include <algorithm> 14b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 15281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/common_video/interface/i420_video_frame.h" 16281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 17022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org#include "webrtc/system_wrappers/interface/logging.h" 18281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h" 19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_defines.h" 20b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 21b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc { 22b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 23b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFrameProviderBase::ViEFrameProviderBase(int Id, int engine_id) 24b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org : id_(Id), 25b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org engine_id_(engine_id), 26b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org provider_cs_(CriticalSectionWrapper::CreateCriticalSection()), 27b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_delay_(0) { 28b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 29b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 30b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEFrameProviderBase::~ViEFrameProviderBase() { 31b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frame_callbacks_.size() > 0) { 32022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org LOG_F(LS_WARNING) << "FrameCallbacks still exist when Provider deleted: " 33022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org << frame_callbacks_.size(); 34b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (FrameCallbacks::iterator it = frame_callbacks_.begin(); 37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org it != frame_callbacks_.end(); ++it) { 38b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (*it)->ProviderDestroyed(id_); 39b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 40b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_callbacks_.clear(); 41b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 42b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 43b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::Id() { 44b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return id_; 45b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 46b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 47b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFrameProviderBase::DeliverFrame( 483bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org I420VideoFrame* video_frame, 49b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int num_csrcs, 5067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org const uint32_t CSRC[kRtpCsrcSize]) { 51b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef DEBUG_ 52b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const TickTime start_process_time = TickTime::Now(); 53b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 54b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 55b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 56b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Deliver the frame to all registered callbacks. 57b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (frame_callbacks_.size() > 0) { 584ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org if (frame_callbacks_.size() == 1) { 59b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // We don't have to copy the frame. 60b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC); 61b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } else { 62b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (FrameCallbacks::iterator it = frame_callbacks_.begin(); 63b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org it != frame_callbacks_.end(); ++it) { 644ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org if (video_frame->native_handle() != NULL) { 654ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org (*it)->DeliverFrame(id_, video_frame, num_csrcs, CSRC); 664ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org } else { 674ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org // Make a copy of the frame for all callbacks. 684ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org if (!extra_frame_.get()) { 694ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org extra_frame_.reset(new I420VideoFrame()); 704ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org } 714ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org extra_frame_->CopyFrame(*video_frame); 724ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC); 73b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 74b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef DEBUG_ 78b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const int process_time = 79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org static_cast<int>((TickTime::Now() - start_process_time).Milliseconds()); 80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (process_time > 25) { 81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Warn if the delivery time is too long. 82022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org LOG(LS_WARNING) << "Too long time delivering frame " << process_time; 83b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 84b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#endif 85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEFrameProviderBase::SetFrameDelay(int frame_delay) { 88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_delay_ = frame_delay; 90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (FrameCallbacks::iterator it = frame_callbacks_.begin(); 92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org it != frame_callbacks_.end(); ++it) { 93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org (*it)->DelayChanged(id_, frame_delay); 94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 95b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::FrameDelay() { 98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return frame_delay_; 99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::GetBestFormat(int* best_width, 102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int* best_height, 103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int* best_frame_rate) { 104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int largest_width = 0; 105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int largest_height = 0; 106b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int highest_frame_rate = 0; 107b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 108b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 109b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org for (FrameCallbacks::iterator it = frame_callbacks_.begin(); 110b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org it != frame_callbacks_.end(); ++it) { 111b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int prefered_width = 0; 112b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int prefered_height = 0; 113b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int prefered_frame_rate = 0; 114b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height, 115b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org &prefered_frame_rate) == 0) { 116b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (prefered_width > largest_width) { 117b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org largest_width = prefered_width; 118b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 119b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (prefered_height > largest_height) { 120b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org largest_height = prefered_height; 121b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 122b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (prefered_frame_rate > highest_frame_rate) { 123b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org highest_frame_rate = prefered_frame_rate; 124b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 125b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 126b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 127b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *best_width = largest_width; 128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *best_height = largest_height; 129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *best_frame_rate = highest_frame_rate; 130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 133b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::RegisterFrameCallback( 134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org int observer_id, ViEFrameCallback* callback_object) { 135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(callback_object); 136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org { 137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(), 139b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org callback_object) != frame_callbacks_.end()) { 140b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(false && "frameObserver already registered"); 141b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 142b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 143b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_callbacks_.push_back(callback_object); 144b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 145b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Report current capture delay. 146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org callback_object->DelayChanged(id_, frame_delay_); 147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Notify implementer of this class that the callback list have changed. 149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FrameCallbackChanged(); 150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::DeregisterFrameCallback( 154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const ViEFrameCallback* callback_object) { 155b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(callback_object); 156b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 157b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(), 159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_callbacks_.end(), 160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org callback_object); 161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org if (it == frame_callbacks_.end()) { 162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return -1; 163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org } 164b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org frame_callbacks_.erase(it); 165b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 166b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org // Notify implementer of this class that the callback list have changed. 167b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org FrameCallbackChanged(); 168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return 0; 169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ViEFrameProviderBase::IsFrameCallbackRegistered( 172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org const ViEFrameCallback* callback_object) { 173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org assert(callback_object); 174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return std::find(frame_callbacks_.begin(), frame_callbacks_.end(), 177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org callback_object) != frame_callbacks_.end(); 178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 179b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org 180b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() { 181b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org CriticalSectionScoped cs(provider_cs_.get()); 182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org return frame_callbacks_.size(); 183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} 184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org} // namespac webrtc 185