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