WebRTC Opus C interface: Add support for non-48 kHz decode sample rate
Plus tests for 16 kHz. Bug: webrtc:10631 Change-Id: I2d89bc6d0d9548f0ad7bb1e36d6dfde6b6b31f83 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/138072 Commit-Queue: Karl Wiberg <kwiberg@webrtc.org> Reviewed-by: Minyue Li <minyue@webrtc.org> Cr-Commit-Position: refs/heads/master@{#28099}
This commit is contained in:
@ -157,7 +157,7 @@ int AudioDecoderMultiChannelOpusImpl::PacketDurationRedundant(
|
||||
return PacketDuration(encoded, encoded_len);
|
||||
}
|
||||
|
||||
return WebRtcOpus_FecDurationEst(encoded, encoded_len);
|
||||
return WebRtcOpus_FecDurationEst(encoded, encoded_len, 48000);
|
||||
}
|
||||
|
||||
bool AudioDecoderMultiChannelOpusImpl::PacketHasFec(const uint8_t* encoded,
|
||||
|
||||
@ -23,7 +23,7 @@ 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_);
|
||||
const int error = WebRtcOpus_DecoderCreate(&dec_state_, channels_, 48000);
|
||||
RTC_DCHECK(error == 0);
|
||||
WebRtcOpus_DecoderInit(dec_state_);
|
||||
}
|
||||
@ -104,7 +104,7 @@ int AudioDecoderOpusImpl::PacketDurationRedundant(const uint8_t* encoded,
|
||||
return PacketDuration(encoded, encoded_len);
|
||||
}
|
||||
|
||||
return WebRtcOpus_FecDurationEst(encoded, encoded_len);
|
||||
return WebRtcOpus_FecDurationEst(encoded, encoded_len, 48000);
|
||||
}
|
||||
|
||||
bool AudioDecoderOpusImpl::PacketHasFec(const uint8_t* encoded,
|
||||
|
||||
@ -110,7 +110,7 @@ void OpusFecTest::SetUp() {
|
||||
|
||||
// Create encoder memory.
|
||||
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_, 48000));
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ struct WebRtcOpusDecInst {
|
||||
int prev_decoded_samples;
|
||||
size_t channels;
|
||||
int in_dtx_mode;
|
||||
int sample_rate_hz;
|
||||
};
|
||||
|
||||
#endif // MODULES_AUDIO_CODING_CODECS_OPUS_OPUS_INST_H_
|
||||
|
||||
@ -28,15 +28,26 @@ enum {
|
||||
* side, we must allow for packets of that size. NetEq is currently limited
|
||||
* to 60 ms on the receive side. */
|
||||
kWebRtcOpusMaxDecodeFrameSizeMs = 120,
|
||||
|
||||
/* Maximum sample count per channel is 48 kHz * maximum frame size in
|
||||
* milliseconds. */
|
||||
kWebRtcOpusMaxFrameSizePerChannel = 48 * kWebRtcOpusMaxDecodeFrameSizeMs,
|
||||
|
||||
/* Default frame size, 20 ms @ 48 kHz, in samples (for one channel). */
|
||||
kWebRtcOpusDefaultFrameSize = 960,
|
||||
};
|
||||
|
||||
static int FrameSizePerChannel(int frame_size_ms, int sample_rate_hz) {
|
||||
RTC_DCHECK_GT(frame_size_ms, 0);
|
||||
RTC_DCHECK_EQ(frame_size_ms % 10, 0);
|
||||
RTC_DCHECK_GT(sample_rate_hz, 0);
|
||||
RTC_DCHECK_EQ(sample_rate_hz % 1000, 0);
|
||||
return frame_size_ms * (sample_rate_hz / 1000);
|
||||
}
|
||||
|
||||
// Maximum sample count per channel.
|
||||
static int MaxFrameSizePerChannel(int sample_rate_hz) {
|
||||
return FrameSizePerChannel(kWebRtcOpusMaxDecodeFrameSizeMs, sample_rate_hz);
|
||||
}
|
||||
|
||||
// Default sample count per channel.
|
||||
static int DefaultFrameSizePerChannel(int sample_rate_hz) {
|
||||
return FrameSizePerChannel(20, sample_rate_hz);
|
||||
}
|
||||
|
||||
int16_t WebRtcOpus_EncoderCreate(OpusEncInst** inst,
|
||||
size_t channels,
|
||||
int32_t application,
|
||||
@ -374,7 +385,9 @@ int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels) {
|
||||
}
|
||||
}
|
||||
|
||||
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
|
||||
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst,
|
||||
size_t channels,
|
||||
int sample_rate_hz) {
|
||||
int error;
|
||||
OpusDecInst* state;
|
||||
|
||||
@ -385,14 +398,13 @@ int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Create new memory, always at 48000 Hz.
|
||||
state->decoder = opus_decoder_create(48000,
|
||||
(int)channels, &error);
|
||||
state->decoder = opus_decoder_create(sample_rate_hz, (int)channels, &error);
|
||||
if (error == OPUS_OK && state->decoder) {
|
||||
// Creation of memory all ok.
|
||||
state->channels = channels;
|
||||
state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
|
||||
state->prev_decoded_samples = DefaultFrameSizePerChannel(sample_rate_hz);
|
||||
state->in_dtx_mode = 0;
|
||||
state->sample_rate_hz = sample_rate_hz;
|
||||
*inst = state;
|
||||
return 0;
|
||||
}
|
||||
@ -432,8 +444,9 @@ int16_t WebRtcOpus_MultistreamDecoderCreate(
|
||||
if (error == OPUS_OK && state->multistream_decoder) {
|
||||
// Creation of memory all ok.
|
||||
state->channels = channels;
|
||||
state->prev_decoded_samples = kWebRtcOpusDefaultFrameSize;
|
||||
state->prev_decoded_samples = DefaultFrameSizePerChannel(48000);
|
||||
state->in_dtx_mode = 0;
|
||||
state->sample_rate_hz = 48000;
|
||||
*inst = state;
|
||||
return 0;
|
||||
}
|
||||
@ -529,13 +542,9 @@ int WebRtcOpus_Decode(OpusDecInst* inst, const uint8_t* encoded,
|
||||
*audio_type = DetermineAudioType(inst, encoded_bytes);
|
||||
decoded_samples = WebRtcOpus_DecodePlc(inst, decoded, 1);
|
||||
} else {
|
||||
decoded_samples = DecodeNative(inst,
|
||||
encoded,
|
||||
encoded_bytes,
|
||||
kWebRtcOpusMaxFrameSizePerChannel,
|
||||
decoded,
|
||||
audio_type,
|
||||
0);
|
||||
decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
|
||||
MaxFrameSizePerChannel(inst->sample_rate_hz),
|
||||
decoded, audio_type, 0);
|
||||
}
|
||||
if (decoded_samples < 0) {
|
||||
return -1;
|
||||
@ -555,10 +564,13 @@ int WebRtcOpus_DecodePlc(OpusDecInst* inst, int16_t* decoded,
|
||||
|
||||
/* The number of samples we ask for is |number_of_lost_frames| times
|
||||
* |prev_decoded_samples_|. Limit the number of samples to maximum
|
||||
* |kWebRtcOpusMaxFrameSizePerChannel|. */
|
||||
* |MaxFrameSizePerChannel()|. */
|
||||
plc_samples = number_of_lost_frames * inst->prev_decoded_samples;
|
||||
plc_samples = (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
|
||||
plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
|
||||
const int max_samples_per_channel =
|
||||
MaxFrameSizePerChannel(inst->sample_rate_hz);
|
||||
plc_samples = plc_samples <= max_samples_per_channel
|
||||
? plc_samples
|
||||
: max_samples_per_channel;
|
||||
decoded_samples = DecodeNative(inst, NULL, 0, plc_samples,
|
||||
decoded, &audio_type, 0);
|
||||
if (decoded_samples < 0) {
|
||||
@ -578,7 +590,8 @@ int WebRtcOpus_DecodeFec(OpusDecInst* inst, const uint8_t* encoded,
|
||||
return 0;
|
||||
}
|
||||
|
||||
fec_samples = opus_packet_get_samples_per_frame(encoded, 48000);
|
||||
fec_samples =
|
||||
opus_packet_get_samples_per_frame(encoded, inst->sample_rate_hz);
|
||||
|
||||
decoded_samples = DecodeNative(inst, encoded, encoded_bytes,
|
||||
fec_samples, decoded, audio_type, 1);
|
||||
@ -604,9 +617,10 @@ int WebRtcOpus_DurationEst(OpusDecInst* inst,
|
||||
/* Invalid payload data. */
|
||||
return 0;
|
||||
}
|
||||
samples = frames * opus_packet_get_samples_per_frame(payload, 48000);
|
||||
if (samples < 120 || samples > 5760) {
|
||||
/* Invalid payload duration. */
|
||||
samples =
|
||||
frames * opus_packet_get_samples_per_frame(payload, inst->sample_rate_hz);
|
||||
if (samples > 120 * inst->sample_rate_hz / 1000) {
|
||||
// More than 120 ms' worth of samples.
|
||||
return 0;
|
||||
}
|
||||
return samples;
|
||||
@ -615,21 +629,24 @@ int WebRtcOpus_DurationEst(OpusDecInst* inst,
|
||||
int WebRtcOpus_PlcDuration(OpusDecInst* inst) {
|
||||
/* The number of samples we ask for is |number_of_lost_frames| times
|
||||
* |prev_decoded_samples_|. Limit the number of samples to maximum
|
||||
* |kWebRtcOpusMaxFrameSizePerChannel|. */
|
||||
* |MaxFrameSizePerChannel()|. */
|
||||
const int plc_samples = inst->prev_decoded_samples;
|
||||
return (plc_samples <= kWebRtcOpusMaxFrameSizePerChannel) ?
|
||||
plc_samples : kWebRtcOpusMaxFrameSizePerChannel;
|
||||
const int max_samples_per_channel =
|
||||
MaxFrameSizePerChannel(inst->sample_rate_hz);
|
||||
return plc_samples <= max_samples_per_channel ? plc_samples
|
||||
: max_samples_per_channel;
|
||||
}
|
||||
|
||||
int WebRtcOpus_FecDurationEst(const uint8_t* payload,
|
||||
size_t payload_length_bytes) {
|
||||
int samples;
|
||||
size_t payload_length_bytes,
|
||||
int sample_rate_hz) {
|
||||
if (WebRtcOpus_PacketHasFec(payload, payload_length_bytes) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
samples = opus_packet_get_samples_per_frame(payload, 48000);
|
||||
if (samples < 480 || samples > 5760) {
|
||||
const int samples =
|
||||
opus_packet_get_samples_per_frame(payload, sample_rate_hz);
|
||||
const int samples_per_ms = sample_rate_hz / 1000;
|
||||
if (samples < 10 * samples_per_ms || samples > 120 * samples_per_ms) {
|
||||
/* Invalid payload duration. */
|
||||
return 0;
|
||||
}
|
||||
@ -650,6 +667,8 @@ int WebRtcOpus_PacketHasFec(const uint8_t* payload,
|
||||
if (payload[0] & 0x80)
|
||||
return 0;
|
||||
|
||||
// For computing the payload length in ms, the sample rate is not important
|
||||
// since it cancels out. We use 48 kHz, but any valid sample rate would work.
|
||||
payload_length_ms = opus_packet_get_samples_per_frame(payload, 48000) / 48;
|
||||
if (10 > payload_length_ms)
|
||||
payload_length_ms = 10;
|
||||
|
||||
@ -328,7 +328,9 @@ int16_t WebRtcOpus_SetBandwidth(OpusEncInst* inst, int32_t bandwidth);
|
||||
*/
|
||||
int16_t WebRtcOpus_SetForceChannels(OpusEncInst* inst, size_t num_channels);
|
||||
|
||||
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst, size_t channels);
|
||||
int16_t WebRtcOpus_DecoderCreate(OpusDecInst** inst,
|
||||
size_t channels,
|
||||
int sample_rate_hz);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcOpus_MultistreamDecoderCreate(...)
|
||||
@ -488,13 +490,15 @@ int WebRtcOpus_PlcDuration(OpusDecInst* inst);
|
||||
* Input:
|
||||
* - payload : Encoded data pointer
|
||||
* - payload_length_bytes : Bytes of encoded data
|
||||
* - sample_rate_hz : Sample rate of output audio
|
||||
*
|
||||
* Return value : >0 - The duration of the FEC data in the
|
||||
* packet in samples per channel.
|
||||
* 0 - No FEC data in the packet.
|
||||
*/
|
||||
int WebRtcOpus_FecDurationEst(const uint8_t* payload,
|
||||
size_t payload_length_bytes);
|
||||
size_t payload_length_bytes,
|
||||
int sample_rate_hz);
|
||||
|
||||
/****************************************************************************
|
||||
* WebRtcOpus_PacketHasFec(...)
|
||||
|
||||
@ -47,7 +47,7 @@ void OpusSpeedTest::SetUp() {
|
||||
int app = channels_ == 1 ? 0 : 1;
|
||||
/* Create encoder memory. */
|
||||
EXPECT_EQ(0, WebRtcOpus_EncoderCreate(&opus_encoder_, channels_, app, 48000));
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_));
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(&opus_decoder_, channels_, 48000));
|
||||
/* Set bitrate. */
|
||||
EXPECT_EQ(0, WebRtcOpus_SetBitRate(opus_encoder_, bit_rate_));
|
||||
}
|
||||
|
||||
@ -67,9 +67,11 @@ void CreateSingleOrMultiStreamEncoder(WebRtcOpusEncInst** opus_encoder,
|
||||
|
||||
void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder,
|
||||
int channels,
|
||||
bool use_multistream) {
|
||||
bool use_multistream,
|
||||
int decoder_sample_rate_hz) {
|
||||
EXPECT_TRUE(channels == 1 || channels == 2 || use_multistream);
|
||||
if (use_multistream) {
|
||||
EXPECT_EQ(decoder_sample_rate_hz, 48000);
|
||||
if (channels == 1) {
|
||||
EXPECT_EQ(0, WebRtcOpus_MultistreamDecoderCreate(
|
||||
opus_decoder, channels, kMonoTotalStreams,
|
||||
@ -86,10 +88,16 @@ void CreateSingleOrMultiStreamDecoder(WebRtcOpusDecInst** opus_decoder,
|
||||
EXPECT_TRUE(false) << channels;
|
||||
}
|
||||
} else {
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels));
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderCreate(opus_decoder, channels,
|
||||
decoder_sample_rate_hz));
|
||||
}
|
||||
}
|
||||
|
||||
int SamplesPerChannel(int sample_rate_hz, int duration_ms) {
|
||||
const int samples_per_ms = rtc::CheckedDivExact(sample_rate_hz, 1000);
|
||||
return samples_per_ms * duration_ms;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using test::AudioLoop;
|
||||
@ -99,16 +107,11 @@ using ::testing::Combine;
|
||||
|
||||
// Maximum number of bytes in output bitstream.
|
||||
const size_t kMaxBytes = 2000;
|
||||
// Sample rate of Opus.
|
||||
const size_t kOpusDecodeRateKhz = 48;
|
||||
// Number of samples-per-channel in a 20 ms frame, sampled at 48 kHz.
|
||||
const size_t kOpus20msFrameDecodeSamples = kOpusDecodeRateKhz * 20;
|
||||
// Number of samples-per-channel in a 10 ms frame, sampled at 48 kHz.
|
||||
const size_t kOpus10msFrameDecodeSamples = kOpusDecodeRateKhz * 10;
|
||||
|
||||
class OpusTest : public TestWithParam<::testing::tuple<int, int, bool, int>> {
|
||||
class OpusTest
|
||||
: public TestWithParam<::testing::tuple<size_t, int, bool, int, int>> {
|
||||
protected:
|
||||
OpusTest();
|
||||
OpusTest() = default;
|
||||
|
||||
void TestDtxEffect(bool dtx, int block_length_ms);
|
||||
|
||||
@ -135,26 +138,35 @@ class OpusTest : public TestWithParam<::testing::tuple<int, int, bool, int>> {
|
||||
size_t channels,
|
||||
uint16_t bound) const;
|
||||
|
||||
WebRtcOpusEncInst* opus_encoder_;
|
||||
WebRtcOpusDecInst* opus_decoder_;
|
||||
|
||||
WebRtcOpusEncInst* opus_encoder_ = nullptr;
|
||||
WebRtcOpusDecInst* opus_decoder_ = nullptr;
|
||||
AudioLoop speech_data_;
|
||||
uint8_t bitstream_[kMaxBytes];
|
||||
size_t encoded_bytes_;
|
||||
const size_t channels_;
|
||||
const int application_;
|
||||
const bool use_multistream_;
|
||||
const int encoder_sample_rate_hz_;
|
||||
size_t encoded_bytes_ = 0;
|
||||
const size_t channels_{std::get<0>(GetParam())};
|
||||
const int application_{std::get<1>(GetParam())};
|
||||
const bool use_multistream_{std::get<2>(GetParam())};
|
||||
const int encoder_sample_rate_hz_{std::get<3>(GetParam())};
|
||||
const int decoder_sample_rate_hz_{std::get<4>(GetParam())};
|
||||
};
|
||||
|
||||
OpusTest::OpusTest()
|
||||
: opus_encoder_(NULL),
|
||||
opus_decoder_(NULL),
|
||||
encoded_bytes_(0),
|
||||
channels_(static_cast<size_t>(::testing::get<0>(GetParam()))),
|
||||
application_(::testing::get<1>(GetParam())),
|
||||
use_multistream_(::testing::get<2>(GetParam())),
|
||||
encoder_sample_rate_hz_(::testing::get<3>(GetParam())) {}
|
||||
// Singlestream: Try all combinations.
|
||||
INSTANTIATE_TEST_SUITE_P(Singlestream,
|
||||
OpusTest,
|
||||
testing::Combine(testing::Values(1, 2),
|
||||
testing::Values(0, 1),
|
||||
testing::Values(false),
|
||||
testing::Values(16000, 48000),
|
||||
testing::Values(16000, 48000)));
|
||||
|
||||
// Multistream: Some representative cases (only 48 kHz for now).
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
Multistream,
|
||||
OpusTest,
|
||||
testing::Values(std::make_tuple(1, 0, true, 48000, 48000),
|
||||
std::make_tuple(2, 1, true, 48000, 48000),
|
||||
std::make_tuple(4, 0, true, 48000, 48000),
|
||||
std::make_tuple(4, 1, true, 48000, 48000)));
|
||||
|
||||
void OpusTest::PrepareSpeechData(int block_length_ms, int loop_length_ms) {
|
||||
std::map<int, std::string> channel_to_basename = {
|
||||
@ -220,12 +232,14 @@ void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) {
|
||||
PrepareSpeechData(block_length_ms, 2000);
|
||||
const size_t input_samples =
|
||||
rtc::CheckedDivExact(encoder_sample_rate_hz_, 1000) * block_length_ms;
|
||||
const size_t output_samples = kOpusDecodeRateKhz * block_length_ms;
|
||||
const size_t output_samples =
|
||||
rtc::CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms;
|
||||
|
||||
// Create encoder memory.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(
|
||||
@ -385,7 +399,8 @@ void OpusTest::TestDtxEffect(bool dtx, int block_length_ms) {
|
||||
// Test if CBR does what we expect.
|
||||
void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
|
||||
PrepareSpeechData(block_length_ms, 2000);
|
||||
const size_t output_samples = kOpusDecodeRateKhz * block_length_ms;
|
||||
const size_t output_samples =
|
||||
rtc::CheckedDivExact(decoder_sample_rate_hz_, 1000) * block_length_ms;
|
||||
|
||||
int32_t max_pkt_size_diff = 0;
|
||||
int32_t prev_pkt_size = 0;
|
||||
@ -393,7 +408,8 @@ void OpusTest::TestCbrEffect(bool cbr, int block_length_ms) {
|
||||
// Create encoder memory.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(
|
||||
@ -443,9 +459,11 @@ TEST(OpusTest, OpusCreateFail) {
|
||||
// Invalid sample rate.
|
||||
EXPECT_EQ(-1, WebRtcOpus_EncoderCreate(&opus_encoder, 1, 0, 12345));
|
||||
|
||||
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1));
|
||||
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(NULL, 1, 48000));
|
||||
// Invalid channel number.
|
||||
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257));
|
||||
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 257, 48000));
|
||||
// Invalid sample rate.
|
||||
EXPECT_EQ(-1, WebRtcOpus_DecoderCreate(&opus_decoder, 1, 12345));
|
||||
}
|
||||
|
||||
// Test failing Free.
|
||||
@ -459,7 +477,8 @@ TEST(OpusTest, OpusFreeFail) {
|
||||
TEST_P(OpusTest, OpusCreateFree) {
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
EXPECT_TRUE(opus_encoder_ != NULL);
|
||||
EXPECT_TRUE(opus_decoder_ != NULL);
|
||||
// Free encoder and decoder memory.
|
||||
@ -478,7 +497,8 @@ TEST_P(OpusTest, OpusEncodeDecode) {
|
||||
// Create encoder memory.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(
|
||||
@ -495,12 +515,13 @@ TEST_P(OpusTest, OpusEncodeDecode) {
|
||||
|
||||
// Encode & decode.
|
||||
int16_t audio_type;
|
||||
const int decode_samples_per_channel =
|
||||
SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
|
||||
int16_t* output_data_decode =
|
||||
new int16_t[kOpus20msFrameDecodeSamples * channels_];
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type)));
|
||||
new int16_t[decode_samples_per_channel * channels_];
|
||||
EXPECT_EQ(decode_samples_per_channel,
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type));
|
||||
|
||||
// Free memory.
|
||||
delete[] output_data_decode;
|
||||
@ -549,8 +570,10 @@ TEST_P(OpusTest, OpusSetBandwidth) {
|
||||
PrepareSpeechData(20, 20);
|
||||
|
||||
int16_t audio_type;
|
||||
const int decode_samples_per_channel =
|
||||
SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
|
||||
std::unique_ptr<int16_t[]> output_data_decode(
|
||||
new int16_t[kOpus20msFrameDecodeSamples * channels_]());
|
||||
new int16_t[decode_samples_per_channel * channels_]());
|
||||
|
||||
// Test without creating encoder memory.
|
||||
EXPECT_EQ(-1,
|
||||
@ -560,7 +583,8 @@ TEST_P(OpusTest, OpusSetBandwidth) {
|
||||
// Create encoder memory, try with different bandwidths.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
EXPECT_EQ(-1, WebRtcOpus_SetBandwidth(opus_encoder_,
|
||||
OPUS_BANDWIDTH_NARROWBAND - 1));
|
||||
@ -618,23 +642,24 @@ TEST_P(OpusTest, OpusDecodeInit) {
|
||||
// Create encoder memory.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// Encode & decode.
|
||||
int16_t audio_type;
|
||||
const int decode_samples_per_channel =
|
||||
SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
|
||||
int16_t* output_data_decode =
|
||||
new int16_t[kOpus20msFrameDecodeSamples * channels_];
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type)));
|
||||
new int16_t[decode_samples_per_channel * channels_];
|
||||
EXPECT_EQ(decode_samples_per_channel,
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type));
|
||||
|
||||
WebRtcOpus_DecoderInit(opus_decoder_);
|
||||
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(
|
||||
WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
|
||||
output_data_decode, &audio_type)));
|
||||
EXPECT_EQ(decode_samples_per_channel,
|
||||
WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
|
||||
output_data_decode, &audio_type));
|
||||
|
||||
// Free memory.
|
||||
delete[] output_data_decode;
|
||||
@ -762,7 +787,8 @@ TEST_P(OpusTest, OpusDecodePlc) {
|
||||
// Create encoder memory.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// Set bitrate.
|
||||
EXPECT_EQ(
|
||||
@ -773,18 +799,18 @@ TEST_P(OpusTest, OpusDecodePlc) {
|
||||
|
||||
// Encode & decode.
|
||||
int16_t audio_type;
|
||||
const int decode_samples_per_channel =
|
||||
SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
|
||||
int16_t* output_data_decode =
|
||||
new int16_t[kOpus20msFrameDecodeSamples * channels_];
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type)));
|
||||
new int16_t[decode_samples_per_channel * channels_];
|
||||
EXPECT_EQ(decode_samples_per_channel,
|
||||
EncodeDecode(opus_encoder_, speech_data_.GetNextBlock(),
|
||||
opus_decoder_, output_data_decode, &audio_type));
|
||||
|
||||
// Call decoder PLC.
|
||||
int16_t* plc_buffer = new int16_t[kOpus20msFrameDecodeSamples * channels_];
|
||||
EXPECT_EQ(
|
||||
kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1)));
|
||||
int16_t* plc_buffer = new int16_t[decode_samples_per_channel * channels_];
|
||||
EXPECT_EQ(decode_samples_per_channel,
|
||||
WebRtcOpus_DecodePlc(opus_decoder_, plc_buffer, 1));
|
||||
|
||||
// Free memory.
|
||||
delete[] plc_buffer;
|
||||
@ -800,7 +826,8 @@ TEST_P(OpusTest, OpusDurationEstimation) {
|
||||
// Create.
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
|
||||
// 10 ms. We use only first 10 ms of a 20 ms block.
|
||||
auto speech_block = speech_data_.GetNextBlock();
|
||||
@ -809,10 +836,9 @@ TEST_P(OpusTest, OpusDurationEstimation) {
|
||||
rtc::CheckedDivExact(speech_block.size(), 2 * channels_), kMaxBytes,
|
||||
bitstream_);
|
||||
EXPECT_GE(encoded_bytes_int, 0);
|
||||
EXPECT_EQ(
|
||||
kOpus10msFrameDecodeSamples,
|
||||
static_cast<size_t>(WebRtcOpus_DurationEst(
|
||||
opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
|
||||
EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/10),
|
||||
WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
|
||||
static_cast<size_t>(encoded_bytes_int)));
|
||||
|
||||
// 20 ms
|
||||
speech_block = speech_data_.GetNextBlock();
|
||||
@ -821,10 +847,9 @@ TEST_P(OpusTest, OpusDurationEstimation) {
|
||||
rtc::CheckedDivExact(speech_block.size(), channels_),
|
||||
kMaxBytes, bitstream_);
|
||||
EXPECT_GE(encoded_bytes_int, 0);
|
||||
EXPECT_EQ(
|
||||
kOpus20msFrameDecodeSamples,
|
||||
static_cast<size_t>(WebRtcOpus_DurationEst(
|
||||
opus_decoder_, bitstream_, static_cast<size_t>(encoded_bytes_int))));
|
||||
EXPECT_EQ(SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20),
|
||||
WebRtcOpus_DurationEst(opus_decoder_, bitstream_,
|
||||
static_cast<size_t>(encoded_bytes_int)));
|
||||
|
||||
// Free memory.
|
||||
EXPECT_EQ(0, WebRtcOpus_EncoderFree(opus_encoder_));
|
||||
@ -846,7 +871,8 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
||||
CreateSingleOrMultiStreamEncoder(&opus_encoder_, channels_, application_,
|
||||
use_multistream_, encoder_sample_rate_hz_);
|
||||
ASSERT_NE(nullptr, opus_encoder_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_);
|
||||
CreateSingleOrMultiStreamDecoder(&opus_decoder_, channels_, use_multistream_,
|
||||
decoder_sample_rate_hz_);
|
||||
ASSERT_NE(nullptr, opus_decoder_);
|
||||
|
||||
// Set bitrate.
|
||||
@ -858,8 +884,10 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
||||
|
||||
// Encode & decode.
|
||||
int16_t audio_type;
|
||||
const int decode_samples_per_channel =
|
||||
SamplesPerChannel(decoder_sample_rate_hz_, /*ms=*/20);
|
||||
std::unique_ptr<int16_t[]> output_data_decode(
|
||||
new int16_t[kPackets * kOpus20msFrameDecodeSamples * channels_]);
|
||||
new int16_t[kPackets * decode_samples_per_channel * channels_]);
|
||||
OpusRepacketizer* rp = opus_repacketizer_create();
|
||||
|
||||
size_t num_packets = 0;
|
||||
@ -887,11 +915,11 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
||||
|
||||
encoded_bytes_ = opus_repacketizer_out(rp, bitstream_, kMaxBytes);
|
||||
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples * kPackets,
|
||||
EXPECT_EQ(decode_samples_per_channel * kPackets,
|
||||
static_cast<size_t>(WebRtcOpus_DurationEst(
|
||||
opus_decoder_, bitstream_, encoded_bytes_)));
|
||||
|
||||
EXPECT_EQ(kOpus20msFrameDecodeSamples * kPackets,
|
||||
EXPECT_EQ(decode_samples_per_channel * kPackets,
|
||||
static_cast<size_t>(
|
||||
WebRtcOpus_Decode(opus_decoder_, bitstream_, encoded_bytes_,
|
||||
output_data_decode.get(), &audio_type)));
|
||||
@ -902,21 +930,4 @@ TEST_P(OpusTest, OpusDecodeRepacketized) {
|
||||
EXPECT_EQ(0, WebRtcOpus_DecoderFree(opus_decoder_));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(VariousMode,
|
||||
OpusTest,
|
||||
::testing::ValuesIn({
|
||||
std::make_tuple(1, 0, false, 16000),
|
||||
std::make_tuple(1, 1, false, 16000),
|
||||
std::make_tuple(2, 0, false, 16000),
|
||||
std::make_tuple(2, 1, false, 16000),
|
||||
std::make_tuple(1, 0, false, 48000),
|
||||
std::make_tuple(1, 1, false, 48000),
|
||||
std::make_tuple(2, 0, false, 48000),
|
||||
std::make_tuple(2, 1, false, 48000),
|
||||
std::make_tuple(1, 0, true, 48000),
|
||||
std::make_tuple(2, 1, true, 48000),
|
||||
std::make_tuple(4, 0, true, 48000),
|
||||
std::make_tuple(4, 1, true, 48000),
|
||||
}));
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user