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