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, ¤t_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