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/codecs/interface/video_codec_interface.h"
     16 
     17 namespace webrtc {
     18 namespace test {
     19 
     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 
     32 FakeEncoder::~FakeEncoder() {}
     33 
     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 
     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 
     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 
    105 int32_t FakeEncoder::RegisterEncodeCompleteCallback(
    106     EncodedImageCallback* callback) {
    107   callback_ = callback;
    108   return 0;
    109 }
    110 
    111 int32_t FakeEncoder::Release() { return 0; }
    112 
    113 int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int rtt) {
    114   return 0;
    115 }
    116 
    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 
    122 FakeH264Encoder::FakeH264Encoder(Clock* clock)
    123     : FakeEncoder(clock), callback_(NULL), idr_counter_(0) {
    124   FakeEncoder::RegisterEncodeCompleteCallback(this);
    125 }
    126 
    127 int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
    128     EncodedImageCallback* callback) {
    129   callback_ = callback;
    130   return 0;
    131 }
    132 
    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