1/* 2 * Copyright (c) 2014 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/modules/audio_coding/codecs/ilbc/audio_encoder_ilbc.h" 12 13#include <algorithm> 14#include <limits> 15#include "webrtc/base/checks.h" 16#include "webrtc/common_types.h" 17#include "webrtc/modules/audio_coding/codecs/ilbc/ilbc.h" 18 19namespace webrtc { 20 21namespace { 22 23const int kSampleRateHz = 8000; 24 25AudioEncoderIlbc::Config CreateConfig(const CodecInst& codec_inst) { 26 AudioEncoderIlbc::Config config; 27 config.frame_size_ms = codec_inst.pacsize / 8; 28 config.payload_type = codec_inst.pltype; 29 return config; 30} 31 32} // namespace 33 34// static 35const size_t AudioEncoderIlbc::kMaxSamplesPerPacket; 36 37bool AudioEncoderIlbc::Config::IsOk() const { 38 return (frame_size_ms == 20 || frame_size_ms == 30 || frame_size_ms == 40 || 39 frame_size_ms == 60) && 40 static_cast<size_t>(kSampleRateHz / 100 * (frame_size_ms / 10)) <= 41 kMaxSamplesPerPacket; 42} 43 44AudioEncoderIlbc::AudioEncoderIlbc(const Config& config) 45 : config_(config), 46 num_10ms_frames_per_packet_( 47 static_cast<size_t>(config.frame_size_ms / 10)), 48 encoder_(nullptr) { 49 Reset(); 50} 51 52AudioEncoderIlbc::AudioEncoderIlbc(const CodecInst& codec_inst) 53 : AudioEncoderIlbc(CreateConfig(codec_inst)) {} 54 55AudioEncoderIlbc::~AudioEncoderIlbc() { 56 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_)); 57} 58 59size_t AudioEncoderIlbc::MaxEncodedBytes() const { 60 return RequiredOutputSizeBytes(); 61} 62 63int AudioEncoderIlbc::SampleRateHz() const { 64 return kSampleRateHz; 65} 66 67size_t AudioEncoderIlbc::NumChannels() const { 68 return 1; 69} 70 71size_t AudioEncoderIlbc::Num10MsFramesInNextPacket() const { 72 return num_10ms_frames_per_packet_; 73} 74 75size_t AudioEncoderIlbc::Max10MsFramesInAPacket() const { 76 return num_10ms_frames_per_packet_; 77} 78 79int AudioEncoderIlbc::GetTargetBitrate() const { 80 switch (num_10ms_frames_per_packet_) { 81 case 2: case 4: 82 // 38 bytes per frame of 20 ms => 15200 bits/s. 83 return 15200; 84 case 3: case 6: 85 // 50 bytes per frame of 30 ms => (approx) 13333 bits/s. 86 return 13333; 87 default: 88 FATAL(); 89 } 90} 91 92AudioEncoder::EncodedInfo AudioEncoderIlbc::EncodeInternal( 93 uint32_t rtp_timestamp, 94 rtc::ArrayView<const int16_t> audio, 95 size_t max_encoded_bytes, 96 uint8_t* encoded) { 97 RTC_DCHECK_GE(max_encoded_bytes, RequiredOutputSizeBytes()); 98 99 // Save timestamp if starting a new packet. 100 if (num_10ms_frames_buffered_ == 0) 101 first_timestamp_in_buffer_ = rtp_timestamp; 102 103 // Buffer input. 104 RTC_DCHECK_EQ(static_cast<size_t>(kSampleRateHz / 100), audio.size()); 105 std::copy(audio.cbegin(), audio.cend(), 106 input_buffer_ + kSampleRateHz / 100 * num_10ms_frames_buffered_); 107 108 // If we don't yet have enough buffered input for a whole packet, we're done 109 // for now. 110 if (++num_10ms_frames_buffered_ < num_10ms_frames_per_packet_) { 111 return EncodedInfo(); 112 } 113 114 // Encode buffered input. 115 RTC_DCHECK_EQ(num_10ms_frames_buffered_, num_10ms_frames_per_packet_); 116 num_10ms_frames_buffered_ = 0; 117 const int output_len = WebRtcIlbcfix_Encode( 118 encoder_, 119 input_buffer_, 120 kSampleRateHz / 100 * num_10ms_frames_per_packet_, 121 encoded); 122 RTC_CHECK_GE(output_len, 0); 123 EncodedInfo info; 124 info.encoded_bytes = static_cast<size_t>(output_len); 125 RTC_DCHECK_EQ(info.encoded_bytes, RequiredOutputSizeBytes()); 126 info.encoded_timestamp = first_timestamp_in_buffer_; 127 info.payload_type = config_.payload_type; 128 return info; 129} 130 131void AudioEncoderIlbc::Reset() { 132 if (encoder_) 133 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_)); 134 RTC_CHECK(config_.IsOk()); 135 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderCreate(&encoder_)); 136 const int encoder_frame_size_ms = config_.frame_size_ms > 30 137 ? config_.frame_size_ms / 2 138 : config_.frame_size_ms; 139 RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderInit(encoder_, encoder_frame_size_ms)); 140 num_10ms_frames_buffered_ = 0; 141} 142 143size_t AudioEncoderIlbc::RequiredOutputSizeBytes() const { 144 switch (num_10ms_frames_per_packet_) { 145 case 2: return 38; 146 case 3: return 50; 147 case 4: return 2 * 38; 148 case 6: return 2 * 50; 149 default: FATAL(); 150 } 151} 152 153} // namespace webrtc 154