• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
19 namespace webrtc {
20 
21 namespace {
22 
23 const int kSampleRateHz = 8000;
24 
CreateConfig(const CodecInst & codec_inst)25 AudioEncoderIlbc::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
35 const size_t AudioEncoderIlbc::kMaxSamplesPerPacket;
36 
IsOk() const37 bool 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 
AudioEncoderIlbc(const Config & config)44 AudioEncoderIlbc::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 
AudioEncoderIlbc(const CodecInst & codec_inst)52 AudioEncoderIlbc::AudioEncoderIlbc(const CodecInst& codec_inst)
53     : AudioEncoderIlbc(CreateConfig(codec_inst)) {}
54 
~AudioEncoderIlbc()55 AudioEncoderIlbc::~AudioEncoderIlbc() {
56   RTC_CHECK_EQ(0, WebRtcIlbcfix_EncoderFree(encoder_));
57 }
58 
MaxEncodedBytes() const59 size_t AudioEncoderIlbc::MaxEncodedBytes() const {
60   return RequiredOutputSizeBytes();
61 }
62 
SampleRateHz() const63 int AudioEncoderIlbc::SampleRateHz() const {
64   return kSampleRateHz;
65 }
66 
NumChannels() const67 size_t AudioEncoderIlbc::NumChannels() const {
68   return 1;
69 }
70 
Num10MsFramesInNextPacket() const71 size_t AudioEncoderIlbc::Num10MsFramesInNextPacket() const {
72   return num_10ms_frames_per_packet_;
73 }
74 
Max10MsFramesInAPacket() const75 size_t AudioEncoderIlbc::Max10MsFramesInAPacket() const {
76   return num_10ms_frames_per_packet_;
77 }
78 
GetTargetBitrate() const79 int 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 
EncodeInternal(uint32_t rtp_timestamp,rtc::ArrayView<const int16_t> audio,size_t max_encoded_bytes,uint8_t * encoded)92 AudioEncoder::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 
Reset()131 void 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 
RequiredOutputSizeBytes() const143 size_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