1 /*
2 * Copyright (c) 2013 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 "test/fake_encoder.h"
12
13 #include <string.h>
14
15 #include <algorithm>
16 #include <cstdint>
17 #include <memory>
18 #include <string>
19
20 #include "api/video/video_content_type.h"
21 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
22 #include "modules/video_coding/include/video_codec_interface.h"
23 #include "modules/video_coding/include/video_error_codes.h"
24 #include "rtc_base/checks.h"
25 #include "system_wrappers/include/sleep.h"
26
27 namespace webrtc {
28 namespace test {
29 namespace {
30 const int kKeyframeSizeFactor = 5;
31
32 // Inverse of proportion of frames assigned to each temporal layer for all
33 // possible temporal layers numbers.
34 const int kTemporalLayerRateFactor[4][4] = {
35 {1, 0, 0, 0}, // 1/1
36 {2, 2, 0, 0}, // 1/2 + 1/2
37 {4, 4, 2, 0}, // 1/4 + 1/4 + 1/2
38 {8, 8, 4, 2}, // 1/8 + 1/8 + 1/4 + 1/2
39 };
40
WriteCounter(unsigned char * payload,uint32_t counter)41 void WriteCounter(unsigned char* payload, uint32_t counter) {
42 payload[0] = (counter & 0x00FF);
43 payload[1] = (counter & 0xFF00) >> 8;
44 payload[2] = (counter & 0xFF0000) >> 16;
45 payload[3] = (counter & 0xFF000000) >> 24;
46 }
47
48 } // namespace
49
FakeEncoder(Clock * clock)50 FakeEncoder::FakeEncoder(Clock* clock)
51 : clock_(clock),
52 num_initializations_(0),
53 callback_(nullptr),
54 max_target_bitrate_kbps_(-1),
55 pending_keyframe_(true),
56 counter_(0),
57 debt_bytes_(0) {
58 for (bool& used : used_layers_) {
59 used = false;
60 }
61 }
62
SetFecControllerOverride(FecControllerOverride * fec_controller_override)63 void FakeEncoder::SetFecControllerOverride(
64 FecControllerOverride* fec_controller_override) {
65 // Ignored.
66 }
67
SetMaxBitrate(int max_kbps)68 void FakeEncoder::SetMaxBitrate(int max_kbps) {
69 RTC_DCHECK_GE(max_kbps, -1); // max_kbps == -1 disables it.
70 MutexLock lock(&mutex_);
71 max_target_bitrate_kbps_ = max_kbps;
72 SetRatesLocked(current_rate_settings_);
73 }
74
SetQp(int qp)75 void FakeEncoder::SetQp(int qp) {
76 MutexLock lock(&mutex_);
77 qp_ = qp;
78 }
79
InitEncode(const VideoCodec * config,const Settings & settings)80 int32_t FakeEncoder::InitEncode(const VideoCodec* config,
81 const Settings& settings) {
82 MutexLock lock(&mutex_);
83 config_ = *config;
84 ++num_initializations_;
85 current_rate_settings_.bitrate.SetBitrate(0, 0, config_.startBitrate * 1000);
86 current_rate_settings_.framerate_fps = config_.maxFramerate;
87 pending_keyframe_ = true;
88 last_frame_info_ = FrameInfo();
89 return 0;
90 }
91
Encode(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)92 int32_t FakeEncoder::Encode(const VideoFrame& input_image,
93 const std::vector<VideoFrameType>* frame_types) {
94 unsigned char max_framerate;
95 unsigned char num_simulcast_streams;
96 SimulcastStream simulcast_streams[kMaxSimulcastStreams];
97 EncodedImageCallback* callback;
98 RateControlParameters rates;
99 bool keyframe;
100 uint32_t counter;
101 absl::optional<int> qp;
102 {
103 MutexLock lock(&mutex_);
104 max_framerate = config_.maxFramerate;
105 num_simulcast_streams = config_.numberOfSimulcastStreams;
106 for (int i = 0; i < num_simulcast_streams; ++i) {
107 simulcast_streams[i] = config_.simulcastStream[i];
108 }
109 callback = callback_;
110 rates = current_rate_settings_;
111 if (rates.framerate_fps <= 0.0) {
112 rates.framerate_fps = max_framerate;
113 }
114 keyframe = pending_keyframe_;
115 pending_keyframe_ = false;
116 counter = counter_++;
117 qp = qp_;
118 }
119
120 FrameInfo frame_info =
121 NextFrame(frame_types, keyframe, num_simulcast_streams, rates.bitrate,
122 simulcast_streams, static_cast<int>(rates.framerate_fps + 0.5));
123 for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
124 constexpr int kMinPayLoadLength = 14;
125 if (frame_info.layers[i].size < kMinPayLoadLength) {
126 // Drop this temporal layer.
127 continue;
128 }
129
130 auto buffer = EncodedImageBuffer::Create(frame_info.layers[i].size);
131 // Fill the buffer with arbitrary data. Write someting to make Asan happy.
132 memset(buffer->data(), 9, frame_info.layers[i].size);
133 // Write a counter to the image to make each frame unique.
134 WriteCounter(buffer->data() + frame_info.layers[i].size - 4, counter);
135
136 EncodedImage encoded;
137 encoded.SetEncodedData(buffer);
138
139 encoded.SetTimestamp(input_image.timestamp());
140 encoded._frameType = frame_info.keyframe ? VideoFrameType::kVideoFrameKey
141 : VideoFrameType::kVideoFrameDelta;
142 encoded._encodedWidth = simulcast_streams[i].width;
143 encoded._encodedHeight = simulcast_streams[i].height;
144 if (qp)
145 encoded.qp_ = *qp;
146 encoded.SetSpatialIndex(i);
147 CodecSpecificInfo codec_specific = EncodeHook(encoded, buffer);
148
149 if (callback->OnEncodedImage(encoded, &codec_specific).error !=
150 EncodedImageCallback::Result::OK) {
151 return -1;
152 }
153 }
154 return 0;
155 }
156
EncodeHook(EncodedImage & encoded_image,rtc::scoped_refptr<EncodedImageBuffer> buffer)157 CodecSpecificInfo FakeEncoder::EncodeHook(
158 EncodedImage& encoded_image,
159 rtc::scoped_refptr<EncodedImageBuffer> buffer) {
160 CodecSpecificInfo codec_specific;
161 codec_specific.codecType = kVideoCodecGeneric;
162 return codec_specific;
163 }
164
NextFrame(const std::vector<VideoFrameType> * frame_types,bool keyframe,uint8_t num_simulcast_streams,const VideoBitrateAllocation & target_bitrate,SimulcastStream simulcast_streams[kMaxSimulcastStreams],int framerate)165 FakeEncoder::FrameInfo FakeEncoder::NextFrame(
166 const std::vector<VideoFrameType>* frame_types,
167 bool keyframe,
168 uint8_t num_simulcast_streams,
169 const VideoBitrateAllocation& target_bitrate,
170 SimulcastStream simulcast_streams[kMaxSimulcastStreams],
171 int framerate) {
172 FrameInfo frame_info;
173 frame_info.keyframe = keyframe;
174
175 if (frame_types) {
176 for (VideoFrameType frame_type : *frame_types) {
177 if (frame_type == VideoFrameType::kVideoFrameKey) {
178 frame_info.keyframe = true;
179 break;
180 }
181 }
182 }
183
184 MutexLock lock(&mutex_);
185 for (uint8_t i = 0; i < num_simulcast_streams; ++i) {
186 if (target_bitrate.GetBitrate(i, 0) > 0) {
187 int temporal_id = last_frame_info_.layers.size() > i
188 ? ++last_frame_info_.layers[i].temporal_id %
189 simulcast_streams[i].numberOfTemporalLayers
190 : 0;
191 frame_info.layers.emplace_back(0, temporal_id);
192 }
193 }
194
195 if (last_frame_info_.layers.size() < frame_info.layers.size()) {
196 // A new keyframe is needed since a new layer will be added.
197 frame_info.keyframe = true;
198 }
199
200 for (uint8_t i = 0; i < frame_info.layers.size(); ++i) {
201 FrameInfo::SpatialLayer& layer_info = frame_info.layers[i];
202 if (frame_info.keyframe) {
203 layer_info.temporal_id = 0;
204 size_t avg_frame_size =
205 (target_bitrate.GetBitrate(i, 0) + 7) *
206 kTemporalLayerRateFactor[frame_info.layers.size() - 1][i] /
207 (8 * framerate);
208
209 // The first frame is a key frame and should be larger.
210 // Store the overshoot bytes and distribute them over the coming frames,
211 // so that we on average meet the bitrate target.
212 debt_bytes_ += (kKeyframeSizeFactor - 1) * avg_frame_size;
213 layer_info.size = kKeyframeSizeFactor * avg_frame_size;
214 } else {
215 size_t avg_frame_size =
216 (target_bitrate.GetBitrate(i, layer_info.temporal_id) + 7) *
217 kTemporalLayerRateFactor[frame_info.layers.size() - 1][i] /
218 (8 * framerate);
219 layer_info.size = avg_frame_size;
220 if (debt_bytes_ > 0) {
221 // Pay at most half of the frame size for old debts.
222 size_t payment_size = std::min(avg_frame_size / 2, debt_bytes_);
223 debt_bytes_ -= payment_size;
224 layer_info.size -= payment_size;
225 }
226 }
227 }
228 last_frame_info_ = frame_info;
229 return frame_info;
230 }
231
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)232 int32_t FakeEncoder::RegisterEncodeCompleteCallback(
233 EncodedImageCallback* callback) {
234 MutexLock lock(&mutex_);
235 callback_ = callback;
236 return 0;
237 }
238
Release()239 int32_t FakeEncoder::Release() {
240 return 0;
241 }
242
SetRates(const RateControlParameters & parameters)243 void FakeEncoder::SetRates(const RateControlParameters& parameters) {
244 MutexLock lock(&mutex_);
245 SetRatesLocked(parameters);
246 }
247
SetRatesLocked(const RateControlParameters & parameters)248 void FakeEncoder::SetRatesLocked(const RateControlParameters& parameters) {
249 current_rate_settings_ = parameters;
250 int allocated_bitrate_kbps = parameters.bitrate.get_sum_kbps();
251
252 // Scale bitrate allocation to not exceed the given max target bitrate.
253 if (max_target_bitrate_kbps_ > 0 &&
254 allocated_bitrate_kbps > max_target_bitrate_kbps_) {
255 for (uint8_t spatial_idx = 0; spatial_idx < kMaxSpatialLayers;
256 ++spatial_idx) {
257 for (uint8_t temporal_idx = 0; temporal_idx < kMaxTemporalStreams;
258 ++temporal_idx) {
259 if (current_rate_settings_.bitrate.HasBitrate(spatial_idx,
260 temporal_idx)) {
261 uint32_t bitrate = current_rate_settings_.bitrate.GetBitrate(
262 spatial_idx, temporal_idx);
263 bitrate = static_cast<uint32_t>(
264 (bitrate * int64_t{max_target_bitrate_kbps_}) /
265 allocated_bitrate_kbps);
266 current_rate_settings_.bitrate.SetBitrate(spatial_idx, temporal_idx,
267 bitrate);
268 }
269 }
270 }
271 }
272 }
273
274 const char* FakeEncoder::kImplementationName = "fake_encoder";
GetEncoderInfo() const275 VideoEncoder::EncoderInfo FakeEncoder::GetEncoderInfo() const {
276 EncoderInfo info;
277 info.implementation_name = kImplementationName;
278 info.is_hardware_accelerated = true;
279 MutexLock lock(&mutex_);
280 for (int sid = 0; sid < config_.numberOfSimulcastStreams; ++sid) {
281 int number_of_temporal_layers =
282 config_.simulcastStream[sid].numberOfTemporalLayers;
283 info.fps_allocation[sid].clear();
284 for (int tid = 0; tid < number_of_temporal_layers; ++tid) {
285 // {1/4, 1/2, 1} allocation for num layers = 3.
286 info.fps_allocation[sid].push_back(255 /
287 (number_of_temporal_layers - tid));
288 }
289 }
290 return info;
291 }
292
GetConfiguredInputFramerate() const293 int FakeEncoder::GetConfiguredInputFramerate() const {
294 MutexLock lock(&mutex_);
295 return static_cast<int>(current_rate_settings_.framerate_fps + 0.5);
296 }
297
GetNumInitializations() const298 int FakeEncoder::GetNumInitializations() const {
299 MutexLock lock(&mutex_);
300 return num_initializations_;
301 }
302
config() const303 const VideoCodec& FakeEncoder::config() const {
304 MutexLock lock(&mutex_);
305 return config_;
306 }
307
FakeH264Encoder(Clock * clock)308 FakeH264Encoder::FakeH264Encoder(Clock* clock)
309 : FakeEncoder(clock), idr_counter_(0) {}
310
EncodeHook(EncodedImage & encoded_image,rtc::scoped_refptr<EncodedImageBuffer> buffer)311 CodecSpecificInfo FakeH264Encoder::EncodeHook(
312 EncodedImage& encoded_image,
313 rtc::scoped_refptr<EncodedImageBuffer> buffer) {
314 static constexpr std::array<uint8_t, 3> kStartCode = {0, 0, 1};
315 const size_t kSpsSize = 8;
316 const size_t kPpsSize = 11;
317 const int kIdrFrequency = 10;
318 int current_idr_counter;
319 {
320 MutexLock lock(&local_mutex_);
321 current_idr_counter = idr_counter_;
322 ++idr_counter_;
323 }
324 for (size_t i = 0; i < encoded_image.size(); ++i) {
325 buffer->data()[i] = static_cast<uint8_t>(i);
326 }
327
328 if (current_idr_counter % kIdrFrequency == 0 &&
329 encoded_image.size() > kSpsSize + kPpsSize + 1 + 3 * kStartCode.size()) {
330 const size_t kSpsNalHeader = 0x67;
331 const size_t kPpsNalHeader = 0x68;
332 const size_t kIdrNalHeader = 0x65;
333 uint8_t* data = buffer->data();
334 memcpy(data, kStartCode.data(), kStartCode.size());
335 data += kStartCode.size();
336 data[0] = kSpsNalHeader;
337 data += kSpsSize;
338
339 memcpy(data, kStartCode.data(), kStartCode.size());
340 data += kStartCode.size();
341 data[0] = kPpsNalHeader;
342 data += kPpsSize;
343
344 memcpy(data, kStartCode.data(), kStartCode.size());
345 data += kStartCode.size();
346 data[0] = kIdrNalHeader;
347 } else {
348 memcpy(buffer->data(), kStartCode.data(), kStartCode.size());
349 const size_t kNalHeader = 0x41;
350 buffer->data()[kStartCode.size()] = kNalHeader;
351 }
352
353 CodecSpecificInfo codec_specific;
354 codec_specific.codecType = kVideoCodecH264;
355 codec_specific.codecSpecific.H264.packetization_mode =
356 H264PacketizationMode::NonInterleaved;
357 return codec_specific;
358 }
359
DelayedEncoder(Clock * clock,int delay_ms)360 DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms)
361 : test::FakeEncoder(clock), delay_ms_(delay_ms) {
362 // The encoder could be created on a different thread than
363 // it is being used on.
364 sequence_checker_.Detach();
365 }
366
SetDelay(int delay_ms)367 void DelayedEncoder::SetDelay(int delay_ms) {
368 RTC_DCHECK_RUN_ON(&sequence_checker_);
369 delay_ms_ = delay_ms;
370 }
371
Encode(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)372 int32_t DelayedEncoder::Encode(const VideoFrame& input_image,
373 const std::vector<VideoFrameType>* frame_types) {
374 RTC_DCHECK_RUN_ON(&sequence_checker_);
375
376 SleepMs(delay_ms_);
377
378 return FakeEncoder::Encode(input_image, frame_types);
379 }
380
MultithreadedFakeH264Encoder(Clock * clock,TaskQueueFactory * task_queue_factory)381 MultithreadedFakeH264Encoder::MultithreadedFakeH264Encoder(
382 Clock* clock,
383 TaskQueueFactory* task_queue_factory)
384 : test::FakeH264Encoder(clock),
385 task_queue_factory_(task_queue_factory),
386 current_queue_(0),
387 queue1_(nullptr),
388 queue2_(nullptr) {
389 // The encoder could be created on a different thread than
390 // it is being used on.
391 sequence_checker_.Detach();
392 }
393
InitEncode(const VideoCodec * config,const Settings & settings)394 int32_t MultithreadedFakeH264Encoder::InitEncode(const VideoCodec* config,
395 const Settings& settings) {
396 RTC_DCHECK_RUN_ON(&sequence_checker_);
397
398 queue1_ = task_queue_factory_->CreateTaskQueue(
399 "Queue 1", TaskQueueFactory::Priority::NORMAL);
400 queue2_ = task_queue_factory_->CreateTaskQueue(
401 "Queue 2", TaskQueueFactory::Priority::NORMAL);
402
403 return FakeH264Encoder::InitEncode(config, settings);
404 }
405
Encode(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)406 int32_t MultithreadedFakeH264Encoder::Encode(
407 const VideoFrame& input_image,
408 const std::vector<VideoFrameType>* frame_types) {
409 RTC_DCHECK_RUN_ON(&sequence_checker_);
410
411 TaskQueueBase* queue =
412 (current_queue_++ % 2 == 0) ? queue1_.get() : queue2_.get();
413
414 if (!queue) {
415 return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
416 }
417
418 queue->PostTask([this, input_image, frame_types = *frame_types] {
419 EncodeCallback(input_image, &frame_types);
420 });
421
422 return WEBRTC_VIDEO_CODEC_OK;
423 }
424
EncodeCallback(const VideoFrame & input_image,const std::vector<VideoFrameType> * frame_types)425 int32_t MultithreadedFakeH264Encoder::EncodeCallback(
426 const VideoFrame& input_image,
427 const std::vector<VideoFrameType>* frame_types) {
428 return FakeH264Encoder::Encode(input_image, frame_types);
429 }
430
Release()431 int32_t MultithreadedFakeH264Encoder::Release() {
432 RTC_DCHECK_RUN_ON(&sequence_checker_);
433
434 queue1_.reset();
435 queue2_.reset();
436
437 return FakeH264Encoder::Release();
438 }
439
440 } // namespace test
441 } // namespace webrtc
442