| /* |
| * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "video_engine/vie_frame_provider_base.h" |
| |
| #include <algorithm> |
| |
| #include "modules/interface/module_common_types.h" |
| #include "system_wrappers/interface/critical_section_wrapper.h" |
| #include "system_wrappers/interface/tick_util.h" |
| #include "system_wrappers/interface/trace.h" |
| #include "video_engine/vie_defines.h" |
| |
| namespace webrtc { |
| |
| ViEFrameProviderBase::ViEFrameProviderBase(int Id, int engine_id) |
| : id_(Id), |
| engine_id_(engine_id), |
| provider_cs_(CriticalSectionWrapper::CreateCriticalSection()), |
| frame_delay_(0) { |
| } |
| |
| ViEFrameProviderBase::~ViEFrameProviderBase() { |
| if (frame_callbacks_.size() > 0) { |
| WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, id_), |
| "FrameCallbacks still exist when Provider deleted %d", |
| frame_callbacks_.size()); |
| } |
| |
| for (FrameCallbacks::iterator it = frame_callbacks_.begin(); |
| it != frame_callbacks_.end(); ++it) { |
| (*it)->ProviderDestroyed(id_); |
| } |
| frame_callbacks_.clear(); |
| } |
| |
| int ViEFrameProviderBase::Id() { |
| return id_; |
| } |
| |
| void ViEFrameProviderBase::DeliverFrame( |
| VideoFrame& video_frame, |
| int num_csrcs, |
| const WebRtc_UWord32 CSRC[kRtpCsrcSize]) { |
| #ifdef DEBUG_ |
| const TickTime start_process_time = TickTime::Now(); |
| #endif |
| CriticalSectionScoped cs(provider_cs_.get()); |
| |
| // Deliver the frame to all registered callbacks. |
| if (frame_callbacks_.size() > 0) { |
| if (frame_callbacks_.size() == 1) { |
| // We don't have to copy the frame. |
| frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC); |
| } else { |
| // Make a copy of the frame for all callbacks.callback |
| for (FrameCallbacks::iterator it = frame_callbacks_.begin(); |
| it != frame_callbacks_.end(); ++it) { |
| if (!extra_frame_.get()) { |
| extra_frame_.reset(new VideoFrame()); |
| } |
| extra_frame_->CopyFrame(video_frame); |
| (*it)->DeliverFrame(id_, *(extra_frame_.get()), num_csrcs, CSRC); |
| } |
| } |
| } |
| #ifdef DEBUG_ |
| const int process_time = |
| static_cast<int>((TickTime::Now() - start_process_time).Milliseconds()); |
| if (process_time > 25) { |
| // Warn if the delivery time is too long. |
| WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, id_), |
| "%s Too long time: %ums", __FUNCTION__, process_time); |
| } |
| #endif |
| } |
| |
| void ViEFrameProviderBase::SetFrameDelay(int frame_delay) { |
| CriticalSectionScoped cs(provider_cs_.get()); |
| frame_delay_ = frame_delay; |
| |
| for (FrameCallbacks::iterator it = frame_callbacks_.begin(); |
| it != frame_callbacks_.end(); ++it) { |
| (*it)->DelayChanged(id_, frame_delay); |
| } |
| } |
| |
| int ViEFrameProviderBase::FrameDelay() { |
| return frame_delay_; |
| } |
| |
| int ViEFrameProviderBase::GetBestFormat(int& best_width, |
| int& best_height, |
| int& best_frame_rate) { |
| int largest_width = 0; |
| int largest_height = 0; |
| int highest_frame_rate = 0; |
| |
| CriticalSectionScoped cs(provider_cs_.get()); |
| for (FrameCallbacks::iterator it = frame_callbacks_.begin(); |
| it != frame_callbacks_.end(); ++it) { |
| int prefered_width = 0; |
| int prefered_height = 0; |
| int prefered_frame_rate = 0; |
| if ((*it)->GetPreferedFrameSettings(prefered_width, prefered_height, |
| prefered_frame_rate) == 0) { |
| if (prefered_width > largest_width) { |
| largest_width = prefered_width; |
| } |
| if (prefered_height > largest_height) { |
| largest_height = prefered_height; |
| } |
| if (prefered_frame_rate > highest_frame_rate) { |
| highest_frame_rate = prefered_frame_rate; |
| } |
| } |
| } |
| best_width = largest_width; |
| best_height = largest_height; |
| best_frame_rate = highest_frame_rate; |
| return 0; |
| } |
| |
| int ViEFrameProviderBase::RegisterFrameCallback( |
| int observer_id, ViEFrameCallback* callback_object) { |
| assert(callback_object); |
| WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, id_), "%s(0x%p)", |
| __FUNCTION__, callback_object); |
| { |
| CriticalSectionScoped cs(provider_cs_.get()); |
| if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(), |
| callback_object) != frame_callbacks_.end()) { |
| // This object is already registered. |
| WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, id_), |
| "%s 0x%p already registered", __FUNCTION__, |
| callback_object); |
| assert("!frameObserver already registered"); |
| return -1; |
| } |
| frame_callbacks_.push_back(callback_object); |
| } |
| // Report current capture delay. |
| callback_object->DelayChanged(id_, frame_delay_); |
| |
| // Notify implementer of this class that the callback list have changed. |
| FrameCallbackChanged(); |
| return 0; |
| } |
| |
| int ViEFrameProviderBase::DeregisterFrameCallback( |
| const ViEFrameCallback* callback_object) { |
| assert(callback_object); |
| WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, id_), "%s(0x%p)", |
| __FUNCTION__, callback_object); |
| CriticalSectionScoped cs(provider_cs_.get()); |
| |
| FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(), |
| frame_callbacks_.end(), |
| callback_object); |
| if (it == frame_callbacks_.end()) { |
| WEBRTC_TRACE(kTraceWarning, kTraceVideo, ViEId(engine_id_, id_), |
| "%s 0x%p not found", __FUNCTION__, callback_object); |
| return -1; |
| } |
| frame_callbacks_.erase(it); |
| WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, id_), |
| "%s 0x%p deregistered", __FUNCTION__, callback_object); |
| |
| // Notify implementer of this class that the callback list have changed. |
| FrameCallbackChanged(); |
| return 0; |
| } |
| |
| bool ViEFrameProviderBase::IsFrameCallbackRegistered( |
| const ViEFrameCallback* callback_object) { |
| assert(callback_object); |
| WEBRTC_TRACE(kTraceInfo, kTraceVideo, ViEId(engine_id_, id_), |
| "%s(0x%p)", __FUNCTION__, callback_object); |
| |
| CriticalSectionScoped cs(provider_cs_.get()); |
| return std::find(frame_callbacks_.begin(), frame_callbacks_.end(), |
| callback_object) != frame_callbacks_.end(); |
| } |
| |
| int ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() { |
| CriticalSectionScoped cs(provider_cs_.get()); |
| return frame_callbacks_.size(); |
| } |
| |
| } // namespac webrtc |