• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ViEFrameProviderBase(int Id,int engine_id)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 
~ViEFrameProviderBase()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 
Id()43 int ViEFrameProviderBase::Id() {
44   return id_;
45 }
46 
DeliverFrame(I420VideoFrame * video_frame,int num_csrcs,const uint32_t CSRC[kRtpCsrcSize])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) {
59       // We don't have to copy the frame.
60       frame_callbacks_.front()->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
61     } else {
62       for (FrameCallbacks::iterator it = frame_callbacks_.begin();
63            it != frame_callbacks_.end(); ++it) {
64         if (video_frame->native_handle() != NULL) {
65           (*it)->DeliverFrame(id_, video_frame, num_csrcs, CSRC);
66         } else {
67           // Make a copy of the frame for all callbacks.
68           if (!extra_frame_.get()) {
69             extra_frame_.reset(new I420VideoFrame());
70           }
71           extra_frame_->CopyFrame(*video_frame);
72           (*it)->DeliverFrame(id_, extra_frame_.get(), num_csrcs, CSRC);
73         }
74       }
75     }
76   }
77 #ifdef DEBUG_
78   const int process_time =
79       static_cast<int>((TickTime::Now() - start_process_time).Milliseconds());
80   if (process_time > 25) {
81     // Warn if the delivery time is too long.
82     LOG(LS_WARNING) << "Too long time delivering frame " << process_time;
83   }
84 #endif
85 }
86 
SetFrameDelay(int frame_delay)87 void ViEFrameProviderBase::SetFrameDelay(int frame_delay) {
88   CriticalSectionScoped cs(provider_cs_.get());
89   frame_delay_ = frame_delay;
90 
91   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
92        it != frame_callbacks_.end(); ++it) {
93     (*it)->DelayChanged(id_, frame_delay);
94   }
95 }
96 
FrameDelay()97 int ViEFrameProviderBase::FrameDelay() {
98   return frame_delay_;
99 }
100 
GetBestFormat(int * best_width,int * best_height,int * best_frame_rate)101 int ViEFrameProviderBase::GetBestFormat(int* best_width,
102                                         int* best_height,
103                                         int* best_frame_rate) {
104   int largest_width = 0;
105   int largest_height = 0;
106   int highest_frame_rate = 0;
107 
108   CriticalSectionScoped cs(provider_cs_.get());
109   for (FrameCallbacks::iterator it = frame_callbacks_.begin();
110        it != frame_callbacks_.end(); ++it) {
111     int prefered_width = 0;
112     int prefered_height = 0;
113     int prefered_frame_rate = 0;
114     if ((*it)->GetPreferedFrameSettings(&prefered_width, &prefered_height,
115                                         &prefered_frame_rate) == 0) {
116       if (prefered_width > largest_width) {
117         largest_width = prefered_width;
118       }
119       if (prefered_height > largest_height) {
120         largest_height = prefered_height;
121       }
122       if (prefered_frame_rate > highest_frame_rate) {
123         highest_frame_rate = prefered_frame_rate;
124       }
125     }
126   }
127   *best_width = largest_width;
128   *best_height = largest_height;
129   *best_frame_rate = highest_frame_rate;
130   return 0;
131 }
132 
RegisterFrameCallback(int observer_id,ViEFrameCallback * callback_object)133 int ViEFrameProviderBase::RegisterFrameCallback(
134     int observer_id, ViEFrameCallback* callback_object) {
135   assert(callback_object);
136   {
137     CriticalSectionScoped cs(provider_cs_.get());
138     if (std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
139                   callback_object) != frame_callbacks_.end()) {
140       assert(false && "frameObserver already registered");
141       return -1;
142     }
143     frame_callbacks_.push_back(callback_object);
144   }
145   // Report current capture delay.
146   callback_object->DelayChanged(id_, frame_delay_);
147 
148   // Notify implementer of this class that the callback list have changed.
149   FrameCallbackChanged();
150   return 0;
151 }
152 
DeregisterFrameCallback(const ViEFrameCallback * callback_object)153 int ViEFrameProviderBase::DeregisterFrameCallback(
154     const ViEFrameCallback* callback_object) {
155   assert(callback_object);
156   CriticalSectionScoped cs(provider_cs_.get());
157 
158   FrameCallbacks::iterator it = std::find(frame_callbacks_.begin(),
159                                           frame_callbacks_.end(),
160                                           callback_object);
161   if (it == frame_callbacks_.end()) {
162     return -1;
163   }
164   frame_callbacks_.erase(it);
165 
166   // Notify implementer of this class that the callback list have changed.
167   FrameCallbackChanged();
168   return 0;
169 }
170 
IsFrameCallbackRegistered(const ViEFrameCallback * callback_object)171 bool ViEFrameProviderBase::IsFrameCallbackRegistered(
172     const ViEFrameCallback* callback_object) {
173   assert(callback_object);
174 
175   CriticalSectionScoped cs(provider_cs_.get());
176   return std::find(frame_callbacks_.begin(), frame_callbacks_.end(),
177                    callback_object) != frame_callbacks_.end();
178 }
179 
NumberOfRegisteredFrameCallbacks()180 int ViEFrameProviderBase::NumberOfRegisteredFrameCallbacks() {
181   CriticalSectionScoped cs(provider_cs_.get());
182   return frame_callbacks_.size();
183 }
184 }  // namespac webrtc
185