• 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 "webrtc/test/fake_encoder.h"
12 
13 #include "testing/gtest/include/gtest/gtest.h"
14 
15 #include "webrtc/modules/video_coding/include/video_codec_interface.h"
16 #include "webrtc/system_wrappers/include/sleep.h"
17 
18 namespace webrtc {
19 namespace test {
20 
FakeEncoder(Clock * clock)21 FakeEncoder::FakeEncoder(Clock* clock)
22     : clock_(clock),
23       callback_(NULL),
24       target_bitrate_kbps_(0),
25       max_target_bitrate_kbps_(-1),
26       last_encode_time_ms_(0) {
27   // Generate some arbitrary not-all-zero data
28   for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
29     encoded_buffer_[i] = static_cast<uint8_t>(i);
30   }
31 }
32 
~FakeEncoder()33 FakeEncoder::~FakeEncoder() {}
34 
SetMaxBitrate(int max_kbps)35 void FakeEncoder::SetMaxBitrate(int max_kbps) {
36   assert(max_kbps >= -1);  // max_kbps == -1 disables it.
37   max_target_bitrate_kbps_ = max_kbps;
38 }
39 
InitEncode(const VideoCodec * config,int32_t number_of_cores,size_t max_payload_size)40 int32_t FakeEncoder::InitEncode(const VideoCodec* config,
41                                 int32_t number_of_cores,
42                                 size_t max_payload_size) {
43   config_ = *config;
44   target_bitrate_kbps_ = config_.startBitrate;
45   return 0;
46 }
47 
Encode(const VideoFrame & input_image,const CodecSpecificInfo * codec_specific_info,const std::vector<FrameType> * frame_types)48 int32_t FakeEncoder::Encode(const VideoFrame& input_image,
49                             const CodecSpecificInfo* codec_specific_info,
50                             const std::vector<FrameType>* frame_types) {
51   assert(config_.maxFramerate > 0);
52   int64_t time_since_last_encode_ms = 1000 / config_.maxFramerate;
53   int64_t time_now_ms = clock_->TimeInMilliseconds();
54   const bool first_encode = last_encode_time_ms_ == 0;
55   if (!first_encode) {
56     // For all frames but the first we can estimate the display time by looking
57     // at the display time of the previous frame.
58     time_since_last_encode_ms = time_now_ms - last_encode_time_ms_;
59   }
60   if (time_since_last_encode_ms > 3 * 1000 / config_.maxFramerate) {
61     // Rudimentary check to make sure we don't widely overshoot bitrate target
62     // when resuming encoding after a suspension.
63     time_since_last_encode_ms = 3 * 1000 / config_.maxFramerate;
64   }
65 
66   size_t bits_available =
67       static_cast<size_t>(target_bitrate_kbps_ * time_since_last_encode_ms);
68   size_t min_bits = static_cast<size_t>(
69       config_.simulcastStream[0].minBitrate * time_since_last_encode_ms);
70   if (bits_available < min_bits)
71     bits_available = min_bits;
72   size_t max_bits =
73       static_cast<size_t>(max_target_bitrate_kbps_ * time_since_last_encode_ms);
74   if (max_bits > 0 && max_bits < bits_available)
75     bits_available = max_bits;
76   last_encode_time_ms_ = time_now_ms;
77 
78   assert(config_.numberOfSimulcastStreams > 0);
79   for (unsigned char i = 0; i < config_.numberOfSimulcastStreams; ++i) {
80     CodecSpecificInfo specifics;
81     memset(&specifics, 0, sizeof(specifics));
82     specifics.codecType = kVideoCodecGeneric;
83     specifics.codecSpecific.generic.simulcast_idx = i;
84     size_t min_stream_bits = static_cast<size_t>(
85         config_.simulcastStream[i].minBitrate * time_since_last_encode_ms);
86     size_t max_stream_bits = static_cast<size_t>(
87         config_.simulcastStream[i].maxBitrate * time_since_last_encode_ms);
88     size_t stream_bits = (bits_available > max_stream_bits) ? max_stream_bits :
89         bits_available;
90     size_t stream_bytes = (stream_bits + 7) / 8;
91     if (first_encode) {
92       // The first frame is a key frame and should be larger.
93       // TODO(holmer): The FakeEncoder should store the bits_available between
94       // encodes so that it can compensate for oversized frames.
95       stream_bytes *= 10;
96     }
97     if (stream_bytes > sizeof(encoded_buffer_))
98       stream_bytes = sizeof(encoded_buffer_);
99 
100     EncodedImage encoded(
101         encoded_buffer_, stream_bytes, sizeof(encoded_buffer_));
102     encoded._timeStamp = input_image.timestamp();
103     encoded.capture_time_ms_ = input_image.render_time_ms();
104     encoded._frameType = (*frame_types)[i];
105     encoded._encodedWidth = config_.simulcastStream[i].width;
106     encoded._encodedHeight = config_.simulcastStream[i].height;
107     // Always encode something on the first frame.
108     if (min_stream_bits > bits_available && i > 0)
109       continue;
110     assert(callback_ != NULL);
111     if (callback_->Encoded(encoded, &specifics, NULL) != 0)
112       return -1;
113     bits_available -= std::min(encoded._length * 8, bits_available);
114   }
115   return 0;
116 }
117 
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)118 int32_t FakeEncoder::RegisterEncodeCompleteCallback(
119     EncodedImageCallback* callback) {
120   callback_ = callback;
121   return 0;
122 }
123 
Release()124 int32_t FakeEncoder::Release() { return 0; }
125 
SetChannelParameters(uint32_t packet_loss,int64_t rtt)126 int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int64_t rtt) {
127   return 0;
128 }
129 
SetRates(uint32_t new_target_bitrate,uint32_t framerate)130 int32_t FakeEncoder::SetRates(uint32_t new_target_bitrate, uint32_t framerate) {
131   target_bitrate_kbps_ = new_target_bitrate;
132   return 0;
133 }
134 
135 const char* FakeEncoder::kImplementationName = "fake_encoder";
ImplementationName() const136 const char* FakeEncoder::ImplementationName() const {
137   return kImplementationName;
138 }
139 
FakeH264Encoder(Clock * clock)140 FakeH264Encoder::FakeH264Encoder(Clock* clock)
141     : FakeEncoder(clock), callback_(NULL), idr_counter_(0) {
142   FakeEncoder::RegisterEncodeCompleteCallback(this);
143 }
144 
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)145 int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
146     EncodedImageCallback* callback) {
147   callback_ = callback;
148   return 0;
149 }
150 
Encoded(const EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info,const RTPFragmentationHeader * fragments)151 int32_t FakeH264Encoder::Encoded(const EncodedImage& encoded_image,
152                                  const CodecSpecificInfo* codec_specific_info,
153                                  const RTPFragmentationHeader* fragments) {
154   const size_t kSpsSize = 8;
155   const size_t kPpsSize = 11;
156   const int kIdrFrequency = 10;
157   RTPFragmentationHeader fragmentation;
158   if (idr_counter_++ % kIdrFrequency == 0 &&
159       encoded_image._length > kSpsSize + kPpsSize + 1) {
160     const size_t kNumSlices = 3;
161     fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
162     fragmentation.fragmentationOffset[0] = 0;
163     fragmentation.fragmentationLength[0] = kSpsSize;
164     fragmentation.fragmentationOffset[1] = kSpsSize;
165     fragmentation.fragmentationLength[1] = kPpsSize;
166     fragmentation.fragmentationOffset[2] = kSpsSize + kPpsSize;
167     fragmentation.fragmentationLength[2] =
168         encoded_image._length - (kSpsSize + kPpsSize);
169     const size_t kSpsNalHeader = 0x67;
170     const size_t kPpsNalHeader = 0x68;
171     const size_t kIdrNalHeader = 0x65;
172     encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kSpsNalHeader;
173     encoded_image._buffer[fragmentation.fragmentationOffset[1]] = kPpsNalHeader;
174     encoded_image._buffer[fragmentation.fragmentationOffset[2]] = kIdrNalHeader;
175   } else {
176     const size_t kNumSlices = 1;
177     fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
178     fragmentation.fragmentationOffset[0] = 0;
179     fragmentation.fragmentationLength[0] = encoded_image._length;
180     const size_t kNalHeader = 0x41;
181     encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kNalHeader;
182   }
183   uint8_t value = 0;
184   int fragment_counter = 0;
185   for (size_t i = 0; i < encoded_image._length; ++i) {
186     if (fragment_counter == fragmentation.fragmentationVectorSize ||
187         i != fragmentation.fragmentationOffset[fragment_counter]) {
188       encoded_image._buffer[i] = value++;
189     } else {
190       ++fragment_counter;
191     }
192   }
193   return callback_->Encoded(encoded_image, NULL, &fragmentation);
194 }
195 
DelayedEncoder(Clock * clock,int delay_ms)196 DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms)
197     : test::FakeEncoder(clock),
198       delay_ms_(delay_ms) {}
199 
Encode(const VideoFrame & input_image,const CodecSpecificInfo * codec_specific_info,const std::vector<FrameType> * frame_types)200 int32_t DelayedEncoder::Encode(const VideoFrame& input_image,
201                                const CodecSpecificInfo* codec_specific_info,
202                                const std::vector<FrameType>* frame_types) {
203   SleepMs(delay_ms_);
204   return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
205 }
206 }  // namespace test
207 }  // namespace webrtc
208