blob: 39eccb56da9169cd07e1e05376e66003e88dc20f [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>
Yves Gerey3e707812018-11-28 16:47:49 +010014#include <memory>
philipel5908c712015-12-21 08:23:20 -080015
Jiawei Ouc2ebe212018-11-08 10:02:56 -080016#include "api/video/builtin_video_bitrate_allocator_factory.h"
Yves Gerey3e707812018-11-28 16:47:49 +010017#include "api/video/encoded_image.h"
Jiawei Ou4206a0a2018-07-20 15:49:43 -070018#include "api/video/video_bitrate_allocator.h"
Yves Gerey3e707812018-11-28 16:47:49 +010019#include "api/video/video_bitrate_allocator_factory.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020020#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "modules/video_coding/include/video_codec_interface.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "modules/video_coding/timing.h"
23#include "rtc_base/criticalsection.h"
24#include "rtc_base/thread_checker.h"
25#include "system_wrappers/include/clock.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000026
agalusza@google.coma7e360e2013-08-01 03:15:08 +000027namespace webrtc {
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000028namespace vcm {
niklase@google.com470e71d2011-07-07 08:21:25 +000029
philipel5908c712015-12-21 08:23:20 -080030int64_t VCMProcessTimer::Period() const {
31 return _periodMs;
niklase@google.com470e71d2011-07-07 08:21:25 +000032}
33
philipel5908c712015-12-21 08:23:20 -080034int64_t VCMProcessTimer::TimeUntilProcess() const {
35 const int64_t time_since_process = _clock->TimeInMilliseconds() - _latestMs;
36 const int64_t time_until_process = _periodMs - time_since_process;
37 return std::max<int64_t>(time_until_process, 0);
niklase@google.com470e71d2011-07-07 08:21:25 +000038}
39
philipel5908c712015-12-21 08:23:20 -080040void VCMProcessTimer::Processed() {
41 _latestMs = _clock->TimeInMilliseconds();
niklase@google.com470e71d2011-07-07 08:21:25 +000042}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000043} // namespace vcm
niklase@google.com470e71d2011-07-07 08:21:25 +000044
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000045namespace {
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000046// This wrapper provides a way to modify the callback without the need to expose
47// a register method all the way down to the function calling it.
48class EncodedImageCallbackWrapper : public EncodedImageCallback {
49 public:
kthelgasond701dfd2017-03-27 07:24:57 -070050 EncodedImageCallbackWrapper() : callback_(nullptr) {}
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000051
52 virtual ~EncodedImageCallbackWrapper() {}
53
54 void Register(EncodedImageCallback* callback) {
kthelgasond701dfd2017-03-27 07:24:57 -070055 rtc::CritScope lock(&cs_);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000056 callback_ = callback;
57 }
58
Sergey Ulanov525df3f2016-08-02 17:46:41 -070059 virtual Result OnEncodedImage(const EncodedImage& encoded_image,
60 const CodecSpecificInfo* codec_specific_info,
61 const RTPFragmentationHeader* fragmentation) {
kthelgasond701dfd2017-03-27 07:24:57 -070062 rtc::CritScope lock(&cs_);
Sergey Ulanov525df3f2016-08-02 17:46:41 -070063 if (callback_) {
64 return callback_->OnEncodedImage(encoded_image, codec_specific_info,
65 fragmentation);
66 }
67 return Result(Result::ERROR_SEND_FAILED);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000068 }
69
70 private:
kthelgasond701dfd2017-03-27 07:24:57 -070071 rtc::CriticalSection cs_;
danilchap56359be2017-09-07 07:53:45 -070072 EncodedImageCallback* callback_ RTC_GUARDED_BY(cs_);
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +000073};
74
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000075class VideoCodingModuleImpl : public VideoCodingModule {
76 public:
stefan@webrtc.org34c5da62014-04-11 14:08:35 +000077 VideoCodingModuleImpl(Clock* clock,
philipel83f831a2016-03-12 03:30:23 -080078 NackSender* nack_sender,
Niels Möller9eb44ac2018-10-02 12:47:47 +020079 KeyFrameRequestSender* keyframe_request_sender)
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000080 : VideoCodingModule(),
Niels Möllera0565992017-10-24 11:37:08 +020081 sender_(clock, &post_encode_callback_),
Jiawei Ouc2ebe212018-11-08 10:02:56 -080082 rate_allocator_factory_(CreateBuiltinVideoBitrateAllocatorFactory()),
philipel721d4022016-12-15 07:10:57 -080083 timing_(new VCMTiming(clock)),
Niels Möller689983f2018-11-07 16:36:22 +010084 receiver_(clock, timing_.get(), nack_sender, keyframe_request_sender) {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000085
Peter Boström0b250722016-04-22 18:23:15 +020086 virtual ~VideoCodingModuleImpl() {}
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000087
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000088 int64_t TimeUntilNextProcess() override {
pbos0fa9b222015-11-13 05:59:57 -080089 int64_t receiver_time = receiver_.TimeUntilNextProcess();
tommid0a71ba2017-03-14 04:16:20 -070090 RTC_DCHECK_GE(receiver_time, 0);
Niels Möllera0565992017-10-24 11:37:08 +020091 return receiver_time;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000092 }
93
Yves Gerey665174f2018-06-19 15:03:05 +020094 void Process() override { receiver_.Process(); }
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +000095
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +000096 int32_t RegisterSendCodec(const VideoCodec* sendCodec,
97 uint32_t numberOfCores,
98 uint32_t maxPayloadSize) override {
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +020099 if (sendCodec != nullptr && ((sendCodec->codecType == kVideoCodecVP8) ||
100 (sendCodec->codecType == kVideoCodecH264))) {
101 // Set up a rate allocator and temporal layers factory for this codec
Erik Språng08127a92016-11-16 16:41:30 +0100102 // instance. The codec impl will have a raw pointer to the TL factory,
103 // and will call it when initializing. Since this can happen
104 // asynchronously keep the instance alive until destruction or until a
105 // new send codec is registered.
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200106 VideoCodec codec = *sendCodec;
Jiawei Ouc2ebe212018-11-08 10:02:56 -0800107 rate_allocator_ =
108 rate_allocator_factory_->CreateVideoBitrateAllocator(codec);
Sergio Garcia Murillo43800f92018-06-21 16:16:38 +0200109 return sender_.RegisterSendCodec(&codec, numberOfCores, maxPayloadSize);
Erik Språng08127a92016-11-16 16:41:30 +0100110 }
pbos0fa9b222015-11-13 05:59:57 -0800111 return sender_.RegisterSendCodec(sendCodec, numberOfCores, maxPayloadSize);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000112 }
113
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000114 int32_t RegisterExternalEncoder(VideoEncoder* externalEncoder,
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100115 uint8_t /* payloadType */,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000116 bool internalSource) override {
Yves Gerey665174f2018-06-19 15:03:05 +0200117 sender_.RegisterExternalEncoder(externalEncoder, internalSource);
Peter Boström795dbe42015-11-27 14:09:07 +0100118 return 0;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000119 }
120
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000121 int32_t SetChannelParameters(uint32_t target_bitrate, // bits/s.
122 uint8_t lossRate,
123 int64_t rtt) override {
Erik Språng08127a92016-11-16 16:41:30 +0100124 return sender_.SetChannelParameters(target_bitrate, lossRate, rtt,
sprang1a646ee2016-12-01 06:34:11 -0800125 rate_allocator_.get(), nullptr);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000126 }
127
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000128 int32_t SetVideoProtection(VCMVideoProtection videoProtection,
129 bool enable) override {
pbosba8c15b2015-07-14 09:36:34 -0700130 // TODO(pbos): Remove enable from receive-side protection modes as well.
pbos0fa9b222015-11-13 05:59:57 -0800131 return receiver_.SetVideoProtection(videoProtection, enable);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000132 }
133
Miguel Casas-Sanchez47650702015-05-29 17:21:40 -0700134 int32_t AddVideoFrame(const VideoFrame& videoFrame,
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000135 const CodecSpecificInfo* codecSpecificInfo) override {
Erik Språngeee39202018-11-15 17:52:43 +0100136 return sender_.AddVideoFrame(videoFrame, codecSpecificInfo, absl::nullopt);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000137 }
138
perkj600246e2016-05-04 11:26:51 -0700139 int32_t IntraFrameRequest(size_t stream_index) override {
pbos0fa9b222015-11-13 05:59:57 -0800140 return sender_.IntraFrameRequest(stream_index);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000141 }
142
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000143 int32_t EnableFrameDropper(bool enable) override {
pbos0fa9b222015-11-13 05:59:57 -0800144 return sender_.EnableFrameDropper(enable);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000145 }
146
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000147 int32_t RegisterReceiveCodec(const VideoCodec* receiveCodec,
148 int32_t numberOfCores,
149 bool requireKeyFrame) override {
pbos0fa9b222015-11-13 05:59:57 -0800150 return receiver_.RegisterReceiveCodec(receiveCodec, numberOfCores,
151 requireKeyFrame);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000152 }
153
Anders Carlsson7eb8e9f2018-05-18 10:33:04 +0200154 void RegisterExternalDecoder(VideoDecoder* externalDecoder,
155 uint8_t payloadType) override {
156 receiver_.RegisterExternalDecoder(externalDecoder, payloadType);
157 }
158
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000159 int32_t RegisterReceiveCallback(
160 VCMReceiveCallback* receiveCallback) override {
tommid0a71ba2017-03-14 04:16:20 -0700161 RTC_DCHECK(construction_thread_.CalledOnValidThread());
pbos0fa9b222015-11-13 05:59:57 -0800162 return receiver_.RegisterReceiveCallback(receiveCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000163 }
164
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000165 int32_t RegisterFrameTypeCallback(
166 VCMFrameTypeCallback* frameTypeCallback) override {
pbos0fa9b222015-11-13 05:59:57 -0800167 return receiver_.RegisterFrameTypeCallback(frameTypeCallback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000168 }
169
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000170 int32_t RegisterPacketRequestCallback(
171 VCMPacketRequestCallback* callback) override {
tommid0a71ba2017-03-14 04:16:20 -0700172 RTC_DCHECK(construction_thread_.CalledOnValidThread());
pbos0fa9b222015-11-13 05:59:57 -0800173 return receiver_.RegisterPacketRequestCallback(callback);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000174 }
175
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000176 int32_t Decode(uint16_t maxWaitTimeMs) override {
pbos0fa9b222015-11-13 05:59:57 -0800177 return receiver_.Decode(maxWaitTimeMs);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000178 }
179
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000180 int32_t IncomingPacket(const uint8_t* incomingPayload,
181 size_t payloadLength,
182 const WebRtcRTPHeader& rtpInfo) override {
pbos0fa9b222015-11-13 05:59:57 -0800183 return receiver_.IncomingPacket(incomingPayload, payloadLength, rtpInfo);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000184 }
185
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000186 int SetReceiverRobustnessMode(ReceiverRobustness robustnessMode,
187 VCMDecodeErrorMode errorMode) override {
pbos0fa9b222015-11-13 05:59:57 -0800188 return receiver_.SetReceiverRobustnessMode(robustnessMode, errorMode);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000189 }
190
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000191 void SetNackSettings(size_t max_nack_list_size,
192 int max_packet_age_to_nack,
193 int max_incomplete_time_ms) override {
pbos0fa9b222015-11-13 05:59:57 -0800194 return receiver_.SetNackSettings(max_nack_list_size, max_packet_age_to_nack,
195 max_incomplete_time_ms);
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000196 }
197
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000198 void RegisterPostEncodeImageCallback(
199 EncodedImageCallback* observer) override {
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +0000200 post_encode_callback_.Register(observer);
sprang@webrtc.org40709352013-11-26 11:41:59 +0000201 }
202
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000203 private:
tommid0a71ba2017-03-14 04:16:20 -0700204 rtc::ThreadChecker construction_thread_;
andresp@webrtc.org1df9dc32014-01-09 08:01:57 +0000205 EncodedImageCallbackWrapper post_encode_callback_;
pbos0fa9b222015-11-13 05:59:57 -0800206 vcm::VideoSender sender_;
Jiawei Ouc2ebe212018-11-08 10:02:56 -0800207 const std::unique_ptr<VideoBitrateAllocatorFactory> rate_allocator_factory_;
Erik Språng08127a92016-11-16 16:41:30 +0100208 std::unique_ptr<VideoBitrateAllocator> rate_allocator_;
Jiawei Ouc2ebe212018-11-08 10:02:56 -0800209 const std::unique_ptr<VCMTiming> timing_;
pbos0fa9b222015-11-13 05:59:57 -0800210 vcm::VideoReceiver receiver_;
andresp@webrtc.orgf7eb75b2013-09-14 00:25:28 +0000211};
212} // namespace
213
tommia5c18d72017-03-20 10:43:23 -0700214// DEPRECATED. Create method for current interface, will be removed when the
philipel83f831a2016-03-12 03:30:23 -0800215// new jitter buffer is in place.
Niels Möller689983f2018-11-07 16:36:22 +0100216VideoCodingModule* VideoCodingModule::Create(Clock* clock) {
tommid0a71ba2017-03-14 04:16:20 -0700217 RTC_DCHECK(clock);
Niels Möllerc4e98252018-11-08 13:08:26 +0100218 return new VideoCodingModuleImpl(clock, nullptr, nullptr);
niklase@google.com470e71d2011-07-07 08:21:25 +0000219}
220
stefan@webrtc.org791eec72011-10-11 07:53:43 +0000221} // namespace webrtc