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/g711/audio_encoder_pcm.h"
12 
13 #include <limits>
14 
15 #include "webrtc/base/checks.h"
16 #include "webrtc/common_types.h"
17 #include "webrtc/modules/audio_coding/codecs/g711/g711_interface.h"
18 
19 namespace webrtc {
20 
21 namespace {
22 
23 template <typename T>
CreateConfig(const CodecInst & codec_inst)24 typename T::Config CreateConfig(const CodecInst& codec_inst) {
25   typename T::Config config;
26   config.frame_size_ms = codec_inst.pacsize / 8;
27   config.num_channels = codec_inst.channels;
28   config.payload_type = codec_inst.pltype;
29   return config;
30 }
31 
32 }  // namespace
33 
IsOk() const34 bool AudioEncoderPcm::Config::IsOk() const {
35   return (frame_size_ms % 10 == 0) && (num_channels >= 1);
36 }
37 
AudioEncoderPcm(const Config & config,int sample_rate_hz)38 AudioEncoderPcm::AudioEncoderPcm(const Config& config, int sample_rate_hz)
39     : sample_rate_hz_(sample_rate_hz),
40       num_channels_(config.num_channels),
41       payload_type_(config.payload_type),
42       num_10ms_frames_per_packet_(
43           static_cast<size_t>(config.frame_size_ms / 10)),
44       full_frame_samples_(
45           config.num_channels * config.frame_size_ms * sample_rate_hz / 1000),
46       first_timestamp_in_buffer_(0) {
47   RTC_CHECK_GT(sample_rate_hz, 0) << "Sample rate must be larger than 0 Hz";
48   RTC_CHECK_EQ(config.frame_size_ms % 10, 0)
49       << "Frame size must be an integer multiple of 10 ms.";
50   speech_buffer_.reserve(full_frame_samples_);
51 }
52 
53 AudioEncoderPcm::~AudioEncoderPcm() = default;
54 
MaxEncodedBytes() const55 size_t AudioEncoderPcm::MaxEncodedBytes() const {
56   return full_frame_samples_ * BytesPerSample();
57 }
58 
SampleRateHz() const59 int AudioEncoderPcm::SampleRateHz() const {
60   return sample_rate_hz_;
61 }
62 
NumChannels() const63 size_t AudioEncoderPcm::NumChannels() const {
64   return num_channels_;
65 }
66 
Num10MsFramesInNextPacket() const67 size_t AudioEncoderPcm::Num10MsFramesInNextPacket() const {
68   return num_10ms_frames_per_packet_;
69 }
70 
Max10MsFramesInAPacket() const71 size_t AudioEncoderPcm::Max10MsFramesInAPacket() const {
72   return num_10ms_frames_per_packet_;
73 }
74 
GetTargetBitrate() const75 int AudioEncoderPcm::GetTargetBitrate() const {
76   return static_cast<int>(
77       8 * BytesPerSample() * SampleRateHz() * NumChannels());
78 }
79 
EncodeInternal(uint32_t rtp_timestamp,rtc::ArrayView<const int16_t> audio,size_t max_encoded_bytes,uint8_t * encoded)80 AudioEncoder::EncodedInfo AudioEncoderPcm::EncodeInternal(
81     uint32_t rtp_timestamp,
82     rtc::ArrayView<const int16_t> audio,
83     size_t max_encoded_bytes,
84     uint8_t* encoded) {
85   if (speech_buffer_.empty()) {
86     first_timestamp_in_buffer_ = rtp_timestamp;
87   }
88   speech_buffer_.insert(speech_buffer_.end(), audio.begin(), audio.end());
89   if (speech_buffer_.size() < full_frame_samples_) {
90     return EncodedInfo();
91   }
92   RTC_CHECK_EQ(speech_buffer_.size(), full_frame_samples_);
93   RTC_CHECK_GE(max_encoded_bytes, full_frame_samples_);
94   EncodedInfo info;
95   info.encoded_timestamp = first_timestamp_in_buffer_;
96   info.payload_type = payload_type_;
97   info.encoded_bytes =
98       EncodeCall(&speech_buffer_[0], full_frame_samples_, encoded);
99   speech_buffer_.clear();
100   return info;
101 }
102 
Reset()103 void AudioEncoderPcm::Reset() {
104   speech_buffer_.clear();
105 }
106 
AudioEncoderPcmA(const CodecInst & codec_inst)107 AudioEncoderPcmA::AudioEncoderPcmA(const CodecInst& codec_inst)
108     : AudioEncoderPcmA(CreateConfig<AudioEncoderPcmA>(codec_inst)) {}
109 
EncodeCall(const int16_t * audio,size_t input_len,uint8_t * encoded)110 size_t AudioEncoderPcmA::EncodeCall(const int16_t* audio,
111                                     size_t input_len,
112                                     uint8_t* encoded) {
113   return WebRtcG711_EncodeA(audio, input_len, encoded);
114 }
115 
BytesPerSample() const116 size_t AudioEncoderPcmA::BytesPerSample() const {
117   return 1;
118 }
119 
AudioEncoderPcmU(const CodecInst & codec_inst)120 AudioEncoderPcmU::AudioEncoderPcmU(const CodecInst& codec_inst)
121     : AudioEncoderPcmU(CreateConfig<AudioEncoderPcmU>(codec_inst)) {}
122 
EncodeCall(const int16_t * audio,size_t input_len,uint8_t * encoded)123 size_t AudioEncoderPcmU::EncodeCall(const int16_t* audio,
124                                     size_t input_len,
125                                     uint8_t* encoded) {
126   return WebRtcG711_EncodeU(audio, input_len, encoded);
127 }
128 
BytesPerSample() const129 size_t AudioEncoderPcmU::BytesPerSample() const {
130   return 1;
131 }
132 
133 }  // namespace webrtc
134