Make FakeDecodeFromFile handle codec-internal CNG
This implementation interprets payloads of size 1 as codec-internal SID frames, marking the start of a CNG period. Changes were made to other parts of the test payload chain, since it had to make use of the virtual payload size in the case of header-only RTP files. BUG=webrtc:2692 Review-Url: https://codereview.webrtc.org/2275903002 Cr-Commit-Position: refs/heads/master@{#13901}
This commit is contained in:
committed by
Commit bot
parent
f02207dde9
commit
d1a10a0f77
@ -19,14 +19,37 @@ namespace test {
|
||||
|
||||
int FakeDecodeFromFile::DecodeInternal(const uint8_t* encoded,
|
||||
size_t encoded_len,
|
||||
int /*sample_rate_hz*/,
|
||||
int sample_rate_hz,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_CHECK_GE(encoded_len, 8u);
|
||||
if (encoded_len == 0) {
|
||||
// Decoder is asked to produce codec-internal comfort noise.
|
||||
RTC_DCHECK(!encoded); // NetEq always sends nullptr in this case.
|
||||
RTC_DCHECK(cng_mode_);
|
||||
RTC_DCHECK_GT(last_decoded_length_, 0u);
|
||||
std::fill_n(decoded, last_decoded_length_, 0);
|
||||
*speech_type = kComfortNoise;
|
||||
return last_decoded_length_;
|
||||
}
|
||||
|
||||
RTC_CHECK_GE(encoded_len, 12u);
|
||||
uint32_t timestamp_to_decode =
|
||||
ByteReader<uint32_t>::ReadLittleEndian(encoded);
|
||||
uint32_t samples_to_decode =
|
||||
ByteReader<uint32_t>::ReadLittleEndian(&encoded[4]);
|
||||
if (samples_to_decode == 0) {
|
||||
// Number of samples in packet is unknown.
|
||||
if (last_decoded_length_ > 0) {
|
||||
// Use length of last decoded packet, but since this is the total for all
|
||||
// channels, we have to divide by 2 in the stereo case.
|
||||
samples_to_decode = rtc::CheckedDivExact(
|
||||
last_decoded_length_, static_cast<size_t>(stereo_ ? 2uL : 1uL));
|
||||
} else {
|
||||
// This is the first packet to decode, and we do not know the length of
|
||||
// it. Set it to 10 ms.
|
||||
samples_to_decode = rtc::CheckedDivExact(sample_rate_hz, 100);
|
||||
}
|
||||
}
|
||||
|
||||
if (next_timestamp_from_input_ &&
|
||||
timestamp_to_decode != *next_timestamp_from_input_) {
|
||||
@ -36,10 +59,23 @@ int FakeDecodeFromFile::DecodeInternal(const uint8_t* encoded,
|
||||
RTC_CHECK(input_->Seek(jump));
|
||||
}
|
||||
|
||||
RTC_CHECK(input_->Read(static_cast<size_t>(samples_to_decode), decoded));
|
||||
next_timestamp_from_input_ =
|
||||
rtc::Optional<uint32_t>(timestamp_to_decode + samples_to_decode);
|
||||
|
||||
uint32_t original_payload_size_bytes =
|
||||
ByteReader<uint32_t>::ReadLittleEndian(&encoded[8]);
|
||||
if (original_payload_size_bytes == 1) {
|
||||
// This is a comfort noise payload.
|
||||
RTC_DCHECK_GT(last_decoded_length_, 0u);
|
||||
std::fill_n(decoded, last_decoded_length_, 0);
|
||||
*speech_type = kComfortNoise;
|
||||
cng_mode_ = true;
|
||||
return last_decoded_length_;
|
||||
}
|
||||
|
||||
cng_mode_ = false;
|
||||
RTC_CHECK(input_->Read(static_cast<size_t>(samples_to_decode), decoded));
|
||||
|
||||
if (stereo_) {
|
||||
InputAudioFile::DuplicateInterleaved(decoded, samples_to_decode, 2,
|
||||
decoded);
|
||||
@ -47,16 +83,19 @@ int FakeDecodeFromFile::DecodeInternal(const uint8_t* encoded,
|
||||
}
|
||||
|
||||
*speech_type = kSpeech;
|
||||
return samples_to_decode;
|
||||
return last_decoded_length_ = samples_to_decode;
|
||||
}
|
||||
|
||||
void FakeDecodeFromFile::PrepareEncoded(uint32_t timestamp,
|
||||
size_t samples,
|
||||
size_t original_payload_size_bytes,
|
||||
rtc::ArrayView<uint8_t> encoded) {
|
||||
RTC_CHECK_GE(encoded.size(), 8u);
|
||||
RTC_CHECK_GE(encoded.size(), 12u);
|
||||
ByteWriter<uint32_t>::WriteLittleEndian(&encoded[0], timestamp);
|
||||
ByteWriter<uint32_t>::WriteLittleEndian(&encoded[4],
|
||||
rtc::checked_cast<uint32_t>(samples));
|
||||
ByteWriter<uint32_t>::WriteLittleEndian(
|
||||
&encoded[8], rtc::checked_cast<uint32_t>(original_payload_size_bytes));
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -50,11 +50,13 @@ class FakeDecodeFromFile : public AudioDecoder {
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) override;
|
||||
|
||||
// Helper method. Writes |timestamp| and |samples| to |encoded| in a format
|
||||
// that the FakeDecpdeFromFile decoder will understand. |encoded| must be at
|
||||
// least 8 bytes long.
|
||||
// Helper method. Writes |timestamp|, |samples| and
|
||||
// |original_payload_size_bytes| to |encoded| in a format that the
|
||||
// FakeDecodeFromFile decoder will understand. |encoded| must be at least 12
|
||||
// bytes long.
|
||||
static void PrepareEncoded(uint32_t timestamp,
|
||||
size_t samples,
|
||||
size_t original_payload_size_bytes,
|
||||
rtc::ArrayView<uint8_t> encoded);
|
||||
|
||||
private:
|
||||
@ -62,6 +64,8 @@ class FakeDecodeFromFile : public AudioDecoder {
|
||||
rtc::Optional<uint32_t> next_timestamp_from_input_;
|
||||
const int sample_rate_hz_;
|
||||
const bool stereo_;
|
||||
size_t last_decoded_length_ = 0;
|
||||
bool cng_mode_ = false;
|
||||
};
|
||||
|
||||
} // namespace test
|
||||
|
||||
@ -43,8 +43,16 @@ std::unique_ptr<NetEqInput::PacketData> NetEqPacketSourceInput::PopPacket() {
|
||||
}
|
||||
std::unique_ptr<PacketData> packet_data(new PacketData);
|
||||
packet_->ConvertHeader(&packet_data->header);
|
||||
if (packet_->payload_length_bytes() == 0 &&
|
||||
packet_->virtual_payload_length_bytes() > 0) {
|
||||
// This is a header-only "dummy" packet. Set the payload to all zeros, with
|
||||
// length according to the virtual length.
|
||||
packet_data->payload.SetSize(packet_->virtual_payload_length_bytes());
|
||||
std::fill_n(packet_data->payload.data(), packet_data->payload.size(), 0);
|
||||
} else {
|
||||
packet_data->payload.SetData(packet_->payload(),
|
||||
packet_->payload_length_bytes());
|
||||
}
|
||||
packet_data->time_ms = packet_->time_ms();
|
||||
|
||||
LoadNextPacket();
|
||||
|
||||
@ -84,11 +84,17 @@ void NetEqReplacementInput::ReplacePacket() {
|
||||
|
||||
rtc::Optional<RTPHeader> next_hdr = source_->NextHeader();
|
||||
RTC_DCHECK(next_hdr);
|
||||
uint8_t payload[8];
|
||||
uint8_t payload[12];
|
||||
uint32_t input_frame_size_timestamps =
|
||||
next_hdr->timestamp - packet_->header.header.timestamp;
|
||||
if (next_hdr->sequenceNumber != packet_->header.header.sequenceNumber + 1) {
|
||||
// Gap in packet sequence. Cannot estimate payload length based on timestamp
|
||||
// difference.
|
||||
input_frame_size_timestamps = 0;
|
||||
}
|
||||
FakeDecodeFromFile::PrepareEncoded(packet_->header.header.timestamp,
|
||||
input_frame_size_timestamps, payload);
|
||||
input_frame_size_timestamps,
|
||||
packet_->payload.size(), payload);
|
||||
packet_->payload.SetData(payload);
|
||||
packet_->header.header.payloadType = replacement_payload_type_;
|
||||
return;
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "webrtc/base/checks.h"
|
||||
#include "webrtc/modules/include/module_common_types.h"
|
||||
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
|
||||
|
||||
@ -142,6 +143,7 @@ bool Packet::ParseHeader(const RtpHeaderParser& parser) {
|
||||
payload_ = &payload_memory_[header_.headerLength];
|
||||
assert(packet_length_bytes_ >= header_.headerLength);
|
||||
payload_length_bytes_ = packet_length_bytes_ - header_.headerLength;
|
||||
RTC_CHECK_GE(virtual_packet_length_bytes_, packet_length_bytes_);
|
||||
assert(virtual_packet_length_bytes_ >= header_.headerLength);
|
||||
virtual_payload_length_bytes_ =
|
||||
virtual_packet_length_bytes_ - header_.headerLength;
|
||||
|
||||
Reference in New Issue
Block a user