OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/base/checks.h" | 11 #include "webrtc/base/checks.h" |
12 #include "webrtc/base/logging.h" | 12 #include "webrtc/base/logging.h" |
13 #include "webrtc/base/trace_event.h" | 13 #include "webrtc/base/trace_event.h" |
14 #include "webrtc/common_types.h" | 14 #include "webrtc/common_types.h" |
15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 15 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
16 #include "webrtc/modules/video_coding/include/video_codec_interface.h" | 16 #include "webrtc/modules/video_coding/include/video_codec_interface.h" |
17 #include "webrtc/modules/video_coding/encoded_frame.h" | 17 #include "webrtc/modules/video_coding/encoded_frame.h" |
18 #include "webrtc/modules/video_coding/jitter_buffer.h" | 18 #include "webrtc/modules/video_coding/jitter_buffer.h" |
19 #include "webrtc/modules/video_coding/packet.h" | 19 #include "webrtc/modules/video_coding/packet.h" |
20 #include "webrtc/modules/video_coding/video_coding_impl.h" | 20 #include "webrtc/modules/video_coding/video_coding_impl.h" |
21 #include "webrtc/system_wrappers/include/clock.h" | 21 #include "webrtc/system_wrappers/include/clock.h" |
22 | 22 |
23 // #define DEBUG_DECODER_BIT_STREAM | |
24 | |
25 namespace webrtc { | 23 namespace webrtc { |
26 namespace vcm { | 24 namespace vcm { |
27 | 25 |
28 VideoReceiver::VideoReceiver(Clock* clock, | 26 VideoReceiver::VideoReceiver(Clock* clock, |
29 EventFactory* event_factory, | 27 EventFactory* event_factory, |
30 NackSender* nack_sender, | 28 NackSender* nack_sender, |
31 KeyFrameRequestSender* keyframe_request_sender) | 29 KeyFrameRequestSender* keyframe_request_sender) |
32 : clock_(clock), | 30 : clock_(clock), |
33 process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()), | |
34 _receiveCritSect(CriticalSectionWrapper::CreateCriticalSection()), | |
35 _timing(clock_), | 31 _timing(clock_), |
36 _receiver(&_timing, | 32 _receiver(&_timing, |
37 clock_, | 33 clock_, |
38 event_factory, | 34 event_factory, |
39 nack_sender, | 35 nack_sender, |
40 keyframe_request_sender), | 36 keyframe_request_sender), |
41 _decodedFrameCallback(&_timing, clock_), | 37 _decodedFrameCallback(&_timing, clock_), |
42 _frameTypeCallback(NULL), | 38 _frameTypeCallback(nullptr), |
43 _receiveStatsCallback(NULL), | 39 _receiveStatsCallback(nullptr), |
44 _decoderTimingCallback(NULL), | 40 _decoderTimingCallback(nullptr), |
45 _packetRequestCallback(NULL), | 41 _packetRequestCallback(nullptr), |
46 render_buffer_callback_(NULL), | 42 render_buffer_callback_(nullptr), |
47 _decoder(NULL), | 43 _decoder(nullptr), |
48 #ifdef DEBUG_DECODER_BIT_STREAM | |
49 _bitStreamBeforeDecoder(NULL), | |
50 #endif | |
51 _frameFromFile(), | 44 _frameFromFile(), |
52 _scheduleKeyRequest(false), | 45 _scheduleKeyRequest(false), |
53 drop_frames_until_keyframe_(false), | 46 drop_frames_until_keyframe_(false), |
54 max_nack_list_size_(0), | 47 max_nack_list_size_(0), |
55 _codecDataBase(nullptr, nullptr), | 48 _codecDataBase(nullptr, nullptr), |
56 pre_decode_image_callback_(NULL), | 49 pre_decode_image_callback_(nullptr), |
57 _receiveStatsTimer(1000, clock_), | 50 _receiveStatsTimer(1000, clock_), |
58 _retransmissionTimer(10, clock_), | 51 _retransmissionTimer(10, clock_), |
59 _keyRequestTimer(500, clock_) { | 52 _keyRequestTimer(500, clock_), |
60 assert(clock_); | 53 ssrc_(0) {} |
61 #ifdef DEBUG_DECODER_BIT_STREAM | |
62 _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb"); | |
63 #endif | |
64 } | |
65 | 54 |
66 VideoReceiver::~VideoReceiver() { | 55 VideoReceiver::~VideoReceiver() {} |
67 delete _receiveCritSect; | |
68 #ifdef DEBUG_DECODER_BIT_STREAM | |
69 fclose(_bitStreamBeforeDecoder); | |
70 #endif | |
71 } | |
72 | 56 |
73 void VideoReceiver::Process() { | 57 void VideoReceiver::Process() { |
74 // Receive-side statistics | 58 // Receive-side statistics |
75 if (_receiveStatsTimer.TimeUntilProcess() == 0) { | 59 if (_receiveStatsTimer.TimeUntilProcess() == 0) { |
76 _receiveStatsTimer.Processed(); | 60 _receiveStatsTimer.Processed(); |
77 CriticalSectionScoped cs(process_crit_sect_.get()); | 61 rtc::CritScope cs(&process_lock_); |
78 if (_receiveStatsCallback != NULL) { | 62 if (_receiveStatsCallback != nullptr) { |
79 uint32_t bitRate; | 63 uint32_t bitRate; |
80 uint32_t frameRate; | 64 uint32_t frameRate; |
81 _receiver.ReceiveStatistics(&bitRate, &frameRate); | 65 _receiver.ReceiveStatistics(&bitRate, &frameRate); |
82 _receiveStatsCallback->OnReceiveRatesUpdated(bitRate, frameRate); | 66 _receiveStatsCallback->OnReceiveRatesUpdated(bitRate, frameRate); |
83 } | 67 } |
84 | 68 |
85 if (_decoderTimingCallback != NULL) { | 69 if (_decoderTimingCallback != nullptr) { |
86 int decode_ms; | 70 int decode_ms; |
87 int max_decode_ms; | 71 int max_decode_ms; |
88 int current_delay_ms; | 72 int current_delay_ms; |
89 int target_delay_ms; | 73 int target_delay_ms; |
90 int jitter_buffer_ms; | 74 int jitter_buffer_ms; |
91 int min_playout_delay_ms; | 75 int min_playout_delay_ms; |
92 int render_delay_ms; | 76 int render_delay_ms; |
93 _timing.GetTimings(&decode_ms, &max_decode_ms, ¤t_delay_ms, | 77 _timing.GetTimings(&decode_ms, &max_decode_ms, ¤t_delay_ms, |
94 &target_delay_ms, &jitter_buffer_ms, | 78 &target_delay_ms, &jitter_buffer_ms, |
95 &min_playout_delay_ms, &render_delay_ms); | 79 &min_playout_delay_ms, &render_delay_ms); |
96 _decoderTimingCallback->OnDecoderTiming( | 80 _decoderTimingCallback->OnDecoderTiming( |
97 decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, | 81 decode_ms, max_decode_ms, current_delay_ms, target_delay_ms, |
98 jitter_buffer_ms, min_playout_delay_ms, render_delay_ms); | 82 jitter_buffer_ms, min_playout_delay_ms, render_delay_ms); |
99 } | 83 } |
100 | 84 |
101 // Size of render buffer. | 85 // Size of render buffer. |
102 if (render_buffer_callback_) { | 86 if (render_buffer_callback_) { |
103 int buffer_size_ms = _receiver.RenderBufferSizeMs(); | 87 int buffer_size_ms = _receiver.RenderBufferSizeMs(); |
104 render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms); | 88 render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms); |
105 } | 89 } |
106 } | 90 } |
107 | 91 |
108 // Key frame requests | 92 // Key frame requests |
109 if (_keyRequestTimer.TimeUntilProcess() == 0) { | 93 if (_keyRequestTimer.TimeUntilProcess() == 0) { |
110 _keyRequestTimer.Processed(); | 94 _keyRequestTimer.Processed(); |
111 bool request_key_frame = false; | 95 bool request_key_frame = false; |
112 { | 96 { |
113 CriticalSectionScoped cs(process_crit_sect_.get()); | 97 rtc::CritScope cs(&process_lock_); |
114 request_key_frame = _scheduleKeyRequest && _frameTypeCallback != NULL; | 98 request_key_frame = _scheduleKeyRequest && _frameTypeCallback != nullptr; |
115 } | 99 } |
116 if (request_key_frame) | 100 if (request_key_frame) |
117 RequestKeyFrame(); | 101 RequestKeyFrame(); |
118 } | 102 } |
119 | 103 |
120 if (_receiver.TimeUntilNextProcess() == 0) { | 104 if (_receiver.TimeUntilNextProcess() == 0) { |
121 _receiver.Process(); | 105 _receiver.Process(); |
122 } | 106 } |
123 | 107 |
124 // Packet retransmission requests | 108 // Packet retransmission requests |
125 // TODO(holmer): Add API for changing Process interval and make sure it's | 109 // TODO(holmer): Add API for changing Process interval and make sure it's |
126 // disabled when NACK is off. | 110 // disabled when NACK is off. |
127 if (_retransmissionTimer.TimeUntilProcess() == 0) { | 111 if (_retransmissionTimer.TimeUntilProcess() == 0) { |
128 _retransmissionTimer.Processed(); | 112 _retransmissionTimer.Processed(); |
129 bool callback_registered = false; | 113 bool callback_registered = false; |
130 uint16_t length; | 114 uint16_t length; |
131 { | 115 { |
132 CriticalSectionScoped cs(process_crit_sect_.get()); | 116 rtc::CritScope cs(&process_lock_); |
133 length = max_nack_list_size_; | 117 length = max_nack_list_size_; |
134 callback_registered = _packetRequestCallback != NULL; | 118 callback_registered = _packetRequestCallback != nullptr; |
135 } | 119 } |
136 if (callback_registered && length > 0) { | 120 if (callback_registered && length > 0) { |
137 // Collect sequence numbers from the default receiver. | 121 // Collect sequence numbers from the default receiver. |
138 bool request_key_frame = false; | 122 bool request_key_frame = false; |
139 std::vector<uint16_t> nackList = _receiver.NackList(&request_key_frame); | 123 std::vector<uint16_t> nackList = _receiver.NackList(&request_key_frame); |
140 int32_t ret = VCM_OK; | 124 int32_t ret = VCM_OK; |
141 if (request_key_frame) { | 125 if (request_key_frame) { |
142 ret = RequestKeyFrame(); | 126 ret = RequestKeyFrame(); |
143 } | 127 } |
144 if (ret == VCM_OK && !nackList.empty()) { | 128 if (ret == VCM_OK && !nackList.empty()) { |
145 CriticalSectionScoped cs(process_crit_sect_.get()); | 129 rtc::CritScope cs(&process_lock_); |
146 if (_packetRequestCallback != NULL) { | 130 if (_packetRequestCallback != nullptr) { |
147 _packetRequestCallback->ResendPackets(&nackList[0], nackList.size()); | 131 _packetRequestCallback->ResendPackets(&nackList[0], nackList.size()); |
148 } | 132 } |
149 } | 133 } |
150 } | 134 } |
151 } | 135 } |
152 } | 136 } |
153 | 137 |
154 int64_t VideoReceiver::TimeUntilNextProcess() { | 138 int64_t VideoReceiver::TimeUntilNextProcess() { |
155 int64_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess(); | 139 int64_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess(); |
156 if (_receiver.NackMode() != kNoNack) { | 140 if (_receiver.NackMode() != kNoNack) { |
157 // We need a Process call more often if we are relying on | 141 // We need a Process call more often if we are relying on |
158 // retransmissions | 142 // retransmissions |
159 timeUntilNextProcess = | 143 timeUntilNextProcess = |
160 VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess()); | 144 VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess()); |
161 } | 145 } |
162 timeUntilNextProcess = | 146 timeUntilNextProcess = |
163 VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess()); | 147 VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess()); |
164 timeUntilNextProcess = | 148 timeUntilNextProcess = |
165 VCM_MIN(timeUntilNextProcess, _receiver.TimeUntilNextProcess()); | 149 VCM_MIN(timeUntilNextProcess, _receiver.TimeUntilNextProcess()); |
166 | 150 |
167 return timeUntilNextProcess; | 151 return timeUntilNextProcess; |
168 } | 152 } |
169 | 153 |
170 int32_t VideoReceiver::SetReceiveChannelParameters(int64_t rtt) { | 154 int32_t VideoReceiver::SetReceiveChannelParameters(int64_t rtt) { |
171 CriticalSectionScoped receiveCs(_receiveCritSect); | 155 rtc::CritScope cs(&receive_lock_); |
172 _receiver.UpdateRtt(rtt); | 156 _receiver.UpdateRtt(rtt); |
173 return 0; | 157 return 0; |
174 } | 158 } |
175 | 159 |
176 // Enable or disable a video protection method. | 160 // Enable or disable a video protection method. |
177 // Note: This API should be deprecated, as it does not offer a distinction | 161 // Note: This API should be deprecated, as it does not offer a distinction |
178 // between the protection method and decoding with or without errors. If such a | 162 // between the protection method and decoding with or without errors. If such a |
179 // behavior is desired, use the following API: SetReceiverRobustnessMode. | 163 // behavior is desired, use the following API: SetReceiverRobustnessMode. |
180 int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection, | 164 int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection, |
181 bool enable) { | 165 bool enable) { |
182 // By default, do not decode with errors. | 166 // By default, do not decode with errors. |
183 _receiver.SetDecodeErrorMode(kNoErrors); | 167 _receiver.SetDecodeErrorMode(kNoErrors); |
184 switch (videoProtection) { | 168 switch (videoProtection) { |
185 case kProtectionNack: { | 169 case kProtectionNack: { |
186 RTC_DCHECK(enable); | 170 RTC_DCHECK(enable); |
187 _receiver.SetNackMode(kNack, -1, -1); | 171 _receiver.SetNackMode(kNack, -1, -1); |
188 break; | 172 break; |
189 } | 173 } |
190 | 174 |
191 case kProtectionNackFEC: { | 175 case kProtectionNackFEC: { |
192 CriticalSectionScoped cs(_receiveCritSect); | 176 rtc::CritScope cs(&receive_lock_); |
193 RTC_DCHECK(enable); | 177 RTC_DCHECK(enable); |
194 _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); | 178 _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1); |
195 _receiver.SetDecodeErrorMode(kNoErrors); | 179 _receiver.SetDecodeErrorMode(kNoErrors); |
196 break; | 180 break; |
197 } | 181 } |
198 case kProtectionFEC: | 182 case kProtectionFEC: |
199 case kProtectionNone: | 183 case kProtectionNone: |
200 // No receiver-side protection. | 184 // No receiver-side protection. |
201 RTC_DCHECK(enable); | 185 RTC_DCHECK(enable); |
202 _receiver.SetNackMode(kNoNack, -1, -1); | 186 _receiver.SetNackMode(kNoNack, -1, -1); |
203 _receiver.SetDecodeErrorMode(kWithErrors); | 187 _receiver.SetDecodeErrorMode(kWithErrors); |
204 break; | 188 break; |
205 } | 189 } |
206 return VCM_OK; | 190 return VCM_OK; |
207 } | 191 } |
208 | 192 |
209 // Register a receive callback. Will be called whenever there is a new frame | 193 // Register a receive callback. Will be called whenever there is a new frame |
210 // ready for rendering. | 194 // ready for rendering. |
211 int32_t VideoReceiver::RegisterReceiveCallback( | 195 int32_t VideoReceiver::RegisterReceiveCallback( |
212 VCMReceiveCallback* receiveCallback) { | 196 VCMReceiveCallback* receiveCallback) { |
213 CriticalSectionScoped cs(_receiveCritSect); | 197 rtc::CritScope cs(&receive_lock_); |
214 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); | 198 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); |
215 return VCM_OK; | 199 return VCM_OK; |
216 } | 200 } |
217 | 201 |
218 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( | 202 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( |
219 VCMReceiveStatisticsCallback* receiveStats) { | 203 VCMReceiveStatisticsCallback* receiveStats) { |
220 CriticalSectionScoped cs(process_crit_sect_.get()); | 204 rtc::CritScope cs(&process_lock_); |
221 _receiver.RegisterStatsCallback(receiveStats); | 205 _receiver.RegisterStatsCallback(receiveStats); |
222 _receiveStatsCallback = receiveStats; | 206 _receiveStatsCallback = receiveStats; |
223 return VCM_OK; | 207 return VCM_OK; |
224 } | 208 } |
225 | 209 |
226 int32_t VideoReceiver::RegisterDecoderTimingCallback( | 210 int32_t VideoReceiver::RegisterDecoderTimingCallback( |
227 VCMDecoderTimingCallback* decoderTiming) { | 211 VCMDecoderTimingCallback* decoderTiming) { |
228 CriticalSectionScoped cs(process_crit_sect_.get()); | 212 rtc::CritScope cs(&process_lock_); |
229 _decoderTimingCallback = decoderTiming; | 213 _decoderTimingCallback = decoderTiming; |
230 return VCM_OK; | 214 return VCM_OK; |
231 } | 215 } |
232 | 216 |
233 // Register an externally defined decoder object. | 217 // Register an externally defined decoder object. |
234 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, | 218 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, |
235 uint8_t payloadType) { | 219 uint8_t payloadType) { |
236 CriticalSectionScoped cs(_receiveCritSect); | 220 rtc::CritScope cs(&receive_lock_); |
237 if (externalDecoder == NULL) { | 221 if (externalDecoder == nullptr) { |
238 // Make sure the VCM updates the decoder next time it decodes. | 222 // Make sure the VCM updates the decoder next time it decodes. |
239 _decoder = NULL; | 223 _decoder = nullptr; |
240 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType)); | 224 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType)); |
241 return; | 225 return; |
242 } | 226 } |
243 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType); | 227 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType); |
244 } | 228 } |
245 | 229 |
246 // Register a frame type request callback. | 230 // Register a frame type request callback. |
247 int32_t VideoReceiver::RegisterFrameTypeCallback( | 231 int32_t VideoReceiver::RegisterFrameTypeCallback( |
248 VCMFrameTypeCallback* frameTypeCallback) { | 232 VCMFrameTypeCallback* frameTypeCallback) { |
249 CriticalSectionScoped cs(process_crit_sect_.get()); | 233 rtc::CritScope cs(&process_lock_); |
250 _frameTypeCallback = frameTypeCallback; | 234 _frameTypeCallback = frameTypeCallback; |
251 return VCM_OK; | 235 return VCM_OK; |
252 } | 236 } |
253 | 237 |
254 int32_t VideoReceiver::RegisterPacketRequestCallback( | 238 int32_t VideoReceiver::RegisterPacketRequestCallback( |
255 VCMPacketRequestCallback* callback) { | 239 VCMPacketRequestCallback* callback) { |
256 CriticalSectionScoped cs(process_crit_sect_.get()); | 240 rtc::CritScope cs(&process_lock_); |
257 _packetRequestCallback = callback; | 241 _packetRequestCallback = callback; |
258 return VCM_OK; | 242 return VCM_OK; |
259 } | 243 } |
260 | 244 |
261 int VideoReceiver::RegisterRenderBufferSizeCallback( | 245 int VideoReceiver::RegisterRenderBufferSizeCallback( |
262 VCMRenderBufferSizeCallback* callback) { | 246 VCMRenderBufferSizeCallback* callback) { |
263 CriticalSectionScoped cs(process_crit_sect_.get()); | 247 rtc::CritScope cs(&process_lock_); |
264 render_buffer_callback_ = callback; | 248 render_buffer_callback_ = callback; |
265 return VCM_OK; | 249 return VCM_OK; |
266 } | 250 } |
267 | 251 |
268 void VideoReceiver::TriggerDecoderShutdown() { | 252 void VideoReceiver::TriggerDecoderShutdown() { |
269 _receiver.TriggerDecoderShutdown(); | 253 _receiver.TriggerDecoderShutdown(); |
270 } | 254 } |
271 | 255 |
272 // Decode next frame, blocking. | 256 // Decode next frame, blocking. |
273 // Should be called as often as possible to get the most out of the decoder. | 257 // Should be called as often as possible to get the most out of the decoder. |
274 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { | 258 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { |
275 int64_t nextRenderTimeMs; | 259 int64_t nextRenderTimeMs; |
276 bool prefer_late_decoding = false; | 260 bool prefer_late_decoding = false; |
277 { | 261 { |
278 CriticalSectionScoped cs(_receiveCritSect); | 262 rtc::CritScope cs(&receive_lock_); |
279 prefer_late_decoding = _codecDataBase.PrefersLateDecoding(); | 263 prefer_late_decoding = _codecDataBase.PrefersLateDecoding(); |
280 } | 264 } |
281 | 265 |
282 VCMEncodedFrame* frame = _receiver.FrameForDecoding( | 266 VCMEncodedFrame* frame = _receiver.FrameForDecoding( |
283 maxWaitTimeMs, &nextRenderTimeMs, prefer_late_decoding); | 267 maxWaitTimeMs, &nextRenderTimeMs, prefer_late_decoding); |
284 | 268 |
285 if (!frame) | 269 if (!frame) |
286 return VCM_FRAME_NOT_READY; | 270 return VCM_FRAME_NOT_READY; |
287 | 271 |
288 { | 272 { |
289 CriticalSectionScoped cs(process_crit_sect_.get()); | 273 rtc::CritScope cs(&process_lock_); |
290 if (drop_frames_until_keyframe_) { | 274 if (drop_frames_until_keyframe_) { |
291 // Still getting delta frames, schedule another keyframe request as if | 275 // Still getting delta frames, schedule another keyframe request as if |
292 // decode failed. | 276 // decode failed. |
293 if (frame->FrameType() != kVideoFrameKey) { | 277 if (frame->FrameType() != kVideoFrameKey) { |
294 _scheduleKeyRequest = true; | 278 _scheduleKeyRequest = true; |
295 _receiver.ReleaseFrame(frame); | 279 _receiver.ReleaseFrame(frame); |
296 return VCM_FRAME_NOT_READY; | 280 return VCM_FRAME_NOT_READY; |
297 } | 281 } |
298 drop_frames_until_keyframe_ = false; | 282 drop_frames_until_keyframe_ = false; |
299 } | 283 } |
300 } | 284 } |
301 CriticalSectionScoped cs(_receiveCritSect); | |
302 | 285 |
286 rtc::CritScope cs(&receive_lock_); | |
303 // If this frame was too late, we should adjust the delay accordingly | 287 // If this frame was too late, we should adjust the delay accordingly |
304 _timing.UpdateCurrentDelay(frame->RenderTimeMs(), | 288 _timing.UpdateCurrentDelay(frame->RenderTimeMs(), |
305 clock_->TimeInMilliseconds()); | 289 clock_->TimeInMilliseconds()); |
306 | 290 |
307 if (pre_decode_image_callback_) { | 291 if (pre_decode_image_callback_) { |
308 EncodedImage encoded_image(frame->EncodedImage()); | 292 EncodedImage encoded_image(frame->EncodedImage()); |
309 int qp = -1; | 293 int qp = -1; |
310 if (qp_parser_.GetQp(*frame, &qp)) { | 294 if (qp_parser_.GetQp(*frame, &qp)) { |
311 encoded_image.qp_ = qp; | 295 encoded_image.qp_ = qp; |
312 } | 296 } |
313 pre_decode_image_callback_->Encoded(encoded_image, frame->CodecSpecific(), | 297 pre_decode_image_callback_->Encoded(encoded_image, frame->CodecSpecific(), |
pbos-webrtc
2016/04/12 11:20:55
Can you wire up this through here instead? Then yo
sprang_webrtc
2016/04/12 14:06:17
Done.
| |
314 NULL); | 298 nullptr); |
315 } | 299 } |
316 | 300 |
317 #ifdef DEBUG_DECODER_BIT_STREAM | |
318 if (_bitStreamBeforeDecoder != NULL) { | |
319 // Write bit stream to file for debugging purposes | |
320 if (fwrite(frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) != | |
321 frame->Length()) { | |
322 return -1; | |
323 } | |
324 } | |
325 #endif | |
326 | |
327 if (first_frame_received_()) { | 301 if (first_frame_received_()) { |
328 LOG(LS_INFO) << "Received first " | 302 LOG(LS_INFO) << "Received first " |
329 << (frame->Complete() ? "complete" : "incomplete") | 303 << (frame->Complete() ? "complete" : "incomplete") |
330 << " decodable video frame"; | 304 << " decodable video frame"; |
331 } | 305 } |
332 | 306 |
333 const int32_t ret = Decode(*frame); | 307 const int32_t ret = Decode(*frame); |
334 _receiver.ReleaseFrame(frame); | 308 _receiver.ReleaseFrame(frame); |
335 return ret; | 309 return ret; |
336 } | 310 } |
337 | 311 |
338 int32_t VideoReceiver::RequestSliceLossIndication( | 312 int32_t VideoReceiver::RequestSliceLossIndication( |
339 const uint64_t pictureID) const { | 313 const uint64_t pictureID) const { |
340 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); | 314 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); |
341 CriticalSectionScoped cs(process_crit_sect_.get()); | 315 rtc::CritScope cs(&process_lock_); |
342 if (_frameTypeCallback != NULL) { | 316 if (_frameTypeCallback != nullptr) { |
343 const int32_t ret = | 317 const int32_t ret = |
344 _frameTypeCallback->SliceLossIndicationRequest(pictureID); | 318 _frameTypeCallback->SliceLossIndicationRequest(pictureID); |
345 if (ret < 0) { | 319 if (ret < 0) { |
346 return ret; | 320 return ret; |
347 } | 321 } |
348 } else { | 322 } else { |
349 return VCM_MISSING_CALLBACK; | 323 return VCM_MISSING_CALLBACK; |
350 } | 324 } |
351 return VCM_OK; | 325 return VCM_OK; |
352 } | 326 } |
353 | 327 |
354 int32_t VideoReceiver::RequestKeyFrame() { | 328 int32_t VideoReceiver::RequestKeyFrame() { |
355 TRACE_EVENT0("webrtc", "RequestKeyFrame"); | 329 TRACE_EVENT0("webrtc", "RequestKeyFrame"); |
356 CriticalSectionScoped process_cs(process_crit_sect_.get()); | 330 rtc::CritScope cs(&process_lock_); |
357 if (_frameTypeCallback != NULL) { | 331 if (_frameTypeCallback != nullptr) { |
358 const int32_t ret = _frameTypeCallback->RequestKeyFrame(); | 332 const int32_t ret = _frameTypeCallback->RequestKeyFrame(); |
359 if (ret < 0) { | 333 if (ret < 0) { |
360 return ret; | 334 return ret; |
361 } | 335 } |
362 _scheduleKeyRequest = false; | 336 _scheduleKeyRequest = false; |
363 } else { | 337 } else { |
364 return VCM_MISSING_CALLBACK; | 338 return VCM_MISSING_CALLBACK; |
365 } | 339 } |
366 return VCM_OK; | 340 return VCM_OK; |
367 } | 341 } |
368 | 342 |
369 // Must be called from inside the receive side critical section. | 343 // Must be called from inside the receive side critical section. |
370 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { | 344 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { |
345 if (kEnableFrameRecording) { | |
346 rtc::CritScope cs(&file_write_lock_); | |
347 if (!file_writer_.get()) { | |
348 RTC_DCHECK(frame.CodecSpecific()); | |
349 RtpVideoCodecTypes rtp_codec_type; | |
350 switch (frame.CodecSpecific()->codecType) { | |
351 case kVideoCodecVP8: | |
352 rtp_codec_type = kRtpVideoVp8; | |
353 break; | |
354 case kVideoCodecVP9: | |
355 rtp_codec_type = kRtpVideoVp9; | |
356 break; | |
357 case kVideoCodecH264: | |
358 rtp_codec_type = kRtpVideoH264; | |
359 break; | |
360 default: | |
361 rtp_codec_type = kRtpVideoNone; | |
362 RTC_NOTREACHED() << "Unsupported codec " | |
363 << frame.CodecSpecific()->codecType; | |
364 } | |
365 std::ostringstream oss; | |
366 oss << "receive_bitstream_ssrc_" << ssrc_ << ".ivf"; | |
367 file_writer_ = IvfFileWriter::Open(oss.str(), rtp_codec_type); | |
368 } | |
369 if (file_writer_.get()) { | |
370 bool ok = file_writer_->WriteFrame(frame.EncodedImage()); | |
pbos-webrtc
2016/04/12 11:20:55
This is now done under the receive critsect?
sprang_webrtc
2016/04/12 14:06:17
Yes.
| |
371 RTC_DCHECK(ok); | |
372 } | |
373 } | |
374 | |
371 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame.TimeStamp(), "Decode", | 375 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame.TimeStamp(), "Decode", |
372 "type", frame.FrameType()); | 376 "type", frame.FrameType()); |
373 // Change decoder if payload type has changed | 377 // Change decoder if payload type has changed |
374 _decoder = _codecDataBase.GetDecoder(frame, &_decodedFrameCallback); | 378 _decoder = _codecDataBase.GetDecoder(frame, &_decodedFrameCallback); |
375 if (_decoder == NULL) { | 379 if (_decoder == nullptr) { |
376 return VCM_NO_CODEC_REGISTERED; | 380 return VCM_NO_CODEC_REGISTERED; |
377 } | 381 } |
378 // Decode a frame | 382 // Decode a frame |
379 int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds()); | 383 int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds()); |
380 | 384 |
381 // Check for failed decoding, run frame type request callback if needed. | 385 // Check for failed decoding, run frame type request callback if needed. |
382 bool request_key_frame = false; | 386 bool request_key_frame = false; |
383 if (ret < 0) { | 387 if (ret < 0) { |
384 if (ret == VCM_ERROR_REQUEST_SLI) { | 388 if (ret == VCM_ERROR_REQUEST_SLI) { |
385 return RequestSliceLossIndication( | 389 return RequestSliceLossIndication( |
386 _decodedFrameCallback.LastReceivedPictureID() + 1); | 390 _decodedFrameCallback.LastReceivedPictureID() + 1); |
387 } else { | 391 } else { |
388 request_key_frame = true; | 392 request_key_frame = true; |
389 } | 393 } |
390 } else if (ret == VCM_REQUEST_SLI) { | 394 } else if (ret == VCM_REQUEST_SLI) { |
391 ret = RequestSliceLossIndication( | 395 ret = RequestSliceLossIndication( |
392 _decodedFrameCallback.LastReceivedPictureID() + 1); | 396 _decodedFrameCallback.LastReceivedPictureID() + 1); |
393 } | 397 } |
394 if (!frame.Complete() || frame.MissingFrame()) { | 398 if (!frame.Complete() || frame.MissingFrame()) { |
395 request_key_frame = true; | 399 request_key_frame = true; |
396 ret = VCM_OK; | 400 ret = VCM_OK; |
397 } | 401 } |
398 if (request_key_frame) { | 402 if (request_key_frame) { |
399 CriticalSectionScoped cs(process_crit_sect_.get()); | 403 rtc::CritScope cs(&process_lock_); |
400 _scheduleKeyRequest = true; | 404 _scheduleKeyRequest = true; |
401 } | 405 } |
402 TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp()); | 406 TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp()); |
403 return ret; | 407 return ret; |
404 } | 408 } |
405 | 409 |
406 // Register possible receive codecs, can be called multiple times | 410 // Register possible receive codecs, can be called multiple times |
407 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, | 411 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, |
408 int32_t numberOfCores, | 412 int32_t numberOfCores, |
409 bool requireKeyFrame) { | 413 bool requireKeyFrame) { |
410 CriticalSectionScoped cs(_receiveCritSect); | 414 rtc::CritScope cs(&receive_lock_); |
411 if (receiveCodec == NULL) { | 415 if (receiveCodec == nullptr) { |
412 return VCM_PARAMETER_ERROR; | 416 return VCM_PARAMETER_ERROR; |
413 } | 417 } |
414 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, | 418 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, |
415 requireKeyFrame)) { | 419 requireKeyFrame)) { |
416 return -1; | 420 return -1; |
417 } | 421 } |
418 return 0; | 422 return 0; |
419 } | 423 } |
420 | 424 |
421 // Get current received codec | 425 // Get current received codec |
422 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { | 426 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { |
423 CriticalSectionScoped cs(_receiveCritSect); | 427 rtc::CritScope cs(&receive_lock_); |
424 if (currentReceiveCodec == NULL) { | 428 if (currentReceiveCodec == nullptr) { |
425 return VCM_PARAMETER_ERROR; | 429 return VCM_PARAMETER_ERROR; |
426 } | 430 } |
427 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; | 431 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; |
428 } | 432 } |
429 | 433 |
430 // Get current received codec | 434 // Get current received codec |
431 VideoCodecType VideoReceiver::ReceiveCodec() const { | 435 VideoCodecType VideoReceiver::ReceiveCodec() const { |
432 CriticalSectionScoped cs(_receiveCritSect); | 436 rtc::CritScope cs(&receive_lock_); |
433 return _codecDataBase.ReceiveCodec(); | 437 return _codecDataBase.ReceiveCodec(); |
434 } | 438 } |
435 | 439 |
436 // Incoming packet from network parsed and ready for decode, non blocking. | 440 // Incoming packet from network parsed and ready for decode, non blocking. |
437 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, | 441 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, |
438 size_t payloadLength, | 442 size_t payloadLength, |
439 const WebRtcRTPHeader& rtpInfo) { | 443 const WebRtcRTPHeader& rtpInfo) { |
440 if (rtpInfo.frameType == kVideoFrameKey) { | 444 if (rtpInfo.frameType == kVideoFrameKey) { |
441 TRACE_EVENT1("webrtc", "VCM::PacketKeyFrame", "seqnum", | 445 TRACE_EVENT1("webrtc", "VCM::PacketKeyFrame", "seqnum", |
442 rtpInfo.header.sequenceNumber); | 446 rtpInfo.header.sequenceNumber); |
443 } | 447 } |
444 if (incomingPayload == NULL) { | 448 if (incomingPayload == nullptr) { |
445 // The jitter buffer doesn't handle non-zero payload lengths for packets | 449 // The jitter buffer doesn't handle non-zero payload lengths for packets |
446 // without payload. | 450 // without payload. |
447 // TODO(holmer): We should fix this in the jitter buffer. | 451 // TODO(holmer): We should fix this in the jitter buffer. |
448 payloadLength = 0; | 452 payloadLength = 0; |
449 } | 453 } |
450 const VCMPacket packet(incomingPayload, payloadLength, rtpInfo); | 454 const VCMPacket packet(incomingPayload, payloadLength, rtpInfo); |
451 int32_t ret = _receiver.InsertPacket(packet, rtpInfo.type.Video.width, | 455 int32_t ret = _receiver.InsertPacket(packet, rtpInfo.type.Video.width, |
452 rtpInfo.type.Video.height); | 456 rtpInfo.type.Video.height); |
457 | |
458 if (kEnableFrameRecording) { | |
459 rtc::CritScope cs(&file_write_lock_); | |
460 ssrc_ = rtpInfo.header.ssrc; | |
461 } | |
462 | |
453 // TODO(holmer): Investigate if this somehow should use the key frame | 463 // TODO(holmer): Investigate if this somehow should use the key frame |
454 // request scheduling to throttle the requests. | 464 // request scheduling to throttle the requests. |
455 if (ret == VCM_FLUSH_INDICATOR) { | 465 if (ret == VCM_FLUSH_INDICATOR) { |
456 { | 466 { |
457 CriticalSectionScoped process_cs(process_crit_sect_.get()); | 467 rtc::CritScope cs(&process_lock_); |
458 drop_frames_until_keyframe_ = true; | 468 drop_frames_until_keyframe_ = true; |
459 } | 469 } |
460 RequestKeyFrame(); | 470 RequestKeyFrame(); |
461 } else if (ret < 0) { | 471 } else if (ret < 0) { |
462 return ret; | 472 return ret; |
463 } | 473 } |
464 return VCM_OK; | 474 return VCM_OK; |
465 } | 475 } |
466 | 476 |
467 // Minimum playout delay (used for lip-sync). This is the minimum delay required | 477 // Minimum playout delay (used for lip-sync). This is the minimum delay required |
(...skipping 16 matching lines...) Expand all Loading... | |
484 return _timing.TargetVideoDelay(); | 494 return _timing.TargetVideoDelay(); |
485 } | 495 } |
486 | 496 |
487 uint32_t VideoReceiver::DiscardedPackets() const { | 497 uint32_t VideoReceiver::DiscardedPackets() const { |
488 return _receiver.DiscardedPackets(); | 498 return _receiver.DiscardedPackets(); |
489 } | 499 } |
490 | 500 |
491 int VideoReceiver::SetReceiverRobustnessMode( | 501 int VideoReceiver::SetReceiverRobustnessMode( |
492 ReceiverRobustness robustnessMode, | 502 ReceiverRobustness robustnessMode, |
493 VCMDecodeErrorMode decode_error_mode) { | 503 VCMDecodeErrorMode decode_error_mode) { |
494 CriticalSectionScoped cs(_receiveCritSect); | 504 rtc::CritScope cs(&receive_lock_); |
495 switch (robustnessMode) { | 505 switch (robustnessMode) { |
496 case VideoCodingModule::kNone: | 506 case VideoCodingModule::kNone: |
497 _receiver.SetNackMode(kNoNack, -1, -1); | 507 _receiver.SetNackMode(kNoNack, -1, -1); |
498 break; | 508 break; |
499 case VideoCodingModule::kHardNack: | 509 case VideoCodingModule::kHardNack: |
500 // Always wait for retransmissions (except when decoding with errors). | 510 // Always wait for retransmissions (except when decoding with errors). |
501 _receiver.SetNackMode(kNack, -1, -1); | 511 _receiver.SetNackMode(kNack, -1, -1); |
502 break; | 512 break; |
503 case VideoCodingModule::kSoftNack: | 513 case VideoCodingModule::kSoftNack: |
504 #if 1 | 514 #if 1 |
(...skipping 15 matching lines...) Expand all Loading... | |
520 } | 530 } |
521 _receiver.SetNackMode(kNoNack, -1, -1); | 531 _receiver.SetNackMode(kNoNack, -1, -1); |
522 break; | 532 break; |
523 #endif | 533 #endif |
524 } | 534 } |
525 _receiver.SetDecodeErrorMode(decode_error_mode); | 535 _receiver.SetDecodeErrorMode(decode_error_mode); |
526 return VCM_OK; | 536 return VCM_OK; |
527 } | 537 } |
528 | 538 |
529 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) { | 539 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) { |
530 CriticalSectionScoped cs(_receiveCritSect); | 540 rtc::CritScope cs(&receive_lock_); |
531 _receiver.SetDecodeErrorMode(decode_error_mode); | 541 _receiver.SetDecodeErrorMode(decode_error_mode); |
532 } | 542 } |
533 | 543 |
534 void VideoReceiver::SetNackSettings(size_t max_nack_list_size, | 544 void VideoReceiver::SetNackSettings(size_t max_nack_list_size, |
535 int max_packet_age_to_nack, | 545 int max_packet_age_to_nack, |
536 int max_incomplete_time_ms) { | 546 int max_incomplete_time_ms) { |
537 if (max_nack_list_size != 0) { | 547 if (max_nack_list_size != 0) { |
538 CriticalSectionScoped process_cs(process_crit_sect_.get()); | 548 rtc::CritScope cs(&process_lock_); |
539 max_nack_list_size_ = max_nack_list_size; | 549 max_nack_list_size_ = max_nack_list_size; |
540 } | 550 } |
541 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, | 551 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, |
542 max_incomplete_time_ms); | 552 max_incomplete_time_ms); |
543 } | 553 } |
544 | 554 |
545 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { | 555 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { |
546 return _receiver.SetMinReceiverDelay(desired_delay_ms); | 556 return _receiver.SetMinReceiverDelay(desired_delay_ms); |
547 } | 557 } |
548 | 558 |
549 void VideoReceiver::RegisterPreDecodeImageCallback( | 559 void VideoReceiver::RegisterPreDecodeImageCallback( |
550 EncodedImageCallback* observer) { | 560 EncodedImageCallback* observer) { |
551 CriticalSectionScoped cs(_receiveCritSect); | 561 rtc::CritScope cs(&receive_lock_); |
552 pre_decode_image_callback_ = observer; | 562 pre_decode_image_callback_ = observer; |
pbos-webrtc
2016/04/12 11:22:33
Actually, can we require this to be set before rec
sprang_webrtc
2016/04/12 14:06:17
Done.
| |
553 } | 563 } |
554 | 564 |
555 } // namespace vcm | 565 } // namespace vcm |
556 } // namespace webrtc | 566 } // namespace webrtc |
OLD | NEW |