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