LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/video_coding - video_receiver.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 269 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13