• 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/codecs/interface/video_codec_interface.h"
16 
17 namespace webrtc {
18 namespace test {
19 
FakeEncoder(Clock * clock)20 FakeEncoder::FakeEncoder(Clock* clock)
21     : clock_(clock),
22       callback_(NULL),
23       target_bitrate_kbps_(0),
24       max_target_bitrate_kbps_(-1),
25       last_encode_time_ms_(0) {
26   // Generate some arbitrary not-all-zero data
27   for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
28     encoded_buffer_[i] = static_cast<uint8_t>(i);
29   }
30 }
31 
~FakeEncoder()32 FakeEncoder::~FakeEncoder() {}
33 
SetMaxBitrate(int max_kbps)34 void FakeEncoder::SetMaxBitrate(int max_kbps) {
35   assert(max_kbps >= -1);  // max_kbps == -1 disables it.
36   max_target_bitrate_kbps_ = max_kbps;
37 }
38 
InitEncode(const VideoCodec * config,int32_t number_of_cores,uint32_t max_payload_size)39 int32_t FakeEncoder::InitEncode(const VideoCodec* config,
40                                 int32_t number_of_cores,
41                                 uint32_t max_payload_size) {
42   config_ = *config;
43   target_bitrate_kbps_ = config_.startBitrate;
44   return 0;
45 }
46 
Encode(const I420VideoFrame & input_image,const CodecSpecificInfo * codec_specific_info,const std::vector<VideoFrameType> * frame_types)47 int32_t FakeEncoder::Encode(
48     const I420VideoFrame& input_image,
49     const CodecSpecificInfo* codec_specific_info,
50     const std::vector<VideoFrameType>* frame_types) {
51   assert(config_.maxFramerate > 0);
52   int time_since_last_encode_ms = 1000 / config_.maxFramerate;
53   int64_t time_now_ms = clock_->TimeInMilliseconds();
54   if (last_encode_time_ms_ > 0) {
55     // For all frames but the first we can estimate the display time by looking
56     // at the display time of the previous frame.
57     time_since_last_encode_ms = time_now_ms - last_encode_time_ms_;
58   }
59 
60   int bits_available = target_bitrate_kbps_ * time_since_last_encode_ms;
61   int min_bits =
62       config_.simulcastStream[0].minBitrate * time_since_last_encode_ms;
63   if (bits_available < min_bits)
64     bits_available = min_bits;
65   int max_bits = max_target_bitrate_kbps_ * time_since_last_encode_ms;
66   if (max_bits > 0 && max_bits < bits_available)
67     bits_available = max_bits;
68   last_encode_time_ms_ = time_now_ms;
69 
70   assert(config_.numberOfSimulcastStreams > 0);
71   for (int i = 0; i < config_.numberOfSimulcastStreams; ++i) {
72     CodecSpecificInfo specifics;
73     memset(&specifics, 0, sizeof(specifics));
74     specifics.codecType = kVideoCodecGeneric;
75     specifics.codecSpecific.generic.simulcast_idx = i;
76     int min_stream_bits =
77         config_.simulcastStream[i].minBitrate * time_since_last_encode_ms;
78     int max_stream_bits =
79         config_.simulcastStream[i].maxBitrate * time_since_last_encode_ms;
80     int stream_bits = (bits_available > max_stream_bits) ? max_stream_bits :
81         bits_available;
82     int stream_bytes = (stream_bits + 7) / 8;
83     if (static_cast<size_t>(stream_bytes) > sizeof(encoded_buffer_))
84       stream_bytes = sizeof(encoded_buffer_);
85 
86     EncodedImage encoded(
87         encoded_buffer_, stream_bytes, sizeof(encoded_buffer_));
88     encoded._timeStamp = input_image.timestamp();
89     encoded.capture_time_ms_ = input_image.render_time_ms();
90     encoded._frameType = (*frame_types)[i];
91     // Always encode something on the first frame.
92     if (min_stream_bits > bits_available && i > 0) {
93       encoded._length = 0;
94       encoded._frameType = kSkipFrame;
95     }
96     assert(callback_ != NULL);
97     if (callback_->Encoded(encoded, &specifics, NULL) != 0)
98       return -1;
99 
100     bits_available -= encoded._length * 8;
101   }
102   return 0;
103 }
104 
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)105 int32_t FakeEncoder::RegisterEncodeCompleteCallback(
106     EncodedImageCallback* callback) {
107   callback_ = callback;
108   return 0;
109 }
110 
Release()111 int32_t FakeEncoder::Release() { return 0; }
112 
SetChannelParameters(uint32_t packet_loss,int rtt)113 int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
114   return 0;
115 }
116 
SetRates(uint32_t new_target_bitrate,uint32_t framerate)117 int32_t FakeEncoder::SetRates(uint32_t new_target_bitrate, uint32_t framerate) {
118   target_bitrate_kbps_ = new_target_bitrate;
119   return 0;
120 }
121 
FakeH264Encoder(Clock * clock)122 FakeH264Encoder::FakeH264Encoder(Clock* clock)
123     : FakeEncoder(clock), callback_(NULL), idr_counter_(0) {
124   FakeEncoder::RegisterEncodeCompleteCallback(this);
125 }
126 
RegisterEncodeCompleteCallback(EncodedImageCallback * callback)127 int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
128     EncodedImageCallback* callback) {
129   callback_ = callback;
130   return 0;
131 }
132 
Encoded(EncodedImage & encoded_image,const CodecSpecificInfo * codec_specific_info,const RTPFragmentationHeader * fragments)133 int32_t FakeH264Encoder::Encoded(EncodedImage& encoded_image,
134                                  const CodecSpecificInfo* codec_specific_info,
135                                  const RTPFragmentationHeader* fragments) {
136   const size_t kSpsSize = 8;
137   const size_t kPpsSize = 11;
138   const int kIdrFrequency = 10;
139   RTPFragmentationHeader fragmentation;
140   if (idr_counter_++ % kIdrFrequency == 0 &&
141       encoded_image._length > kSpsSize + kPpsSize + 1) {
142     const size_t kNumSlices = 3;
143     fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
144     fragmentation.fragmentationOffset[0] = 0;
145     fragmentation.fragmentationLength[0] = kSpsSize;
146     fragmentation.fragmentationOffset[1] = kSpsSize;
147     fragmentation.fragmentationLength[1] = kPpsSize;
148     fragmentation.fragmentationOffset[2] = kSpsSize + kPpsSize;
149     fragmentation.fragmentationLength[2] =
150         encoded_image._length - (kSpsSize + kPpsSize);
151     const uint8_t kSpsNalHeader = 0x37;
152     const uint8_t kPpsNalHeader = 0x38;
153     const uint8_t kIdrNalHeader = 0x15;
154     encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kSpsNalHeader;
155     encoded_image._buffer[fragmentation.fragmentationOffset[1]] = kPpsNalHeader;
156     encoded_image._buffer[fragmentation.fragmentationOffset[2]] = kIdrNalHeader;
157   } else {
158     const size_t kNumSlices = 1;
159     fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
160     fragmentation.fragmentationOffset[0] = 0;
161     fragmentation.fragmentationLength[0] = encoded_image._length;
162     const uint8_t kNalHeader = 0x11;
163     encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kNalHeader;
164   }
165   uint8_t value = 0;
166   int fragment_counter = 0;
167   for (size_t i = 0; i < encoded_image._length; ++i) {
168     if (fragment_counter == fragmentation.fragmentationVectorSize ||
169         i != fragmentation.fragmentationOffset[fragment_counter]) {
170       encoded_image._buffer[i] = value++;
171     } else {
172       ++fragment_counter;
173     }
174   }
175   return callback_->Encoded(encoded_image, NULL, &fragmentation);
176 }
177 }  // namespace test
178 }  // namespace webrtc
179