Home | History | Annotate | Download | only in test
      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 
     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 
     33 FakeEncoder::~FakeEncoder() {}
     34 
     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 
     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 
     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 
    118 int32_t FakeEncoder::RegisterEncodeCompleteCallback(
    119     EncodedImageCallback* callback) {
    120   callback_ = callback;
    121   return 0;
    122 }
    123 
    124 int32_t FakeEncoder::Release() { return 0; }
    125 
    126 int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int64_t rtt) {
    127   return 0;
    128 }
    129 
    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";
    136 const char* FakeEncoder::ImplementationName() const {
    137   return kImplementationName;
    138 }
    139 
    140 FakeH264Encoder::FakeH264Encoder(Clock* clock)
    141     : FakeEncoder(clock), callback_(NULL), idr_counter_(0) {
    142   FakeEncoder::RegisterEncodeCompleteCallback(this);
    143 }
    144 
    145 int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
    146     EncodedImageCallback* callback) {
    147   callback_ = callback;
    148   return 0;
    149 }
    150 
    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 
    196 DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms)
    197     : test::FakeEncoder(clock),
    198       delay_ms_(delay_ms) {}
    199 
    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