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