• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (c) 2013 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/common_types.h"
12 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
13 #include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
14 #include "webrtc/modules/video_coding/main/source/encoded_frame.h"
15 #include "webrtc/modules/video_coding/main/source/jitter_buffer.h"
16 #include "webrtc/modules/video_coding/main/source/packet.h"
17 #include "webrtc/modules/video_coding/main/source/video_coding_impl.h"
18 #include "webrtc/system_wrappers/interface/clock.h"
19 #include "webrtc/system_wrappers/interface/logging.h"
20 #include "webrtc/system_wrappers/interface/trace_event.h"
21 
22 // #define DEBUG_DECODER_BIT_STREAM
23 
24 namespace webrtc {
25 namespace vcm {
26 
VideoReceiver(Clock * clock,EventFactory * event_factory)27 VideoReceiver::VideoReceiver(Clock* clock, EventFactory* event_factory)
28     : clock_(clock),
29       process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
30       _receiveCritSect(CriticalSectionWrapper::CreateCriticalSection()),
31       _receiverInited(false),
32       _timing(clock_),
33       _dualTiming(clock_, &_timing),
34       _receiver(&_timing, clock_, event_factory, true),
35       _dualReceiver(&_dualTiming, clock_, event_factory, false),
36       _decodedFrameCallback(_timing, clock_),
37       _dualDecodedFrameCallback(_dualTiming, clock_),
38       _frameTypeCallback(NULL),
39       _receiveStatsCallback(NULL),
40       _decoderTimingCallback(NULL),
41       _packetRequestCallback(NULL),
42       render_buffer_callback_(NULL),
43       _decoder(NULL),
44       _dualDecoder(NULL),
45 #ifdef DEBUG_DECODER_BIT_STREAM
46       _bitStreamBeforeDecoder(NULL),
47 #endif
48       _frameFromFile(),
49       _keyRequestMode(kKeyOnError),
50       _scheduleKeyRequest(false),
51       max_nack_list_size_(0),
52       pre_decode_image_callback_(NULL),
53       _codecDataBase(),
54       _receiveStatsTimer(1000, clock_),
55       _retransmissionTimer(10, clock_),
56       _keyRequestTimer(500, clock_) {
57   assert(clock_);
58 #ifdef DEBUG_DECODER_BIT_STREAM
59   _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb");
60 #endif
61 }
62 
~VideoReceiver()63 VideoReceiver::~VideoReceiver() {
64   if (_dualDecoder != NULL) {
65     _codecDataBase.ReleaseDecoder(_dualDecoder);
66   }
67   delete _receiveCritSect;
68 #ifdef DEBUG_DECODER_BIT_STREAM
69   fclose(_bitStreamBeforeDecoder);
70 #endif
71 }
72 
Process()73 int32_t VideoReceiver::Process() {
74   int32_t returnValue = VCM_OK;
75 
76   // Receive-side statistics
77   if (_receiveStatsTimer.TimeUntilProcess() == 0) {
78     _receiveStatsTimer.Processed();
79     CriticalSectionScoped cs(process_crit_sect_.get());
80     if (_receiveStatsCallback != NULL) {
81       uint32_t bitRate;
82       uint32_t frameRate;
83       _receiver.ReceiveStatistics(&bitRate, &frameRate);
84       _receiveStatsCallback->OnReceiveStatisticsUpdate(bitRate, frameRate);
85     }
86 
87     if (_decoderTimingCallback != NULL) {
88       int decode_ms;
89       int max_decode_ms;
90       int current_delay_ms;
91       int target_delay_ms;
92       int jitter_buffer_ms;
93       int min_playout_delay_ms;
94       int render_delay_ms;
95       _timing.GetTimings(&decode_ms,
96                          &max_decode_ms,
97                          &current_delay_ms,
98                          &target_delay_ms,
99                          &jitter_buffer_ms,
100                          &min_playout_delay_ms,
101                          &render_delay_ms);
102       _decoderTimingCallback->OnDecoderTiming(decode_ms,
103                                               max_decode_ms,
104                                               current_delay_ms,
105                                               target_delay_ms,
106                                               jitter_buffer_ms,
107                                               min_playout_delay_ms,
108                                               render_delay_ms);
109     }
110 
111     // Size of render buffer.
112     if (render_buffer_callback_) {
113       int buffer_size_ms = _receiver.RenderBufferSizeMs();
114       render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms);
115     }
116   }
117 
118   // Key frame requests
119   if (_keyRequestTimer.TimeUntilProcess() == 0) {
120     _keyRequestTimer.Processed();
121     bool request_key_frame = false;
122     {
123       CriticalSectionScoped cs(process_crit_sect_.get());
124       request_key_frame = _scheduleKeyRequest && _frameTypeCallback != NULL;
125     }
126     if (request_key_frame) {
127       const int32_t ret = RequestKeyFrame();
128       if (ret != VCM_OK && returnValue == VCM_OK) {
129         returnValue = ret;
130       }
131     }
132   }
133 
134   // Packet retransmission requests
135   // TODO(holmer): Add API for changing Process interval and make sure it's
136   // disabled when NACK is off.
137   if (_retransmissionTimer.TimeUntilProcess() == 0) {
138     _retransmissionTimer.Processed();
139     bool callback_registered = false;
140     uint16_t length;
141     {
142       CriticalSectionScoped cs(process_crit_sect_.get());
143       length = max_nack_list_size_;
144       callback_registered = _packetRequestCallback != NULL;
145     }
146     if (callback_registered && length > 0) {
147       std::vector<uint16_t> nackList(length);
148       const int32_t ret = NackList(&nackList[0], &length);
149       if (ret != VCM_OK && returnValue == VCM_OK) {
150         returnValue = ret;
151       }
152       if (ret == VCM_OK && length > 0) {
153         CriticalSectionScoped cs(process_crit_sect_.get());
154         if (_packetRequestCallback != NULL) {
155           _packetRequestCallback->ResendPackets(&nackList[0], length);
156         }
157       }
158     }
159   }
160 
161   return returnValue;
162 }
163 
TimeUntilNextProcess()164 int32_t VideoReceiver::TimeUntilNextProcess() {
165   uint32_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess();
166   if ((_receiver.NackMode() != kNoNack) ||
167       (_dualReceiver.State() != kPassive)) {
168     // We need a Process call more often if we are relying on
169     // retransmissions
170     timeUntilNextProcess =
171         VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess());
172   }
173   timeUntilNextProcess =
174       VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess());
175 
176   return timeUntilNextProcess;
177 }
178 
SetReceiveChannelParameters(uint32_t rtt)179 int32_t VideoReceiver::SetReceiveChannelParameters(uint32_t rtt) {
180   CriticalSectionScoped receiveCs(_receiveCritSect);
181   _receiver.UpdateRtt(rtt);
182   return 0;
183 }
184 
185 // Enable or disable a video protection method.
186 // Note: This API should be deprecated, as it does not offer a distinction
187 // between the protection method and decoding with or without errors. If such a
188 // behavior is desired, use the following API: SetReceiverRobustnessMode.
SetVideoProtection(VCMVideoProtection videoProtection,bool enable)189 int32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
190                                           bool enable) {
191   // By default, do not decode with errors.
192   _receiver.SetDecodeErrorMode(kNoErrors);
193   // The dual decoder should always be error free.
194   _dualReceiver.SetDecodeErrorMode(kNoErrors);
195   switch (videoProtection) {
196     case kProtectionNack:
197     case kProtectionNackReceiver: {
198       CriticalSectionScoped cs(_receiveCritSect);
199       if (enable) {
200         // Enable NACK and always wait for retransmits.
201         _receiver.SetNackMode(kNack, -1, -1);
202       } else {
203         _receiver.SetNackMode(kNoNack, -1, -1);
204       }
205       break;
206     }
207 
208     case kProtectionDualDecoder: {
209       CriticalSectionScoped cs(_receiveCritSect);
210       if (enable) {
211         // Enable NACK but don't wait for retransmissions and don't
212         // add any extra delay.
213         _receiver.SetNackMode(kNack, 0, 0);
214         // Enable NACK and always wait for retransmissions and
215         // compensate with extra delay.
216         _dualReceiver.SetNackMode(kNack, -1, -1);
217         _receiver.SetDecodeErrorMode(kWithErrors);
218       } else {
219         _dualReceiver.SetNackMode(kNoNack, -1, -1);
220       }
221       break;
222     }
223 
224     case kProtectionKeyOnLoss: {
225       CriticalSectionScoped cs(_receiveCritSect);
226       if (enable) {
227         _keyRequestMode = kKeyOnLoss;
228         _receiver.SetDecodeErrorMode(kWithErrors);
229       } else if (_keyRequestMode == kKeyOnLoss) {
230         _keyRequestMode = kKeyOnError;  // default mode
231       } else {
232         return VCM_PARAMETER_ERROR;
233       }
234       break;
235     }
236 
237     case kProtectionKeyOnKeyLoss: {
238       CriticalSectionScoped cs(_receiveCritSect);
239       if (enable) {
240         _keyRequestMode = kKeyOnKeyLoss;
241       } else if (_keyRequestMode == kKeyOnKeyLoss) {
242         _keyRequestMode = kKeyOnError;  // default mode
243       } else {
244         return VCM_PARAMETER_ERROR;
245       }
246       break;
247     }
248 
249     case kProtectionNackFEC: {
250       CriticalSectionScoped cs(_receiveCritSect);
251       if (enable) {
252         // Enable hybrid NACK/FEC. Always wait for retransmissions
253         // and don't add extra delay when RTT is above
254         // kLowRttNackMs.
255         _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
256         _receiver.SetDecodeErrorMode(kNoErrors);
257         _receiver.SetDecodeErrorMode(kNoErrors);
258       } else {
259         _receiver.SetNackMode(kNoNack, -1, -1);
260       }
261       break;
262     }
263     case kProtectionNackSender:
264     case kProtectionFEC:
265     case kProtectionPeriodicKeyFrames:
266       // Ignore encoder modes.
267       return VCM_OK;
268   }
269   return VCM_OK;
270 }
271 
272 // Initialize receiver, resets codec database etc
InitializeReceiver()273 int32_t VideoReceiver::InitializeReceiver() {
274   CriticalSectionScoped receive_cs(_receiveCritSect);
275   CriticalSectionScoped process_cs(process_crit_sect_.get());
276   int32_t ret = _receiver.Initialize();
277   if (ret < 0) {
278     return ret;
279   }
280 
281   ret = _dualReceiver.Initialize();
282   if (ret < 0) {
283     return ret;
284   }
285   _codecDataBase.ResetReceiver();
286   _timing.Reset();
287 
288   _decoder = NULL;
289   _decodedFrameCallback.SetUserReceiveCallback(NULL);
290   _receiverInited = true;
291   _frameTypeCallback = NULL;
292   _receiveStatsCallback = NULL;
293   _decoderTimingCallback = NULL;
294   _packetRequestCallback = NULL;
295   _keyRequestMode = kKeyOnError;
296   _scheduleKeyRequest = false;
297 
298   return VCM_OK;
299 }
300 
301 // Register a receive callback. Will be called whenever there is a new frame
302 // ready for rendering.
RegisterReceiveCallback(VCMReceiveCallback * receiveCallback)303 int32_t VideoReceiver::RegisterReceiveCallback(
304     VCMReceiveCallback* receiveCallback) {
305   CriticalSectionScoped cs(_receiveCritSect);
306   _decodedFrameCallback.SetUserReceiveCallback(receiveCallback);
307   return VCM_OK;
308 }
309 
RegisterReceiveStatisticsCallback(VCMReceiveStatisticsCallback * receiveStats)310 int32_t VideoReceiver::RegisterReceiveStatisticsCallback(
311     VCMReceiveStatisticsCallback* receiveStats) {
312   CriticalSectionScoped cs(process_crit_sect_.get());
313   _receiveStatsCallback = receiveStats;
314   return VCM_OK;
315 }
316 
RegisterDecoderTimingCallback(VCMDecoderTimingCallback * decoderTiming)317 int32_t VideoReceiver::RegisterDecoderTimingCallback(
318     VCMDecoderTimingCallback* decoderTiming) {
319   CriticalSectionScoped cs(process_crit_sect_.get());
320   _decoderTimingCallback = decoderTiming;
321   return VCM_OK;
322 }
323 
324 // Register an externally defined decoder/render object.
325 // Can be a decoder only or a decoder coupled with a renderer.
RegisterExternalDecoder(VideoDecoder * externalDecoder,uint8_t payloadType,bool internalRenderTiming)326 int32_t VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder,
327                                                uint8_t payloadType,
328                                                bool internalRenderTiming) {
329   CriticalSectionScoped cs(_receiveCritSect);
330   if (externalDecoder == NULL) {
331     // Make sure the VCM updates the decoder next time it decodes.
332     _decoder = NULL;
333     return _codecDataBase.DeregisterExternalDecoder(payloadType) ? 0 : -1;
334   }
335   return _codecDataBase.RegisterExternalDecoder(
336              externalDecoder, payloadType, internalRenderTiming)
337              ? 0
338              : -1;
339 }
340 
341 // Register a frame type request callback.
RegisterFrameTypeCallback(VCMFrameTypeCallback * frameTypeCallback)342 int32_t VideoReceiver::RegisterFrameTypeCallback(
343     VCMFrameTypeCallback* frameTypeCallback) {
344   CriticalSectionScoped cs(process_crit_sect_.get());
345   _frameTypeCallback = frameTypeCallback;
346   return VCM_OK;
347 }
348 
RegisterPacketRequestCallback(VCMPacketRequestCallback * callback)349 int32_t VideoReceiver::RegisterPacketRequestCallback(
350     VCMPacketRequestCallback* callback) {
351   CriticalSectionScoped cs(process_crit_sect_.get());
352   _packetRequestCallback = callback;
353   return VCM_OK;
354 }
355 
RegisterRenderBufferSizeCallback(VCMRenderBufferSizeCallback * callback)356 int VideoReceiver::RegisterRenderBufferSizeCallback(
357     VCMRenderBufferSizeCallback* callback) {
358   CriticalSectionScoped cs(process_crit_sect_.get());
359   render_buffer_callback_ = callback;
360   return VCM_OK;
361 }
362 
363 // Decode next frame, blocking.
364 // Should be called as often as possible to get the most out of the decoder.
Decode(uint16_t maxWaitTimeMs)365 int32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) {
366   int64_t nextRenderTimeMs;
367   {
368     CriticalSectionScoped cs(_receiveCritSect);
369     if (!_receiverInited) {
370       return VCM_UNINITIALIZED;
371     }
372     if (!_codecDataBase.DecoderRegistered()) {
373       return VCM_NO_CODEC_REGISTERED;
374     }
375   }
376 
377   const bool dualReceiverEnabledNotReceiving = (
378       _dualReceiver.State() != kReceiving && _dualReceiver.NackMode() == kNack);
379 
380   VCMEncodedFrame* frame =
381       _receiver.FrameForDecoding(maxWaitTimeMs,
382                                  nextRenderTimeMs,
383                                  _codecDataBase.SupportsRenderScheduling(),
384                                  &_dualReceiver);
385 
386   if (dualReceiverEnabledNotReceiving && _dualReceiver.State() == kReceiving) {
387     // Dual receiver is enabled (kNACK enabled), but was not receiving
388     // before the call to FrameForDecoding(). After the call the state
389     // changed to receiving, and therefore we must copy the primary decoder
390     // state to the dual decoder to make it possible for the dual decoder to
391     // start decoding retransmitted frames and recover.
392     CriticalSectionScoped cs(_receiveCritSect);
393     if (_dualDecoder != NULL) {
394       _codecDataBase.ReleaseDecoder(_dualDecoder);
395     }
396     _dualDecoder = _codecDataBase.CreateDecoderCopy();
397     if (_dualDecoder != NULL) {
398       _dualDecoder->RegisterDecodeCompleteCallback(&_dualDecodedFrameCallback);
399     } else {
400       _dualReceiver.Reset();
401     }
402   }
403 
404   if (frame == NULL) {
405     return VCM_FRAME_NOT_READY;
406   } else {
407     CriticalSectionScoped cs(_receiveCritSect);
408 
409     // If this frame was too late, we should adjust the delay accordingly
410     _timing.UpdateCurrentDelay(frame->RenderTimeMs(),
411                                clock_->TimeInMilliseconds());
412 
413     if (pre_decode_image_callback_) {
414       EncodedImage encoded_image(frame->EncodedImage());
415       pre_decode_image_callback_->Encoded(encoded_image);
416     }
417 
418 #ifdef DEBUG_DECODER_BIT_STREAM
419     if (_bitStreamBeforeDecoder != NULL) {
420       // Write bit stream to file for debugging purposes
421       if (fwrite(
422               frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) !=
423           frame->Length()) {
424         return -1;
425       }
426     }
427 #endif
428     const int32_t ret = Decode(*frame);
429     _receiver.ReleaseFrame(frame);
430     frame = NULL;
431     if (ret != VCM_OK) {
432       return ret;
433     }
434   }
435   return VCM_OK;
436 }
437 
RequestSliceLossIndication(const uint64_t pictureID) const438 int32_t VideoReceiver::RequestSliceLossIndication(
439     const uint64_t pictureID) const {
440   TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID);
441   CriticalSectionScoped cs(process_crit_sect_.get());
442   if (_frameTypeCallback != NULL) {
443     const int32_t ret =
444         _frameTypeCallback->SliceLossIndicationRequest(pictureID);
445     if (ret < 0) {
446       return ret;
447     }
448   } else {
449     return VCM_MISSING_CALLBACK;
450   }
451   return VCM_OK;
452 }
453 
RequestKeyFrame()454 int32_t VideoReceiver::RequestKeyFrame() {
455   TRACE_EVENT0("webrtc", "RequestKeyFrame");
456   CriticalSectionScoped process_cs(process_crit_sect_.get());
457   if (_frameTypeCallback != NULL) {
458     const int32_t ret = _frameTypeCallback->RequestKeyFrame();
459     if (ret < 0) {
460       return ret;
461     }
462     _scheduleKeyRequest = false;
463   } else {
464     return VCM_MISSING_CALLBACK;
465   }
466   return VCM_OK;
467 }
468 
DecodeDualFrame(uint16_t maxWaitTimeMs)469 int32_t VideoReceiver::DecodeDualFrame(uint16_t maxWaitTimeMs) {
470   CriticalSectionScoped cs(_receiveCritSect);
471   if (_dualReceiver.State() != kReceiving ||
472       _dualReceiver.NackMode() != kNack) {
473     // The dual receiver is currently not receiving or
474     // dual decoder mode is disabled.
475     return VCM_OK;
476   }
477   int64_t dummyRenderTime;
478   int32_t decodeCount = 0;
479   // The dual decoder's state is copied from the main decoder, which may
480   // decode with errors. Make sure that the dual decoder does not introduce
481   // error.
482   _dualReceiver.SetDecodeErrorMode(kNoErrors);
483   VCMEncodedFrame* dualFrame =
484       _dualReceiver.FrameForDecoding(maxWaitTimeMs, dummyRenderTime);
485   if (dualFrame != NULL && _dualDecoder != NULL) {
486     // Decode dualFrame and try to catch up
487     int32_t ret =
488         _dualDecoder->Decode(*dualFrame, clock_->TimeInMilliseconds());
489     if (ret != WEBRTC_VIDEO_CODEC_OK) {
490       LOG(LS_ERROR) << "Failed to decode frame with dual decoder. Error code: "
491                     << ret;
492       _dualReceiver.ReleaseFrame(dualFrame);
493       return VCM_CODEC_ERROR;
494     }
495     if (_receiver.DualDecoderCaughtUp(dualFrame, _dualReceiver)) {
496       // Copy the complete decoder state of the dual decoder
497       // to the primary decoder.
498       _codecDataBase.CopyDecoder(*_dualDecoder);
499       _codecDataBase.ReleaseDecoder(_dualDecoder);
500       _dualDecoder = NULL;
501     }
502     decodeCount++;
503   }
504   _dualReceiver.ReleaseFrame(dualFrame);
505   return decodeCount;
506 }
507 
508 // Must be called from inside the receive side critical section.
Decode(const VCMEncodedFrame & frame)509 int32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) {
510   TRACE_EVENT_ASYNC_STEP1("webrtc",
511                           "Video",
512                           frame.TimeStamp(),
513                           "Decode",
514                           "type",
515                           frame.FrameType());
516   // Change decoder if payload type has changed
517   const bool renderTimingBefore = _codecDataBase.SupportsRenderScheduling();
518   _decoder =
519       _codecDataBase.GetDecoder(frame.PayloadType(), &_decodedFrameCallback);
520   if (renderTimingBefore != _codecDataBase.SupportsRenderScheduling()) {
521     // Make sure we reset the decode time estimate since it will
522     // be zero for codecs without render timing.
523     _timing.ResetDecodeTime();
524   }
525   if (_decoder == NULL) {
526     return VCM_NO_CODEC_REGISTERED;
527   }
528   // Decode a frame
529   int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds());
530 
531   // Check for failed decoding, run frame type request callback if needed.
532   bool request_key_frame = false;
533   if (ret < 0) {
534     if (ret == VCM_ERROR_REQUEST_SLI) {
535       return RequestSliceLossIndication(
536           _decodedFrameCallback.LastReceivedPictureID() + 1);
537     } else {
538       request_key_frame = true;
539     }
540   } else if (ret == VCM_REQUEST_SLI) {
541     ret = RequestSliceLossIndication(
542         _decodedFrameCallback.LastReceivedPictureID() + 1);
543   }
544   if (!frame.Complete() || frame.MissingFrame()) {
545     switch (_keyRequestMode) {
546       case kKeyOnKeyLoss: {
547         if (frame.FrameType() == kVideoFrameKey) {
548           request_key_frame = true;
549           ret = VCM_OK;
550         }
551         break;
552       }
553       case kKeyOnLoss: {
554         request_key_frame = true;
555         ret = VCM_OK;
556       }
557       default:
558         break;
559     }
560   }
561   if (request_key_frame) {
562     CriticalSectionScoped cs(process_crit_sect_.get());
563     _scheduleKeyRequest = true;
564   }
565   TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp());
566   return ret;
567 }
568 
569 // Reset the decoder state
ResetDecoder()570 int32_t VideoReceiver::ResetDecoder() {
571   bool reset_key_request = false;
572   {
573     CriticalSectionScoped cs(_receiveCritSect);
574     if (_decoder != NULL) {
575       _receiver.Initialize();
576       _timing.Reset();
577       reset_key_request = true;
578       _decoder->Reset();
579     }
580     if (_dualReceiver.State() != kPassive) {
581       _dualReceiver.Initialize();
582     }
583     if (_dualDecoder != NULL) {
584       _codecDataBase.ReleaseDecoder(_dualDecoder);
585       _dualDecoder = NULL;
586     }
587   }
588   if (reset_key_request) {
589     CriticalSectionScoped cs(process_crit_sect_.get());
590     _scheduleKeyRequest = false;
591   }
592   return VCM_OK;
593 }
594 
595 // Register possible receive codecs, can be called multiple times
RegisterReceiveCodec(const VideoCodec * receiveCodec,int32_t numberOfCores,bool requireKeyFrame)596 int32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec,
597                                             int32_t numberOfCores,
598                                             bool requireKeyFrame) {
599   CriticalSectionScoped cs(_receiveCritSect);
600   if (receiveCodec == NULL) {
601     return VCM_PARAMETER_ERROR;
602   }
603   if (!_codecDataBase.RegisterReceiveCodec(
604           receiveCodec, numberOfCores, requireKeyFrame)) {
605     return -1;
606   }
607   return 0;
608 }
609 
610 // Get current received codec
ReceiveCodec(VideoCodec * currentReceiveCodec) const611 int32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const {
612   CriticalSectionScoped cs(_receiveCritSect);
613   if (currentReceiveCodec == NULL) {
614     return VCM_PARAMETER_ERROR;
615   }
616   return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1;
617 }
618 
619 // Get current received codec
ReceiveCodec() const620 VideoCodecType VideoReceiver::ReceiveCodec() const {
621   CriticalSectionScoped cs(_receiveCritSect);
622   return _codecDataBase.ReceiveCodec();
623 }
624 
625 // Incoming packet from network parsed and ready for decode, non blocking.
IncomingPacket(const uint8_t * incomingPayload,uint32_t payloadLength,const WebRtcRTPHeader & rtpInfo)626 int32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload,
627                                       uint32_t payloadLength,
628                                       const WebRtcRTPHeader& rtpInfo) {
629   if (rtpInfo.frameType == kVideoFrameKey) {
630     TRACE_EVENT1("webrtc",
631                  "VCM::PacketKeyFrame",
632                  "seqnum",
633                  rtpInfo.header.sequenceNumber);
634   }
635   if (incomingPayload == NULL) {
636     // The jitter buffer doesn't handle non-zero payload lengths for packets
637     // without payload.
638     // TODO(holmer): We should fix this in the jitter buffer.
639     payloadLength = 0;
640   }
641   const VCMPacket packet(incomingPayload, payloadLength, rtpInfo);
642   int32_t ret;
643   if (_dualReceiver.State() != kPassive) {
644     ret = _dualReceiver.InsertPacket(
645         packet, rtpInfo.type.Video.width, rtpInfo.type.Video.height);
646     if (ret == VCM_FLUSH_INDICATOR) {
647       RequestKeyFrame();
648       ResetDecoder();
649     } else if (ret < 0) {
650       return ret;
651     }
652   }
653   ret = _receiver.InsertPacket(
654       packet, rtpInfo.type.Video.width, rtpInfo.type.Video.height);
655   // TODO(holmer): Investigate if this somehow should use the key frame
656   // request scheduling to throttle the requests.
657   if (ret == VCM_FLUSH_INDICATOR) {
658     RequestKeyFrame();
659     ResetDecoder();
660   } else if (ret < 0) {
661     return ret;
662   }
663   return VCM_OK;
664 }
665 
666 // Minimum playout delay (used for lip-sync). This is the minimum delay required
667 // to sync with audio. Not included in  VideoCodingModule::Delay()
668 // Defaults to 0 ms.
SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs)669 int32_t VideoReceiver::SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) {
670   _timing.set_min_playout_delay(minPlayoutDelayMs);
671   return VCM_OK;
672 }
673 
674 // The estimated delay caused by rendering, defaults to
675 // kDefaultRenderDelayMs = 10 ms
SetRenderDelay(uint32_t timeMS)676 int32_t VideoReceiver::SetRenderDelay(uint32_t timeMS) {
677   _timing.set_render_delay(timeMS);
678   return VCM_OK;
679 }
680 
681 // Current video delay
Delay() const682 int32_t VideoReceiver::Delay() const { return _timing.TargetVideoDelay(); }
683 
684 // Nack list
NackList(uint16_t * nackList,uint16_t * size)685 int32_t VideoReceiver::NackList(uint16_t* nackList, uint16_t* size) {
686   VCMNackStatus nackStatus = kNackOk;
687   uint16_t nack_list_length = 0;
688   // Collect sequence numbers from the default receiver
689   // if in normal nack mode. Otherwise collect them from
690   // the dual receiver if the dual receiver is receiving.
691   if (_receiver.NackMode() != kNoNack) {
692     nackStatus = _receiver.NackList(nackList, *size, &nack_list_length);
693   }
694   if (nack_list_length == 0 && _dualReceiver.State() != kPassive) {
695     nackStatus = _dualReceiver.NackList(nackList, *size, &nack_list_length);
696   }
697   *size = nack_list_length;
698   if (nackStatus == kNackKeyFrameRequest) {
699       return RequestKeyFrame();
700   }
701   return VCM_OK;
702 }
703 
ReceivedFrameCount(VCMFrameCount * frameCount) const704 int32_t VideoReceiver::ReceivedFrameCount(VCMFrameCount* frameCount) const {
705   _receiver.ReceivedFrameCount(frameCount);
706   return VCM_OK;
707 }
708 
DiscardedPackets() const709 uint32_t VideoReceiver::DiscardedPackets() const {
710   return _receiver.DiscardedPackets();
711 }
712 
SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,VCMDecodeErrorMode decode_error_mode)713 int VideoReceiver::SetReceiverRobustnessMode(
714     ReceiverRobustness robustnessMode,
715     VCMDecodeErrorMode decode_error_mode) {
716   CriticalSectionScoped cs(_receiveCritSect);
717   switch (robustnessMode) {
718     case VideoCodingModule::kNone:
719       _receiver.SetNackMode(kNoNack, -1, -1);
720       _dualReceiver.SetNackMode(kNoNack, -1, -1);
721       if (decode_error_mode == kNoErrors) {
722         _keyRequestMode = kKeyOnLoss;
723       } else {
724         _keyRequestMode = kKeyOnError;
725       }
726       break;
727     case VideoCodingModule::kHardNack:
728       // Always wait for retransmissions (except when decoding with errors).
729       _receiver.SetNackMode(kNack, -1, -1);
730       _dualReceiver.SetNackMode(kNoNack, -1, -1);
731       _keyRequestMode = kKeyOnError;  // TODO(hlundin): On long NACK list?
732       break;
733     case VideoCodingModule::kSoftNack:
734 #if 1
735       assert(false);  // TODO(hlundin): Not completed.
736       return VCM_NOT_IMPLEMENTED;
737 #else
738       // Enable hybrid NACK/FEC. Always wait for retransmissions and don't add
739       // extra delay when RTT is above kLowRttNackMs.
740       _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
741       _dualReceiver.SetNackMode(kNoNack, -1, -1);
742       _keyRequestMode = kKeyOnError;
743       break;
744 #endif
745     case VideoCodingModule::kDualDecoder:
746       if (decode_error_mode == kNoErrors) {
747         return VCM_PARAMETER_ERROR;
748       }
749       // Enable NACK but don't wait for retransmissions and don't add any extra
750       // delay.
751       _receiver.SetNackMode(kNack, 0, 0);
752       // Enable NACK, compensate with extra delay and wait for retransmissions.
753       _dualReceiver.SetNackMode(kNack, -1, -1);
754       _keyRequestMode = kKeyOnError;
755       break;
756     case VideoCodingModule::kReferenceSelection:
757 #if 1
758       assert(false);  // TODO(hlundin): Not completed.
759       return VCM_NOT_IMPLEMENTED;
760 #else
761       if (decode_error_mode == kNoErrors) {
762         return VCM_PARAMETER_ERROR;
763       }
764       _receiver.SetNackMode(kNoNack, -1, -1);
765       _dualReceiver.SetNackMode(kNoNack, -1, -1);
766       break;
767 #endif
768   }
769   _receiver.SetDecodeErrorMode(decode_error_mode);
770   // The dual decoder should never decode with errors.
771   _dualReceiver.SetDecodeErrorMode(kNoErrors);
772   return VCM_OK;
773 }
774 
SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode)775 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
776   CriticalSectionScoped cs(_receiveCritSect);
777   _receiver.SetDecodeErrorMode(decode_error_mode);
778 }
779 
SetNackSettings(size_t max_nack_list_size,int max_packet_age_to_nack,int max_incomplete_time_ms)780 void VideoReceiver::SetNackSettings(size_t max_nack_list_size,
781                                     int max_packet_age_to_nack,
782                                     int max_incomplete_time_ms) {
783   if (max_nack_list_size != 0) {
784     CriticalSectionScoped receive_cs(_receiveCritSect);
785     CriticalSectionScoped process_cs(process_crit_sect_.get());
786     max_nack_list_size_ = max_nack_list_size;
787   }
788   _receiver.SetNackSettings(
789       max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms);
790   _dualReceiver.SetNackSettings(
791       max_nack_list_size, max_packet_age_to_nack, max_incomplete_time_ms);
792 }
793 
SetMinReceiverDelay(int desired_delay_ms)794 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) {
795   return _receiver.SetMinReceiverDelay(desired_delay_ms);
796 }
797 
RegisterPreDecodeImageCallback(EncodedImageCallback * observer)798 void VideoReceiver::RegisterPreDecodeImageCallback(
799     EncodedImageCallback* observer) {
800   CriticalSectionScoped cs(_receiveCritSect);
801   pre_decode_image_callback_ = observer;
802 }
803 
804 }  // namespace vcm
805 }  // namespace webrtc
806