Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: webrtc/modules/video_coding/video_receiver.cc

Issue 2744013002: Updates to VCMDecodedFrameCallback, VideoReceiver and a few related classes/tests. (Closed)
Patch Set: Update DCHECKs Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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. Use the signal we now get that tells us when the decoder
173 // thread isn't running, to DCHECK that the method is never called while it
174 // is. Once we're confident, we can remove the lock.
171 rtc::CritScope cs(&receive_crit_); 175 rtc::CritScope cs(&receive_crit_);
172 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback); 176 _decodedFrameCallback.SetUserReceiveCallback(receiveCallback);
173 return VCM_OK; 177 return VCM_OK;
174 } 178 }
175 179
176 int32_t VideoReceiver::RegisterReceiveStatisticsCallback( 180 int32_t VideoReceiver::RegisterReceiveStatisticsCallback(
177 VCMReceiveStatisticsCallback* receiveStats) { 181 VCMReceiveStatisticsCallback* receiveStats) {
182 RTC_DCHECK(construction_thread_.CalledOnValidThread());
178 rtc::CritScope cs(&process_crit_); 183 rtc::CritScope cs(&process_crit_);
179 _receiver.RegisterStatsCallback(receiveStats); 184 _receiver.RegisterStatsCallback(receiveStats);
180 _receiveStatsCallback = receiveStats; 185 _receiveStatsCallback = receiveStats;
181 return VCM_OK; 186 return VCM_OK;
182 } 187 }
183 188
184 int32_t VideoReceiver::RegisterDecoderTimingCallback( 189 int32_t VideoReceiver::RegisterDecoderTimingCallback(
185 VCMDecoderTimingCallback* decoderTiming) { 190 VCMDecoderTimingCallback* decoderTiming) {
191 RTC_DCHECK(construction_thread_.CalledOnValidThread());
186 rtc::CritScope cs(&process_crit_); 192 rtc::CritScope cs(&process_crit_);
187 _decoderTimingCallback = decoderTiming; 193 _decoderTimingCallback = decoderTiming;
188 return VCM_OK; 194 return VCM_OK;
189 } 195 }
190 196
191 // Register an externally defined decoder object. 197 // Register an externally defined decoder object.
192 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder, 198 void VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder,
193 uint8_t payloadType) { 199 uint8_t payloadType) {
200 RTC_DCHECK(construction_thread_.CalledOnValidThread());
201 // TODO(tommi): This method must be called when the decoder thread is not
202 // running. Do we need a lock in that case?
194 rtc::CritScope cs(&receive_crit_); 203 rtc::CritScope cs(&receive_crit_);
195 if (externalDecoder == nullptr) { 204 if (externalDecoder == nullptr) {
196 // Make sure the VCM updates the decoder next time it decodes.
197 _decoder = nullptr;
198 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType)); 205 RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType));
199 return; 206 return;
200 } 207 }
201 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType); 208 _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType);
202 } 209 }
203 210
204 // Register a frame type request callback. 211 // Register a frame type request callback.
205 int32_t VideoReceiver::RegisterFrameTypeCallback( 212 int32_t VideoReceiver::RegisterFrameTypeCallback(
206 VCMFrameTypeCallback* frameTypeCallback) { 213 VCMFrameTypeCallback* frameTypeCallback) {
207 rtc::CritScope cs(&process_crit_); 214 rtc::CritScope cs(&process_crit_);
208 _frameTypeCallback = frameTypeCallback; 215 _frameTypeCallback = frameTypeCallback;
209 return VCM_OK; 216 return VCM_OK;
210 } 217 }
211 218
212 int32_t VideoReceiver::RegisterPacketRequestCallback( 219 int32_t VideoReceiver::RegisterPacketRequestCallback(
213 VCMPacketRequestCallback* callback) { 220 VCMPacketRequestCallback* callback) {
214 rtc::CritScope cs(&process_crit_); 221 rtc::CritScope cs(&process_crit_);
215 _packetRequestCallback = callback; 222 _packetRequestCallback = callback;
216 return VCM_OK; 223 return VCM_OK;
217 } 224 }
218 225
219 void VideoReceiver::TriggerDecoderShutdown() { 226 void VideoReceiver::TriggerDecoderShutdown() {
227 RTC_DCHECK(construction_thread_.CalledOnValidThread());
220 _receiver.TriggerDecoderShutdown(); 228 _receiver.TriggerDecoderShutdown();
221 } 229 }
222 230
223 // Decode next frame, blocking. 231 // Decode next frame, blocking.
224 // Should be called as often as possible to get the most out of the decoder. 232 // Should be called as often as possible to get the most out of the decoder.
225 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) { 233 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) {
226 bool prefer_late_decoding = false; 234 bool prefer_late_decoding = false;
227 { 235 {
236 // TODO(tommi): Chances are that this lock isn't required.
228 rtc::CritScope cs(&receive_crit_); 237 rtc::CritScope cs(&receive_crit_);
229 prefer_late_decoding = _codecDataBase.PrefersLateDecoding(); 238 prefer_late_decoding = _codecDataBase.PrefersLateDecoding();
230 } 239 }
231 240
232 VCMEncodedFrame* frame = 241 VCMEncodedFrame* frame =
233 _receiver.FrameForDecoding(maxWaitTimeMs, prefer_late_decoding); 242 _receiver.FrameForDecoding(maxWaitTimeMs, prefer_late_decoding);
234 243
235 if (!frame) 244 if (!frame)
236 return VCM_FRAME_NOT_READY; 245 return VCM_FRAME_NOT_READY;
237 246
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 int qp = -1; 294 int qp = -1;
286 if (qp_parser_.GetQp(*frame, &qp)) { 295 if (qp_parser_.GetQp(*frame, &qp)) {
287 encoded_image.qp_ = qp; 296 encoded_image.qp_ = qp;
288 } 297 }
289 pre_decode_image_callback_->OnEncodedImage(encoded_image, 298 pre_decode_image_callback_->OnEncodedImage(encoded_image,
290 frame->CodecSpecific(), nullptr); 299 frame->CodecSpecific(), nullptr);
291 } 300 }
292 return Decode(*frame); 301 return Decode(*frame);
293 } 302 }
294 303
304 void VideoReceiver::DecodingStopped() {
305 // No further calls to Decode() will be made after this point.
306 // TODO(tommi): Make use of this to clarify and check threading model.
307 }
308
295 int32_t VideoReceiver::RequestSliceLossIndication( 309 int32_t VideoReceiver::RequestSliceLossIndication(
296 const uint64_t pictureID) const { 310 const uint64_t pictureID) const {
297 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID); 311 TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID);
298 rtc::CritScope cs(&process_crit_); 312 rtc::CritScope cs(&process_crit_);
299 if (_frameTypeCallback != nullptr) { 313 if (_frameTypeCallback != nullptr) {
300 const int32_t ret = 314 const int32_t ret =
301 _frameTypeCallback->SliceLossIndicationRequest(pictureID); 315 _frameTypeCallback->SliceLossIndicationRequest(pictureID);
302 if (ret < 0) { 316 if (ret < 0) {
303 return ret; 317 return ret;
304 } 318 }
(...skipping 15 matching lines...) Expand all
320 } else { 334 } else {
321 return VCM_MISSING_CALLBACK; 335 return VCM_MISSING_CALLBACK;
322 } 336 }
323 return VCM_OK; 337 return VCM_OK;
324 } 338 }
325 339
326 // Must be called from inside the receive side critical section. 340 // Must be called from inside the receive side critical section.
327 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) { 341 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) {
328 TRACE_EVENT0("webrtc", "VideoReceiver::Decode"); 342 TRACE_EVENT0("webrtc", "VideoReceiver::Decode");
329 // Change decoder if payload type has changed 343 // Change decoder if payload type has changed
330 _decoder = _codecDataBase.GetDecoder(frame, &_decodedFrameCallback); 344 VCMGenericDecoder* decoder =
331 if (_decoder == nullptr) { 345 _codecDataBase.GetDecoder(frame, &_decodedFrameCallback);
346 if (decoder == nullptr) {
332 return VCM_NO_CODEC_REGISTERED; 347 return VCM_NO_CODEC_REGISTERED;
333 } 348 }
334 // Decode a frame 349 // Decode a frame
335 int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds()); 350 int32_t ret = decoder->Decode(frame, clock_->TimeInMilliseconds());
336 351
337 // Check for failed decoding, run frame type request callback if needed. 352 // Check for failed decoding, run frame type request callback if needed.
338 bool request_key_frame = false; 353 bool request_key_frame = false;
339 if (ret < 0) { 354 if (ret < 0) {
340 if (ret == VCM_ERROR_REQUEST_SLI) { 355 if (ret == VCM_ERROR_REQUEST_SLI) {
341 return RequestSliceLossIndication( 356 return RequestSliceLossIndication(
342 _decodedFrameCallback.LastReceivedPictureID() + 1); 357 _decodedFrameCallback.LastReceivedPictureID() + 1);
343 } else { 358 } else {
344 request_key_frame = true; 359 request_key_frame = true;
345 } 360 }
346 } else if (ret == VCM_REQUEST_SLI) { 361 } else if (ret == VCM_REQUEST_SLI) {
347 ret = RequestSliceLossIndication( 362 ret = RequestSliceLossIndication(
348 _decodedFrameCallback.LastReceivedPictureID() + 1); 363 _decodedFrameCallback.LastReceivedPictureID() + 1);
349 } 364 }
350 if (!frame.Complete() || frame.MissingFrame()) { 365 if (!frame.Complete() || frame.MissingFrame()) {
351 request_key_frame = true; 366 request_key_frame = true;
352 ret = VCM_OK; 367 ret = VCM_OK;
353 } 368 }
354 if (request_key_frame) { 369 if (request_key_frame) {
355 rtc::CritScope cs(&process_crit_); 370 rtc::CritScope cs(&process_crit_);
356 _scheduleKeyRequest = true; 371 _scheduleKeyRequest = true;
357 } 372 }
358 return ret; 373 return ret;
359 } 374 }
360 375
361 // Register possible receive codecs, can be called multiple times 376 // Register possible receive codecs, can be called multiple times
362 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec, 377 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec,
363 int32_t numberOfCores, 378 int32_t numberOfCores,
364 bool requireKeyFrame) { 379 bool requireKeyFrame) {
380 RTC_DCHECK(construction_thread_.CalledOnValidThread());
381 // TODO(tommi): This method must only be called when the decoder thread
382 // is not running. Do we need a lock? If not, it looks like we might not need
383 // a lock at all for |_codecDataBase|.
365 rtc::CritScope cs(&receive_crit_); 384 rtc::CritScope cs(&receive_crit_);
366 if (receiveCodec == nullptr) { 385 if (receiveCodec == nullptr) {
367 return VCM_PARAMETER_ERROR; 386 return VCM_PARAMETER_ERROR;
368 } 387 }
369 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores, 388 if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores,
370 requireKeyFrame)) { 389 requireKeyFrame)) {
371 return -1; 390 return -1;
372 } 391 }
373 return 0; 392 return 0;
374 } 393 }
375 394
376 // Get current received codec 395 // Get current received codec
396 // TODO(tommi): See if there are any actual callers to this method.
397 // Neither me nor Stefan could find callers. If we can remove it, threading
398 // will be simpler.
377 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const { 399 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const {
378 rtc::CritScope cs(&receive_crit_); 400 rtc::CritScope cs(&receive_crit_);
379 if (currentReceiveCodec == nullptr) { 401 if (currentReceiveCodec == nullptr) {
380 return VCM_PARAMETER_ERROR; 402 return VCM_PARAMETER_ERROR;
381 } 403 }
382 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1; 404 return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1;
383 } 405 }
384 406
385 // Get current received codec 407 // Get current received codec
408 // TODO(tommi): See if there are any actual callers to this method.
409 // If not, it will make threading simpler.
386 VideoCodecType VideoReceiver::ReceiveCodec() const { 410 VideoCodecType VideoReceiver::ReceiveCodec() const {
387 rtc::CritScope cs(&receive_crit_); 411 rtc::CritScope cs(&receive_crit_);
388 return _codecDataBase.ReceiveCodec(); 412 return _codecDataBase.ReceiveCodec();
389 } 413 }
390 414
391 // Incoming packet from network parsed and ready for decode, non blocking. 415 // Incoming packet from network parsed and ready for decode, non blocking.
392 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload, 416 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload,
393 size_t payloadLength, 417 size_t payloadLength,
394 const WebRtcRTPHeader& rtpInfo) { 418 const WebRtcRTPHeader& rtpInfo) {
395 if (rtpInfo.frameType == kVideoFrameKey) { 419 if (rtpInfo.frameType == kVideoFrameKey) {
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack, 520 _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
497 max_incomplete_time_ms); 521 max_incomplete_time_ms);
498 } 522 }
499 523
500 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) { 524 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) {
501 return _receiver.SetMinReceiverDelay(desired_delay_ms); 525 return _receiver.SetMinReceiverDelay(desired_delay_ms);
502 } 526 }
503 527
504 } // namespace vcm 528 } // namespace vcm
505 } // namespace webrtc 529 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698