blob: 0497e3a72ca9d733a939ea27e6b3ab9b636986f3 [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
Yves Gerey3e707812018-11-28 16:47:49 +010013#include <string.h>
14
15#include "common_types.h" // NOLINT(build/include)
Niels Möllerf9063782018-02-20 16:09:48 +010016#include "rtc_base/checks.h"
17#include "rtc_base/logging.h"
18
19namespace webrtc {
20
21namespace {
22const size_t kDefaultPayloadSize = 1440;
23}
24
25VCMEncoderDataBase::VCMEncoderDataBase(
26 VCMEncodedFrameCallback* encoded_frame_callback)
27 : number_of_cores_(0),
28 max_payload_size_(kDefaultPayloadSize),
Niels Möllerf9063782018-02-20 16:09:48 +010029 pending_encoder_reset_(true),
30 send_codec_(),
Niels Möllerf9063782018-02-20 16:09:48 +010031 external_encoder_(nullptr),
32 internal_source_(false),
33 encoded_frame_callback_(encoded_frame_callback) {}
34
35VCMEncoderDataBase::~VCMEncoderDataBase() {
36 DeleteEncoder();
37}
38
39// Assuming only one registered encoder - since only one used, no need for more.
40bool VCMEncoderDataBase::SetSendCodec(const VideoCodec* send_codec,
41 int number_of_cores,
42 size_t max_payload_size) {
43 RTC_DCHECK(send_codec);
44 if (max_payload_size == 0) {
45 max_payload_size = kDefaultPayloadSize;
46 }
47 RTC_DCHECK_GE(number_of_cores, 1);
Niels Möllerf9063782018-02-20 16:09:48 +010048 // Make sure the start bit rate is sane...
49 RTC_DCHECK_LE(send_codec->startBitrate, 1000000);
Niels Möllerf9063782018-02-20 16:09:48 +010050 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();
Niels Möllerf9063782018-02-20 16:09:48 +010091 ptr_encoder_.reset(new VCMGenericEncoder(
92 external_encoder_, encoded_frame_callback_, internal_source_));
93 encoded_frame_callback_->SetInternalSource(internal_source_);
94 if (ptr_encoder_->InitEncode(&send_codec_, number_of_cores_,
95 max_payload_size_) < 0) {
96 RTC_LOG(LS_ERROR) << "Failed to initialize video encoder.";
97 DeleteEncoder();
98 return false;
99 }
100
Niels Möllerf9063782018-02-20 16:09:48 +0100101 pending_encoder_reset_ = false;
102
103 return true;
104}
105
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100106void VCMEncoderDataBase::DeregisterExternalEncoder() {
107 DeleteEncoder();
108 memset(&send_codec_, 0, sizeof(VideoCodec));
Niels Möllerf9063782018-02-20 16:09:48 +0100109 external_encoder_ = nullptr;
110 internal_source_ = false;
Niels Möllerf9063782018-02-20 16:09:48 +0100111}
112
113void VCMEncoderDataBase::RegisterExternalEncoder(VideoEncoder* external_encoder,
Niels Möllerf9063782018-02-20 16:09:48 +0100114 bool internal_source) {
115 // Since only one encoder can be used at a given time, only one external
116 // encoder can be registered/used.
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100117 RTC_CHECK(external_encoder_ == nullptr);
Niels Möllerf9063782018-02-20 16:09:48 +0100118 external_encoder_ = external_encoder;
Niels Möllerf9063782018-02-20 16:09:48 +0100119 internal_source_ = internal_source;
120 pending_encoder_reset_ = true;
121}
122
123bool VCMEncoderDataBase::RequiresEncoderReset(
124 const VideoCodec& new_send_codec) {
125 if (!ptr_encoder_)
126 return true;
127
Niels Möllerbf3dbb42018-03-16 13:38:46 +0100128 // Does not check startBitrate, maxFramerate or plType
Niels Möllerf9063782018-02-20 16:09:48 +0100129 if (new_send_codec.codecType != send_codec_.codecType ||
Niels Möllerf9063782018-02-20 16:09:48 +0100130 new_send_codec.width != send_codec_.width ||
131 new_send_codec.height != send_codec_.height ||
132 new_send_codec.maxBitrate != send_codec_.maxBitrate ||
133 new_send_codec.minBitrate != send_codec_.minBitrate ||
134 new_send_codec.qpMax != send_codec_.qpMax ||
135 new_send_codec.numberOfSimulcastStreams !=
136 send_codec_.numberOfSimulcastStreams ||
137 new_send_codec.mode != send_codec_.mode) {
138 return true;
139 }
140
141 switch (new_send_codec.codecType) {
142 case kVideoCodecVP8:
Niels Möllerdef1ef52018-03-19 13:48:44 +0100143 if (new_send_codec.VP8() != *send_codec_.VP8()) {
Niels Möllerf9063782018-02-20 16:09:48 +0100144 return true;
145 }
146 break;
Niels Möllerdef1ef52018-03-19 13:48:44 +0100147
Niels Möllerf9063782018-02-20 16:09:48 +0100148 case kVideoCodecVP9:
Niels Möllerdef1ef52018-03-19 13:48:44 +0100149 if (new_send_codec.VP9() != *send_codec_.VP9()) {
Niels Möllerf9063782018-02-20 16:09:48 +0100150 return true;
151 }
152 break;
Niels Möllerdef1ef52018-03-19 13:48:44 +0100153
Niels Möllerf9063782018-02-20 16:09:48 +0100154 case kVideoCodecH264:
Niels Möllerdef1ef52018-03-19 13:48:44 +0100155 if (new_send_codec.H264() != *send_codec_.H264()) {
Niels Möllerf9063782018-02-20 16:09:48 +0100156 return true;
157 }
158 break;
Niels Möllerdef1ef52018-03-19 13:48:44 +0100159
Kári Tristan Helgason84ccb2d2018-08-16 14:35:26 +0200160 default:
Niels Möllerf9063782018-02-20 16:09:48 +0100161 break;
Niels Möllerf9063782018-02-20 16:09:48 +0100162 }
163
Niels Möllerdef1ef52018-03-19 13:48:44 +0100164 for (unsigned char i = 0; i < new_send_codec.numberOfSimulcastStreams; ++i) {
165 if (new_send_codec.simulcastStream[i] != send_codec_.simulcastStream[i])
166 return true;
Niels Möllerf9063782018-02-20 16:09:48 +0100167 }
168 return false;
169}
170
171VCMGenericEncoder* VCMEncoderDataBase::GetEncoder() {
172 return ptr_encoder_.get();
173}
174
Niels Möllerf9063782018-02-20 16:09:48 +0100175void VCMEncoderDataBase::DeleteEncoder() {
176 if (!ptr_encoder_)
177 return;
178 ptr_encoder_->Release();
179 ptr_encoder_.reset();
180}
181
182bool VCMEncoderDataBase::MatchesCurrentResolution(int width, int height) const {
183 return send_codec_.width == width && send_codec_.height == height;
184}
185
186} // namespace webrtc