Home | History | Annotate | Download | only in source
      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 
     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 
     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 
     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 
    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 
    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.
    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
    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.
    303 int32_t VideoReceiver::RegisterReceiveCallback(
    304     VCMReceiveCallback* receiveCallback) {
    305   CriticalSectionScoped cs(_receiveCritSect);
    306   _decodedFrameCallback.SetUserReceiveCallback(receiveCallback);
    307   return VCM_OK;
    308 }
    309 
    310 int32_t VideoReceiver::RegisterReceiveStatisticsCallback(
    311     VCMReceiveStatisticsCallback* receiveStats) {
    312   CriticalSectionScoped cs(process_crit_sect_.get());
    313   _receiveStatsCallback = receiveStats;
    314   return VCM_OK;
    315 }
    316 
    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.
    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.
    342 int32_t VideoReceiver::RegisterFrameTypeCallback(
    343     VCMFrameTypeCallback* frameTypeCallback) {
    344   CriticalSectionScoped cs(process_crit_sect_.get());
    345   _frameTypeCallback = frameTypeCallback;
    346   return VCM_OK;
    347 }
    348 
    349 int32_t VideoReceiver::RegisterPacketRequestCallback(
    350     VCMPacketRequestCallback* callback) {
    351   CriticalSectionScoped cs(process_crit_sect_.get());
    352   _packetRequestCallback = callback;
    353   return VCM_OK;
    354 }
    355 
    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.
    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 
    438 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 
    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 
    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.
    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
    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
    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
    611 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
    620 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.
    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.
    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
    676 int32_t VideoReceiver::SetRenderDelay(uint32_t timeMS) {
    677   _timing.set_render_delay(timeMS);
    678   return VCM_OK;
    679 }
    680 
    681 // Current video delay
    682 int32_t VideoReceiver::Delay() const { return _timing.TargetVideoDelay(); }
    683 
    684 // Nack list
    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 
    704 int32_t VideoReceiver::ReceivedFrameCount(VCMFrameCount* frameCount) const {
    705   _receiver.ReceivedFrameCount(frameCount);
    706   return VCM_OK;
    707 }
    708 
    709 uint32_t VideoReceiver::DiscardedPackets() const {
    710   return _receiver.DiscardedPackets();
    711 }
    712 
    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 
    775 void VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
    776   CriticalSectionScoped cs(_receiveCritSect);
    777   _receiver.SetDecodeErrorMode(decode_error_mode);
    778 }
    779 
    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 
    794 int VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) {
    795   return _receiver.SetMinReceiverDelay(desired_delay_ms);
    796 }
    797 
    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