blob: 509707f155083f0453f9a6c71232a19e62369b2f [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
mflodman@webrtc.orgc80d9d92012-02-06 10:11:25 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "modules/video_coding/video_coding_impl.h"
philipel5908c712015-12-21 08:23:20 -080012
13#include <algorithm>
Erik Språng08127a92016-11-16 16:41:30 +010014#include <utility>
philipel5908c712015-12-21 08:23:20 -080015
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "common_types.h"
17#include "common_video/include/video_bitrate_allocator.h"
18#include "common_video/libyuv/include/webrtc_libyuv.h"
19#include "modules/video_coding/codecs/vp8/temporal_layers.h"
20#include "modules/video_coding/encoded_frame.h"
21#include "modules/video_coding/include/video_codec_initializer.h"
22#include "modules/video_coding/include/video_codec_interface.h"
23#include "modules/video_coding/jitter_buffer.h"
24#include "modules/video_coding/packet.h"
25#include "modules/video_coding/timing.h"
26#include "rtc_base/criticalsection.h"
27#include "rtc_base/thread_checker.h"
28#include "system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000029
agalusza@google.coma7e360e2013-08-01 03:15:08 +000030namespace webrtc {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000031namespace vcm {
niklase@google.com470e71d2011-07-07 08:21:25 +000032
philipel5908c712015-12-21 08:23:20 -080033int64_t VCMProcessTimer::Period() const {
34 return _periodMs;
niklase@google.com470e71d2011-07-07 08:21:25 +000035}
36
philipel5908c712015-12-21 08:23:20 -080037int64_t VCMProcessTimer::TimeUntilProcess() const {
38 const int64_t time_since_process = _clock->TimeInMilliseconds() - _latestMs;
39 const int64_t time_until_process = _periodMs - time_since_process;
40 return std::max<int64_t>(time_until_process, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000041}
42
philipel5908c712015-12-21 08:23:20 -080043void VCMProcessTimer::Processed() {
44 _latestMs = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +000045}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000046} // namespace vcm
niklase@google.com470e71d2011-07-07 08:21:25 +000047
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000048namespace {
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000049// This wrapper provides a way to modify the callback without the need to expose
50// a register method all the way down to the function calling it.
51class EncodedImageCallbackWrapper : public EncodedImageCallback {
52 public:
kthelgasond701dfd2017-03-27 07:24:57 -070053 EncodedImageCallbackWrapper() : callback_(nullptr) {}
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000054
55 virtual ~EncodedImageCallbackWrapper() {}
56
57 void Register(EncodedImageCallback* callback) {
kthelgasond701dfd2017-03-27 07:24:57 -070058 rtc::CritScope lock(&cs_);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000059 callback_ = callback;
60 }
61
Sergey Ulanov525df3f2016-08-02 17:46:41 -070062 virtual Result OnEncodedImage(const EncodedImage& encoded_image,
63 const CodecSpecificInfo* codec_specific_info,
64 const RTPFragmentationHeader* fragmentation) {
kthelgasond701dfd2017-03-27 07:24:57 -070065 rtc::CritScope lock(&cs_);
Sergey Ulanov525df3f2016-08-02 17:46:41 -070066 if (callback_) {
67 return callback_->OnEncodedImage(encoded_image, codec_specific_info,
68 fragmentation);
69 }
70 return Result(Result::ERROR_SEND_FAILED);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000071 }
72
73 private:
kthelgasond701dfd2017-03-27 07:24:57 -070074 rtc::CriticalSection cs_;
danilchap56359be2017-09-07 07:53:45 -070075 EncodedImageCallback* callback_ RTC_GUARDED_BY(cs_);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000076};
77
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000078class VideoCodingModuleImpl : public VideoCodingModule {
79 public:
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000080 VideoCodingModuleImpl(Clock* clock,
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000081 EventFactory* event_factory,
philipel83f831a2016-03-12 03:30:23 -080082 NackSender* nack_sender,
sprang3911c262016-04-15 01:24:14 -070083 KeyFrameRequestSender* keyframe_request_sender,
84 EncodedImageCallback* pre_decode_image_callback)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000085 : VideoCodingModule(),
perkjf5b2e512016-07-05 08:34:04 -070086 sender_(clock, &post_encode_callback_, nullptr),
philipel721d4022016-12-15 07:10:57 -080087 timing_(new VCMTiming(clock)),
philipel83f831a2016-03-12 03:30:23 -080088 receiver_(clock,
89 event_factory,
sprang3911c262016-04-15 01:24:14 -070090 pre_decode_image_callback,
philipel721d4022016-12-15 07:10:57 -080091 timing_.get(),
philipel83f831a2016-03-12 03:30:23 -080092 nack_sender,
Peter Boström0b250722016-04-22 18:23:15 +020093 keyframe_request_sender) {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000094
Peter Boström0b250722016-04-22 18:23:15 +020095 virtual ~VideoCodingModuleImpl() {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000096
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000097 int64_t TimeUntilNextProcess() override {
pbos0fa9b222015-11-13 05:59:57 -080098 int64_t sender_time = sender_.TimeUntilNextProcess();
99 int64_t receiver_time = receiver_.TimeUntilNextProcess();
tommid0a71ba2017-03-14 04:16:20 -0700100 RTC_DCHECK_GE(sender_time, 0);
101 RTC_DCHECK_GE(receiver_time, 0);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000102 return VCM_MIN(sender_time, receiver_time);
103 }
104
pbosa26ac922016-02-25 04:50:01 -0800105 void Process() override {
106 sender_.Process();
107 receiver_.Process();
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000108 }
109
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000110 int32_t RegisterSendCodec(const VideoCodec* sendCodec,
111 uint32_t numberOfCores,
112 uint32_t maxPayloadSize) override {
Erik Språng08127a92016-11-16 16:41:30 +0100113 if (sendCodec != nullptr && sendCodec->codecType == kVideoCodecVP8) {
114 // Set up a rate allocator and temporal layers factory for this vp8
115 // instance. The codec impl will have a raw pointer to the TL factory,
116 // and will call it when initializing. Since this can happen
117 // asynchronously keep the instance alive until destruction or until a
118 // new send codec is registered.
119 VideoCodec vp8_codec = *sendCodec;
120 std::unique_ptr<TemporalLayersFactory> tl_factory(
121 new TemporalLayersFactory());
122 vp8_codec.VP8()->tl_factory = tl_factory.get();
123 rate_allocator_ = VideoCodecInitializer::CreateBitrateAllocator(
124 vp8_codec, std::move(tl_factory));
125 return sender_.RegisterSendCodec(&vp8_codec, numberOfCores,
126 maxPayloadSize);
127 }
pbos0fa9b222015-11-13 05:59:57 -0800128 return sender_.RegisterSendCodec(sendCodec, numberOfCores, maxPayloadSize);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000129 }
130
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000131 int32_t RegisterExternalEncoder(VideoEncoder* externalEncoder,
132 uint8_t payloadType,
133 bool internalSource) override {
Peter Boström795dbe42015-11-27 14:09:07 +0100134 sender_.RegisterExternalEncoder(externalEncoder, payloadType,
135 internalSource);
136 return 0;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000137 }
138
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000139 int Bitrate(unsigned int* bitrate) const override {
pbos0fa9b222015-11-13 05:59:57 -0800140 return sender_.Bitrate(bitrate);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000141 }
142
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000143 int FrameRate(unsigned int* framerate) const override {
pbos0fa9b222015-11-13 05:59:57 -0800144 return sender_.FrameRate(framerate);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000145 }
146
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000147 int32_t SetChannelParameters(uint32_t target_bitrate, // bits/s.
148 uint8_t lossRate,
149 int64_t rtt) override {
Erik Språng08127a92016-11-16 16:41:30 +0100150 return sender_.SetChannelParameters(target_bitrate, lossRate, rtt,
sprang1a646ee2016-12-01 06:34:11 -0800151 rate_allocator_.get(), nullptr);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000152 }
153
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000154 int32_t RegisterProtectionCallback(
155 VCMProtectionCallback* protection) override {
pbos0fa9b222015-11-13 05:59:57 -0800156 return sender_.RegisterProtectionCallback(protection);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000157 }
158
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000159 int32_t SetVideoProtection(VCMVideoProtection videoProtection,
160 bool enable) override {
pbosba8c15b2015-07-14 09:36:34 -0700161 // TODO(pbos): Remove enable from receive-side protection modes as well.
pbos0fa9b222015-11-13 05:59:57 -0800162 return receiver_.SetVideoProtection(videoProtection, enable);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000163 }
164
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700165 int32_t AddVideoFrame(const VideoFrame& videoFrame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000166 const CodecSpecificInfo* codecSpecificInfo) override {
Peter Boströmad6fc5a2016-05-12 03:01:31 +0200167 return sender_.AddVideoFrame(videoFrame, codecSpecificInfo);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000168 }
169
perkj600246e2016-05-04 11:26:51 -0700170 int32_t IntraFrameRequest(size_t stream_index) override {
pbos0fa9b222015-11-13 05:59:57 -0800171 return sender_.IntraFrameRequest(stream_index);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000172 }
173
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000174 int32_t EnableFrameDropper(bool enable) override {
pbos0fa9b222015-11-13 05:59:57 -0800175 return sender_.EnableFrameDropper(enable);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000176 }
177
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000178 int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec,
179 int32_t numberOfCores,
180 bool requireKeyFrame) override {
pbos0fa9b222015-11-13 05:59:57 -0800181 return receiver_.RegisterReceiveCodec(receiveCodec, numberOfCores,
182 requireKeyFrame);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000183 }
184
Peter Boström795dbe42015-11-27 14:09:07 +0100185 void RegisterExternalDecoder(VideoDecoder* externalDecoder,
perkj796cfaf2015-12-10 09:27:38 -0800186 uint8_t payloadType) override {
187 receiver_.RegisterExternalDecoder(externalDecoder, payloadType);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000188 }
189
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000190 int32_t RegisterReceiveCallback(
191 VCMReceiveCallback* receiveCallback) override {
tommid0a71ba2017-03-14 04:16:20 -0700192 RTC_DCHECK(construction_thread_.CalledOnValidThread());
pbos0fa9b222015-11-13 05:59:57 -0800193 return receiver_.RegisterReceiveCallback(receiveCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000194 }
195
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000196 int32_t RegisterReceiveStatisticsCallback(
197 VCMReceiveStatisticsCallback* receiveStats) override {
pbos0fa9b222015-11-13 05:59:57 -0800198 return receiver_.RegisterReceiveStatisticsCallback(receiveStats);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000199 }
200
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000201 int32_t RegisterFrameTypeCallback(
202 VCMFrameTypeCallback* frameTypeCallback) override {
pbos0fa9b222015-11-13 05:59:57 -0800203 return receiver_.RegisterFrameTypeCallback(frameTypeCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000204 }
205
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000206 int32_t RegisterPacketRequestCallback(
207 VCMPacketRequestCallback* callback) override {
tommid0a71ba2017-03-14 04:16:20 -0700208 RTC_DCHECK(construction_thread_.CalledOnValidThread());
pbos0fa9b222015-11-13 05:59:57 -0800209 return receiver_.RegisterPacketRequestCallback(callback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000210 }
211
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000212 int32_t Decode(uint16_t maxWaitTimeMs) override {
pbos0fa9b222015-11-13 05:59:57 -0800213 return receiver_.Decode(maxWaitTimeMs);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000214 }
215
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000216 int32_t IncomingPacket(const uint8_t* incomingPayload,
217 size_t payloadLength,
218 const WebRtcRTPHeader& rtpInfo) override {
pbos0fa9b222015-11-13 05:59:57 -0800219 return receiver_.IncomingPacket(incomingPayload, payloadLength, rtpInfo);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000220 }
221
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000222 int32_t SetMinimumPlayoutDelay(uint32_t minPlayoutDelayMs) override {
pbos0fa9b222015-11-13 05:59:57 -0800223 return receiver_.SetMinimumPlayoutDelay(minPlayoutDelayMs);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000224 }
225
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000226 int32_t SetRenderDelay(uint32_t timeMS) override {
pbos0fa9b222015-11-13 05:59:57 -0800227 return receiver_.SetRenderDelay(timeMS);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000228 }
229
pbos0fa9b222015-11-13 05:59:57 -0800230 int32_t Delay() const override { return receiver_.Delay(); }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000231
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000232 int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
233 VCMDecodeErrorMode errorMode) override {
pbos0fa9b222015-11-13 05:59:57 -0800234 return receiver_.SetReceiverRobustnessMode(robustnessMode, errorMode);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000235 }
236
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000237 void SetNackSettings(size_t max_nack_list_size,
238 int max_packet_age_to_nack,
239 int max_incomplete_time_ms) override {
pbos0fa9b222015-11-13 05:59:57 -0800240 return receiver_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
241 max_incomplete_time_ms);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000242 }
243
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000244 void SetDecodeErrorMode(VCMDecodeErrorMode decode_error_mode) override {
pbos0fa9b222015-11-13 05:59:57 -0800245 return receiver_.SetDecodeErrorMode(decode_error_mode);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000246 }
247
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000248 int SetMinReceiverDelay(int desired_delay_ms) override {
pbos0fa9b222015-11-13 05:59:57 -0800249 return receiver_.SetMinReceiverDelay(desired_delay_ms);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000250 }
251
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000252 int32_t SetReceiveChannelParameters(int64_t rtt) override {
pbos0fa9b222015-11-13 05:59:57 -0800253 return receiver_.SetReceiveChannelParameters(rtt);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000254 }
255
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000256 void RegisterPostEncodeImageCallback(
257 EncodedImageCallback* observer) override {
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +0000258 post_encode_callback_.Register(observer);
sprang@webrtc.org40709352013-11-26 11:41:59 +0000259 }
260
pbos0fa9b222015-11-13 05:59:57 -0800261 void TriggerDecoderShutdown() override { receiver_.TriggerDecoderShutdown(); }
pbos@webrtc.org4dd40d62015-02-17 13:22:43 +0000262
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000263 private:
tommid0a71ba2017-03-14 04:16:20 -0700264 rtc::ThreadChecker construction_thread_;
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +0000265 EncodedImageCallbackWrapper post_encode_callback_;
pbos0fa9b222015-11-13 05:59:57 -0800266 vcm::VideoSender sender_;
Erik Språng08127a92016-11-16 16:41:30 +0100267 std::unique_ptr<VideoBitrateAllocator> rate_allocator_;
philipel721d4022016-12-15 07:10:57 -0800268 std::unique_ptr<VCMTiming> timing_;
pbos0fa9b222015-11-13 05:59:57 -0800269 vcm::VideoReceiver receiver_;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000270};
271} // namespace
272
tommia5c18d72017-03-20 10:43:23 -0700273// DEPRECATED. Create method for current interface, will be removed when the
philipel83f831a2016-03-12 03:30:23 -0800274// new jitter buffer is in place.
philipel5908c712015-12-21 08:23:20 -0800275VideoCodingModule* VideoCodingModule::Create(Clock* clock,
276 EventFactory* event_factory) {
tommid0a71ba2017-03-14 04:16:20 -0700277 RTC_DCHECK(clock);
278 RTC_DCHECK(event_factory);
tommia5c18d72017-03-20 10:43:23 -0700279 return new VideoCodingModuleImpl(clock, event_factory, nullptr, nullptr,
280 nullptr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000281}
282
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000283} // namespace webrtc