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