• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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