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 |
(...skipping 23 matching lines...) Expand all Loading... | |
34 _receiver(_timing, | 34 _receiver(_timing, |
35 clock_, | 35 clock_, |
36 event_factory, | 36 event_factory, |
37 nack_sender, | 37 nack_sender, |
38 keyframe_request_sender), | 38 keyframe_request_sender), |
39 _decodedFrameCallback(_timing, clock_), | 39 _decodedFrameCallback(_timing, clock_), |
40 _frameTypeCallback(nullptr), | 40 _frameTypeCallback(nullptr), |
41 _receiveStatsCallback(nullptr), | 41 _receiveStatsCallback(nullptr), |
42 _decoderTimingCallback(nullptr), | 42 _decoderTimingCallback(nullptr), |
43 _packetRequestCallback(nullptr), | 43 _packetRequestCallback(nullptr), |
44 _decoder(nullptr), | |
45 _frameFromFile(), | 44 _frameFromFile(), |
46 _scheduleKeyRequest(false), | 45 _scheduleKeyRequest(false), |
47 drop_frames_until_keyframe_(false), | 46 drop_frames_until_keyframe_(false), |
48 max_nack_list_size_(0), | 47 max_nack_list_size_(0), |
49 _codecDataBase(nullptr), | 48 _codecDataBase(nullptr), |
50 pre_decode_image_callback_(pre_decode_image_callback), | 49 pre_decode_image_callback_(pre_decode_image_callback), |
51 _receiveStatsTimer(1000, clock_), | 50 _receiveStatsTimer(1000, clock_), |
52 _retransmissionTimer(10, clock_), | 51 _retransmissionTimer(10, clock_), |
53 _keyRequestTimer(500, clock_) {} | 52 _keyRequestTimer(500, clock_) {} |
54 | 53 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 _receiver.SetDecodeErrorMode(kWithErrors); | 160 _receiver.SetDecodeErrorMode(kWithErrors); |
162 break; | 161 break; |
163 } | 162 } |
164 return VCM_OK; | 163 return VCM_OK; |
165 } | 164 } |
166 | 165 |
167 // Register a receive callback. Will be called whenever there is a new frame | 166 // Register a receive callback. Will be called whenever there is a new frame |
168 // ready for rendering. | 167 // ready for rendering. |
169 int32_t VideoReceiver::RegisterReceiveCallback( | 168 int32_t VideoReceiver::RegisterReceiveCallback( |
170 VCMReceiveCallback* receiveCallback) { | 169 VCMReceiveCallback* receiveCallback) { |
170 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
171 // TODO(tommi): Callback may be null, but only after the decoder thread has | |
172 // been stopped. | |
stefan-webrtc
2017/03/11 12:57:37
Clarify what is to be done to remove this TODO
tommi
2017/03/11 15:24:03
Done.
| |
171 rtc::CritScope cs(&receive_crit_); | 173 rtc::CritScope cs(&receive_crit_); |
172 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); | 174 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); |
173 return VCM_OK; | 175 return VCM_OK; |
174 } | 176 } |
175 | 177 |
176 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( | 178 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( |
177 VCMReceiveStatisticsCallback* receiveStats) { | 179 VCMReceiveStatisticsCallback* receiveStats) { |
180 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
178 rtc::CritScope cs(&process_crit_); | 181 rtc::CritScope cs(&process_crit_); |
179 _receiver.RegisterStatsCallback(receiveStats); | 182 _receiver.RegisterStatsCallback(receiveStats); |
180 _receiveStatsCallback = receiveStats; | 183 _receiveStatsCallback = receiveStats; |
181 return VCM_OK; | 184 return VCM_OK; |
182 } | 185 } |
183 | 186 |
184 int32_t VideoReceiver::RegisterDecoderTimingCallback( | 187 int32_t VideoReceiver::RegisterDecoderTimingCallback( |
185 VCMDecoderTimingCallback* decoderTiming) { | 188 VCMDecoderTimingCallback* decoderTiming) { |
189 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
186 rtc::CritScope cs(&process_crit_); | 190 rtc::CritScope cs(&process_crit_); |
187 _decoderTimingCallback = decoderTiming; | 191 _decoderTimingCallback = decoderTiming; |
188 return VCM_OK; | 192 return VCM_OK; |
189 } | 193 } |
190 | 194 |
191 // Register an externally defined decoder object. | 195 // Register an externally defined decoder object. |
192 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, | 196 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, |
193 uint8_t payloadType) { | 197 uint8_t payloadType) { |
198 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
199 // TODO(tommi): This method must be called when the decoder thread is not | |
200 // running. Do we need a lock in that case? | |
stefan-webrtc
2017/03/11 12:57:37
I think the answer is no as _codecDataBase only se
tommi
2017/03/11 15:24:03
Yes, this is more of a rhetorical question/TODO fr
| |
194 rtc::CritScope cs(&receive_crit_); | 201 rtc::CritScope cs(&receive_crit_); |
195 if (externalDecoder == nullptr) { | 202 if (externalDecoder == nullptr) { |
196 // Make sure the VCM updates the decoder next time it decodes. | |
197 _decoder = nullptr; | |
198 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType)); | 203 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType)); |
199 return; | 204 return; |
200 } | 205 } |
201 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType); | 206 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType); |
202 } | 207 } |
203 | 208 |
204 // Register a frame type request callback. | 209 // Register a frame type request callback. |
205 int32_t VideoReceiver::RegisterFrameTypeCallback( | 210 int32_t VideoReceiver::RegisterFrameTypeCallback( |
206 VCMFrameTypeCallback* frameTypeCallback) { | 211 VCMFrameTypeCallback* frameTypeCallback) { |
207 rtc::CritScope cs(&process_crit_); | 212 rtc::CritScope cs(&process_crit_); |
208 _frameTypeCallback = frameTypeCallback; | 213 _frameTypeCallback = frameTypeCallback; |
209 return VCM_OK; | 214 return VCM_OK; |
210 } | 215 } |
211 | 216 |
212 int32_t VideoReceiver::RegisterPacketRequestCallback( | 217 int32_t VideoReceiver::RegisterPacketRequestCallback( |
213 VCMPacketRequestCallback* callback) { | 218 VCMPacketRequestCallback* callback) { |
214 rtc::CritScope cs(&process_crit_); | 219 rtc::CritScope cs(&process_crit_); |
215 _packetRequestCallback = callback; | 220 _packetRequestCallback = callback; |
216 return VCM_OK; | 221 return VCM_OK; |
217 } | 222 } |
218 | 223 |
219 void VideoReceiver::TriggerDecoderShutdown() { | 224 void VideoReceiver::TriggerDecoderShutdown() { |
225 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
220 _receiver.TriggerDecoderShutdown(); | 226 _receiver.TriggerDecoderShutdown(); |
221 } | 227 } |
222 | 228 |
223 // Decode next frame, blocking. | 229 // Decode next frame, blocking. |
224 // Should be called as often as possible to get the most out of the decoder. | 230 // Should be called as often as possible to get the most out of the decoder. |
225 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { | 231 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { |
226 bool prefer_late_decoding = false; | 232 bool prefer_late_decoding = false; |
227 { | 233 { |
234 // TODO(tommi): Chances are that this lock isn't required. | |
228 rtc::CritScope cs(&receive_crit_); | 235 rtc::CritScope cs(&receive_crit_); |
229 prefer_late_decoding = _codecDataBase.PrefersLateDecoding(); | 236 prefer_late_decoding = _codecDataBase.PrefersLateDecoding(); |
230 } | 237 } |
231 | 238 |
232 VCMEncodedFrame* frame = | 239 VCMEncodedFrame* frame = |
233 _receiver.FrameForDecoding(maxWaitTimeMs, prefer_late_decoding); | 240 _receiver.FrameForDecoding(maxWaitTimeMs, prefer_late_decoding); |
234 | 241 |
235 if (!frame) | 242 if (!frame) |
236 return VCM_FRAME_NOT_READY; | 243 return VCM_FRAME_NOT_READY; |
237 | 244 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 int qp = -1; | 292 int qp = -1; |
286 if (qp_parser_.GetQp(*frame, &qp)) { | 293 if (qp_parser_.GetQp(*frame, &qp)) { |
287 encoded_image.qp_ = qp; | 294 encoded_image.qp_ = qp; |
288 } | 295 } |
289 pre_decode_image_callback_->OnEncodedImage(encoded_image, | 296 pre_decode_image_callback_->OnEncodedImage(encoded_image, |
290 frame->CodecSpecific(), nullptr); | 297 frame->CodecSpecific(), nullptr); |
291 } | 298 } |
292 return Decode(*frame); | 299 return Decode(*frame); |
293 } | 300 } |
294 | 301 |
302 void VideoReceiver::DecodingStopped() { | |
303 // No further calls to Decode() will be made after this point. | |
304 // TODO(tommi): Make use of this to clarify and check threading model. | |
305 } | |
306 | |
295 int32_t VideoReceiver::RequestSliceLossIndication( | 307 int32_t VideoReceiver::RequestSliceLossIndication( |
296 const uint64_t pictureID) const { | 308 const uint64_t pictureID) const { |
297 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); | 309 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); |
298 rtc::CritScope cs(&process_crit_); | 310 rtc::CritScope cs(&process_crit_); |
299 if (_frameTypeCallback != nullptr) { | 311 if (_frameTypeCallback != nullptr) { |
300 const int32_t ret = | 312 const int32_t ret = |
301 _frameTypeCallback->SliceLossIndicationRequest(pictureID); | 313 _frameTypeCallback->SliceLossIndicationRequest(pictureID); |
302 if (ret < 0) { | 314 if (ret < 0) { |
303 return ret; | 315 return ret; |
304 } | 316 } |
(...skipping 15 matching lines...) Expand all Loading... | |
320 } else { | 332 } else { |
321 return VCM_MISSING_CALLBACK; | 333 return VCM_MISSING_CALLBACK; |
322 } | 334 } |
323 return VCM_OK; | 335 return VCM_OK; |
324 } | 336 } |
325 | 337 |
326 // Must be called from inside the receive side critical section. | 338 // Must be called from inside the receive side critical section. |
327 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { | 339 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { |
328 TRACE_EVENT0("webrtc", "VideoReceiver::Decode"); | 340 TRACE_EVENT0("webrtc", "VideoReceiver::Decode"); |
329 // Change decoder if payload type has changed | 341 // Change decoder if payload type has changed |
330 _decoder = _codecDataBase.GetDecoder(frame, &_decodedFrameCallback); | 342 VCMGenericDecoder* decoder = |
331 if (_decoder == nullptr) { | 343 _codecDataBase.GetDecoder(frame, &_decodedFrameCallback); |
344 if (decoder == nullptr) { | |
332 return VCM_NO_CODEC_REGISTERED; | 345 return VCM_NO_CODEC_REGISTERED; |
333 } | 346 } |
334 // Decode a frame | 347 // Decode a frame |
335 int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds()); | 348 int32_t ret = decoder->Decode(frame, clock_->TimeInMilliseconds()); |
336 | 349 |
337 // Check for failed decoding, run frame type request callback if needed. | 350 // Check for failed decoding, run frame type request callback if needed. |
338 bool request_key_frame = false; | 351 bool request_key_frame = false; |
339 if (ret < 0) { | 352 if (ret < 0) { |
340 if (ret == VCM_ERROR_REQUEST_SLI) { | 353 if (ret == VCM_ERROR_REQUEST_SLI) { |
341 return RequestSliceLossIndication( | 354 return RequestSliceLossIndication( |
342 _decodedFrameCallback.LastReceivedPictureID() + 1); | 355 _decodedFrameCallback.LastReceivedPictureID() + 1); |
343 } else { | 356 } else { |
344 request_key_frame = true; | 357 request_key_frame = true; |
345 } | 358 } |
346 } else if (ret == VCM_REQUEST_SLI) { | 359 } else if (ret == VCM_REQUEST_SLI) { |
347 ret = RequestSliceLossIndication( | 360 ret = RequestSliceLossIndication( |
348 _decodedFrameCallback.LastReceivedPictureID() + 1); | 361 _decodedFrameCallback.LastReceivedPictureID() + 1); |
349 } | 362 } |
350 if (!frame.Complete() || frame.MissingFrame()) { | 363 if (!frame.Complete() || frame.MissingFrame()) { |
351 request_key_frame = true; | 364 request_key_frame = true; |
352 ret = VCM_OK; | 365 ret = VCM_OK; |
353 } | 366 } |
354 if (request_key_frame) { | 367 if (request_key_frame) { |
355 rtc::CritScope cs(&process_crit_); | 368 rtc::CritScope cs(&process_crit_); |
356 _scheduleKeyRequest = true; | 369 _scheduleKeyRequest = true; |
357 } | 370 } |
358 return ret; | 371 return ret; |
359 } | 372 } |
360 | 373 |
361 // Register possible receive codecs, can be called multiple times | 374 // Register possible receive codecs, can be called multiple times |
362 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, | 375 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, |
363 int32_t numberOfCores, | 376 int32_t numberOfCores, |
364 bool requireKeyFrame) { | 377 bool requireKeyFrame) { |
378 RTC_DCHECK(construction_thread_.CalledOnValidThread()); | |
379 // TODO(tommi): This method must only be called when the decoder thread | |
380 // is not running. Do we need a lock? If not, it looks like we might not need | |
381 // a lock at all for |_codecDataBase|. | |
365 rtc::CritScope cs(&receive_crit_); | 382 rtc::CritScope cs(&receive_crit_); |
366 if (receiveCodec == nullptr) { | 383 if (receiveCodec == nullptr) { |
367 return VCM_PARAMETER_ERROR; | 384 return VCM_PARAMETER_ERROR; |
368 } | 385 } |
369 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, | 386 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, |
370 requireKeyFrame)) { | 387 requireKeyFrame)) { |
371 return -1; | 388 return -1; |
372 } | 389 } |
373 return 0; | 390 return 0; |
374 } | 391 } |
375 | 392 |
376 // Get current received codec | 393 // Get current received codec |
394 // TODO(tommi): See if there are any actual callers to this method. | |
395 // If not, it will make threading simpler. | |
stefan-webrtc
2017/03/11 12:57:37
No calls that I can find.
tommi
2017/03/11 15:24:03
Thanks for looking. I didn't find any either. I'l
| |
377 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { | 396 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { |
378 rtc::CritScope cs(&receive_crit_); | 397 rtc::CritScope cs(&receive_crit_); |
379 if (currentReceiveCodec == nullptr) { | 398 if (currentReceiveCodec == nullptr) { |
380 return VCM_PARAMETER_ERROR; | 399 return VCM_PARAMETER_ERROR; |
381 } | 400 } |
382 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; | 401 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; |
383 } | 402 } |
384 | 403 |
385 // Get current received codec | 404 // Get current received codec |
405 // TODO(tommi): See if there are any actual callers to this method. | |
406 // If not, it will make threading simpler. | |
386 VideoCodecType VideoReceiver::ReceiveCodec() const { | 407 VideoCodecType VideoReceiver::ReceiveCodec() const { |
387 rtc::CritScope cs(&receive_crit_); | 408 rtc::CritScope cs(&receive_crit_); |
388 return _codecDataBase.ReceiveCodec(); | 409 return _codecDataBase.ReceiveCodec(); |
389 } | 410 } |
390 | 411 |
391 // Incoming packet from network parsed and ready for decode, non blocking. | 412 // Incoming packet from network parsed and ready for decode, non blocking. |
392 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, | 413 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, |
393 size_t payloadLength, | 414 size_t payloadLength, |
394 const WebRtcRTPHeader& rtpInfo) { | 415 const WebRtcRTPHeader& rtpInfo) { |
395 if (rtpInfo.frameType == kVideoFrameKey) { | 416 if (rtpInfo.frameType == kVideoFrameKey) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
496 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, | 517 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, |
497 max_incomplete_time_ms); | 518 max_incomplete_time_ms); |
498 } | 519 } |
499 | 520 |
500 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { | 521 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { |
501 return _receiver.SetMinReceiverDelay(desired_delay_ms); | 522 return _receiver.SetMinReceiverDelay(desired_delay_ms); |
502 } | 523 } |
503 | 524 |
504 } // namespace vcm | 525 } // namespace vcm |
505 } // namespace webrtc | 526 } // namespace webrtc |
OLD | NEW |