
We encounter a sample-underrun if NetEq is initialized with a sampling rate fs =16000 and receive Opus packets with frame-size less than 5 ms. The reason is as follows. Let say NetEq buffer has 4 packets of Opus each of size 2.5ms this means that internally timestamp of packets incremented by 80 (internally Opus treated as 32 kHz codec). Given the initial sampling rate of NetEq, at the first time that it wants to fetch packets, it targets to fetch 160 samples. Therefore, it will only extracts 2 packets. Decoding these packets give us exactly 160 samples (5 ms at 32 kHz), however, upon decoding the first packet the internal sampling rate will be updated to 32 kHz. So it is expected that sync buffer to deliver 320 samples while it does only have 160 samples (or maybe few more as it starts with some zeros). And we encounter and under-run. Even if we ignore the under-run "assert(sync_buffer_->FutureLength() >= expand_->overlap_length())" (neteq_impl.cc::811) is trigered. I'm not sure what happens if we remove this assert perhaps NetEq will work fine in subsequent calls. However the first under-run is blocking ACM2 test to pass. Here I have a solution to update sample rate as soon as a packet is inserted, if required. It not a very efficient approach as we do the same reset in NetEqImpl::Decode(). It is a bit tricky to reproduce this because the TOT ACM tests do not run ACM2. In https://webrtc-codereview.appspot.com/2192005/ I have a patch to run both ACMs. To reproduce the problem, one can patch that CL and run $ out/Debug/modules_tests --gtest_filter=AudioCodingModuleTest.TestOpus Note that we would not encounter any problem if NetEq4 is initiated with 32000 Hz sampling rate. You can test this by setting |kNeteqInitSampleRateHz| to 32000 in webrtc/modules/audio_coding/main/acm2/acm_receiver.cc BUG= R=andrew@webrtc.org, henrik.lundin@webrtc.org, kjellander@webrtc.org Review URL: https://webrtc-codereview.appspot.com/2306004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@4896 4adac7df-926f-26a2-2b94-8c16560cd09d
142 lines
4.3 KiB
C++
142 lines
4.3 KiB
C++
/*
|
|
* Copyright (c) 2012 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.
|
|
*/
|
|
|
|
#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ4_INTERFACE_AUDIO_DECODER_H_
|
|
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ4_INTERFACE_AUDIO_DECODER_H_
|
|
|
|
#include <stdlib.h> // NULL
|
|
|
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
|
#include "webrtc/typedefs.h"
|
|
|
|
namespace webrtc {
|
|
|
|
enum NetEqDecoder {
|
|
kDecoderPCMu,
|
|
kDecoderPCMa,
|
|
kDecoderPCMu_2ch,
|
|
kDecoderPCMa_2ch,
|
|
kDecoderILBC,
|
|
kDecoderISAC,
|
|
kDecoderISACswb,
|
|
kDecoderISACfb,
|
|
kDecoderPCM16B,
|
|
kDecoderPCM16Bwb,
|
|
kDecoderPCM16Bswb32kHz,
|
|
kDecoderPCM16Bswb48kHz,
|
|
kDecoderPCM16B_2ch,
|
|
kDecoderPCM16Bwb_2ch,
|
|
kDecoderPCM16Bswb32kHz_2ch,
|
|
kDecoderPCM16Bswb48kHz_2ch,
|
|
kDecoderPCM16B_5ch,
|
|
kDecoderG722,
|
|
kDecoderG722_2ch,
|
|
kDecoderRED,
|
|
kDecoderAVT,
|
|
kDecoderCNGnb,
|
|
kDecoderCNGwb,
|
|
kDecoderCNGswb32kHz,
|
|
kDecoderCNGswb48kHz,
|
|
kDecoderArbitrary,
|
|
kDecoderOpus,
|
|
kDecoderOpus_2ch,
|
|
kDecoderCELT_32,
|
|
kDecoderCELT_32_2ch,
|
|
};
|
|
|
|
// This is the interface class for decoders in NetEQ. Each codec type will have
|
|
// and implementation of this class.
|
|
class AudioDecoder {
|
|
public:
|
|
enum SpeechType {
|
|
kSpeech = 1,
|
|
kComfortNoise = 2
|
|
};
|
|
|
|
// Used by PacketDuration below. Save the value -1 for errors.
|
|
enum { kNotImplemented = -2 };
|
|
|
|
explicit AudioDecoder(enum NetEqDecoder type)
|
|
: codec_type_(type),
|
|
channels_(1),
|
|
state_(NULL) {
|
|
}
|
|
|
|
virtual ~AudioDecoder() {}
|
|
|
|
// Decodes |encode_len| bytes from |encoded| and writes the result in
|
|
// |decoded|. The number of samples from all channels produced is in
|
|
// the return value. If the decoder produced comfort noise, |speech_type|
|
|
// is set to kComfortNoise, otherwise it is kSpeech.
|
|
virtual int Decode(const uint8_t* encoded, size_t encoded_len,
|
|
int16_t* decoded, SpeechType* speech_type) = 0;
|
|
|
|
// Same as Decode(), but interfaces to the decoders redundant decode function.
|
|
// The default implementation simply calls the regular Decode() method.
|
|
virtual int DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
|
|
int16_t* decoded, SpeechType* speech_type);
|
|
|
|
// Indicates if the decoder implements the DecodePlc method.
|
|
virtual bool HasDecodePlc() const;
|
|
|
|
// Calls the packet-loss concealment of the decoder to update the state after
|
|
// one or several lost packets.
|
|
virtual int DecodePlc(int num_frames, int16_t* decoded);
|
|
|
|
// Initializes the decoder.
|
|
virtual int Init() = 0;
|
|
|
|
// Notifies the decoder of an incoming packet to NetEQ.
|
|
virtual int IncomingPacket(const uint8_t* payload,
|
|
size_t payload_len,
|
|
uint16_t rtp_sequence_number,
|
|
uint32_t rtp_timestamp,
|
|
uint32_t arrival_timestamp);
|
|
|
|
// Returns the last error code from the decoder.
|
|
virtual int ErrorCode();
|
|
|
|
// Returns the duration in samples of the payload in |encoded| which is
|
|
// |encoded_len| bytes long. Returns kNotImplemented if no duration estimate
|
|
// is available, or -1 in case of an error.
|
|
virtual int PacketDuration(const uint8_t* encoded, size_t encoded_len);
|
|
|
|
virtual NetEqDecoder codec_type() const;
|
|
|
|
// Returns the underlying decoder state.
|
|
void* state() { return state_; }
|
|
|
|
// Returns true if |codec_type| is supported.
|
|
static bool CodecSupported(NetEqDecoder codec_type);
|
|
|
|
// Returns the sample rate for |codec_type|.
|
|
static int CodecSampleRateHz(NetEqDecoder codec_type);
|
|
|
|
// Creates an AudioDecoder object of type |codec_type|. Returns NULL for
|
|
// for unsupported codecs, and when creating an AudioDecoder is not
|
|
// applicable (e.g., for RED and DTMF/AVT types).
|
|
static AudioDecoder* CreateAudioDecoder(NetEqDecoder codec_type);
|
|
|
|
size_t channels() const { return channels_; }
|
|
|
|
protected:
|
|
static SpeechType ConvertSpeechType(int16_t type);
|
|
|
|
enum NetEqDecoder codec_type_;
|
|
size_t channels_;
|
|
void* state_;
|
|
|
|
private:
|
|
DISALLOW_COPY_AND_ASSIGN(AudioDecoder);
|
|
};
|
|
|
|
} // namespace webrtc
|
|
#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ4_INTERFACE_AUDIO_DECODER_H_
|