Add encode/decode time tracing to audio_coding.
Also removes virtual from VideoDecoder::Decode and updated mocks and tests accordingly to use VideoDecoder::DecodeInternal instead. BUG=webrtc:5167 R=henrik.lundin@webrtc.org Review URL: https://codereview.webrtc.org/1512483003 . Cr-Commit-Position: refs/heads/master@{#10935}
This commit is contained in:
parent
9f45a45a62
commit
d7b7ae8bda
@ -976,7 +976,29 @@ TEST_F(AcmReceiverBitExactnessOldApi, IF_ALL_CODECS(MAYBE_48kHzOutput)) {
|
||||
#endif
|
||||
TEST_F(AcmReceiverBitExactnessOldApi,
|
||||
IF_ALL_CODECS(MAYBE_48kHzOutputExternalDecoder)) {
|
||||
// Class intended to forward a call from a mock DecodeInternal to Decode on
|
||||
// the real decoder's Decode. DecodeInternal for the real decoder isn't
|
||||
// public.
|
||||
class DecodeForwarder {
|
||||
public:
|
||||
DecodeForwarder(AudioDecoder* decoder) : decoder_(decoder) {}
|
||||
int Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
AudioDecoder::SpeechType* speech_type) {
|
||||
return decoder_->Decode(encoded, encoded_len, sample_rate_hz,
|
||||
decoder_->PacketDuration(encoded, encoded_len) *
|
||||
decoder_->Channels() * sizeof(int16_t),
|
||||
decoded, speech_type);
|
||||
}
|
||||
|
||||
private:
|
||||
AudioDecoder* const decoder_;
|
||||
};
|
||||
|
||||
AudioDecoderPcmU decoder(1);
|
||||
DecodeForwarder decode_forwarder(&decoder);
|
||||
MockAudioDecoder mock_decoder;
|
||||
// Set expectations on the mock decoder and also delegate the calls to the
|
||||
// real decoder.
|
||||
@ -986,9 +1008,9 @@ TEST_F(AcmReceiverBitExactnessOldApi,
|
||||
EXPECT_CALL(mock_decoder, Channels())
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::Channels));
|
||||
EXPECT_CALL(mock_decoder, Decode(_, _, _, _, _, _))
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(_, _, _, _, _))
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::Decode));
|
||||
.WillRepeatedly(Invoke(&decode_forwarder, &DecodeForwarder::Decode));
|
||||
EXPECT_CALL(mock_decoder, HasDecodePlc())
|
||||
.Times(AtLeast(1))
|
||||
.WillRepeatedly(Invoke(&decoder, &AudioDecoderPcmU::HasDecodePlc));
|
||||
|
||||
@ -13,12 +13,14 @@
|
||||
#include <assert.h>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
int AudioDecoder::Decode(const uint8_t* encoded, size_t encoded_len,
|
||||
int sample_rate_hz, size_t max_decoded_bytes,
|
||||
int16_t* decoded, SpeechType* speech_type) {
|
||||
TRACE_EVENT0("webrtc", "AudioDecoder::Decode");
|
||||
int duration = PacketDuration(encoded, encoded_len);
|
||||
if (duration >= 0 &&
|
||||
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
|
||||
@ -31,6 +33,7 @@ int AudioDecoder::Decode(const uint8_t* encoded, size_t encoded_len,
|
||||
int AudioDecoder::DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
|
||||
int sample_rate_hz, size_t max_decoded_bytes,
|
||||
int16_t* decoded, SpeechType* speech_type) {
|
||||
TRACE_EVENT0("webrtc", "AudioDecoder::DecodeRedundant");
|
||||
int duration = PacketDurationRedundant(encoded, encoded_len);
|
||||
if (duration >= 0 &&
|
||||
duration * Channels() * sizeof(int16_t) > max_decoded_bytes) {
|
||||
@ -40,12 +43,6 @@ int AudioDecoder::DecodeRedundant(const uint8_t* encoded, size_t encoded_len,
|
||||
speech_type);
|
||||
}
|
||||
|
||||
int AudioDecoder::DecodeInternal(const uint8_t* encoded, size_t encoded_len,
|
||||
int sample_rate_hz, int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
return kNotImplemented;
|
||||
}
|
||||
|
||||
int AudioDecoder::DecodeRedundantInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz, int16_t* decoded,
|
||||
|
||||
@ -41,21 +41,21 @@ class AudioDecoder {
|
||||
// is set to kComfortNoise, otherwise it is kSpeech. The desired output
|
||||
// sample rate is provided in |sample_rate_hz|, which must be valid for the
|
||||
// codec at hand.
|
||||
virtual int Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
int Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
|
||||
// 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,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
int DecodeRedundant(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
|
||||
// Indicates if the decoder implements the DecodePlc method.
|
||||
virtual bool HasDecodePlc() const;
|
||||
@ -107,7 +107,7 @@ class AudioDecoder {
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type);
|
||||
SpeechType* speech_type) = 0;
|
||||
|
||||
virtual int DecodeRedundantInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
|
||||
@ -9,7 +9,9 @@
|
||||
*/
|
||||
|
||||
#include "webrtc/modules/audio_coding/codecs/audio_encoder.h"
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/base/trace_event.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -26,6 +28,7 @@ AudioEncoder::EncodedInfo AudioEncoder::Encode(
|
||||
rtc::ArrayView<const int16_t> audio,
|
||||
size_t max_encoded_bytes,
|
||||
uint8_t* encoded) {
|
||||
TRACE_EVENT0("webrtc", "AudioEncoder::Encode");
|
||||
RTC_CHECK_EQ(audio.size(),
|
||||
static_cast<size_t>(NumChannels() * SampleRateHz() / 100));
|
||||
EncodedInfo info =
|
||||
|
||||
@ -22,9 +22,8 @@ class MockAudioDecoder : public AudioDecoder {
|
||||
MockAudioDecoder() {}
|
||||
virtual ~MockAudioDecoder() { Die(); }
|
||||
MOCK_METHOD0(Die, void());
|
||||
MOCK_METHOD6(
|
||||
Decode,
|
||||
int(const uint8_t*, size_t, int, size_t, int16_t*, SpeechType*));
|
||||
MOCK_METHOD5(DecodeInternal,
|
||||
int(const uint8_t*, size_t, int, int16_t*, SpeechType*));
|
||||
MOCK_CONST_METHOD0(HasDecodePlc, bool());
|
||||
MOCK_METHOD2(DecodePlc, size_t(size_t, int16_t*));
|
||||
MOCK_METHOD0(Reset, void());
|
||||
|
||||
@ -30,7 +30,6 @@ class ExternalPcm16B : public AudioDecoder {
|
||||
ExternalPcm16B() {}
|
||||
void Reset() override {}
|
||||
|
||||
protected:
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
@ -52,8 +51,8 @@ class MockExternalPcm16B : public ExternalPcm16B {
|
||||
public:
|
||||
MockExternalPcm16B() {
|
||||
// By default, all calls are delegated to the real object.
|
||||
ON_CALL(*this, Decode(_, _, _, _, _, _))
|
||||
.WillByDefault(Invoke(&real_, &ExternalPcm16B::Decode));
|
||||
ON_CALL(*this, DecodeInternal(_, _, _, _, _))
|
||||
.WillByDefault(Invoke(&real_, &ExternalPcm16B::DecodeInternal));
|
||||
ON_CALL(*this, HasDecodePlc())
|
||||
.WillByDefault(Invoke(&real_, &ExternalPcm16B::HasDecodePlc));
|
||||
ON_CALL(*this, DecodePlc(_, _))
|
||||
@ -68,11 +67,10 @@ class MockExternalPcm16B : public ExternalPcm16B {
|
||||
virtual ~MockExternalPcm16B() { Die(); }
|
||||
|
||||
MOCK_METHOD0(Die, void());
|
||||
MOCK_METHOD6(Decode,
|
||||
MOCK_METHOD5(DecodeInternal,
|
||||
int(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int sample_rate_hz,
|
||||
size_t max_decoded_bytes,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type));
|
||||
MOCK_CONST_METHOD0(HasDecodePlc,
|
||||
|
||||
@ -98,8 +98,9 @@ class NetEqExternalDecoderUnitTest : public test::NetEqExternalDecoderTest {
|
||||
next_arrival_time = GetArrivalTime(next_send_time);
|
||||
} while (Lost()); // If lost, immediately read the next packet.
|
||||
|
||||
EXPECT_CALL(*external_decoder_,
|
||||
Decode(_, payload_size_bytes_, 1000 * samples_per_ms_, _, _, _))
|
||||
EXPECT_CALL(
|
||||
*external_decoder_,
|
||||
DecodeInternal(_, payload_size_bytes_, 1000 * samples_per_ms_, _, _))
|
||||
.Times(NumExpectedDecodeCalls(num_loops));
|
||||
|
||||
uint32_t time_now = 0;
|
||||
|
||||
@ -431,12 +431,11 @@ TEST_F(NetEqImplTest, VerifyTimestampPropagation) {
|
||||
CountingSamplesDecoder() : next_value_(1) {}
|
||||
|
||||
// Produce as many samples as input bytes (|encoded_len|).
|
||||
int Decode(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int /* sample_rate_hz */,
|
||||
size_t /* max_decoded_bytes */,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override {
|
||||
int DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int /* sample_rate_hz */,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override {
|
||||
for (size_t i = 0; i < encoded_len; ++i) {
|
||||
decoded[i] = next_value_++;
|
||||
}
|
||||
@ -527,11 +526,11 @@ TEST_F(NetEqImplTest, ReorderedPacket) {
|
||||
int16_t dummy_output[kPayloadLengthSamples] = {0};
|
||||
// The below expectation will make the mock decoder write
|
||||
// |kPayloadLengthSamples| zeros to the output array, and mark it as speech.
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(Pointee(0), kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(0), kPayloadLengthBytes,
|
||||
kSampleRateHz, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kPayloadLengthSamples)));
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
|
||||
&mock_decoder, NetEqDecoder::kDecoderPCM16B,
|
||||
@ -570,11 +569,11 @@ TEST_F(NetEqImplTest, ReorderedPacket) {
|
||||
|
||||
// Expect only the second packet to be decoded (the one with "2" as the first
|
||||
// payload byte).
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(Pointee(2), kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(2), kPayloadLengthBytes,
|
||||
kSampleRateHz, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
// Pull audio once.
|
||||
@ -688,31 +687,32 @@ TEST_F(NetEqImplTest, CodecInternalCng) {
|
||||
|
||||
// Pointee(x) verifies that first byte of the payload equals x, this makes it
|
||||
// possible to verify that the correct payload is fed to Decode().
|
||||
EXPECT_CALL(mock_decoder, Decode(Pointee(0), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(0), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
EXPECT_CALL(mock_decoder, Decode(Pointee(1), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(1), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kComfortNoise),
|
||||
SetArgPointee<4>(AudioDecoder::kComfortNoise),
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
EXPECT_CALL(mock_decoder, Decode(IsNull(), 0, kSampleRateKhz * 1000, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder,
|
||||
DecodeInternal(IsNull(), 0, kSampleRateKhz * 1000, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kComfortNoise),
|
||||
SetArgPointee<4>(AudioDecoder::kComfortNoise),
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
EXPECT_CALL(mock_decoder, Decode(Pointee(2), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<4>(dummy_output,
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(Pointee(2), kPayloadLengthBytes,
|
||||
kSampleRateKhz * 1000, _, _))
|
||||
.WillOnce(DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kPayloadLengthSamples)));
|
||||
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
|
||||
@ -960,11 +960,11 @@ TEST_F(NetEqImplTest, DecodedPayloadTooShort) {
|
||||
// |kPayloadLengthSamples| - 5 zeros to the output array, and mark it as
|
||||
// speech. That is, the decoded length is 5 samples shorter than the expected.
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _))
|
||||
.WillOnce(
|
||||
DoAll(SetArrayArgument<4>(dummy_output,
|
||||
DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kPayloadLengthSamples - 5),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kPayloadLengthSamples - 5)));
|
||||
EXPECT_EQ(NetEq::kOK, neteq_->RegisterExternalDecoder(
|
||||
&mock_decoder, NetEqDecoder::kDecoderPCM16B,
|
||||
@ -1034,30 +1034,30 @@ TEST_F(NetEqImplTest, DecodingError) {
|
||||
InSequence sequence; // Dummy variable.
|
||||
// Mock decoder works normally the first time.
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _))
|
||||
.Times(3)
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArrayArgument<4>(dummy_output,
|
||||
DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kFrameLengthSamples)))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
// Then mock decoder fails. A common reason for failure can be buffer being
|
||||
// too short
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _))
|
||||
.WillOnce(Return(-1))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
// Mock decoder finally returns to normal.
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArrayArgument<4>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kSpeech),
|
||||
DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<4>(AudioDecoder::kSpeech),
|
||||
Return(kFrameLengthSamples)));
|
||||
}
|
||||
|
||||
@ -1157,28 +1157,28 @@ TEST_F(NetEqImplTest, DecodingErrorDuringInternalCng) {
|
||||
InSequence sequence; // Dummy variable.
|
||||
// Mock decoder works normally the first 2 times.
|
||||
EXPECT_CALL(mock_decoder,
|
||||
Decode(_, kPayloadLengthBytes, kSampleRateHz, _, _, _))
|
||||
DecodeInternal(_, kPayloadLengthBytes, kSampleRateHz, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArrayArgument<4>(dummy_output,
|
||||
DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kComfortNoise),
|
||||
SetArgPointee<4>(AudioDecoder::kComfortNoise),
|
||||
Return(kFrameLengthSamples)))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
// Then mock decoder fails. A common reason for failure can be buffer being
|
||||
// too short
|
||||
EXPECT_CALL(mock_decoder, Decode(nullptr, 0, kSampleRateHz, _, _, _))
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(nullptr, 0, kSampleRateHz, _, _))
|
||||
.WillOnce(Return(-1))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
// Mock decoder finally returns to normal.
|
||||
EXPECT_CALL(mock_decoder, Decode(nullptr, 0, kSampleRateHz, _, _, _))
|
||||
EXPECT_CALL(mock_decoder, DecodeInternal(nullptr, 0, kSampleRateHz, _, _))
|
||||
.Times(2)
|
||||
.WillRepeatedly(
|
||||
DoAll(SetArrayArgument<4>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<5>(AudioDecoder::kComfortNoise),
|
||||
DoAll(SetArrayArgument<3>(dummy_output,
|
||||
dummy_output + kFrameLengthSamples),
|
||||
SetArgPointee<4>(AudioDecoder::kComfortNoise),
|
||||
Return(kFrameLengthSamples)));
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user