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