blob: c8fd176fbb2bcfa96cb95643a2b8334088fc6e69 [file] [log] [blame]
Alex Loikoe5b94162019-04-08 17:19:41 +02001/*
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
23namespace webrtc {
24
25std::unique_ptr<AudioDecoderMultiChannelOpusImpl>
26AudioDecoderMultiChannelOpusImpl::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
47AudioDecoderMultiChannelOpusImpl::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
55AudioDecoderMultiChannelOpusImpl::~AudioDecoderMultiChannelOpusImpl() {
56 WebRtcOpus_DecoderFree(dec_state_);
57}
58
59absl::optional<AudioDecoderMultiChannelOpusConfig>
60AudioDecoderMultiChannelOpusImpl::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
84std::vector<AudioDecoder::ParseResult>
85AudioDecoderMultiChannelOpusImpl::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
104int 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
120int 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
143void AudioDecoderMultiChannelOpusImpl::Reset() {
144 WebRtcOpus_DecoderInit(dec_state_);
145}
146
147int AudioDecoderMultiChannelOpusImpl::PacketDuration(const uint8_t* encoded,
148 size_t encoded_len) const {
149 return WebRtcOpus_DurationEst(dec_state_, encoded, encoded_len);
150}
151
152int 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
Karl Wiberga1d1a1e2019-05-28 14:41:07 +0200160 return WebRtcOpus_FecDurationEst(encoded, encoded_len, 48000);
Alex Loikoe5b94162019-04-08 17:19:41 +0200161}
162
163bool 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
170int AudioDecoderMultiChannelOpusImpl::SampleRateHz() const {
171 return 48000;
172}
173
174size_t AudioDecoderMultiChannelOpusImpl::Channels() const {
175 return config_.num_channels;
176}
177
178} // namespace webrtc