1 /*
2 * Copyright (c) 2019 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/opus/audio_decoder_multi_channel_opus_impl.h"
12
13 #include <algorithm>
14 #include <memory>
15 #include <string>
16 #include <utility>
17 #include <vector>
18
19 #include "absl/memory/memory.h"
20 #include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
21 #include "rtc_base/string_to_number.h"
22
23 namespace webrtc {
24
25 std::unique_ptr<AudioDecoderMultiChannelOpusImpl>
MakeAudioDecoder(AudioDecoderMultiChannelOpusConfig config)26 AudioDecoderMultiChannelOpusImpl::MakeAudioDecoder(
27 AudioDecoderMultiChannelOpusConfig config) {
28 if (!config.IsOk()) {
29 RTC_DCHECK_NOTREACHED();
30 return nullptr;
31 }
32 // Fill the pointer with a working decoder through the C interface. This
33 // allocates memory.
34 OpusDecInst* dec_state = nullptr;
35 const int error = WebRtcOpus_MultistreamDecoderCreate(
36 &dec_state, config.num_channels, config.num_streams,
37 config.coupled_streams, config.channel_mapping.data());
38 if (error != 0) {
39 return nullptr;
40 }
41
42 // Pass the ownership to DecoderImpl. Not using 'make_unique' because the
43 // c-tor is private.
44 return std::unique_ptr<AudioDecoderMultiChannelOpusImpl>(
45 new AudioDecoderMultiChannelOpusImpl(dec_state, config));
46 }
47
AudioDecoderMultiChannelOpusImpl(OpusDecInst * dec_state,AudioDecoderMultiChannelOpusConfig config)48 AudioDecoderMultiChannelOpusImpl::AudioDecoderMultiChannelOpusImpl(
49 OpusDecInst* dec_state,
50 AudioDecoderMultiChannelOpusConfig config)
51 : dec_state_(dec_state), config_(config) {
52 RTC_DCHECK(dec_state);
53 WebRtcOpus_DecoderInit(dec_state_);
54 }
55
~AudioDecoderMultiChannelOpusImpl()56 AudioDecoderMultiChannelOpusImpl::~AudioDecoderMultiChannelOpusImpl() {
57 WebRtcOpus_DecoderFree(dec_state_);
58 }
59
60 absl::optional<AudioDecoderMultiChannelOpusConfig>
SdpToConfig(const SdpAudioFormat & format)61 AudioDecoderMultiChannelOpusImpl::SdpToConfig(const SdpAudioFormat& format) {
62 AudioDecoderMultiChannelOpusConfig config;
63 config.num_channels = format.num_channels;
64 auto num_streams = GetFormatParameter<int>(format, "num_streams");
65 if (!num_streams.has_value()) {
66 return absl::nullopt;
67 }
68 config.num_streams = *num_streams;
69
70 auto coupled_streams = GetFormatParameter<int>(format, "coupled_streams");
71 if (!coupled_streams.has_value()) {
72 return absl::nullopt;
73 }
74 config.coupled_streams = *coupled_streams;
75
76 auto channel_mapping =
77 GetFormatParameter<std::vector<unsigned char>>(format, "channel_mapping");
78 if (!channel_mapping.has_value()) {
79 return absl::nullopt;
80 }
81 config.channel_mapping = *channel_mapping;
82 if (!config.IsOk()) {
83 return absl::nullopt;
84 }
85 return config;
86 }
87
88 std::vector<AudioDecoder::ParseResult>
ParsePayload(rtc::Buffer && payload,uint32_t timestamp)89 AudioDecoderMultiChannelOpusImpl::ParsePayload(rtc::Buffer&& payload,
90 uint32_t timestamp) {
91 std::vector<ParseResult> results;
92
93 if (PacketHasFec(payload.data(), payload.size())) {
94 const int duration =
95 PacketDurationRedundant(payload.data(), payload.size());
96 RTC_DCHECK_GE(duration, 0);
97 rtc::Buffer payload_copy(payload.data(), payload.size());
98 std::unique_ptr<EncodedAudioFrame> fec_frame(
99 new OpusFrame(this, std::move(payload_copy), false));
100 results.emplace_back(timestamp - duration, 1, std::move(fec_frame));
101 }
102 std::unique_ptr<EncodedAudioFrame> frame(
103 new OpusFrame(this, std::move(payload), true));
104 results.emplace_back(timestamp, 0, std::move(frame));
105 return results;
106 }
107
DecodeInternal(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,SpeechType * speech_type)108 int AudioDecoderMultiChannelOpusImpl::DecodeInternal(const uint8_t* encoded,
109 size_t encoded_len,
110 int sample_rate_hz,
111 int16_t* decoded,
112 SpeechType* speech_type) {
113 RTC_DCHECK_EQ(sample_rate_hz, 48000);
114 int16_t temp_type = 1; // Default is speech.
115 int ret =
116 WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
117 if (ret > 0)
118 ret *= static_cast<int>(
119 config_.num_channels); // Return total number of samples.
120 *speech_type = ConvertSpeechType(temp_type);
121 return ret;
122 }
123
DecodeRedundantInternal(const uint8_t * encoded,size_t encoded_len,int sample_rate_hz,int16_t * decoded,SpeechType * speech_type)124 int AudioDecoderMultiChannelOpusImpl::DecodeRedundantInternal(
125 const uint8_t* encoded,
126 size_t encoded_len,
127 int sample_rate_hz,
128 int16_t* decoded,
129 SpeechType* speech_type) {
130 if (!PacketHasFec(encoded, encoded_len)) {
131 // This packet is a RED packet.
132 return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
133 speech_type);
134 }
135
136 RTC_DCHECK_EQ(sample_rate_hz, 48000);
137 int16_t temp_type = 1; // Default is speech.
138 int ret = WebRtcOpus_DecodeFec(dec_state_, encoded, encoded_len, decoded,
139 &temp_type);
140 if (ret > 0)
141 ret *= static_cast<int>(
142 config_.num_channels); // Return total number of samples.
143 *speech_type = ConvertSpeechType(temp_type);
144 return ret;
145 }
146
Reset()147 void AudioDecoderMultiChannelOpusImpl::Reset() {
148 WebRtcOpus_DecoderInit(dec_state_);
149 }
150
PacketDuration(const uint8_t * encoded,size_t encoded_len) const151 int AudioDecoderMultiChannelOpusImpl::PacketDuration(const uint8_t* encoded,
152 size_t encoded_len) const {
153 return WebRtcOpus_DurationEst(dec_state_, encoded, encoded_len);
154 }
155
PacketDurationRedundant(const uint8_t * encoded,size_t encoded_len) const156 int AudioDecoderMultiChannelOpusImpl::PacketDurationRedundant(
157 const uint8_t* encoded,
158 size_t encoded_len) const {
159 if (!PacketHasFec(encoded, encoded_len)) {
160 // This packet is a RED packet.
161 return PacketDuration(encoded, encoded_len);
162 }
163
164 return WebRtcOpus_FecDurationEst(encoded, encoded_len, 48000);
165 }
166
PacketHasFec(const uint8_t * encoded,size_t encoded_len) const167 bool AudioDecoderMultiChannelOpusImpl::PacketHasFec(const uint8_t* encoded,
168 size_t encoded_len) const {
169 int fec;
170 fec = WebRtcOpus_PacketHasFec(encoded, encoded_len);
171 return (fec == 1);
172 }
173
SampleRateHz() const174 int AudioDecoderMultiChannelOpusImpl::SampleRateHz() const {
175 return 48000;
176 }
177
Channels() const178 size_t AudioDecoderMultiChannelOpusImpl::Channels() const {
179 return config_.num_channels;
180 }
181
182 } // namespace webrtc
183