summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/test/fake_encoder.h
blob: b804f2ce35a923bfad77835b640d64900777dce3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
 *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#ifndef TEST_FAKE_ENCODER_H_
#define TEST_FAKE_ENCODER_H_

#include <stddef.h>
#include <stdint.h>

#include <memory>
#include <vector>

#include "absl/strings/string_view.h"
#include "api/fec_controller_override.h"
#include "api/sequence_checker.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/video/encoded_image.h"
#include "api/video/video_bitrate_allocation.h"
#include "api/video/video_frame.h"
#include "api/video_codecs/video_codec.h"
#include "api/video_codecs/video_encoder.h"
#include "modules/video_coding/include/video_codec_interface.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"

namespace webrtc {
namespace test {

class FakeEncoder : public VideoEncoder {
 public:
  explicit FakeEncoder(Clock* clock);
  virtual ~FakeEncoder() = default;

  // Sets max bitrate. Not thread-safe, call before registering the encoder.
  void SetMaxBitrate(int max_kbps) RTC_LOCKS_EXCLUDED(mutex_);
  void SetQp(int qp) RTC_LOCKS_EXCLUDED(mutex_);

  void SetImplementationName(absl::string_view implementation_name)
      RTC_LOCKS_EXCLUDED(mutex_);

  void SetFecControllerOverride(
      FecControllerOverride* fec_controller_override) override;

  int32_t InitEncode(const VideoCodec* config, const Settings& settings)
      RTC_LOCKS_EXCLUDED(mutex_) override;
  int32_t Encode(const VideoFrame& input_image,
                 const std::vector<VideoFrameType>* frame_types)
      RTC_LOCKS_EXCLUDED(mutex_) override;
  int32_t RegisterEncodeCompleteCallback(EncodedImageCallback* callback)
      RTC_LOCKS_EXCLUDED(mutex_) override;
  int32_t Release() override;
  void SetRates(const RateControlParameters& parameters)
      RTC_LOCKS_EXCLUDED(mutex_) override;
  EncoderInfo GetEncoderInfo() const RTC_LOCKS_EXCLUDED(mutex_) override;

  int GetConfiguredInputFramerate() const RTC_LOCKS_EXCLUDED(mutex_);
  int GetNumInitializations() const RTC_LOCKS_EXCLUDED(mutex_);
  const VideoCodec& config() const RTC_LOCKS_EXCLUDED(mutex_);

  static constexpr char kImplementationName[] = "fake_encoder";

 protected:
  struct FrameInfo {
    bool keyframe;
    struct SpatialLayer {
      SpatialLayer() = default;
      SpatialLayer(int size, int temporal_id)
          : size(size), temporal_id(temporal_id) {}
      // Size of a current frame in the layer.
      int size = 0;
      // Temporal index of a current frame in the layer.
      int temporal_id = 0;
    };
    std::vector<SpatialLayer> layers;
  };

  FrameInfo NextFrame(const std::vector<VideoFrameType>* frame_types,
                      bool keyframe,
                      uint8_t num_simulcast_streams,
                      const VideoBitrateAllocation& target_bitrate,
                      SimulcastStream simulcast_streams[kMaxSimulcastStreams],
                      int framerate) RTC_LOCKS_EXCLUDED(mutex_);

  // Called before the frame is passed to callback_->OnEncodedImage, to let
  // subclasses fill out CodecSpecificInfo, possibly modify `encoded_image` or
  // `buffer`.
  virtual CodecSpecificInfo EncodeHook(
      EncodedImage& encoded_image,
      rtc::scoped_refptr<EncodedImageBuffer> buffer);

  void SetRatesLocked(const RateControlParameters& parameters)
      RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);

  FrameInfo last_frame_info_ RTC_GUARDED_BY(mutex_);
  Clock* const clock_;

  VideoCodec config_ RTC_GUARDED_BY(mutex_);
  int num_initializations_ RTC_GUARDED_BY(mutex_);
  EncodedImageCallback* callback_ RTC_GUARDED_BY(mutex_);
  RateControlParameters current_rate_settings_ RTC_GUARDED_BY(mutex_);
  int max_target_bitrate_kbps_ RTC_GUARDED_BY(mutex_);
  bool pending_keyframe_ RTC_GUARDED_BY(mutex_);
  uint32_t counter_ RTC_GUARDED_BY(mutex_);
  mutable Mutex mutex_;
  bool used_layers_[kMaxSimulcastStreams];
  absl::optional<int> qp_ RTC_GUARDED_BY(mutex_);
  absl::optional<std::string> implementation_name_ RTC_GUARDED_BY(mutex_);

  // Current byte debt to be payed over a number of frames.
  // The debt is acquired by keyframes overshooting the bitrate target.
  size_t debt_bytes_;
};

class FakeH264Encoder : public FakeEncoder {
 public:
  explicit FakeH264Encoder(Clock* clock);
  virtual ~FakeH264Encoder() = default;

 private:
  CodecSpecificInfo EncodeHook(
      EncodedImage& encoded_image,
      rtc::scoped_refptr<EncodedImageBuffer> buffer) override;

  int idr_counter_ RTC_GUARDED_BY(local_mutex_);
  Mutex local_mutex_;
};

class DelayedEncoder : public test::FakeEncoder {
 public:
  DelayedEncoder(Clock* clock, int delay_ms);
  virtual ~DelayedEncoder() = default;

  void SetDelay(int delay_ms);
  int32_t Encode(const VideoFrame& input_image,
                 const std::vector<VideoFrameType>* frame_types) override;

 private:
  int delay_ms_ RTC_GUARDED_BY(sequence_checker_);
  SequenceChecker sequence_checker_;
};

// This class implements a multi-threaded fake encoder by posting
// FakeH264Encoder::Encode(.) tasks to `queue1_` and `queue2_`, in an
// alternating fashion. The class itself does not need to be thread safe,
// as it is called from the task queue in VideoStreamEncoder.
class MultithreadedFakeH264Encoder : public test::FakeH264Encoder {
 public:
  MultithreadedFakeH264Encoder(Clock* clock,
                               TaskQueueFactory* task_queue_factory);
  virtual ~MultithreadedFakeH264Encoder() = default;

  int32_t InitEncode(const VideoCodec* config,
                     const Settings& settings) override;

  int32_t Encode(const VideoFrame& input_image,
                 const std::vector<VideoFrameType>* frame_types) override;

  int32_t EncodeCallback(const VideoFrame& input_image,
                         const std::vector<VideoFrameType>* frame_types);

  int32_t Release() override;

 protected:
  TaskQueueFactory* const task_queue_factory_;
  int current_queue_ RTC_GUARDED_BY(sequence_checker_);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> queue1_
      RTC_GUARDED_BY(sequence_checker_);
  std::unique_ptr<TaskQueueBase, TaskQueueDeleter> queue2_
      RTC_GUARDED_BY(sequence_checker_);
  SequenceChecker sequence_checker_;
};

}  // namespace test
}  // namespace webrtc

#endif  // TEST_FAKE_ENCODER_H_