blob: c37d47b68592714e2c85e488b563810258f98f79 [file] [log] [blame]
Niels Möllerf9063782018-02-20 16:09:48 +01001/*
2 * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
3 *
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
11#include "modules/video_coding/encoder_database.h"
12
13#include "rtc_base/checks.h"
14#include "rtc_base/logging.h"
15
16namespace webrtc {
17
18namespace {
19const size_t kDefaultPayloadSize = 1440;
20}
21
22VCMEncoderDataBase::VCMEncoderDataBase(
23 VCMEncodedFrameCallback* encoded_frame_callback)
24 : number_of_cores_(0),
25 max_payload_size_(kDefaultPayloadSize),
Niels Möllerf9063782018-02-20 16:09:48 +010026 pending_encoder_reset_(true),
27 send_codec_(),
28 encoder_payload_type_(0),
29 external_encoder_(nullptr),
30 internal_source_(false),
31 encoded_frame_callback_(encoded_frame_callback) {}
32
33VCMEncoderDataBase::~VCMEncoderDataBase() {
34 DeleteEncoder();
35}
36
37// Assuming only one registered encoder - since only one used, no need for more.
38bool VCMEncoderDataBase::SetSendCodec(const VideoCodec* send_codec,
39 int number_of_cores,
40 size_t max_payload_size) {
41 RTC_DCHECK(send_codec);
42 if (max_payload_size == 0) {
43 max_payload_size = kDefaultPayloadSize;
44 }
45 RTC_DCHECK_GE(number_of_cores, 1);
46 RTC_DCHECK_GE(send_codec->plType, 1);
47 // Make sure the start bit rate is sane...
48 RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
49 RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown);
50 bool reset_required = pending_encoder_reset_;
51 if (number_of_cores_ != number_of_cores) {
52 number_of_cores_ = number_of_cores;
53 reset_required = true;
54 }
55 if (max_payload_size_ != max_payload_size) {
56 max_payload_size_ = max_payload_size;
57 reset_required = true;
58 }
59
60 VideoCodec new_send_codec;
61 memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
62
63 if (new_send_codec.maxBitrate == 0) {
64 // max is one bit per pixel
65 new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
66 static_cast<int>(send_codec->width) *
67 static_cast<int>(send_codec->maxFramerate)) /
68 1000;
69 if (send_codec->startBitrate > new_send_codec.maxBitrate) {
70 // But if the user tries to set a higher start bit rate we will
71 // increase the max accordingly.
72 new_send_codec.maxBitrate = send_codec->startBitrate;
73 }
74 }
75
76 if (new_send_codec.startBitrate > new_send_codec.maxBitrate)
77 new_send_codec.startBitrate = new_send_codec.maxBitrate;
78
79 if (!reset_required) {
80 reset_required = RequiresEncoderReset(new_send_codec);
81 }
82
83 memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
84
85 if (!reset_required) {
86 return true;
87 }
88
89 // If encoder exists, will destroy it and create new one.
90 DeleteEncoder();
91 RTC_DCHECK_EQ(encoder_payload_type_, send_codec_.plType)
92 << "Encoder not registered for payload type " << send_codec_.plType;
93 ptr_encoder_.reset(new VCMGenericEncoder(
94 external_encoder_, encoded_frame_callback_, internal_source_));
95 encoded_frame_callback_->SetInternalSource(internal_source_);
96 if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
97 max_payload_size_) < 0) {
98 RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
99 DeleteEncoder();
100 return false;
101 }
102
Niels Möllerf9063782018-02-20 16:09:48 +0100103 pending_encoder_reset_ = false;
104
105 return true;
106}
107
108bool VCMEncoderDataBase::DeregisterExternalEncoder(uint8_t payload_type,
109 bool* was_send_codec) {
110 RTC_DCHECK(was_send_codec);
111 *was_send_codec = false;
112 if (encoder_payload_type_ != payload_type) {
113 return false;
114 }
115 if (send_codec_.plType == payload_type) {
116 // De-register as send codec if needed.
117 DeleteEncoder();
118 memset(&send_codec_, 0, sizeof(VideoCodec));
119 *was_send_codec = true;
120 }
121 encoder_payload_type_ = 0;
122 external_encoder_ = nullptr;
123 internal_source_ = false;
124 return true;
125}
126
127void VCMEncoderDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
128 uint8_t payload_type,
129 bool internal_source) {
130 // Since only one encoder can be used at a given time, only one external
131 // encoder can be registered/used.
132 external_encoder_ = external_encoder;
133 encoder_payload_type_ = payload_type;
134 internal_source_ = internal_source;
135 pending_encoder_reset_ = true;
136}
137
138bool VCMEncoderDataBase::RequiresEncoderReset(
139 const VideoCodec& new_send_codec) {
140 if (!ptr_encoder_)
141 return true;
142
143 // Does not check startBitrate or maxFramerate
144 if (new_send_codec.codecType != send_codec_.codecType ||
Niels Möllerf9063782018-02-20 16:09:48 +0100145 new_send_codec.plType != send_codec_.plType ||
146 new_send_codec.width != send_codec_.width ||
147 new_send_codec.height != send_codec_.height ||
148 new_send_codec.maxBitrate != send_codec_.maxBitrate ||
149 new_send_codec.minBitrate != send_codec_.minBitrate ||
150 new_send_codec.qpMax != send_codec_.qpMax ||
151 new_send_codec.numberOfSimulcastStreams !=
152 send_codec_.numberOfSimulcastStreams ||
153 new_send_codec.mode != send_codec_.mode) {
154 return true;
155 }
156
157 switch (new_send_codec.codecType) {
158 case kVideoCodecVP8:
159 if (memcmp(&new_send_codec.VP8(), send_codec_.VP8(),
160 sizeof(new_send_codec.VP8())) != 0) {
161 return true;
162 }
163 break;
164 case kVideoCodecVP9:
165 if (memcmp(&new_send_codec.VP9(), send_codec_.VP9(),
166 sizeof(new_send_codec.VP9())) != 0) {
167 return true;
168 }
169 break;
170 case kVideoCodecH264:
171 if (memcmp(&new_send_codec.H264(), send_codec_.H264(),
172 sizeof(new_send_codec.H264())) != 0) {
173 return true;
174 }
175 break;
176 case kVideoCodecGeneric:
177 break;
178 // Known codecs without payload-specifics
179 case kVideoCodecI420:
180 case kVideoCodecRED:
181 case kVideoCodecULPFEC:
182 case kVideoCodecFlexfec:
183 case kVideoCodecMultiplex:
184 break;
185 // Unknown codec type, reset just to be sure.
186 case kVideoCodecUnknown:
187 return true;
188 }
189
190 if (new_send_codec.numberOfSimulcastStreams > 0) {
191 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
192 ++i) {
193 if (memcmp(&new_send_codec.simulcastStream[i],
194 &send_codec_.simulcastStream[i],
195 sizeof(new_send_codec.simulcastStream[i])) != 0) {
196 return true;
197 }
198 }
199 }
200 return false;
201}
202
203VCMGenericEncoder* VCMEncoderDataBase::GetEncoder() {
204 return ptr_encoder_.get();
205}
206
Niels Möllerf9063782018-02-20 16:09:48 +0100207void VCMEncoderDataBase::DeleteEncoder() {
208 if (!ptr_encoder_)
209 return;
210 ptr_encoder_->Release();
211 ptr_encoder_.reset();
212}
213
214bool VCMEncoderDataBase::MatchesCurrentResolution(int width, int height) const {
215 return send_codec_.width == width && send_codec_.height == height;
216}
217
218} // namespace webrtc