1 /*
2 * Copyright (c) 2015 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 "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "modules/audio_coding/codecs/ilbc/ilbc.h"
17 #include "modules/audio_coding/codecs/legacy_encoded_audio_frame.h"
18 #include "rtc_base/checks.h"
19 #include "rtc_base/logging.h"
20
21 namespace webrtc {
22
AudioDecoderIlbcImpl()23 AudioDecoderIlbcImpl::AudioDecoderIlbcImpl() {
24 WebRtcIlbcfix_DecoderCreate(&dec_state_);
25 WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
26 }
27
~AudioDecoderIlbcImpl()28 AudioDecoderIlbcImpl::~AudioDecoderIlbcImpl() {
29 WebRtcIlbcfix_DecoderFree(dec_state_);
30 }
31
HasDecodePlc() const32 bool AudioDecoderIlbcImpl::HasDecodePlc() const {
33 return true;
34 }
35
DecodeInternal(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,SpeechType * speech_type)36 int AudioDecoderIlbcImpl::DecodeInternal(const uint8_t* encoded,
37 size_t encoded_len,
38 int sample_rate_hz,
39 int16_t* decoded,
40 SpeechType* speech_type) {
41 RTC_DCHECK_EQ(sample_rate_hz, 8000);
42 int16_t temp_type = 1; // Default is speech.
43 int ret = WebRtcIlbcfix_Decode(dec_state_, encoded, encoded_len, decoded,
44 &temp_type);
45 *speech_type = ConvertSpeechType(temp_type);
46 return ret;
47 }
48
DecodePlc(size_t num_frames,int16_t * decoded)49 size_t AudioDecoderIlbcImpl::DecodePlc(size_t num_frames, int16_t* decoded) {
50 return WebRtcIlbcfix_NetEqPlc(dec_state_, decoded, num_frames);
51 }
52
Reset()53 void AudioDecoderIlbcImpl::Reset() {
54 WebRtcIlbcfix_Decoderinit30Ms(dec_state_);
55 }
56
ParsePayload(rtc::Buffer && payload,uint32_t timestamp)57 std::vector<AudioDecoder::ParseResult> AudioDecoderIlbcImpl::ParsePayload(
58 rtc::Buffer&& payload,
59 uint32_t timestamp) {
60 std::vector<ParseResult> results;
61 size_t bytes_per_frame;
62 int timestamps_per_frame;
63 if (payload.size() >= 950) {
64 RTC_LOG(LS_WARNING)
65 << "AudioDecoderIlbcImpl::ParsePayload: Payload too large";
66 return results;
67 }
68 if (payload.size() % 38 == 0) {
69 // 20 ms frames.
70 bytes_per_frame = 38;
71 timestamps_per_frame = 160;
72 } else if (payload.size() % 50 == 0) {
73 // 30 ms frames.
74 bytes_per_frame = 50;
75 timestamps_per_frame = 240;
76 } else {
77 RTC_LOG(LS_WARNING)
78 << "AudioDecoderIlbcImpl::ParsePayload: Invalid payload";
79 return results;
80 }
81
82 RTC_DCHECK_EQ(0, payload.size() % bytes_per_frame);
83 if (payload.size() == bytes_per_frame) {
84 std::unique_ptr<EncodedAudioFrame> frame(
85 new LegacyEncodedAudioFrame(this, std::move(payload)));
86 results.emplace_back(timestamp, 0, std::move(frame));
87 } else {
88 size_t byte_offset;
89 uint32_t timestamp_offset;
90 for (byte_offset = 0, timestamp_offset = 0; byte_offset < payload.size();
91 byte_offset += bytes_per_frame,
92 timestamp_offset += timestamps_per_frame) {
93 std::unique_ptr<EncodedAudioFrame> frame(new LegacyEncodedAudioFrame(
94 this, rtc::Buffer(payload.data() + byte_offset, bytes_per_frame)));
95 results.emplace_back(timestamp + timestamp_offset, 0, std::move(frame));
96 }
97 }
98
99 return results;
100 }
101
SampleRateHz() const102 int AudioDecoderIlbcImpl::SampleRateHz() const {
103 return 8000;
104 }
105
Channels() const106 size_t AudioDecoderIlbcImpl::Channels() const {
107 return 1;
108 }
109
110 } // namespace webrtc
111