blob: 80716df5c11efce7be301dfbc99349b888090754 [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_(),
Niels Möllerf9063782018-02-20 16:09:48 +010028 external_encoder_(nullptr),
29 internal_source_(false),
30 encoded_frame_callback_(encoded_frame_callback) {}
31
32VCMEncoderDataBase::~VCMEncoderDataBase() {
33 DeleteEncoder();
34}
35
36// Assuming only one registered encoder - since only one used, no need for more.
37bool VCMEncoderDataBase::SetSendCodec(const VideoCodec* send_codec,
38 int number_of_cores,
39 size_t max_payload_size) {
40 RTC_DCHECK(send_codec);
41 if (max_payload_size == 0) {
42 max_payload_size = kDefaultPayloadSize;
43 }
44 RTC_DCHECK_GE(number_of_cores, 1);
Niels Möllerf9063782018-02-20 16:09:48 +010045 // Make sure the start bit rate is sane...
46 RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
47 RTC_DCHECK(send_codec->codecType != kVideoCodecUnknown);
48 bool reset_required = pending_encoder_reset_;
49 if (number_of_cores_ != number_of_cores) {
50 number_of_cores_ = number_of_cores;
51 reset_required = true;
52 }
53 if (max_payload_size_ != max_payload_size) {
54 max_payload_size_ = max_payload_size;
55 reset_required = true;
56 }
57
58 VideoCodec new_send_codec;
59 memcpy(&new_send_codec, send_codec, sizeof(new_send_codec));
60
61 if (new_send_codec.maxBitrate == 0) {
62 // max is one bit per pixel
63 new_send_codec.maxBitrate = (static_cast<int>(send_codec->height) *
64 static_cast<int>(send_codec->width) *
65 static_cast<int>(send_codec->maxFramerate)) /
66 1000;
67 if (send_codec->startBitrate > new_send_codec.maxBitrate) {
68 // But if the user tries to set a higher start bit rate we will
69 // increase the max accordingly.
70 new_send_codec.maxBitrate = send_codec->startBitrate;
71 }
72 }
73
74 if (new_send_codec.startBitrate > new_send_codec.maxBitrate)
75 new_send_codec.startBitrate = new_send_codec.maxBitrate;
76
77 if (!reset_required) {
78 reset_required = RequiresEncoderReset(new_send_codec);
79 }
80
81 memcpy(&send_codec_, &new_send_codec, sizeof(send_codec_));
82
83 if (!reset_required) {
84 return true;
85 }
86
87 // If encoder exists, will destroy it and create new one.
88 DeleteEncoder();
Niels Möllerf9063782018-02-20 16:09:48 +010089 ptr_encoder_.reset(new VCMGenericEncoder(
90 external_encoder_, encoded_frame_callback_, internal_source_));
91 encoded_frame_callback_->SetInternalSource(internal_source_);
92 if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
93 max_payload_size_) < 0) {
94 RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
95 DeleteEncoder();
96 return false;
97 }
98
Niels Möllerf9063782018-02-20 16:09:48 +010099 pending_encoder_reset_ = false;
100
101 return true;
102}
103
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100104void VCMEncoderDataBase::DeregisterExternalEncoder() {
105 DeleteEncoder();
106 memset(&send_codec_, 0, sizeof(VideoCodec));
Niels Möllerf9063782018-02-20 16:09:48 +0100107 external_encoder_ = nullptr;
108 internal_source_ = false;
Niels Möllerf9063782018-02-20 16:09:48 +0100109}
110
111void VCMEncoderDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
Niels Möllerf9063782018-02-20 16:09:48 +0100112 bool internal_source) {
113 // Since only one encoder can be used at a given time, only one external
114 // encoder can be registered/used.
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100115 RTC_CHECK(external_encoder_ == nullptr);
Niels Möllerf9063782018-02-20 16:09:48 +0100116 external_encoder_ = external_encoder;
Niels Möllerf9063782018-02-20 16:09:48 +0100117 internal_source_ = internal_source;
118 pending_encoder_reset_ = true;
119}
120
121bool VCMEncoderDataBase::RequiresEncoderReset(
122 const VideoCodec& new_send_codec) {
123 if (!ptr_encoder_)
124 return true;
125
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100126 // Does not check startBitrate, maxFramerate or plType
Niels Möllerf9063782018-02-20 16:09:48 +0100127 if (new_send_codec.codecType != send_codec_.codecType ||
Niels Möllerf9063782018-02-20 16:09:48 +0100128 new_send_codec.width != send_codec_.width ||
129 new_send_codec.height != send_codec_.height ||
130 new_send_codec.maxBitrate != send_codec_.maxBitrate ||
131 new_send_codec.minBitrate != send_codec_.minBitrate ||
132 new_send_codec.qpMax != send_codec_.qpMax ||
133 new_send_codec.numberOfSimulcastStreams !=
134 send_codec_.numberOfSimulcastStreams ||
135 new_send_codec.mode != send_codec_.mode) {
136 return true;
137 }
138
139 switch (new_send_codec.codecType) {
140 case kVideoCodecVP8:
141 if (memcmp(&new_send_codec.VP8(), send_codec_.VP8(),
142 sizeof(new_send_codec.VP8())) != 0) {
143 return true;
144 }
145 break;
146 case kVideoCodecVP9:
147 if (memcmp(&new_send_codec.VP9(), send_codec_.VP9(),
148 sizeof(new_send_codec.VP9())) != 0) {
149 return true;
150 }
151 break;
152 case kVideoCodecH264:
153 if (memcmp(&new_send_codec.H264(), send_codec_.H264(),
154 sizeof(new_send_codec.H264())) != 0) {
155 return true;
156 }
157 break;
158 case kVideoCodecGeneric:
159 break;
160 // Known codecs without payload-specifics
161 case kVideoCodecI420:
162 case kVideoCodecRED:
163 case kVideoCodecULPFEC:
164 case kVideoCodecFlexfec:
165 case kVideoCodecMultiplex:
166 break;
167 // Unknown codec type, reset just to be sure.
168 case kVideoCodecUnknown:
169 return true;
170 }
171
172 if (new_send_codec.numberOfSimulcastStreams > 0) {
173 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams;
174 ++i) {
175 if (memcmp(&new_send_codec.simulcastStream[i],
176 &send_codec_.simulcastStream[i],
177 sizeof(new_send_codec.simulcastStream[i])) != 0) {
178 return true;
179 }
180 }
181 }
182 return false;
183}
184
185VCMGenericEncoder* VCMEncoderDataBase::GetEncoder() {
186 return ptr_encoder_.get();
187}
188
Niels Möllerf9063782018-02-20 16:09:48 +0100189void VCMEncoderDataBase::DeleteEncoder() {
190 if (!ptr_encoder_)
191 return;
192 ptr_encoder_->Release();
193 ptr_encoder_.reset();
194}
195
196bool VCMEncoderDataBase::MatchesCurrentResolution(int width, int height) const {
197 return send_codec_.width == width && send_codec_.height == height;
198}
199
200} // namespace webrtc