1b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org/*
2b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *
4b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  Use of this source code is governed by a BSD-style license
5b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  that can be found in the LICENSE file in the root of the source
6b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  tree. An additional intellectual property rights grant can be found
7b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  in the file PATENTS.  All contributing project authors may
8b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org */
10b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
11281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_encoder.h"
12b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
133f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org#include <assert.h>
143f45c2e0ac4cb280f941efa3a3476895795e3dd6pbos@webrtc.org
15695ff2a7e4a306e31bdc655d638c79daf115848dstefan@webrtc.org#include <algorithm>
16b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
172e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org#include "webrtc/common_video/interface/video_image.h"
18281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
19281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/pacing/include/paced_sender.h"
20281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp.h"
21281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/utility/interface/process_thread.h"
22281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/video_coding/codecs/interface/video_codec_interface.h"
23281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/video_coding/main/interface/video_coding.h"
24281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/modules/video_coding/main/interface/video_coding_defines.h"
252e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org#include "webrtc/modules/video_coding/main/source/encoded_frame.h"
26c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org#include "webrtc/system_wrappers/interface/clock.h"
27281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
28281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/logging.h"
29281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/tick_util.h"
30281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/system_wrappers/interface/trace_event.h"
31281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/include/vie_codec.h"
32281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/include/vie_image_process.h"
3324e2089750e9e51228b82d6c7ebf4fa064c797bapbos@webrtc.org#include "webrtc/frame_callback.h"
34281cff8cd679728fe395f7f0203c05e763c0c789pbos@webrtc.org#include "webrtc/video_engine/vie_defines.h"
35b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
36b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgnamespace webrtc {
37b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3836bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org// Margin on when we pause the encoder when the pacing buffer overflows relative
3936bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org// to the configured buffer delay.
4036bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.orgstatic const float kEncoderPausePacerMargin = 2.0f;
4136bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org
423816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org// Don't stop the encoder unless the delay is above this configured value.
433816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.orgstatic const int kMinPacingDelayMs = 200;
443816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org
45dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org// Allow packets to be transmitted in up to 2 times max video bitrate if the
46dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org// bandwidth estimate allows it.
47dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org// TODO(holmer): Expose transmission start, min and max bitrates in the
48dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org// VideoEngine API and remove the kTransmissionMaxBitrateMultiplier.
49dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.orgstatic const int kTransmissionMaxBitrateMultiplier = 2;
505e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org
515e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.orgstatic const float kStopPaddingThresholdMs = 2000;
525e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org
537dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.orgstd::vector<uint32_t> AllocateStreamBitrates(
547dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    uint32_t total_bitrate,
557dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    const SimulcastStream* stream_configs,
567dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    size_t number_of_streams) {
577dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  if (number_of_streams == 0) {
587dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    std::vector<uint32_t> stream_bitrates(1, 0);
597dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    stream_bitrates[0] = total_bitrate;
607dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    return stream_bitrates;
617dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  }
627dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  std::vector<uint32_t> stream_bitrates(number_of_streams, 0);
637dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  uint32_t bitrate_remainder = total_bitrate;
647dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) {
657dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) {
667dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      stream_bitrates[i] = bitrate_remainder;
677dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    } else {
687dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      stream_bitrates[i] = stream_configs[i].maxBitrate * 1000;
697dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    }
707dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    bitrate_remainder -= stream_bitrates[i];
717dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  }
727dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  return stream_bitrates;
737dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org}
747dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org
75b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass QMVideoSettingsCallback : public VCMQMSettingsCallback {
76b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
77b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit QMVideoSettingsCallback(VideoProcessingModule* vpm);
78bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org
79b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ~QMVideoSettingsCallback();
80b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
81b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Update VPM with QM (quality modes: frame size & frame rate) settings.
8267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t SetVideoQMSettings(const uint32_t frame_rate,
8367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                             const uint32_t width,
8467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                             const uint32_t height);
85b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
86b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
87b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VideoProcessingModule* vpm_;
88b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
89b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
90b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgclass ViEBitrateObserver : public BitrateObserver {
91b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org public:
92b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  explicit ViEBitrateObserver(ViEEncoder* owner)
93b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      : owner_(owner) {
94b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
95bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org  virtual ~ViEBitrateObserver() {}
96b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Implements BitrateObserver.
97b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  virtual void OnNetworkChanged(const uint32_t bitrate_bps,
98b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                const uint8_t fraction_lost,
99b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                const uint32_t rtt) {
100b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    owner_->OnNetworkChanged(bitrate_bps, fraction_lost, rtt);
101b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
102b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org private:
103b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  ViEEncoder* owner_;
104b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org};
105b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1065e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.orgclass ViEPacedSenderCallback : public PacedSender::Callback {
1075e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org public:
1085e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  explicit ViEPacedSenderCallback(ViEEncoder* owner)
1095e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org      : owner_(owner) {
1105e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  }
111bf76ae2bdfc0b4e8e875f6cce1c85d4d66357bebmflodman@webrtc.org  virtual ~ViEPacedSenderCallback() {}
1120f6f7cb4232fea07a4b2a5a53f8eec6933c08a23hclam@chromium.org  virtual bool TimeToSendPacket(uint32_t ssrc, uint16_t sequence_number,
113b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                int64_t capture_time_ms, bool retransmission) {
114b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org    return owner_->TimeToSendPacket(ssrc, sequence_number, capture_time_ms,
115b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                    retransmission);
1165e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  }
117695ff2a7e4a306e31bdc655d638c79daf115848dstefan@webrtc.org  virtual int TimeToSendPadding(int bytes) {
11869f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org    return owner_->TimeToSendPadding(bytes);
1195e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  }
1205e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org private:
1215e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  ViEEncoder* owner_;
1225e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org};
1235e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org
12467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgViEEncoder::ViEEncoder(int32_t engine_id,
12567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                       int32_t channel_id,
12667879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                       uint32_t number_of_cores,
127ac6d919eec548c708588f29923f617a17283c7e2andresp@webrtc.org                       const Config& config,
128b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       ProcessThread& module_process_thread,
129b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                       BitrateController* bitrate_controller)
130b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  : engine_id_(engine_id),
131b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    channel_id_(channel_id),
132b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    number_of_cores_(number_of_cores),
1338edcccef11eabb0dd98a061c9d640b2b7743609estefan@webrtc.org    vcm_(*webrtc::VideoCodingModule::Create()),
134b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vpm_(*webrtc::VideoProcessingModule::Create(ViEModuleId(engine_id,
135b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                                            channel_id))),
136b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    callback_cs_(CriticalSectionWrapper::CreateCriticalSection()),
137b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    data_cs_(CriticalSectionWrapper::CreateCriticalSection()),
138b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    bitrate_controller_(bitrate_controller),
1395e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org    time_of_last_incoming_frame_ms_(0),
14069f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org    send_padding_(false),
1413f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org    min_transmit_bitrate_kbps_(0),
142dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    target_delay_ms_(0),
143dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    network_is_transmitting_(true),
144dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    encoder_paused_(false),
14536bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    encoder_paused_and_dropped_frame_(false),
146b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    fec_enabled_(false),
147b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    nack_enabled_(false),
148b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    codec_observer_(NULL),
149b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    effect_filter_(NULL),
150b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    module_process_thread_(module_process_thread),
151b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    has_received_sli_(false),
152b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    picture_id_sli_(0),
153b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    has_received_rpsi_(false),
154b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    picture_id_rpsi_(0),
15539079d1ee84faab899c8af92bce984c20e60fd29henrik.lundin@webrtc.org    qm_callback_(NULL),
1564590177aa3346a742e8f71c8bcc5b81618d21919henrik.lundin@webrtc.org    video_suspended_(false),
15763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    pre_encode_callback_(NULL) {
158b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  RtpRtcp::Configuration configuration;
159b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  configuration.id = ViEModuleId(engine_id_, channel_id_);
160b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  configuration.audio = false;  // Video.
161b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
162b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  default_rtp_rtcp_.reset(RtpRtcp::CreateRtpRtcp(configuration));
163b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bitrate_observer_.reset(new ViEBitrateObserver(this));
1645e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  pacing_callback_.reset(new ViEPacedSenderCallback(this));
16536bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org  paced_sender_.reset(
166c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org      new PacedSender(Clock::GetRealTimeClock(), pacing_callback_.get(),
167c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org                      PacedSender::kDefaultInitialPaceKbps, 0));
168b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
169b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
170b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgbool ViEEncoder::Init() {
171b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.InitializeSender() != 0) {
172b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
173b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
174b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  vpm_.EnableTemporalDecimation(true);
175b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
176b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Enable/disable content analysis: off by default for now.
177b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  vpm_.EnableContentAnalysis(false);
178b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
1795e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  if (module_process_thread_.RegisterModule(&vcm_) != 0 ||
1805e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org      module_process_thread_.RegisterModule(default_rtp_rtcp_.get()) != 0 ||
1815e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org      module_process_thread_.RegisterModule(paced_sender_.get()) != 0) {
182b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
183b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
184b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (qm_callback_) {
185b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    delete qm_callback_;
186b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
187b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  qm_callback_ = new QMVideoSettingsCallback(&vpm_);
188b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
189b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org#ifdef VIDEOCODEC_VP8
190c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org  VideoCodecType codec_type = webrtc::kVideoCodecVP8;
191c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org#else
192c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org  VideoCodecType codec_type = webrtc::kVideoCodecI420;
193c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org#endif
194c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org
195b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VideoCodec video_codec;
196c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org  if (vcm_.Codec(codec_type, &video_codec) != VCM_OK) {
197b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
198b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
1995fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org  {
2005fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
2015fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org    send_padding_ = video_codec.numberOfSimulcastStreams > 1;
2025fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org  }
203b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
204b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             default_rtp_rtcp_->MaxDataPayloadLength()) != 0) {
205b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
206b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
207b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
208b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
209b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
210b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterTransportCallback(this) != 0) {
211b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
212b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
213b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterSendStatisticsCallback(this) != 0) {
214b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
215b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
216b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterVideoQMCallback(qm_callback_) != 0) {
217b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return false;
218b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
219b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return true;
220b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
221b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
222b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgViEEncoder::~ViEEncoder() {
223c0539d9351f8942308bf6142adfbb9d1a6c1816cstefan@webrtc.org  if (bitrate_controller_) {
224c0539d9351f8942308bf6142adfbb9d1a6c1816cstefan@webrtc.org    bitrate_controller_->RemoveBitrateObserver(bitrate_observer_.get());
225c0539d9351f8942308bf6142adfbb9d1a6c1816cstefan@webrtc.org  }
226b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  module_process_thread_.DeRegisterModule(&vcm_);
227b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  module_process_thread_.DeRegisterModule(&vpm_);
228b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  module_process_thread_.DeRegisterModule(default_rtp_rtcp_.get());
2295e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  module_process_thread_.DeRegisterModule(paced_sender_.get());
230c6242c92d4357adf377ed7a70f99575e9be1afe8mflodman@webrtc.org  VideoCodingModule::Destroy(&vcm_);
231c6242c92d4357adf377ed7a70f99575e9be1afe8mflodman@webrtc.org  VideoProcessingModule::Destroy(&vpm_);
232b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  delete qm_callback_;
233b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
234b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
235b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEEncoder::Owner() const {
236b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return channel_id_;
237b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
238b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
239dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.orgvoid ViEEncoder::SetNetworkTransmissionState(bool is_transmitting) {
240dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  {
241dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
242dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    network_is_transmitting_ = is_transmitting;
243dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  }
244dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  if (is_transmitting) {
245dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    paced_sender_->Resume();
246dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  } else {
247dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    paced_sender_->Pause();
248dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  }
249dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org}
250dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org
251b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::Pause() {
252b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
253dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  encoder_paused_ = true;
254b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
255b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
256b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::Restart() {
257b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
258dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  encoder_paused_ = false;
259b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
260b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orguint8_t ViEEncoder::NumberOfCodecs() {
262b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return vcm_.NumberOfCodecs();
263b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
264b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
26567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::GetCodec(uint8_t list_index, VideoCodec* video_codec) {
266b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.Codec(list_index, video_codec) != 0) {
267b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
268b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
269b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
270b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
271b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
27267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder,
27367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                                            uint8_t pl_type,
27467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                                            bool internal_source) {
275b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (encoder == NULL)
276b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
277b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
27871f3f686b5b3896cf842b9665a6c28b40a7aa040stefan@webrtc.org  if (vcm_.RegisterExternalEncoder(encoder, pl_type, internal_source) !=
279022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org      VCM_OK) {
280b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
281b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
282b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
283b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
284b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
28567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) {
286b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VideoCodec current_send_codec;
287b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.SendCodec(&current_send_codec) == VCM_OK) {
28863136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org    uint32_t current_bitrate_bps = 0;
28963136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org    if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
290022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org      LOG(LS_WARNING) << "Failed to get the current encoder target bitrate.";
291b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
29263136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org    current_send_codec.startBitrate = (current_bitrate_bps + 500) / 1000;
293b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
294b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
295b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterExternalEncoder(NULL, pl_type) != VCM_OK) {
296b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
297b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
298b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
29969f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  // If the external encoder is the current send codec, use vcm internal
300b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // encoder.
301b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (current_send_codec.plType == pl_type) {
30267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint16_t max_data_payload_length =
303b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        default_rtp_rtcp_->MaxDataPayloadLength();
3045fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org    {
3055fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org      CriticalSectionScoped cs(data_cs_.get());
3065fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org      send_padding_ = current_send_codec.numberOfSimulcastStreams > 1;
3075fcd7dfc6c4bdece48d90000e09d635485031dffstefan@webrtc.org    }
308bbbe9b8714e1f0966327b6a472f116c0f34a7c30fischman@webrtc.org    // TODO(mflodman): Unfortunately the VideoCodec that VCM has cached a
309bbbe9b8714e1f0966327b6a472f116c0f34a7c30fischman@webrtc.org    // raw pointer to an |extra_options| that's long gone.  Clearing it here is
310bbbe9b8714e1f0966327b6a472f116c0f34a7c30fischman@webrtc.org    // a hack to prevent the following code from crashing.  This should be fixed
311bbbe9b8714e1f0966327b6a472f116c0f34a7c30fischman@webrtc.org    // for realz.  https://code.google.com/p/chromium/issues/detail?id=348222
312bbbe9b8714e1f0966327b6a472f116c0f34a7c30fischman@webrtc.org    current_send_codec.extra_options = NULL;
313b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (vcm_.RegisterSendCodec(&current_send_codec, number_of_cores_,
314b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               max_data_payload_length) != VCM_OK) {
3156111d79329d4fffec4eb6b443dc4e04222dec949stefan@webrtc.org      LOG(LS_INFO) << "De-registered the currently used external encoder ("
3166111d79329d4fffec4eb6b443dc4e04222dec949stefan@webrtc.org                   << static_cast<int>(pl_type) << ") and therefore tried to "
3176111d79329d4fffec4eb6b443dc4e04222dec949stefan@webrtc.org                   << "register the corresponding internal encoder, but none "
3186111d79329d4fffec4eb6b443dc4e04222dec949stefan@webrtc.org                   << "was supported.";
319b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
320b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
321b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
322b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
323b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
32467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec) {
325b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Setting target width and height for VPM.
326b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vpm_.SetTargetResolution(video_codec.width, video_codec.height,
327b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               video_codec.maxFramerate) != VPM_OK) {
328b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
329b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
330b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
331b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (default_rtp_rtcp_->RegisterSendPayload(video_codec) != 0) {
332b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
333b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
334b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Convert from kbps to bps.
3357dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
3367dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      video_codec.startBitrate * 1000,
3377dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      video_codec.simulcastStream,
3387dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      video_codec.numberOfSimulcastStreams);
3397dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
340b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
34167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  uint16_t max_data_payload_length =
342b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      default_rtp_rtcp_->MaxDataPayloadLength();
343b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3445a6e6911e6e218a86b585ddd6df906e1ffe52dcfstefan@webrtc.org  {
3455a6e6911e6e218a86b585ddd6df906e1ffe52dcfstefan@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
3465a6e6911e6e218a86b585ddd6df906e1ffe52dcfstefan@webrtc.org    send_padding_ = video_codec.numberOfSimulcastStreams > 1;
3475a6e6911e6e218a86b585ddd6df906e1ffe52dcfstefan@webrtc.org  }
348b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.RegisterSendCodec(&video_codec, number_of_cores_,
349b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                             max_data_payload_length) != VCM_OK) {
350b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
351b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
352b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
353b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Set this module as sending right away, let the slave module in the channel
354b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // start and stop sending.
355c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org  if (default_rtp_rtcp_->SetSendingStatus(true) != 0) {
356c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org    return -1;
357b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
358c1696da9a74c7ed4ed793ce993352bd370cfc414andresp@webrtc.org
359b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bitrate_controller_->SetBitrateObserver(bitrate_observer_.get(),
360b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          video_codec.startBitrate * 1000,
361b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          video_codec.minBitrate * 1000,
362dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org                                          kTransmissionMaxBitrateMultiplier *
363b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                          video_codec.maxBitrate * 1000);
364b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
3653f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  CriticalSectionScoped crit(data_cs_.get());
3663f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  int pad_up_to_bitrate_kbps = video_codec.startBitrate;
3673f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
3683f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org    pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
3693f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org
370c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org  paced_sender_->UpdateBitrate(
371c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org      PacedSender::kDefaultPaceMultiplier * video_codec.startBitrate,
372c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org      pad_up_to_bitrate_kbps);
3733f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org
374b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
375b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
376b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
37767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::GetEncoder(VideoCodec* video_codec) {
378b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.SendCodec(video_codec) != 0) {
379b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
380b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
381b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
382b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
383b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
38467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::GetCodecConfigParameters(
385b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    unsigned char config_parameters[kConfigParameterSize],
386b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    unsigned char& config_parameters_size) {
38767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t num_parameters =
388b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      vcm_.CodecConfigParameters(config_parameters, kConfigParameterSize);
389b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (num_parameters <= 0) {
390b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    config_parameters_size = 0;
391b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
392b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
393b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  config_parameters_size = static_cast<unsigned char>(num_parameters);
394b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
395b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
396b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
39767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::ScaleInputImage(bool enable) {
398b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  VideoFrameResampling resampling_mode = kFastRescaling;
399022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  // TODO(mflodman) What?
400022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  if (enable) {
401b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // kInterpolation is currently not supported.
402022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG_F(LS_ERROR) << "Not supported.";
403b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
404b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
405b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  vpm_.SetInputFrameResampleMode(resampling_mode);
406b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
407b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
408b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
409b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
410b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.orgbool ViEEncoder::TimeToSendPacket(uint32_t ssrc,
411b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                  uint16_t sequence_number,
412b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                  int64_t capture_time_ms,
413b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                  bool retransmission) {
4140f6f7cb4232fea07a4b2a5a53f8eec6933c08a23hclam@chromium.org  return default_rtp_rtcp_->TimeToSendPacket(ssrc, sequence_number,
415b748c9d2022042b2cc04eaf89052945ba7149ba6stefan@webrtc.org                                             capture_time_ms, retransmission);
4165e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org}
4175e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org
41869f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.orgint ViEEncoder::TimeToSendPadding(int bytes) {
419b9f1eb8f2950c45d8dad97183ceb30c7f04d6f8chenrik.lundin@webrtc.org  bool send_padding;
420b9f1eb8f2950c45d8dad97183ceb30c7f04d6f8chenrik.lundin@webrtc.org  {
421b9f1eb8f2950c45d8dad97183ceb30c7f04d6f8chenrik.lundin@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
4223f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org    send_padding =
4233f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org        send_padding_ || video_suspended_ || min_transmit_bitrate_kbps_ > 0;
424b9f1eb8f2950c45d8dad97183ceb30c7f04d6f8chenrik.lundin@webrtc.org  }
425b9f1eb8f2950c45d8dad97183ceb30c7f04d6f8chenrik.lundin@webrtc.org  if (send_padding) {
42669f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org    return default_rtp_rtcp_->TimeToSendPadding(bytes);
42769f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  }
42869f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  return 0;
42969f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org}
43069f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org
431dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.orgbool ViEEncoder::EncoderPaused() const {
4323816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  // Pause video if paused by caller or as long as the network is down or the
4333816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  // pacer queue has grown too large in buffered mode.
4343816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  if (encoder_paused_) {
4353816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org    return true;
4363816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  }
4373816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  if (target_delay_ms_ > 0) {
4383816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org    // Buffered mode.
4393816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org    // TODO(pwestin): Workaround until nack is configured as a time and not
4403816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org    // number of packets.
4413816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org    return paced_sender_->QueueInMs() >=
44236bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org        std::max(static_cast<int>(target_delay_ms_ * kEncoderPausePacerMargin),
44336bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org                 kMinPacingDelayMs);
4443816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  }
4453816c527a9fdf4de6f625ccd5b984d2a59b50131pwestin@webrtc.org  return !network_is_transmitting_;
446dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org}
447dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org
448b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgRtpRtcp* ViEEncoder::SendRtpRtcpModule() {
449b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return default_rtp_rtcp_.get();
450b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
451b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
452b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::DeliverFrame(int id,
4533bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org                              I420VideoFrame* video_frame,
454b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                              int num_csrcs,
45567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                              const uint32_t CSRC[kRtpCsrcSize]) {
45676cd2f7dec281c9842ebc5417eeea376fa54746cwuchengli@chromium.org  if (default_rtp_rtcp_->SendingMedia() == false) {
45776cd2f7dec281c9842ebc5417eeea376fa54746cwuchengli@chromium.org    // We've paused or we have no channels attached, don't encode.
45876cd2f7dec281c9842ebc5417eeea376fa54746cwuchengli@chromium.org    return;
45976cd2f7dec281c9842ebc5417eeea376fa54746cwuchengli@chromium.org  }
460b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  {
461b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
4625e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org    time_of_last_incoming_frame_ms_ = TickTime::MillisecondTimestamp();
46336bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    if (EncoderPaused()) {
46436bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org      if (!encoder_paused_and_dropped_frame_) {
46536bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org        TRACE_EVENT_ASYNC_BEGIN0("webrtc", "EncoderPaused", this);
46636bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org      }
46736bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org      encoder_paused_and_dropped_frame_ = true;
46836bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org      return;
46936bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    }
47036bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    if (encoder_paused_and_dropped_frame_) {
47136bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org      TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this);
47236bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    }
47336bdba4e02894161bc657ef4d933821aba8421efpwestin@webrtc.org    encoder_paused_and_dropped_frame_ = false;
474b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
475b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
476b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Convert render time, in ms, to RTP timestamp.
477b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  const int kMsToRtpTimestamp = 90;
47867879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  const uint32_t time_stamp =
479b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      kMsToRtpTimestamp *
48067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org      static_cast<uint32_t>(video_frame->render_time_ms());
48174472fe9852769d834e135bde1229c24ab844244hclam@chromium.org
4829c0f14d2cd43e388b5136f0ced7951ee58610e86hclam@chromium.org  TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame->render_time_ms(),
4839c0f14d2cd43e388b5136f0ced7951ee58610e86hclam@chromium.org                          "Encode");
4843bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  video_frame->set_timestamp(time_stamp);
485b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
486b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Make sure the CSRC list is correct.
487b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (num_csrcs > 0) {
48867879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint32_t tempCSRC[kRtpCsrcSize];
489b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    for (int i = 0; i < num_csrcs; i++) {
490b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (CSRC[i] == 1) {
491b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        tempCSRC[i] = default_rtp_rtcp_->SSRC();
492b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      } else {
493b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        tempCSRC[i] = CSRC[i];
494b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
495b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
49667879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    default_rtp_rtcp_->SetCSRCs(tempCSRC, (uint8_t) num_csrcs);
497b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
4984ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org
4993bbed74cdcf1f27ce82104ce645ec0dcdd36902dmikhal@webrtc.org  I420VideoFrame* decimated_frame = NULL;
5004ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org  // TODO(wuchengli): support texture frames.
5014ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org  if (video_frame->native_handle() == NULL) {
5024ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    {
5034ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      CriticalSectionScoped cs(callback_cs_.get());
5044ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      if (effect_filter_) {
5054ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org        unsigned int length =
5064ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org            CalcBufferSize(kI420, video_frame->width(), video_frame->height());
5074ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org        scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]);
5084ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org        ExtractBuffer(*video_frame, length, video_buffer.get());
5094ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org        effect_filter_->Transform(length,
5104ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org                                  video_buffer.get(),
5114ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org                                  video_frame->ntp_time_ms(),
5124ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org                                  video_frame->timestamp(),
5134ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org                                  video_frame->width(),
5144ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org                                  video_frame->height());
5154ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      }
5164ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    }
5174ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org
5184ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    // Pass frame via preprocessor.
5194ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    const int ret = vpm_.PreprocessFrame(*video_frame, &decimated_frame);
5204ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    if (ret == 1) {
5214ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      // Drop this frame.
5224ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      return;
5234ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    }
5244ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    if (ret != VPM_OK) {
5254ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org      return;
5264ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    }
527b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
5284ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org  // If the frame was not resampled or scaled => use original.
529b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (decimated_frame == NULL)  {
530b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    decimated_frame = video_frame;
531b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
53263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
53363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  {
53463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    CriticalSectionScoped cs(callback_cs_.get());
53563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    if (pre_encode_callback_)
53663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org      pre_encode_callback_->FrameCallback(decimated_frame);
53763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  }
53863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
5394ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org  if (video_frame->native_handle() != NULL) {
5404ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    // TODO(wuchengli): add texture support. http://crbug.com/362437
5414ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org    return;
5424ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org  }
5434ee63485f3d42c5fc47845be1d62c7d24bb0f96cwuchengli@chromium.org
54428f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org#ifdef VIDEOCODEC_VP8
54528f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org  if (vcm_.SendCodec() == webrtc::kVideoCodecVP8) {
54628f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org    webrtc::CodecSpecificInfo codec_specific_info;
54728f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org    codec_specific_info.codecType = webrtc::kVideoCodecVP8;
548fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org    {
549fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      CriticalSectionScoped cs(data_cs_.get());
550fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      codec_specific_info.codecSpecific.VP8.hasReceivedRPSI =
551fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org          has_received_rpsi_;
552fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      codec_specific_info.codecSpecific.VP8.hasReceivedSLI =
553fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org          has_received_sli_;
554fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      codec_specific_info.codecSpecific.VP8.pictureIdRPSI =
555fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org          picture_id_rpsi_;
556fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      codec_specific_info.codecSpecific.VP8.pictureIdSLI  =
557fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org          picture_id_sli_;
558fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      has_received_sli_ = false;
559fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org      has_received_rpsi_ = false;
560fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org    }
56128f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org
562022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    vcm_.AddVideoFrame(*decimated_frame, vpm_.ContentMetrics(),
563022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org                       &codec_specific_info);
56428f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org    return;
56528f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org  }
56628f76e5249e883f269a5877e5de888035b23cd71pwestin@webrtc.org#endif
567022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  vcm_.AddVideoFrame(*decimated_frame);
568b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
569b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
570b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::DelayChanged(int id, int frame_delay) {
57173ebe67b3e6f0a65efed02efd4eee4dfb1b7729estefan@webrtc.org  default_rtp_rtcp_->SetCameraDelay(frame_delay);
572b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
573b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
574b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEEncoder::GetPreferedFrameSettings(int* width,
575b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         int* height,
576b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                         int* frame_rate) {
577b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VideoCodec video_codec;
578b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  memset(&video_codec, 0, sizeof(video_codec));
579b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.SendCodec(&video_codec) != VCM_OK) {
580b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
581b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
582b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
583b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *width = video_codec.width;
584b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *height = video_codec.height;
585b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *frame_rate = video_codec.maxFramerate;
586b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
587b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
588b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
589b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEEncoder::SendKeyFrame() {
590b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return vcm_.IntraFrameRequest(0);
591b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
592b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
59367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::SendCodecStatistics(
59467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint32_t* num_key_frames, uint32_t* num_delta_frames) {
595b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  webrtc::VCMFrameCount sent_frames;
596b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.SentFrameCount(sent_frames) != VCM_OK) {
597b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
598b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
599b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *num_key_frames = sent_frames.numKeyFrames;
600b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  *num_delta_frames = sent_frames.numDeltaFrames;
601b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
602b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
603b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
60455a2a27d1a1aa9bf8401312a0b31250af4e3bd11jiayl@webrtc.orgint32_t ViEEncoder::PacerQueuingDelayMs() const {
60555a2a27d1a1aa9bf8401312a0b31250af4e3bd11jiayl@webrtc.org  return paced_sender_->QueueInMs();
60655a2a27d1a1aa9bf8401312a0b31250af4e3bd11jiayl@webrtc.org}
60755a2a27d1a1aa9bf8401312a0b31250af4e3bd11jiayl@webrtc.org
60867879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint ViEEncoder::CodecTargetBitrate(uint32_t* bitrate) const {
609b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (vcm_.Bitrate(bitrate) != 0)
610b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
611b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
612b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
613b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
6147fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.orgint32_t ViEEncoder::UpdateProtectionMethod(bool enable_nack) {
615b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  bool fec_enabled = false;
61667879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  uint8_t dummy_ptype_red = 0;
61767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  uint8_t dummy_ptypeFEC = 0;
618b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
619b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Updated protection method to VCM to get correct packetization sizes.
620b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // FEC has larger overhead than NACK -> set FEC if used.
62167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org  int32_t error = default_rtp_rtcp_->GenericFECStatus(fec_enabled,
62267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                                                      dummy_ptype_red,
62367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                                                      dummy_ptypeFEC);
624b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (error) {
625b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return -1;
626b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
6277fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (fec_enabled_ == fec_enabled && nack_enabled_ == enable_nack) {
628b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // No change needed, we're already in correct state.
629b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
630b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
631b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  fec_enabled_ = fec_enabled;
6327fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  nack_enabled_ = enable_nack;
633b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
634b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Set Video Protection for VCM.
6357fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (fec_enabled && nack_enabled_) {
636b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, true);
637b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
638b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vcm_.SetVideoProtection(webrtc::kProtectionFEC, fec_enabled_);
6397fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org    vcm_.SetVideoProtection(webrtc::kProtectionNackSender, nack_enabled_);
640b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vcm_.SetVideoProtection(webrtc::kProtectionNackFEC, false);
641b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
642b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
6437fc75bbb65cc1cd99fdf45d9fce44bcce1396dfawu@webrtc.org  if (fec_enabled_ || nack_enabled_) {
644b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vcm_.RegisterProtectionCallback(this);
645b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // The send codec must be registered to set correct MTU.
646b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    webrtc::VideoCodec codec;
647b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    if (vcm_.SendCodec(&codec) == 0) {
64867879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org      uint16_t max_pay_load = default_rtp_rtcp_->MaxDataPayloadLength();
64963136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org      uint32_t current_bitrate_bps = 0;
65063136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org      if (vcm_.Bitrate(&current_bitrate_bps) != 0) {
651022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org        LOG_F(LS_WARNING) <<
652022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org            "Failed to get the current encoder target bitrate.";
653b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
65463136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org      // Convert to start bitrate in kbps.
65563136921ece04448f1bc71ce6f3e43974f9d385astefan@webrtc.org      codec.startBitrate = (current_bitrate_bps + 500) / 1000;
656b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      if (vcm_.RegisterSendCodec(&codec, number_of_cores_, max_pay_load) != 0) {
657b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org        return -1;
658b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org      }
659b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    }
660b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    return 0;
661b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  } else {
662b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    // FEC and NACK are disabled.
663b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    vcm_.RegisterProtectionCallback(NULL);
664b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
665b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
666b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
667b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
6689d6fcb37be4c9f49e1bb0b32bb01314c31f5e1ddmikhal@webrtc.orgvoid ViEEncoder::SetSenderBufferingMode(int target_delay_ms) {
669dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  {
670dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
671dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    target_delay_ms_ = target_delay_ms;
672dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org  }
6730c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org  if (target_delay_ms > 0) {
674dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    // Disable external frame-droppers.
675dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    vcm_.EnableFrameDropper(false);
676dca71b270896a8501d9f12506e7da48cde9abb20stefan@webrtc.org    vpm_.EnableTemporalDecimation(false);
67704d6593fef1182e8106a67681a1c6c2ebc90f0c2stefan@webrtc.org    // We don't put any limits on the pacer queue when running in buffered mode
67804d6593fef1182e8106a67681a1c6c2ebc90f0c2stefan@webrtc.org    // since the encoder will be paused if the queue grow too large.
67904d6593fef1182e8106a67681a1c6c2ebc90f0c2stefan@webrtc.org    paced_sender_->set_max_queue_length_ms(-1);
6800c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org  } else {
6819d6fcb37be4c9f49e1bb0b32bb01314c31f5e1ddmikhal@webrtc.org    // Real-time mode - enable frame droppers.
6820c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org    vpm_.EnableTemporalDecimation(true);
6830c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org    vcm_.EnableFrameDropper(true);
68404d6593fef1182e8106a67681a1c6c2ebc90f0c2stefan@webrtc.org    paced_sender_->set_max_queue_length_ms(
68504d6593fef1182e8106a67681a1c6c2ebc90f0c2stefan@webrtc.org        PacedSender::kDefaultMaxQueueLengthMs);
6860c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org  }
6870c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org}
6880c66de6e75821a8e86fcbd166d725a5a859cab79mikhal@webrtc.org
68967879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::SendData(
690b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const FrameType frame_type,
69167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint8_t payload_type,
69267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t time_stamp,
693b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    int64_t capture_time_ms,
69467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint8_t* payload_data,
69567879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t payload_size,
696b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const webrtc::RTPFragmentationHeader& fragmentation_header,
697b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const RTPVideoHeader* rtp_video_hdr) {
698b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // New encoded data, hand over to the rtp module.
699b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return default_rtp_rtcp_->SendOutgoingData(frame_type,
700b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             payload_type,
701b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             time_stamp,
702b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             capture_time_ms,
703b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             payload_data,
704b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             payload_size,
705b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             &fragmentation_header,
706b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                             rtp_video_hdr);
707b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
708b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
70967879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::ProtectionRequest(
710b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const FecProtectionParams* delta_fec_params,
711b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    const FecProtectionParams* key_fec_params,
71267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint32_t* sent_video_rate_bps,
71367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint32_t* sent_nack_rate_bps,
71467879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    uint32_t* sent_fec_rate_bps) {
715022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  default_rtp_rtcp_->SetFecParameters(delta_fec_params, key_fec_params);
716022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  default_rtp_rtcp_->BitrateSent(NULL, sent_video_rate_bps, sent_fec_rate_bps,
717b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                sent_nack_rate_bps);
718b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
719b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
720b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
72167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::SendStatistics(const uint32_t bit_rate,
72267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org                                   const uint32_t frame_rate) {
723b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(callback_cs_.get());
724b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  if (codec_observer_) {
725b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    codec_observer_->OutgoingRate(channel_id_, frame_rate, bit_rate);
726b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
727b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
728b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
729b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
73067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::RegisterCodecObserver(ViEEncoderObserver* observer) {
731b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(callback_cs_.get());
732022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  if (observer && codec_observer_) {
733022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG_F(LS_ERROR) << "Observer already set.";
734022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    return -1;
735b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
736022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  codec_observer_ = observer;
737b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
738b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
739b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
740b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::OnReceivedSLI(uint32_t /*ssrc*/,
741b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                               uint8_t picture_id) {
742fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
743b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  picture_id_sli_ = picture_id;
744b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  has_received_sli_ = true;
745b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
746b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
747b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::OnReceivedRPSI(uint32_t /*ssrc*/,
748b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                uint64_t picture_id) {
749fedbe8b196306135b3834b34b19fd455c037172astefan@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
750b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  picture_id_rpsi_ = picture_id;
751b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  has_received_rpsi_ = true;
752b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
753b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
754b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.orgvoid ViEEncoder::OnReceivedIntraFrameRequest(uint32_t ssrc) {
755b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  // Key frame request from remote side, signal to VCM.
756d474c1380229d8b301f6cb4c3b84ad0d4ac18632justinlin@chromium.org  TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
757b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
758b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  int idx = 0;
759b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  {
760b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
761b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    std::map<unsigned int, int>::iterator stream_it = ssrc_streams_.find(ssrc);
762b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    if (stream_it == ssrc_streams_.end()) {
763ac09423d1ac3c758462252a2f27275031a5859damflodman@webrtc.org      LOG_F(LS_WARNING) << "ssrc not found: " << ssrc << ", map size "
764ac09423d1ac3c758462252a2f27275031a5859damflodman@webrtc.org                        << ssrc_streams_.size();
765b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org      return;
766b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    }
76767879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    std::map<unsigned int, int64_t>::iterator time_it =
768b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org        time_last_intra_request_ms_.find(ssrc);
769b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    if (time_it == time_last_intra_request_ms_.end()) {
770b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org      time_last_intra_request_ms_[ssrc] = 0;
771b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    }
772b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
77367879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    int64_t now = TickTime::MillisecondTimestamp();
774b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    if (time_last_intra_request_ms_[ssrc] + kViEMinKeyRequestIntervalMs > now) {
775b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org      return;
776b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    }
777b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    time_last_intra_request_ms_[ssrc] = now;
778b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    idx = stream_it->second;
779b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
780b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  // Release the critsect before triggering key frame.
781b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  vcm_.IntraFrameRequest(idx);
782b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
783b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
7849f269d2d33e102713402c4c6aa84ac65a590f719vikasmarwaha@webrtc.orgvoid ViEEncoder::OnLocalSsrcChanged(uint32_t old_ssrc, uint32_t new_ssrc) {
785b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
786b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  std::map<unsigned int, int>::iterator it = ssrc_streams_.find(old_ssrc);
787b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  if (it == ssrc_streams_.end()) {
788b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    return;
789b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  }
790b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
791b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  ssrc_streams_[new_ssrc] = it->second;
792b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  ssrc_streams_.erase(it);
793b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
794b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  std::map<unsigned int, int64_t>::iterator time_it =
795b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org      time_last_intra_request_ms_.find(old_ssrc);
796b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  int64_t last_intra_request_ms = 0;
797b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  if (time_it != time_last_intra_request_ms_.end()) {
798b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    last_intra_request_ms = time_it->second;
799b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    time_last_intra_request_ms_.erase(time_it);
800b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  }
801b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  time_last_intra_request_ms_[new_ssrc] = last_intra_request_ms;
802b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org}
803b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
804b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.orgbool ViEEncoder::SetSsrcs(const std::list<unsigned int>& ssrcs) {
805b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  VideoCodec codec;
806b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  if (vcm_.SendCodec(&codec) != 0)
807b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    return false;
808b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
809b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  if (codec.numberOfSimulcastStreams > 0 &&
810b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org      ssrcs.size() != codec.numberOfSimulcastStreams) {
811b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    return false;
812b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  }
813b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org
814b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  CriticalSectionScoped cs(data_cs_.get());
815b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  ssrc_streams_.clear();
816b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  time_last_intra_request_ms_.clear();
817b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  int idx = 0;
818b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  for (std::list<unsigned int>::const_iterator it = ssrcs.begin();
819b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org       it != ssrcs.end(); ++it, ++idx) {
820b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    unsigned int ssrc = *it;
821b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org    ssrc_streams_[ssrc] = idx;
822b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  }
823b6d9cfc6347e490751e142ba5fb89e4a975ed442mflodman@webrtc.org  return true;
824b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
825b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
8263f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.orgvoid ViEEncoder::SetMinTransmitBitrate(int min_transmit_bitrate_kbps) {
8273f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  assert(min_transmit_bitrate_kbps >= 0);
8283f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  CriticalSectionScoped crit(data_cs_.get());
8293f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  min_transmit_bitrate_kbps_ = min_transmit_bitrate_kbps;
8303f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org}
8313f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org
832b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org// Called from ViEBitrateObserver.
833b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgvoid ViEEncoder::OnNetworkChanged(const uint32_t bitrate_bps,
834b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  const uint8_t fraction_lost,
835b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org                                  const uint32_t round_trip_time_ms) {
836022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  LOG(LS_VERBOSE) << "OnNetworkChanged, bitrate" << bitrate_bps
837022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org                  << " packet loss " << fraction_lost
838022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org                  << " rtt " << round_trip_time_ms;
83972e204a700e985c1f0c65f7a566fe9aaf7713e64stefan@webrtc.org  vcm_.SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms);
8404590177aa3346a742e8f71c8bcc5b81618d21919henrik.lundin@webrtc.org  bool video_is_suspended = vcm_.VideoSuspended();
8415e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  int bitrate_kbps = bitrate_bps / 1000;
84269f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  VideoCodec send_codec;
84369f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  if (vcm_.SendCodec(&send_codec) != 0) {
84469f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org    return;
84569f76054f5dc242b313e7e0642c8657a885682bastefan@webrtc.org  }
8467dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  SimulcastStream* stream_configs = send_codec.simulcastStream;
8477dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  // Allocate the bandwidth between the streams.
8487dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates(
8497dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      bitrate_bps,
8507dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      stream_configs,
8517dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org      send_codec.numberOfSimulcastStreams);
8527dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  // Find the max amount of padding we can allow ourselves to send at this
8537dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  // point, based on which streams are currently active and what our current
8547dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  // available bandwidth is.
85593cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org  int pad_up_to_bitrate_kbps = 0;
85693cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org  if (send_codec.numberOfSimulcastStreams == 0) {
85793cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org    pad_up_to_bitrate_kbps = send_codec.minBitrate;
85893cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org  } else {
85993cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org    pad_up_to_bitrate_kbps =
86093cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org        stream_configs[send_codec.numberOfSimulcastStreams - 1].minBitrate;
86193cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org    for (int i = 0; i < send_codec.numberOfSimulcastStreams - 1; ++i) {
86293cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org      pad_up_to_bitrate_kbps += stream_configs[i].targetBitrate;
8637dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org    }
8647dc17903111cf74bc28f45d87e595c628481f1acstefan@webrtc.org  }
8651d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org
8661d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org  // Disable padding if only sending one stream and video isn't suspended and
8671d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org  // min-transmit bitrate isn't used (applied later).
8681d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org  if (!video_is_suspended && send_codec.numberOfSimulcastStreams <= 1)
86993cd39766e6484842666c1b2c77283c3c1885f33stefan@webrtc.org    pad_up_to_bitrate_kbps = 0;
8705e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org
8715e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org  {
8725e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org    CriticalSectionScoped cs(data_cs_.get());
8731d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org    // The amount of padding should decay to zero if no frames are being
8741d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org    // captured unless a min-transmit bitrate is used.
8755e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org    int64_t now_ms = TickTime::MillisecondTimestamp();
8765e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org    if (now_ms - time_of_last_incoming_frame_ms_ > kStopPaddingThresholdMs)
8771d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org      pad_up_to_bitrate_kbps = 0;
8785e74d9693504416a5b72a9c8c9a7626f802f969estefan@webrtc.org
8791d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org    // Pad up to min bitrate.
8803f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org    if (pad_up_to_bitrate_kbps < min_transmit_bitrate_kbps_)
8813f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org      pad_up_to_bitrate_kbps = min_transmit_bitrate_kbps_;
8821d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org
8831d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org    // Padding may never exceed bitrate estimate.
8841d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org    if (pad_up_to_bitrate_kbps > bitrate_kbps)
8851d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org      pad_up_to_bitrate_kbps = bitrate_kbps;
8861d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org
887c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org    paced_sender_->UpdateBitrate(
888c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org        PacedSender::kDefaultPaceMultiplier * bitrate_kbps,
889c9995bc06a99f8b82a0ca0ddf5a5bb982cb0c11bstefan@webrtc.org        pad_up_to_bitrate_kbps);
8903f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org    default_rtp_rtcp_->SetTargetSendBitrate(stream_bitrates);
8917673871382e063289a0f7fd8aa77918b243c1788pbos@webrtc.org    if (video_suspended_ == video_is_suspended)
8927673871382e063289a0f7fd8aa77918b243c1788pbos@webrtc.org      return;
8937673871382e063289a0f7fd8aa77918b243c1788pbos@webrtc.org    video_suspended_ = video_is_suspended;
8947673871382e063289a0f7fd8aa77918b243c1788pbos@webrtc.org  }
8951d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org
8961d61e3a79d4a5c6693c959f59d9f9cc6c1bfb359pbos@webrtc.org  // Video suspend-state changed, inform codec observer.
8973f83f9cae99b605aee71b46839e902653baeb3f6pbos@webrtc.org  CriticalSectionScoped crit(callback_cs_.get());
8987673871382e063289a0f7fd8aa77918b243c1788pbos@webrtc.org  if (codec_observer_) {
899022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG(LS_INFO) << "Video suspended " << video_is_suspended
900022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org                 << " for channel " << channel_id_;
90182b883c27168fa801aef8e0530db298e6128eb5chenrik.lundin@webrtc.org    codec_observer_->SuspendChange(channel_id_, video_is_suspended);
90239079d1ee84faab899c8af92bce984c20e60fd29henrik.lundin@webrtc.org  }
903b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
904b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
9055e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.orgPacedSender* ViEEncoder::GetPacedSender() {
9065e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org  return paced_sender_.get();
9075e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org}
9085e87b5f032780f6941a27c2d5068ab1e89e659a6pwestin@webrtc.org
90967879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t ViEEncoder::RegisterEffectFilter(ViEEffectFilter* effect_filter) {
910b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  CriticalSectionScoped cs(callback_cs_.get());
911022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org  if (effect_filter != NULL && effect_filter_ != NULL) {
912022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    LOG_F(LS_ERROR) << "Filter already set.";
913022615bd918aec7671968ad2b873d1487365980cmflodman@webrtc.org    return -1;
914b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  }
915b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  effect_filter_ = effect_filter;
916b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return 0;
917b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
918b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
919b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEEncoder::StartDebugRecording(const char* fileNameUTF8) {
920b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return vcm_.StartDebugRecording(fileNameUTF8);
921b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
922b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
923b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgint ViEEncoder::StopDebugRecording() {
924b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return vcm_.StopDebugRecording();
925b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
926b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
9274590177aa3346a742e8f71c8bcc5b81618d21919henrik.lundin@webrtc.orgvoid ViEEncoder::SuspendBelowMinBitrate() {
9284590177aa3346a742e8f71c8bcc5b81618d21919henrik.lundin@webrtc.org  vcm_.SuspendBelowMinBitrate();
9294ce759057ec1d71b19bd706c5cdc9027096463fdhenrik.lundin@webrtc.org  bitrate_controller_->EnforceMinBitrate(false);
93039079d1ee84faab899c8af92bce984c20e60fd29henrik.lundin@webrtc.org}
93139079d1ee84faab899c8af92bce984c20e60fd29henrik.lundin@webrtc.org
93263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.orgvoid ViEEncoder::RegisterPreEncodeCallback(
93363301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org    I420FrameCallback* pre_encode_callback) {
93463301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CriticalSectionScoped cs(callback_cs_.get());
93563301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  pre_encode_callback_ = pre_encode_callback;
93663301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org}
93763301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
93863301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.orgvoid ViEEncoder::DeRegisterPreEncodeCallback() {
93963301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  CriticalSectionScoped cs(callback_cs_.get());
94063301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org  pre_encode_callback_ = NULL;
94163301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org}
94263301bd03e009d309d1fdca1217f8708be610f32pbos@webrtc.org
9432e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.orgvoid ViEEncoder::RegisterPostEncodeImageCallback(
9442e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org      EncodedImageCallback* post_encode_callback) {
9452e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  vcm_.RegisterPostEncodeImageCallback(post_encode_callback);
9462e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org}
9472e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
9482e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.orgvoid ViEEncoder::DeRegisterPostEncodeImageCallback() {
9492e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org  vcm_.RegisterPostEncodeImageCallback(NULL);
9502e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org}
9512e98d45e2455d3b48ceac1ad5457623d39802c9esprang@webrtc.org
952b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgQMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessingModule* vpm)
953b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org    : vpm_(vpm) {
954b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
955b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
956b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.orgQMVideoSettingsCallback::~QMVideoSettingsCallback() {
957b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
958b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
95967879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.orgint32_t QMVideoSettingsCallback::SetVideoQMSettings(
96067879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t frame_rate,
96167879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t width,
96267879bc2e69d7907b7ceb92135a34f77fe643e7fpbos@webrtc.org    const uint32_t height) {
963b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org  return vpm_->SetTargetResolution(width, height, frame_rate);
964b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}
965b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org
966b015cbede88899f67a53fbbe581b02ce8e32794andrew@webrtc.org}  // namespace webrtc
967