mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 22:00:47 +01:00

See https://webrtc-review.googlesource.com/c/src/+/121764 for the overall vision. This CL adds a multistream Opus decoder. It's a new code-path to not interfere with the standard Opus decoder. We introduce new SDP syntax, which uses terminology of RFC 7845. We also set up the decoder side to parse it. The encoder part will come in a later CL. E.g. this is the new SDP syntax for 6.1 surround sound: "multiopus/48000/6 channel_mapping=0,4,1,2,3,5 num_streams=4 coupled_streams=2" Bug: webrtc:8649 Change-Id: Ifbc584cbb6d07aed373f223512a20d6d72cec5ec Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/129768 Commit-Queue: Alex Loiko <aleloi@webrtc.org> Reviewed-by: Oskar Sundbom <ossu@webrtc.org> Cr-Commit-Position: refs/heads/master@{#27493}
125 lines
4.3 KiB
C++
125 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/array_view.h"
|
|
#include "modules/audio_coding/codecs/opus/audio_coder_opus_common.h"
|
|
#include "rtc_base/checks.h"
|
|
|
|
namespace webrtc {
|
|
|
|
AudioDecoderOpusImpl::AudioDecoderOpusImpl(size_t num_channels)
|
|
: channels_(num_channels) {
|
|
RTC_DCHECK(num_channels == 1 || num_channels == 2);
|
|
const int error = WebRtcOpus_DecoderCreate(&dec_state_, channels_);
|
|
RTC_DCHECK(error == 0);
|
|
WebRtcOpus_DecoderInit(dec_state_);
|
|
}
|
|
|
|
AudioDecoderOpusImpl::~AudioDecoderOpusImpl() {
|
|
WebRtcOpus_DecoderFree(dec_state_);
|
|
}
|
|
|
|
std::vector<AudioDecoder::ParseResult> AudioDecoderOpusImpl::ParsePayload(
|
|
rtc::Buffer&& payload,
|
|
uint32_t timestamp) {
|
|
std::vector<ParseResult> results;
|
|
|
|
if (PacketHasFec(payload.data(), payload.size())) {
|
|
const int duration =
|
|
PacketDurationRedundant(payload.data(), payload.size());
|
|
RTC_DCHECK_GE(duration, 0);
|
|
rtc::Buffer payload_copy(payload.data(), payload.size());
|
|
std::unique_ptr<EncodedAudioFrame> fec_frame(
|
|
new OpusFrame(this, std::move(payload_copy), false));
|
|
results.emplace_back(timestamp - duration, 1, std::move(fec_frame));
|
|
}
|
|
std::unique_ptr<EncodedAudioFrame> frame(
|
|
new OpusFrame(this, std::move(payload), true));
|
|
results.emplace_back(timestamp, 0, std::move(frame));
|
|
return results;
|
|
}
|
|
|
|
int AudioDecoderOpusImpl::DecodeInternal(const uint8_t* encoded,
|
|
size_t encoded_len,
|
|
int sample_rate_hz,
|
|
int16_t* decoded,
|
|
SpeechType* speech_type) {
|
|
RTC_DCHECK_EQ(sample_rate_hz, 48000);
|
|
int16_t temp_type = 1; // Default is speech.
|
|
int ret =
|
|
WebRtcOpus_Decode(dec_state_, encoded, encoded_len, decoded, &temp_type);
|
|
if (ret > 0)
|
|
ret *= static_cast<int>(channels_); // Return total number of samples.
|
|
*speech_type = ConvertSpeechType(temp_type);
|
|
return ret;
|
|
}
|
|
|
|
int AudioDecoderOpusImpl::DecodeRedundantInternal(const uint8_t* encoded,
|
|
size_t encoded_len,
|
|
int sample_rate_hz,
|
|
int16_t* decoded,
|
|
SpeechType* speech_type) {
|
|
if (!PacketHasFec(encoded, encoded_len)) {
|
|
// This packet is a RED packet.
|
|
return DecodeInternal(encoded, encoded_len, sample_rate_hz, decoded,
|
|
speech_type);
|
|
}
|
|
|
|
RTC_DCHECK_EQ(sample_rate_hz, 48000);
|
|
int16_t temp_type = 1; // Default is speech.
|
|
int ret = WebRtcOpus_DecodeFec(dec_state_, encoded, encoded_len, decoded,
|
|
&temp_type);
|
|
if (ret > 0)
|
|
ret *= static_cast<int>(channels_); // Return total number of samples.
|
|
*speech_type = ConvertSpeechType(temp_type);
|
|
return ret;
|
|
}
|
|
|
|
void AudioDecoderOpusImpl::Reset() {
|
|
WebRtcOpus_DecoderInit(dec_state_);
|
|
}
|
|
|
|
int AudioDecoderOpusImpl::PacketDuration(const uint8_t* encoded,
|
|
size_t encoded_len) const {
|
|
return WebRtcOpus_DurationEst(dec_state_, encoded, encoded_len);
|
|
}
|
|
|
|
int AudioDecoderOpusImpl::PacketDurationRedundant(const uint8_t* encoded,
|
|
size_t encoded_len) const {
|
|
if (!PacketHasFec(encoded, encoded_len)) {
|
|
// This packet is a RED packet.
|
|
return PacketDuration(encoded, encoded_len);
|
|
}
|
|
|
|
return WebRtcOpus_FecDurationEst(encoded, encoded_len);
|
|
}
|
|
|
|
bool AudioDecoderOpusImpl::PacketHasFec(const uint8_t* encoded,
|
|
size_t encoded_len) const {
|
|
int fec;
|
|
fec = WebRtcOpus_PacketHasFec(encoded, encoded_len);
|
|
return (fec == 1);
|
|
}
|
|
|
|
int AudioDecoderOpusImpl::SampleRateHz() const {
|
|
return 48000;
|
|
}
|
|
|
|
size_t AudioDecoderOpusImpl::Channels() const {
|
|
return channels_;
|
|
}
|
|
|
|
} // namespace webrtc
|