1f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org/*
2f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *
4f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  Use of this source code is governed by a BSD-style license
5f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org */
10f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
11ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos#include "webrtc/base/checks.h"
12854e84c7fb61972bd8e39c1482e5f3e31f796b5fpbos#include "webrtc/base/logging.h"
13e4f96501fc5b3e6de0d1ccd262372afcda1f5b4ftommi#include "webrtc/base/trace_event.h"
14f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#include "webrtc/common_types.h"
15f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
162557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/include/video_codec_interface.h"
172557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/encoded_frame.h"
182557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/jitter_buffer.h"
192557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/packet.h"
202557b86e7648ffebc5781df9f093ca5a84efc219Henrik Kjellander#include "webrtc/modules/video_coding/video_coding_impl.h"
2198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/clock.h"
22f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
23f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// #define DEBUG_DECODER_BIT_STREAM
24f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
25f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgnamespace webrtc {
26f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgnamespace vcm {
27f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
2834c5da6b5eb75238c0dc86a9db508365ebe63482stefan@webrtc.orgVideoReceiver::VideoReceiver(Clock* clock, EventFactory* event_factory)
2934c5da6b5eb75238c0dc86a9db508365ebe63482stefan@webrtc.org    : clock_(clock),
308db81c5112a7987013292dff47d819df47196696stefan@webrtc.org      process_crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
31f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiveCritSect(CriticalSectionWrapper::CreateCriticalSection()),
3234c5da6b5eb75238c0dc86a9db508365ebe63482stefan@webrtc.org      _timing(clock_),
3392d94898814c2a027bda3993da6510340145720cWan-Teh Chang      _receiver(&_timing, clock_, event_factory),
349d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel      _decodedFrameCallback(&_timing, clock_),
35f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _frameTypeCallback(NULL),
36f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiveStatsCallback(NULL),
3737bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      _decoderTimingCallback(NULL),
38f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _packetRequestCallback(NULL),
39f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      render_buffer_callback_(NULL),
40f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _decoder(NULL),
41f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#ifdef DEBUG_DECODER_BIT_STREAM
42f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _bitStreamBeforeDecoder(NULL),
43f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#endif
44f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _frameFromFile(),
45f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _scheduleKeyRequest(false),
46f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      max_nack_list_size_(0),
474070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org      pre_decode_image_callback_(NULL),
484f5db11e45d8a371704d21e69a1849381d24321bPeter Boström      _codecDataBase(nullptr, nullptr),
49f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiveStatsTimer(1000, clock_),
50f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _retransmissionTimer(10, clock_),
51f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _keyRequestTimer(500, clock_) {
52f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  assert(clock_);
53f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#ifdef DEBUG_DECODER_BIT_STREAM
54f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _bitStreamBeforeDecoder = fopen("decoderBitStream.bit", "wb");
55f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#endif
56f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
57f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
58f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgVideoReceiver::~VideoReceiver() {
59f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  delete _receiveCritSect;
60f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#ifdef DEBUG_DECODER_BIT_STREAM
61f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  fclose(_bitStreamBeforeDecoder);
62f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#endif
63f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
64f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
65f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::Process() {
66f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  int32_t returnValue = VCM_OK;
67f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
68f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Receive-side statistics
69f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_receiveStatsTimer.TimeUntilProcess() == 0) {
70f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    _receiveStatsTimer.Processed();
718db81c5112a7987013292dff47d819df47196696stefan@webrtc.org    CriticalSectionScoped cs(process_crit_sect_.get());
72f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    if (_receiveStatsCallback != NULL) {
73f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      uint32_t bitRate;
74f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      uint32_t frameRate;
75f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiver.ReceiveStatistics(&bitRate, &frameRate);
7655707692105a4765f8f321ec7c30a1034d03d23apbos@webrtc.org      _receiveStatsCallback->OnReceiveRatesUpdated(bitRate, frameRate);
77f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
78f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
7937bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org    if (_decoderTimingCallback != NULL) {
8037bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int decode_ms;
8137bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int max_decode_ms;
8237bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int current_delay_ms;
8337bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int target_delay_ms;
8437bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int jitter_buffer_ms;
8537bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int min_playout_delay_ms;
8637bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org      int render_delay_ms;
879d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel      _timing.GetTimings(&decode_ms, &max_decode_ms, &current_delay_ms,
889d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel                         &target_delay_ms, &jitter_buffer_ms,
899d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel                         &min_playout_delay_ms, &render_delay_ms);
909d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel      _decoderTimingCallback->OnDecoderTiming(
919d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel          decode_ms, max_decode_ms, current_delay_ms, target_delay_ms,
929d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel          jitter_buffer_ms, min_playout_delay_ms, render_delay_ms);
9337bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org    }
9437bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org
95f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // Size of render buffer.
96f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    if (render_buffer_callback_) {
97f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      int buffer_size_ms = _receiver.RenderBufferSizeMs();
98f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      render_buffer_callback_->RenderBufferSizeMs(buffer_size_ms);
99f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
100f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
101f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
102f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Key frame requests
103f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_keyRequestTimer.TimeUntilProcess() == 0) {
104f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    _keyRequestTimer.Processed();
105f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    bool request_key_frame = false;
106f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    {
107f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      CriticalSectionScoped cs(process_crit_sect_.get());
108f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      request_key_frame = _scheduleKeyRequest && _frameTypeCallback != NULL;
109f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    }
110f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    if (request_key_frame) {
111f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      const int32_t ret = RequestKeyFrame();
112f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      if (ret != VCM_OK && returnValue == VCM_OK) {
113f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org        returnValue = ret;
114f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      }
115f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
116f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
117f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
118f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Packet retransmission requests
119f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // TODO(holmer): Add API for changing Process interval and make sure it's
120f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // disabled when NACK is off.
121f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_retransmissionTimer.TimeUntilProcess() == 0) {
122f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    _retransmissionTimer.Processed();
123f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    bool callback_registered = false;
124f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    uint16_t length;
125f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    {
126f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      CriticalSectionScoped cs(process_crit_sect_.get());
127f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      length = max_nack_list_size_;
128f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      callback_registered = _packetRequestCallback != NULL;
129f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    }
130f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    if (callback_registered && length > 0) {
131b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      // Collect sequence numbers from the default receiver.
132b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      bool request_key_frame = false;
133b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      std::vector<uint16_t> nackList = _receiver.NackList(&request_key_frame);
134b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      int32_t ret = VCM_OK;
135b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      if (request_key_frame) {
136b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang        ret = RequestKeyFrame();
137b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang        if (ret != VCM_OK && returnValue == VCM_OK) {
138b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang          returnValue = ret;
139b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang        }
140f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      }
141b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang      if (ret == VCM_OK && !nackList.empty()) {
142f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org        CriticalSectionScoped cs(process_crit_sect_.get());
143f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org        if (_packetRequestCallback != NULL) {
144b1825a40380a1339de713efcebdb8c1d6bfeb173Wan-Teh Chang          _packetRequestCallback->ResendPackets(&nackList[0], nackList.size());
145f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org        }
146f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      }
147f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
148f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
149f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
150f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return returnValue;
151f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
152f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
1530b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.orgint64_t VideoReceiver::TimeUntilNextProcess() {
1540b1534c52eab79372557a6d81aaf4dd9407f55d3pkasting@chromium.org  int64_t timeUntilNextProcess = _receiveStatsTimer.TimeUntilProcess();
1554f16c874c6181ad6bbc3b467c186dbbb69986457pbos@webrtc.org  if (_receiver.NackMode() != kNoNack) {
156f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // We need a Process call more often if we are relying on
157f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // retransmissions
158f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    timeUntilNextProcess =
159f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org        VCM_MIN(timeUntilNextProcess, _retransmissionTimer.TimeUntilProcess());
160f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
161f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  timeUntilNextProcess =
162f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      VCM_MIN(timeUntilNextProcess, _keyRequestTimer.TimeUntilProcess());
163f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
164f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return timeUntilNextProcess;
165f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
166f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
16716825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgint32_t VideoReceiver::SetReceiveChannelParameters(int64_t rtt) {
168f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped receiveCs(_receiveCritSect);
169f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _receiver.UpdateRtt(rtt);
170f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return 0;
171f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
172f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
173f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Enable or disable a video protection method.
174f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Note: This API should be deprecated, as it does not offer a distinction
175f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// between the protection method and decoding with or without errors. If such a
176f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// behavior is desired, use the following API: SetReceiverRobustnessMode.
177f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::SetVideoProtection(VCMVideoProtection videoProtection,
178f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                          bool enable) {
179f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // By default, do not decode with errors.
180f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _receiver.SetDecodeErrorMode(kNoErrors);
181f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  switch (videoProtection) {
182ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos    case kProtectionNack: {
18391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg      RTC_DCHECK(enable);
184ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      _receiver.SetNackMode(kNack, -1, -1);
185f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
186f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
187f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
188f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case kProtectionNackFEC: {
189f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      CriticalSectionScoped cs(_receiveCritSect);
19091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg      RTC_DCHECK(enable);
191ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
192ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      _receiver.SetDecodeErrorMode(kNoErrors);
193f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
194f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
195f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case kProtectionFEC:
196cade82c56ffc53cf67039d9b48085a8b6bceade6pbos@webrtc.org    case kProtectionNone:
197ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      // No receiver-side protection.
19891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg      RTC_DCHECK(enable);
199ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      _receiver.SetNackMode(kNoNack, -1, -1);
200ba8c15b857c0f341d9c1e02d41b6ccd56f9f1030pbos      _receiver.SetDecodeErrorMode(kWithErrors);
201cade82c56ffc53cf67039d9b48085a8b6bceade6pbos@webrtc.org      break;
202f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
203f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
204f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
205f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
206f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Register a receive callback. Will be called whenever there is a new frame
207f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// ready for rendering.
208f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RegisterReceiveCallback(
209f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMReceiveCallback* receiveCallback) {
210f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
211f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _decodedFrameCallback.SetUserReceiveCallback(receiveCallback);
212f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
213f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
214f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
215f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RegisterReceiveStatisticsCallback(
216f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMReceiveStatisticsCallback* receiveStats) {
2178db81c5112a7987013292dff47d819df47196696stefan@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
21855707692105a4765f8f321ec7c30a1034d03d23apbos@webrtc.org  _receiver.RegisterStatsCallback(receiveStats);
219f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _receiveStatsCallback = receiveStats;
220f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
221f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
222f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
22337bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.orgint32_t VideoReceiver::RegisterDecoderTimingCallback(
22437bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org    VCMDecoderTimingCallback* decoderTiming) {
22537bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
22637bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org  _decoderTimingCallback = decoderTiming;
22737bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org  return VCM_OK;
22837bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org}
22937bb4974e7095cbcbbf36602c6603ea4d99347c9fischman@webrtc.org
230796cfaf7f76aa740cc7f4bb2c94f88637e475324perkj// Register an externally defined decoder object.
231795dbe4e0fa78333d52fe39edb08a0b13a281c34Peter Boströmvoid VideoReceiver::RegisterExternalDecoder(VideoDecoder* externalDecoder,
232796cfaf7f76aa740cc7f4bb2c94f88637e475324perkj                                            uint8_t payloadType) {
233f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
234f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (externalDecoder == NULL) {
235f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // Make sure the VCM updates the decoder next time it decodes.
236f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    _decoder = NULL;
237795dbe4e0fa78333d52fe39edb08a0b13a281c34Peter Boström    RTC_CHECK(_codecDataBase.DeregisterExternalDecoder(payloadType));
238395c7c65194988f1102f461ed9ff0cf932f72748Peter Boström    return;
239f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
240796cfaf7f76aa740cc7f4bb2c94f88637e475324perkj  _codecDataBase.RegisterExternalDecoder(externalDecoder, payloadType);
241f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
242f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
243f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Register a frame type request callback.
244f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RegisterFrameTypeCallback(
245f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMFrameTypeCallback* frameTypeCallback) {
2468db81c5112a7987013292dff47d819df47196696stefan@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
247f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _frameTypeCallback = frameTypeCallback;
248f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
249f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
250f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
251f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RegisterPacketRequestCallback(
252f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMPacketRequestCallback* callback) {
2538db81c5112a7987013292dff47d819df47196696stefan@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
254f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _packetRequestCallback = callback;
255f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
256f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
257f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
258f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint VideoReceiver::RegisterRenderBufferSizeCallback(
259f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMRenderBufferSizeCallback* callback) {
2608db81c5112a7987013292dff47d819df47196696stefan@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
261f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  render_buffer_callback_ = callback;
262f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
263f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
264f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
2654dd40d6b88beb7e4e5dd6afe0a2d02f7ced9fff4pbos@webrtc.orgvoid VideoReceiver::TriggerDecoderShutdown() {
2664dd40d6b88beb7e4e5dd6afe0a2d02f7ced9fff4pbos@webrtc.org  _receiver.TriggerDecoderShutdown();
2674dd40d6b88beb7e4e5dd6afe0a2d02f7ced9fff4pbos@webrtc.org}
2684dd40d6b88beb7e4e5dd6afe0a2d02f7ced9fff4pbos@webrtc.org
269f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Decode next frame, blocking.
270f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Should be called as often as possible to get the most out of the decoder.
271f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::Decode(uint16_t maxWaitTimeMs) {
272f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  int64_t nextRenderTimeMs;
273796cfaf7f76aa740cc7f4bb2c94f88637e475324perkj  bool prefer_late_decoding = false;
274f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  {
275f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    CriticalSectionScoped cs(_receiveCritSect);
276796cfaf7f76aa740cc7f4bb2c94f88637e475324perkj    prefer_late_decoding = _codecDataBase.PrefersLateDecoding();
277f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
278f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
2794f16c874c6181ad6bbc3b467c186dbbb69986457pbos@webrtc.org  VCMEncodedFrame* frame = _receiver.FrameForDecoding(
2809d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel      maxWaitTimeMs, &nextRenderTimeMs, prefer_late_decoding);
281f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
282b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  if (!frame)
283f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_FRAME_NOT_READY;
284f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
285b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  CriticalSectionScoped cs(_receiveCritSect);
286b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström
287b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  // If this frame was too late, we should adjust the delay accordingly
288b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  _timing.UpdateCurrentDelay(frame->RenderTimeMs(),
289b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström                             clock_->TimeInMilliseconds());
290f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
291b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  if (pre_decode_image_callback_) {
292b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    EncodedImage encoded_image(frame->EncodedImage());
293b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    int qp = -1;
294b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    if (qp_parser_.GetQp(*frame, &qp)) {
295b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström      encoded_image.qp_ = qp;
2964070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org    }
297b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    pre_decode_image_callback_->Encoded(encoded_image, frame->CodecSpecific(),
298b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström                                        NULL);
299b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  }
3004070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org
301f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org#ifdef DEBUG_DECODER_BIT_STREAM
302b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  if (_bitStreamBeforeDecoder != NULL) {
303b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    // Write bit stream to file for debugging purposes
304b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström    if (fwrite(frame->Buffer(), 1, frame->Length(), _bitStreamBeforeDecoder) !=
305b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström        frame->Length()) {
306b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström      return -1;
307f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
308f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
309b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström#endif
310b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  const int32_t ret = Decode(*frame);
311b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  _receiver.ReleaseFrame(frame);
312b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  return ret;
313f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
314f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
315f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RequestSliceLossIndication(
316f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    const uint64_t pictureID) const {
317f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  TRACE_EVENT1("webrtc", "RequestSLI", "picture_id", pictureID);
3188db81c5112a7987013292dff47d819df47196696stefan@webrtc.org  CriticalSectionScoped cs(process_crit_sect_.get());
319f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_frameTypeCallback != NULL) {
320f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    const int32_t ret =
321f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org        _frameTypeCallback->SliceLossIndicationRequest(pictureID);
322f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    if (ret < 0) {
323f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      return ret;
324f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
325f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  } else {
326f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_MISSING_CALLBACK;
327f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
328f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
329f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
330f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
331f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RequestKeyFrame() {
332f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  TRACE_EVENT0("webrtc", "RequestKeyFrame");
333f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  CriticalSectionScoped process_cs(process_crit_sect_.get());
334f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_frameTypeCallback != NULL) {
335f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    const int32_t ret = _frameTypeCallback->RequestKeyFrame();
336f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    if (ret < 0) {
337f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      return ret;
338f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
339f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    _scheduleKeyRequest = false;
340f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  } else {
341f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_MISSING_CALLBACK;
342f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
343f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
344f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
345f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
346f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Must be called from inside the receive side critical section.
347f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::Decode(const VCMEncodedFrame& frame) {
3489d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel  TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", frame.TimeStamp(), "Decode",
3499d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel                          "type", frame.FrameType());
350f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Change decoder if payload type has changed
351e997a7de1419c447d46cfc230111deffcbdfab19Peter Boström  _decoder = _codecDataBase.GetDecoder(frame, &_decodedFrameCallback);
352f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (_decoder == NULL) {
353f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_NO_CODEC_REGISTERED;
354f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
355f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Decode a frame
356f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  int32_t ret = _decoder->Decode(frame, clock_->TimeInMilliseconds());
357f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
358f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // Check for failed decoding, run frame type request callback if needed.
359f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  bool request_key_frame = false;
360f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (ret < 0) {
361f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    if (ret == VCM_ERROR_REQUEST_SLI) {
362f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      return RequestSliceLossIndication(
363f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org          _decodedFrameCallback.LastReceivedPictureID() + 1);
364f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    } else {
365f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      request_key_frame = true;
366f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    }
367f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  } else if (ret == VCM_REQUEST_SLI) {
368f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    ret = RequestSliceLossIndication(
369f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org        _decodedFrameCallback.LastReceivedPictureID() + 1);
370f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
371f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (!frame.Complete() || frame.MissingFrame()) {
372081af25c11aa3015e5da46d64532eb3b9b92f909pbos    request_key_frame = true;
373081af25c11aa3015e5da46d64532eb3b9b92f909pbos    ret = VCM_OK;
374f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
375f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  if (request_key_frame) {
376f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    CriticalSectionScoped cs(process_crit_sect_.get());
377f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    _scheduleKeyRequest = true;
378f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  }
379f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  TRACE_EVENT_ASYNC_END0("webrtc", "Video", frame.TimeStamp());
380f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return ret;
381f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
382f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
383f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Reset the decoder state
384f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::ResetDecoder() {
385f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  bool reset_key_request = false;
386f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  {
387f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    CriticalSectionScoped cs(_receiveCritSect);
388f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    if (_decoder != NULL) {
3895464a6e548e264dd9774c1dc1275011d4b2ae78ePeter Boström      _receiver.Reset();
390f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      _timing.Reset();
391f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      reset_key_request = true;
392f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org      _decoder->Reset();
393f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    }
394f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
395f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org  if (reset_key_request) {
396f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    CriticalSectionScoped cs(process_crit_sect_.get());
397f7c6e743b38f940b0c1cc94f7756aaf00e68b220stefan@webrtc.org    _scheduleKeyRequest = false;
398f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
399f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
400f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
401f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
402f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Register possible receive codecs, can be called multiple times
403f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::RegisterReceiveCodec(const VideoCodec* receiveCodec,
404f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                            int32_t numberOfCores,
405f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                            bool requireKeyFrame) {
406f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
407f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (receiveCodec == NULL) {
408f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_PARAMETER_ERROR;
409f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
4109d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel  if (!_codecDataBase.RegisterReceiveCodec(receiveCodec, numberOfCores,
4119d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel                                           requireKeyFrame)) {
412f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return -1;
413f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
414f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return 0;
415f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
416f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
417f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Get current received codec
418f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::ReceiveCodec(VideoCodec* currentReceiveCodec) const {
419f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
420f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (currentReceiveCodec == NULL) {
421f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return VCM_PARAMETER_ERROR;
422f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
423f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return _codecDataBase.ReceiveCodec(currentReceiveCodec) ? 0 : -1;
424f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
425f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
426f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Get current received codec
427f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgVideoCodecType VideoReceiver::ReceiveCodec() const {
428f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
429f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return _codecDataBase.ReceiveCodec();
430f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
431f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
432f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Incoming packet from network parsed and ready for decode, non blocking.
433f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::IncomingPacket(const uint8_t* incomingPayload,
4344591fbd09f9cb6e83433c49a12dd8524c2806502pkasting@chromium.org                                      size_t payloadLength,
435f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                      const WebRtcRTPHeader& rtpInfo) {
436f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (rtpInfo.frameType == kVideoFrameKey) {
4379d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel    TRACE_EVENT1("webrtc", "VCM::PacketKeyFrame", "seqnum",
438f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                 rtpInfo.header.sequenceNumber);
439f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
440f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (incomingPayload == NULL) {
441f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // The jitter buffer doesn't handle non-zero payload lengths for packets
442f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // without payload.
443f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    // TODO(holmer): We should fix this in the jitter buffer.
444f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    payloadLength = 0;
445f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
446f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  const VCMPacket packet(incomingPayload, payloadLength, rtpInfo);
4474f16c874c6181ad6bbc3b467c186dbbb69986457pbos@webrtc.org  int32_t ret = _receiver.InsertPacket(packet, rtpInfo.type.Video.width,
4484f16c874c6181ad6bbc3b467c186dbbb69986457pbos@webrtc.org                                       rtpInfo.type.Video.height);
449f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // TODO(holmer): Investigate if this somehow should use the key frame
450f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  // request scheduling to throttle the requests.
451f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (ret == VCM_FLUSH_INDICATOR) {
452f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    RequestKeyFrame();
453f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    ResetDecoder();
454f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  } else if (ret < 0) {
455f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    return ret;
456f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
457f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
458f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
459f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
460f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Minimum playout delay (used for lip-sync). This is the minimum delay required
461f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// to sync with audio. Not included in  VideoCodingModule::Delay()
462f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Defaults to 0 ms.
463f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) {
464f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _timing.set_min_playout_delay(minPlayoutDelayMs);
465f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
466f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
467f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
468f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// The estimated delay caused by rendering, defaults to
469f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// kDefaultRenderDelayMs = 10 ms
470f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint32_t VideoReceiver::SetRenderDelay(uint32_t timeMS) {
471f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _timing.set_render_delay(timeMS);
472f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
473f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
474f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
475f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org// Current video delay
4769d3ab61325c5ed216ea52bc829f1d8c81347459bphilipelint32_t VideoReceiver::Delay() const {
4779d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel  return _timing.TargetVideoDelay();
4789d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel}
479f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
480f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orguint32_t VideoReceiver::DiscardedPackets() const {
481f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return _receiver.DiscardedPackets();
482f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
483f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
484f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint VideoReceiver::SetReceiverRobustnessMode(
485f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    ReceiverRobustness robustnessMode,
486f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    VCMDecodeErrorMode decode_error_mode) {
487f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
488f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  switch (robustnessMode) {
489f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case VideoCodingModule::kNone:
490f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiver.SetNackMode(kNoNack, -1, -1);
491f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
492f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case VideoCodingModule::kHardNack:
493f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      // Always wait for retransmissions (except when decoding with errors).
494f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiver.SetNackMode(kNack, -1, -1);
495f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
496f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case VideoCodingModule::kSoftNack:
4970e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#if 1
498f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      assert(false);  // TODO(hlundin): Not completed.
499f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      return VCM_NOT_IMPLEMENTED;
5000e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#else
501f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      // Enable hybrid NACK/FEC. Always wait for retransmissions and don't add
502f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      // extra delay when RTT is above kLowRttNackMs.
503f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiver.SetNackMode(kNack, media_optimization::kLowRttNackMs, -1);
504f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
5050e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#endif
506f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    case VideoCodingModule::kReferenceSelection:
5070e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#if 1
508f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      assert(false);  // TODO(hlundin): Not completed.
509f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      return VCM_NOT_IMPLEMENTED;
5100e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#else
511f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      if (decode_error_mode == kNoErrors) {
512f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org        return VCM_PARAMETER_ERROR;
513f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      }
514f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      _receiver.SetNackMode(kNoNack, -1, -1);
515f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org      break;
5160e65fdaa3b383e2f882d2059e8e9dfa052099deapbos@webrtc.org#endif
517f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
518f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _receiver.SetDecodeErrorMode(decode_error_mode);
519f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return VCM_OK;
520f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
521f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
522f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgvoid VideoReceiver::SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) {
523f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
524f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  _receiver.SetDecodeErrorMode(decode_error_mode);
525f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
526f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
527f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgvoid VideoReceiver::SetNackSettings(size_t max_nack_list_size,
528f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                    int max_packet_age_to_nack,
529f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org                                    int max_incomplete_time_ms) {
530f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  if (max_nack_list_size != 0) {
5318db81c5112a7987013292dff47d819df47196696stefan@webrtc.org    CriticalSectionScoped process_cs(process_crit_sect_.get());
532f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org    max_nack_list_size_ = max_nack_list_size;
533f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  }
5349d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel  _receiver.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
5359d3ab61325c5ed216ea52bc829f1d8c81347459bphilipel                            max_incomplete_time_ms);
536f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
537f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
538f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.orgint VideoReceiver::SetMinReceiverDelay(int desired_delay_ms) {
539f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org  return _receiver.SetMinReceiverDelay(desired_delay_ms);
540f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}
541f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org
5424070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.orgvoid VideoReceiver::RegisterPreDecodeImageCallback(
5434070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org    EncodedImageCallback* observer) {
5444070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org  CriticalSectionScoped cs(_receiveCritSect);
5454070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org  pre_decode_image_callback_ = observer;
5464070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org}
5474070935f4fb5b9fb2df246d7073fe0ba7e350791sprang@webrtc.org
548f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}  // namespace vcm
549f7eb75be1abe1c45d94881106828eef8cb4d8556andresp@webrtc.org}  // namespace webrtc
550