Removed RTPHeader from NetEq's Packet struct.

Only three items in the (rather large) header were actually used after
InsertPacket: payloadType, timestamp and sequenceNumber. They are now
put directly into Packet. This saves 129 bytes per Packet that no
longer need to be allocated and deallocated.

This also works towards decoupling NetEq from RTP. As part of that,
I've moved the NACK code earlier in InsertPacketInternal, together
with other things that directly reference the RTPHeader.

BUG=webrtc:6549

Review-Url: https://codereview.webrtc.org/2411183003
Cr-Commit-Position: refs/heads/master@{#14658}
This commit is contained in:
ossu
2016-10-18 04:06:13 -07:00
committed by Commit bot
parent 553024ab34
commit 7a3776102f
20 changed files with 217 additions and 251 deletions

View File

@ -27,8 +27,7 @@ void ComfortNoise::Reset() {
int ComfortNoise::UpdateParameters(Packet* packet) {
assert(packet); // Existence is verified by caller.
// Get comfort noise decoder.
if (decoder_database_->SetActiveCngDecoder(packet->header.payloadType)
!= kOK) {
if (decoder_database_->SetActiveCngDecoder(packet->payload_type) != kOK) {
delete packet;
return kUnknownPayloadType;
}

View File

@ -103,7 +103,7 @@ void DecisionLogic::SetSampleRate(int fs_hz, size_t output_size_samples) {
Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
size_t generated_noise_samples,
@ -131,7 +131,7 @@ Operations DecisionLogic::GetDecision(const SyncBuffer& sync_buffer,
FilterBufferLevel(cur_size_samples, prev_mode);
return GetDecisionSpecialized(sync_buffer, expand, decoder_frame_length,
packet_header, prev_mode, play_dtmf,
next_packet, prev_mode, play_dtmf,
reset_decoder, generated_noise_samples);
}

View File

@ -26,7 +26,7 @@ class DelayManager;
class Expand;
class PacketBuffer;
class SyncBuffer;
struct RTPHeader;
struct Packet;
// This is the base class for the decision tree implementations. Derived classes
// must implement the method GetDecisionSpecialized().
@ -66,19 +66,18 @@ class DecisionLogic {
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// obtained from the last decoded frame. If there is a packet available, the
// packet header should be supplied in |packet_header|; otherwise it should
// be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
// supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
// should be set to true. The output variable |reset_decoder| will be set to
// true if a reset is required; otherwise it is left unchanged (i.e., it can
// remain true if it was true before the call).
// This method end with calling GetDecisionSpecialized to get the actual
// return value.
// obtained from the last decoded frame. If there is a packet available, it
// should be supplied in |next_packet|; otherwise it should be NULL. The mode
// resulting from the last call to NetEqImpl::GetAudio is supplied in
// |prev_mode|. If there is a DTMF event to play, |play_dtmf| should be set to
// true. The output variable |reset_decoder| will be set to true if a reset is
// required; otherwise it is left unchanged (i.e., it can remain true if it
// was true before the call). This method end with calling
// GetDecisionSpecialized to get the actual return value.
Operations GetDecision(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
size_t generated_noise_samples,
@ -124,18 +123,17 @@ class DecisionLogic {
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// obtained from the last decoded frame. If there is a packet available, the
// packet header should be supplied in |packet_header|; otherwise it should
// be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
// supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
// should be set to true. The output variable |reset_decoder| will be set to
// true if a reset is required; otherwise it is left unchanged (i.e., it can
// remain true if it was true before the call).
// Should be implemented by derived classes.
// obtained from the last decoded frame. If there is a packet available, it
// should be supplied in |next_packet|; otherwise it should be NULL. The mode
// resulting from the last call to NetEqImpl::GetAudio is supplied in
// |prev_mode|. If there is a DTMF event to play, |play_dtmf| should be set to
// true. The output variable |reset_decoder| will be set to true if a reset is
// required; otherwise it is left unchanged (i.e., it can remain true if it
// was true before the call). Should be implemented by derived classes.
virtual Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
bool* reset_decoder,

View File

@ -23,7 +23,7 @@ Operations DecisionLogicFax::GetDecisionSpecialized(
const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
bool* reset_decoder,
@ -32,10 +32,10 @@ Operations DecisionLogicFax::GetDecisionSpecialized(
uint32_t target_timestamp = sync_buffer.end_timestamp();
uint32_t available_timestamp = 0;
int is_cng_packet = 0;
if (packet_header) {
available_timestamp = packet_header->timestamp;
if (next_packet) {
available_timestamp = next_packet->timestamp;
is_cng_packet =
decoder_database_->IsComfortNoise(packet_header->payloadType);
decoder_database_->IsComfortNoise(next_packet->payload_type);
}
if (is_cng_packet) {
if (static_cast<int32_t>((generated_noise_samples + target_timestamp)
@ -47,7 +47,7 @@ Operations DecisionLogicFax::GetDecisionSpecialized(
return kRfc3389CngNoPacket;
}
}
if (!packet_header) {
if (!next_packet) {
// No packet. If in CNG mode, play as usual. Otherwise, use other method to
// generate data.
if (cng_state_ == kCngRfc3389On) {

View File

@ -40,19 +40,10 @@ class DecisionLogicFax : public DecisionLogic {
tick_timer) {}
protected:
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// obtained from the last decoded frame. If there is a packet available, the
// packet header should be supplied in |packet_header|; otherwise it should
// be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
// supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
// should be set to true. The output variable |reset_decoder| will be set to
// true if a reset is required; otherwise it is left unchanged (i.e., it can
// remain true if it was true before the call).
Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
bool* reset_decoder,

View File

@ -28,7 +28,7 @@ Operations DecisionLogicNormal::GetDecisionSpecialized(
const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
bool* reset_decoder,
@ -36,7 +36,7 @@ Operations DecisionLogicNormal::GetDecisionSpecialized(
assert(playout_mode_ == kPlayoutOn || playout_mode_ == kPlayoutStreaming);
// Guard for errors, to avoid getting stuck in error mode.
if (prev_mode == kModeError) {
if (!packet_header) {
if (!next_packet) {
return kExpand;
} else {
return kUndefined; // Use kUndefined to flag for a reset.
@ -46,10 +46,10 @@ Operations DecisionLogicNormal::GetDecisionSpecialized(
uint32_t target_timestamp = sync_buffer.end_timestamp();
uint32_t available_timestamp = 0;
bool is_cng_packet = false;
if (packet_header) {
available_timestamp = packet_header->timestamp;
if (next_packet) {
available_timestamp = next_packet->timestamp;
is_cng_packet =
decoder_database_->IsComfortNoise(packet_header->payloadType);
decoder_database_->IsComfortNoise(next_packet->payload_type);
}
if (is_cng_packet) {
@ -58,7 +58,7 @@ Operations DecisionLogicNormal::GetDecisionSpecialized(
}
// Handle the case with no packet at all available (except maybe DTMF).
if (!packet_header) {
if (!next_packet) {
return NoPacket(play_dtmf);
}

View File

@ -43,19 +43,10 @@ class DecisionLogicNormal : public DecisionLogic {
static const int kReinitAfterExpands = 100;
static const int kMaxWaitForPacket = 10;
// Returns the operation that should be done next. |sync_buffer| and |expand|
// are provided for reference. |decoder_frame_length| is the number of samples
// obtained from the last decoded frame. If there is a packet available, the
// packet header should be supplied in |packet_header|; otherwise it should
// be NULL. The mode resulting form the last call to NetEqImpl::GetAudio is
// supplied in |prev_mode|. If there is a DTMF event to play, |play_dtmf|
// should be set to true. The output variable |reset_decoder| will be set to
// true if a reset is required; otherwise it is left unchanged (i.e., it can
// remain true if it was true before the call).
Operations GetDecisionSpecialized(const SyncBuffer& sync_buffer,
const Expand& expand,
size_t decoder_frame_length,
const RTPHeader* packet_header,
const Packet* next_packet,
Modes prev_mode,
bool play_dtmf,
bool* reset_decoder,

View File

@ -310,10 +310,10 @@ bool DecoderDatabase::IsRed(uint8_t rtp_payload_type) const {
int DecoderDatabase::CheckPayloadTypes(const PacketList& packet_list) const {
PacketList::const_iterator it;
for (it = packet_list.begin(); it != packet_list.end(); ++it) {
if (!GetDecoderInfo((*it)->header.payloadType)) {
if (!GetDecoderInfo((*it)->payload_type)) {
// Payload type is not found.
LOG(LS_WARNING) << "CheckPayloadTypes: unknown RTP payload type "
<< static_cast<int>((*it)->header.payloadType);
<< static_cast<int>((*it)->payload_type);
return kDecoderNotFound;
}
}

View File

@ -176,7 +176,7 @@ TEST(DecoderDatabase, CheckPayloadTypes) {
// Create packet with payload type |i|. The last packet will have a payload
// type that is not registered in the decoder database.
Packet* packet = new Packet;
packet->header.payloadType = i;
packet->payload_type = i;
packet_list.push_back(packet);
}

View File

@ -38,8 +38,8 @@ class MockPacketBuffer : public PacketBuffer {
int(uint32_t* next_timestamp));
MOCK_CONST_METHOD2(NextHigherTimestamp,
int(uint32_t timestamp, uint32_t* next_timestamp));
MOCK_CONST_METHOD0(NextRtpHeader,
const RTPHeader*());
MOCK_CONST_METHOD0(PeekNextPacket,
const Packet*());
MOCK_METHOD1(GetNextPacket,
Packet*(size_t* discard_count));
MOCK_METHOD0(DiscardNextPacket,

View File

@ -581,48 +581,43 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
}
PacketList packet_list;
RTPHeader main_header;
{
// Convert to Packet.
// Create |packet| within this separate scope, since it should not be used
// directly once it's been inserted in the packet list. This way, |packet|
// is not defined outside of this block.
Packet* packet = new Packet;
packet->header.markerBit = false;
packet->header.payloadType = rtp_header.header.payloadType;
packet->header.sequenceNumber = rtp_header.header.sequenceNumber;
packet->header.timestamp = rtp_header.header.timestamp;
packet->header.ssrc = rtp_header.header.ssrc;
packet->header.numCSRCs = 0;
packet->payload_type = rtp_header.header.payloadType;
packet->sequence_number = rtp_header.header.sequenceNumber;
packet->timestamp = rtp_header.header.timestamp;
packet->payload.SetData(payload.data(), payload.size());
// Waiting time will be set upon inserting the packet in the buffer.
RTC_DCHECK(!packet->waiting_time);
// Insert packet in a packet list.
packet_list.push_back(packet);
// Save main payloads header for later.
memcpy(&main_header, &packet->header, sizeof(main_header));
}
bool update_sample_rate_and_channels = false;
// Reinitialize NetEq if it's needed (changed SSRC or first call).
if ((main_header.ssrc != ssrc_) || first_packet_) {
if ((rtp_header.header.ssrc != ssrc_) || first_packet_) {
// Note: |first_packet_| will be cleared further down in this method, once
// the packet has been successfully inserted into the packet buffer.
rtcp_.Init(main_header.sequenceNumber);
rtcp_.Init(rtp_header.header.sequenceNumber);
// Flush the packet buffer and DTMF buffer.
packet_buffer_->Flush();
dtmf_buffer_->Flush();
// Store new SSRC.
ssrc_ = main_header.ssrc;
ssrc_ = rtp_header.header.ssrc;
// Update audio buffer timestamp.
sync_buffer_->IncreaseEndTimestamp(main_header.timestamp - timestamp_);
sync_buffer_->IncreaseEndTimestamp(rtp_header.header.timestamp -
timestamp_);
// Update codecs.
timestamp_ = main_header.timestamp;
timestamp_ = rtp_header.header.timestamp;
// Reset timestamp scaling.
timestamp_scaler_->Reset();
@ -632,10 +627,19 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
}
// Update RTCP statistics, only for regular packets.
rtcp_.Update(main_header, receive_timestamp);
rtcp_.Update(rtp_header.header, receive_timestamp);
if (nack_enabled_) {
RTC_DCHECK(nack_);
if (update_sample_rate_and_channels) {
nack_->Reset();
}
nack_->UpdateLastReceivedPacket(rtp_header.header.sequenceNumber,
rtp_header.header.timestamp);
}
// Check for RED payload type, and separate payloads into several packets.
if (decoder_database_->IsRed(main_header.payloadType)) {
if (decoder_database_->IsRed(rtp_header.header.payloadType)) {
if (!red_payload_splitter_->SplitRed(&packet_list)) {
PacketBuffer::DeleteAllPackets(&packet_list);
return kRedundancySplitError;
@ -643,9 +647,6 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
// Only accept a few RED payloads of the same type as the main data,
// DTMF events and CNG.
red_payload_splitter_->CheckRedPayloads(&packet_list, *decoder_database_);
// Update the stored main payload header since the main payload has now
// changed.
memcpy(&main_header, &packet_list.front()->header, sizeof(main_header));
}
// Check payload types.
@ -655,6 +656,13 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
return kUnknownRtpPayloadType;
}
RTC_DCHECK(!packet_list.empty());
// Store these for later use, since the first packet may very well disappear
// before we need these values.
const uint32_t main_timestamp = packet_list.front()->timestamp;
const uint8_t main_payload_type = packet_list.front()->payload_type;
const uint16_t main_sequence_number = packet_list.front()->sequence_number;
// Scale timestamp to internal domain (only for some codecs).
timestamp_scaler_->ToInternal(&packet_list);
@ -665,9 +673,9 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
Packet* current_packet = (*it);
assert(current_packet);
assert(!current_packet->payload.empty());
if (decoder_database_->IsDtmf(current_packet->header.payloadType)) {
if (decoder_database_->IsDtmf(current_packet->payload_type)) {
DtmfEvent event;
int ret = DtmfBuffer::ParseEvent(current_packet->header.timestamp,
int ret = DtmfBuffer::ParseEvent(current_packet->timestamp,
current_packet->payload.data(),
current_packet->payload.size(), &event);
if (ret != DtmfBuffer::kOK) {
@ -687,16 +695,15 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
// Update bandwidth estimate, if the packet is not comfort noise.
if (!packet_list.empty() &&
!decoder_database_->IsComfortNoise(main_header.payloadType)) {
!decoder_database_->IsComfortNoise(main_payload_type)) {
// The list can be empty here if we got nothing but DTMF payloads.
AudioDecoder* decoder =
decoder_database_->GetDecoder(main_header.payloadType);
assert(decoder); // Should always get a valid object, since we have
// already checked that the payload types are known.
AudioDecoder* decoder = decoder_database_->GetDecoder(main_payload_type);
RTC_DCHECK(decoder); // Should always get a valid object, since we have
// already checked that the payload types are known.
decoder->IncomingPacket(packet_list.front()->payload.data(),
packet_list.front()->payload.size(),
packet_list.front()->header.sequenceNumber,
packet_list.front()->header.timestamp,
packet_list.front()->sequence_number,
packet_list.front()->timestamp,
receive_timestamp);
}
@ -705,7 +712,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
std::unique_ptr<Packet> packet(packet_list.front());
packet_list.pop_front();
const DecoderDatabase::DecoderInfo* info =
decoder_database_->GetDecoderInfo(packet->header.payloadType);
decoder_database_->GetDecoderInfo(packet->payload_type);
if (!info) {
LOG(LS_WARNING) << "SplitAudio unknown payload type";
return kUnknownRtpPayloadType;
@ -717,17 +724,19 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
} else {
std::vector<AudioDecoder::ParseResult> results =
info->GetDecoder()->ParsePayload(std::move(packet->payload),
packet->header.timestamp);
const RTPHeader& original_header = packet->header;
packet->timestamp);
const auto sequence_number = packet->sequence_number;
const auto payload_type = packet->payload_type;
const Packet::Priority original_priority = packet->priority;
for (auto& result : results) {
RTC_DCHECK(result.frame);
// Reuse the packet if possible.
if (!packet) {
packet.reset(new Packet);
packet->header = original_header;
packet->sequence_number = sequence_number;
packet->payload_type = payload_type;
}
packet->header.timestamp = result.timestamp;
packet->timestamp = result.timestamp;
RTC_DCHECK_GE(result.priority, 0);
packet->priority.codec_level = result.priority;
packet->priority.red_level = original_priority.red_level;
@ -737,16 +746,6 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
}
}
if (nack_enabled_) {
RTC_DCHECK(nack_);
if (update_sample_rate_and_channels) {
nack_->Reset();
}
nack_->UpdateLastReceivedPacket(
parsed_packet_list.front()->header.sequenceNumber,
parsed_packet_list.front()->header.timestamp);
}
// Insert packets in buffer.
const size_t buffer_length_before_insert =
packet_buffer_->NumPacketsInBuffer();
@ -781,9 +780,9 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
// CNG packet with a sample rate different than the current CNG then it
// flushes its buffer, assuming send codec must have been changed. However,
// payload type of the hypothetically new send codec is not known.
const RTPHeader* rtp_header = packet_buffer_->NextRtpHeader();
assert(rtp_header);
int payload_type = rtp_header->payloadType;
const Packet* next_packet = packet_buffer_->PeekNextPacket();
RTC_DCHECK(next_packet);
const int payload_type = next_packet->payload_type;
size_t channels = 1;
if (!decoder_database_->IsComfortNoise(payload_type)) {
AudioDecoder* decoder = decoder_database_->GetDecoder(payload_type);
@ -807,7 +806,7 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
// TODO(hlundin): Move this code to DelayManager class.
const DecoderDatabase::DecoderInfo* dec_info =
decoder_database_->GetDecoderInfo(main_header.payloadType);
decoder_database_->GetDecoderInfo(main_payload_type);
assert(dec_info); // Already checked that the payload type is known.
delay_manager_->LastDecodedWasCngOrDtmf(dec_info->IsComfortNoise() ||
dec_info->IsDtmf());
@ -828,12 +827,10 @@ int NetEqImpl::InsertPacketInternal(const WebRtcRTPHeader& rtp_header,
}
// Update statistics.
if ((int32_t) (main_header.timestamp - timestamp_) >= 0 &&
!new_codec_) {
if ((int32_t)(main_timestamp - timestamp_) >= 0 && !new_codec_) {
// Only update statistics if incoming packet is not older than last played
// out packet, and if new codec flag is not set.
delay_manager_->Update(main_header.sequenceNumber, main_header.timestamp,
fs_hz_);
delay_manager_->Update(main_sequence_number, main_timestamp, fs_hz_);
}
} else if (delay_manager_->last_pack_cng_or_dtmf() == -1) {
// This is first "normal" packet after CNG or DTMF.
@ -1091,7 +1088,7 @@ int NetEqImpl::GetDecision(Operations* operation,
const uint32_t five_seconds_samples = 5 * fs_hz_;
packet_buffer_->DiscardOldPackets(end_timestamp, five_seconds_samples);
}
const RTPHeader* header = packet_buffer_->NextRtpHeader();
const Packet* packet = packet_buffer_->PeekNextPacket();
RTC_DCHECK(!generated_noise_stopwatch_ ||
generated_noise_stopwatch_->ElapsedTicks() >= 1);
@ -1106,9 +1103,9 @@ int NetEqImpl::GetDecision(Operations* operation,
// Because of timestamp peculiarities, we have to "manually" disallow using
// a CNG packet with the same timestamp as the one that was last played.
// This can happen when using redundancy and will cause the timing to shift.
while (header && decoder_database_->IsComfortNoise(header->payloadType) &&
(end_timestamp >= header->timestamp ||
end_timestamp + generated_noise_samples > header->timestamp)) {
while (packet && decoder_database_->IsComfortNoise(packet->payload_type) &&
(end_timestamp >= packet->timestamp ||
end_timestamp + generated_noise_samples > packet->timestamp)) {
// Don't use this packet, discard it.
if (packet_buffer_->DiscardNextPacket() != PacketBuffer::kOK) {
assert(false); // Must be ok by design.
@ -1117,7 +1114,7 @@ int NetEqImpl::GetDecision(Operations* operation,
if (!new_codec_) {
packet_buffer_->DiscardOldPackets(end_timestamp, 5 * fs_hz_);
}
header = packet_buffer_->NextRtpHeader();
packet = packet_buffer_->PeekNextPacket();
}
}
@ -1150,7 +1147,7 @@ int NetEqImpl::GetDecision(Operations* operation,
decision_logic_->noise_fast_forward()
: 0;
*operation = decision_logic_->GetDecision(
*sync_buffer_, *expand_, decoder_frame_length_, header, last_mode_,
*sync_buffer_, *expand_, decoder_frame_length_, packet, last_mode_,
*play_dtmf, generated_noise_samples, &reset_decoder_);
// Check if we already have enough samples in the |sync_buffer_|. If so,
@ -1171,16 +1168,16 @@ int NetEqImpl::GetDecision(Operations* operation,
if (new_codec_ || *operation == kUndefined) {
// The only valid reason to get kUndefined is that new_codec_ is set.
assert(new_codec_);
if (*play_dtmf && !header) {
if (*play_dtmf && !packet) {
timestamp_ = dtmf_event->timestamp;
} else {
if (!header) {
if (!packet) {
LOG(LS_ERROR) << "Packet missing where it shouldn't.";
return -1;
}
timestamp_ = header->timestamp;
timestamp_ = packet->timestamp;
if (*operation == kRfc3389CngNoPacket &&
decoder_database_->IsComfortNoise(header->payloadType)) {
decoder_database_->IsComfortNoise(packet->payload_type)) {
// Change decision to CNG packet, since we do have a CNG packet, but it
// was considered too early to use. Now, use it anyway.
*operation = kRfc3389Cng;
@ -1294,18 +1291,17 @@ int NetEqImpl::GetDecision(Operations* operation,
// Get packets from buffer.
int extracted_samples = 0;
if (header &&
*operation != kAlternativePlc &&
if (packet && *operation != kAlternativePlc &&
*operation != kAlternativePlcIncreaseTimestamp &&
*operation != kAudioRepetition &&
*operation != kAudioRepetitionIncreaseTimestamp) {
sync_buffer_->IncreaseEndTimestamp(header->timestamp - end_timestamp);
sync_buffer_->IncreaseEndTimestamp(packet->timestamp - end_timestamp);
if (decision_logic_->CngOff()) {
// Adjustment of timestamp only corresponds to an actual packet loss
// if comfort noise is not played. If comfort noise was just played,
// this adjustment of timestamp is only done to get back in sync with the
// stream timestamp; no loss to report.
stats_.LostSamples(header->timestamp - end_timestamp);
stats_.LostSamples(packet->timestamp - end_timestamp);
}
if (*operation != kRfc3389Cng) {
@ -1349,7 +1345,7 @@ int NetEqImpl::Decode(PacketList* packet_list, Operations* operation,
if (!packet_list->empty()) {
const Packet* packet = packet_list->front();
uint8_t payload_type = packet->header.payloadType;
uint8_t payload_type = packet->payload_type;
if (!decoder_database_->IsComfortNoise(payload_type)) {
decoder = decoder_database_->GetDecoder(payload_type);
assert(decoder);
@ -1485,8 +1481,7 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation,
}
// Do decoding.
while (packet &&
!decoder_database_->IsComfortNoise(packet->header.payloadType)) {
while (packet && !decoder_database_->IsComfortNoise(packet->payload_type)) {
assert(decoder); // At this point, we must have a decoder object.
// The number of channels in the |sync_buffer_| should be the same as the
// number decoder channels.
@ -1535,7 +1530,7 @@ int NetEqImpl::DecodeLoop(PacketList* packet_list, const Operations& operation,
// the while-loop, or list must hold exactly one CNG packet.
assert(packet_list->empty() || *decoded_length < 0 ||
(packet_list->size() == 1 && packet &&
decoder_database_->IsComfortNoise(packet->header.payloadType)));
decoder_database_->IsComfortNoise(packet->payload_type)));
return 0;
}
@ -1777,7 +1772,7 @@ int NetEqImpl::DoRfc3389Cng(PacketList* packet_list, bool play_dtmf) {
assert(packet_list->size() == 1);
Packet* packet = packet_list->front();
packet_list->pop_front();
if (!decoder_database_->IsComfortNoise(packet->header.payloadType)) {
if (!decoder_database_->IsComfortNoise(packet->payload_type)) {
LOG(LS_ERROR) << "Trying to decode non-CNG payload as CNG.";
return kOtherError;
}
@ -1953,22 +1948,22 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
uint16_t prev_sequence_number = 0;
bool next_packet_available = false;
const RTPHeader* header = packet_buffer_->NextRtpHeader();
assert(header);
if (!header) {
const Packet* next_packet = packet_buffer_->PeekNextPacket();
RTC_DCHECK(next_packet);
if (!next_packet) {
LOG(LS_ERROR) << "Packet buffer unexpectedly empty.";
return -1;
}
uint32_t first_timestamp = header->timestamp;
uint32_t first_timestamp = next_packet->timestamp;
size_t extracted_samples = 0;
// Packet extraction loop.
do {
timestamp_ = header->timestamp;
timestamp_ = next_packet->timestamp;
size_t discard_count = 0;
Packet* packet = packet_buffer_->GetNextPacket(&discard_count);
// |header| may be invalid after the |packet_buffer_| operation.
header = NULL;
// |next_packet| may be invalid after the |packet_buffer_| operation.
next_packet = NULL;
if (!packet) {
LOG(LS_ERROR) << "Should always be able to extract a packet here";
assert(false); // Should always be able to extract a packet here.
@ -1984,12 +1979,12 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
if (nack_enabled_) {
RTC_DCHECK(nack_);
// TODO(henrik.lundin): Should we update this for all decoded packets?
nack_->UpdateLastDecodedPacket(packet->header.sequenceNumber,
packet->header.timestamp);
nack_->UpdateLastDecodedPacket(packet->sequence_number,
packet->timestamp);
}
prev_sequence_number = packet->header.sequenceNumber;
prev_timestamp = packet->header.timestamp;
prev_payload_type = packet->header.payloadType;
prev_sequence_number = packet->sequence_number;
prev_timestamp = packet->timestamp;
prev_payload_type = packet->payload_type;
}
// Store number of extracted samples.
@ -2000,9 +1995,9 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
if (packet->priority.codec_level > 0) {
stats_.SecondaryDecodedSamples(rtc::checked_cast<int>(packet_duration));
}
} else if (!decoder_database_->IsComfortNoise(packet->header.payloadType)) {
} else if (!decoder_database_->IsComfortNoise(packet->payload_type)) {
LOG(LS_WARNING) << "Unknown payload type "
<< static_cast<int>(packet->header.payloadType);
<< static_cast<int>(packet->payload_type);
RTC_NOTREACHED();
}
@ -2011,22 +2006,21 @@ int NetEqImpl::ExtractPackets(size_t required_samples,
// contains the same number of samples as the previous one.
packet_duration = decoder_frame_length_;
}
extracted_samples = packet->header.timestamp - first_timestamp +
packet_duration;
extracted_samples = packet->timestamp - first_timestamp + packet_duration;
// Check what packet is available next.
header = packet_buffer_->NextRtpHeader();
next_packet = packet_buffer_->PeekNextPacket();
next_packet_available = false;
if (header && prev_payload_type == header->payloadType) {
int16_t seq_no_diff = header->sequenceNumber - prev_sequence_number;
size_t ts_diff = header->timestamp - prev_timestamp;
if (next_packet && prev_payload_type == next_packet->payload_type) {
int16_t seq_no_diff = next_packet->sequence_number - prev_sequence_number;
size_t ts_diff = next_packet->timestamp - prev_timestamp;
if (seq_no_diff == 1 ||
(seq_no_diff == 0 && ts_diff == decoder_frame_length_)) {
// The next sequence number is available, or the next part of a packet
// that was split into pieces upon insertion.
next_packet_available = true;
}
prev_sequence_number = header->sequenceNumber;
prev_sequence_number = next_packet->sequence_number;
}
} while (extracted_samples < required_samples && next_packet_available);

View File

@ -259,6 +259,10 @@ TEST_F(NetEqImplTest, InsertPacket) {
rtp_header.header.sequenceNumber = kFirstSequenceNumber;
rtp_header.header.timestamp = kFirstTimestamp;
rtp_header.header.ssrc = kSsrc;
Packet fake_packet;
fake_packet.payload_type = kPayloadType;
fake_packet.sequence_number = kFirstSequenceNumber;
fake_packet.timestamp = kFirstTimestamp;
rtc::scoped_refptr<MockAudioDecoderFactory> mock_decoder_factory(
new rtc::RefCountedObject<MockAudioDecoderFactory>);
@ -309,9 +313,9 @@ TEST_F(NetEqImplTest, InsertPacket) {
// index) is a pointer, and the variable pointed to is set to kPayloadType.
// Also invoke the function DeletePacketsAndReturnOk to properly delete all
// packets in the list (to avoid memory leaks in the test).
EXPECT_CALL(*mock_packet_buffer_, NextRtpHeader())
EXPECT_CALL(*mock_packet_buffer_, PeekNextPacket())
.Times(1)
.WillOnce(Return(&rtp_header.header));
.WillOnce(Return(&fake_packet));
// Expectations for DTMF buffer.
EXPECT_CALL(*mock_dtmf_buffer_, Flush())
@ -376,9 +380,9 @@ TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) {
EXPECT_EQ(NetEq::kOK,
neteq_->InsertPacket(rtp_header, payload, kReceiveTime));
EXPECT_EQ(1u, packet_buffer_->NumPacketsInBuffer());
const RTPHeader* test_header = packet_buffer_->NextRtpHeader();
EXPECT_EQ(rtp_header.header.timestamp, test_header->timestamp);
EXPECT_EQ(rtp_header.header.sequenceNumber, test_header->sequenceNumber);
const Packet* test_packet = packet_buffer_->PeekNextPacket();
EXPECT_EQ(rtp_header.header.timestamp, test_packet->timestamp);
EXPECT_EQ(rtp_header.header.sequenceNumber, test_packet->sequence_number);
}
TEST_F(NetEqImplTest, TestDtmfPacket) {

View File

@ -17,7 +17,6 @@
#include "webrtc/base/buffer.h"
#include "webrtc/modules/audio_coding/codecs/audio_decoder.h"
#include "webrtc/modules/audio_coding/neteq/tick_timer.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/typedefs.h"
namespace webrtc {
@ -66,7 +65,9 @@ struct Packet {
}
};
RTPHeader header;
uint32_t timestamp;
uint16_t sequence_number;
uint8_t payload_type;
// Datagram excluding RTP header and header extension.
rtc::Buffer payload;
Priority priority;
@ -82,23 +83,23 @@ struct Packet {
// account. For two packets with the same sequence number and timestamp a
// primary payload is considered "smaller" than a secondary.
bool operator==(const Packet& rhs) const {
return (this->header.timestamp == rhs.header.timestamp &&
this->header.sequenceNumber == rhs.header.sequenceNumber &&
return (this->timestamp == rhs.timestamp &&
this->sequence_number == rhs.sequence_number &&
this->priority == rhs.priority);
}
bool operator!=(const Packet& rhs) const { return !operator==(rhs); }
bool operator<(const Packet& rhs) const {
if (this->header.timestamp == rhs.header.timestamp) {
if (this->header.sequenceNumber == rhs.header.sequenceNumber) {
if (this->timestamp == rhs.timestamp) {
if (this->sequence_number == rhs.sequence_number) {
// Timestamp and sequence numbers are identical - deem the left hand
// side to be "smaller" (i.e., "earlier") if it has higher priority.
return this->priority < rhs.priority;
}
return (static_cast<uint16_t>(rhs.header.sequenceNumber
- this->header.sequenceNumber) < 0xFFFF / 2);
return (static_cast<uint16_t>(rhs.sequence_number -
this->sequence_number) < 0xFFFF / 2);
}
return (static_cast<uint32_t>(rhs.header.timestamp
- this->header.timestamp) < 0xFFFFFFFF / 2);
return (static_cast<uint32_t>(rhs.timestamp - this->timestamp) <
0xFFFFFFFF / 2);
}
bool operator>(const Packet& rhs) const { return rhs.operator<(*this); }
bool operator<=(const Packet& rhs) const { return !operator>(rhs); }

View File

@ -100,8 +100,7 @@ int PacketBuffer::InsertPacket(Packet* packet) {
// The new packet is to be inserted to the right of |rit|. If it has the same
// timestamp as |rit|, which has a higher priority, do not insert the new
// packet to list.
if (rit != buffer_.rend() &&
packet->header.timestamp == (*rit)->header.timestamp) {
if (rit != buffer_.rend() && packet->timestamp == (*rit)->timestamp) {
delete packet;
return return_val;
}
@ -110,8 +109,7 @@ int PacketBuffer::InsertPacket(Packet* packet) {
// timestamp as |it|, which has a lower priority, replace |it| with the new
// packet.
PacketList::iterator it = rit.base();
if (it != buffer_.end() &&
packet->header.timestamp == (*it)->header.timestamp) {
if (it != buffer_.end() && packet->timestamp == (*it)->timestamp) {
delete *it;
it = buffer_.erase(it);
}
@ -128,30 +126,29 @@ int PacketBuffer::InsertPacketList(
bool flushed = false;
while (!packet_list->empty()) {
Packet* packet = packet_list->front();
if (decoder_database.IsComfortNoise(packet->header.payloadType)) {
if (decoder_database.IsComfortNoise(packet->payload_type)) {
if (*current_cng_rtp_payload_type &&
**current_cng_rtp_payload_type != packet->header.payloadType) {
**current_cng_rtp_payload_type != packet->payload_type) {
// New CNG payload type implies new codec type.
*current_rtp_payload_type = rtc::Optional<uint8_t>();
Flush();
flushed = true;
}
*current_cng_rtp_payload_type =
rtc::Optional<uint8_t>(packet->header.payloadType);
} else if (!decoder_database.IsDtmf(packet->header.payloadType)) {
rtc::Optional<uint8_t>(packet->payload_type);
} else if (!decoder_database.IsDtmf(packet->payload_type)) {
// This must be speech.
if ((*current_rtp_payload_type &&
**current_rtp_payload_type != packet->header.payloadType) ||
**current_rtp_payload_type != packet->payload_type) ||
(*current_cng_rtp_payload_type &&
!EqualSampleRates(packet->header.payloadType,
!EqualSampleRates(packet->payload_type,
**current_cng_rtp_payload_type,
decoder_database))) {
*current_cng_rtp_payload_type = rtc::Optional<uint8_t>();
Flush();
flushed = true;
}
*current_rtp_payload_type =
rtc::Optional<uint8_t>(packet->header.payloadType);
*current_rtp_payload_type = rtc::Optional<uint8_t>(packet->payload_type);
}
int return_val = InsertPacket(packet);
packet_list->pop_front();
@ -174,7 +171,7 @@ int PacketBuffer::NextTimestamp(uint32_t* next_timestamp) const {
if (!next_timestamp) {
return kInvalidPointer;
}
*next_timestamp = buffer_.front()->header.timestamp;
*next_timestamp = buffer_.front()->timestamp;
return kOK;
}
@ -188,20 +185,17 @@ int PacketBuffer::NextHigherTimestamp(uint32_t timestamp,
}
PacketList::const_iterator it;
for (it = buffer_.begin(); it != buffer_.end(); ++it) {
if ((*it)->header.timestamp >= timestamp) {
if ((*it)->timestamp >= timestamp) {
// Found a packet matching the search.
*next_timestamp = (*it)->header.timestamp;
*next_timestamp = (*it)->timestamp;
return kOK;
}
}
return kNotFound;
}
const RTPHeader* PacketBuffer::NextRtpHeader() const {
if (Empty()) {
return NULL;
}
return const_cast<const RTPHeader*>(&(buffer_.front()->header));
const Packet* PacketBuffer::PeekNextPacket() const {
return buffer_.empty() ? nullptr : buffer_.front();
}
Packet* PacketBuffer::GetNextPacket(size_t* discard_count) {
@ -219,8 +213,7 @@ Packet* PacketBuffer::GetNextPacket(size_t* discard_count) {
// redundant payloads that should not be used.
size_t discards = 0;
while (!Empty() &&
buffer_.front()->header.timestamp == packet->header.timestamp) {
while (!Empty() && buffer_.front()->timestamp == packet->timestamp) {
if (DiscardNextPacket() != kOK) {
assert(false); // Must be ok by design.
}
@ -248,9 +241,8 @@ int PacketBuffer::DiscardNextPacket() {
int PacketBuffer::DiscardOldPackets(uint32_t timestamp_limit,
uint32_t horizon_samples) {
while (!Empty() && timestamp_limit != buffer_.front()->header.timestamp &&
IsObsoleteTimestamp(buffer_.front()->header.timestamp,
timestamp_limit,
while (!Empty() && timestamp_limit != buffer_.front()->timestamp &&
IsObsoleteTimestamp(buffer_.front()->timestamp, timestamp_limit,
horizon_samples)) {
if (DiscardNextPacket() != kOK) {
assert(false); // Must be ok by design.
@ -266,7 +258,7 @@ int PacketBuffer::DiscardAllOldPackets(uint32_t timestamp_limit) {
void PacketBuffer::DiscardPacketsWithPayloadType(uint8_t payload_type) {
for (auto it = buffer_.begin(); it != buffer_.end(); /* */) {
Packet* packet = *it;
if (packet->header.payloadType == payload_type) {
if (packet->payload_type == payload_type) {
delete packet;
it = buffer_.erase(it);
} else {

View File

@ -14,6 +14,7 @@
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/optional.h"
#include "webrtc/modules/audio_coding/neteq/packet.h"
#include "webrtc/modules/include/module_common_types.h"
#include "webrtc/typedefs.h"
namespace webrtc {
@ -80,9 +81,9 @@ class PacketBuffer {
virtual int NextHigherTimestamp(uint32_t timestamp,
uint32_t* next_timestamp) const;
// Returns a (constant) pointer the RTP header of the first packet in the
// buffer. Returns NULL if the buffer is empty.
virtual const RTPHeader* NextRtpHeader() const;
// Returns a (constant) pointer to the first packet in the buffer. Returns
// NULL if the buffer is empty.
virtual const Packet* PeekNextPacket() const;
// Extracts the first packet in the buffer and returns a pointer to it.
// Returns NULL if the buffer is empty. The caller is responsible for deleting

View File

@ -53,13 +53,9 @@ void PacketGenerator::Reset(uint16_t seq_no, uint32_t ts, uint8_t pt,
Packet* PacketGenerator::NextPacket(int payload_size_bytes) {
Packet* packet = new Packet;
packet->header.sequenceNumber = seq_no_;
packet->header.timestamp = ts_;
packet->header.payloadType = pt_;
packet->header.markerBit = false;
packet->header.ssrc = 0x12345678;
packet->header.numCSRCs = 0;
packet->header.paddingLength = 0;
packet->sequence_number = seq_no_;
packet->timestamp = ts_;
packet->payload_type = pt_;
packet->payload.SetSize(payload_size_bytes);
++seq_no_;
ts_ += frame_size_;
@ -100,8 +96,8 @@ TEST(PacketBuffer, InsertPacket) {
EXPECT_EQ(4711u, next_ts);
EXPECT_FALSE(buffer.Empty());
EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
const RTPHeader* hdr = buffer.NextRtpHeader();
EXPECT_EQ(&(packet->header), hdr); // Compare pointer addresses.
const Packet* next_packet = buffer.PeekNextPacket();
EXPECT_EQ(packet, next_packet); // Compare pointer addresses.
// Do not explicitly flush buffer or delete packet to test that it is deleted
// with the buffer. (Tested with Valgrind or similar tool.)
@ -152,7 +148,7 @@ TEST(PacketBuffer, OverfillBuffer) {
EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
EXPECT_EQ(PacketBuffer::kOK, buffer.NextTimestamp(&next_ts));
// Expect last inserted packet to be first in line.
EXPECT_EQ(packet->header.timestamp, next_ts);
EXPECT_EQ(packet->timestamp, next_ts);
// Flush buffer to delete all packets.
buffer.Flush();
@ -211,7 +207,7 @@ TEST(PacketBuffer, InsertPacketListChangePayloadType) {
}
// Insert 11th packet of another payload type (not CNG).
Packet* packet = gen.NextPacket(payload_len);
packet->header.payloadType = 1;
packet->payload_type = 1;
list.push_back(packet);
@ -370,7 +366,7 @@ TEST(PacketBuffer, Reordering) {
for (int i = 0; i < 10; ++i) {
Packet* packet = buffer.GetNextPacket(NULL);
ASSERT_FALSE(packet == NULL);
EXPECT_EQ(current_ts, packet->header.timestamp);
EXPECT_EQ(current_ts, packet->timestamp);
current_ts += ts_increment;
delete packet;
}
@ -412,15 +408,15 @@ TEST(PacketBuffer, CngFirstThenSpeechWithNewSampleRate) {
&current_cng_pt));
EXPECT_TRUE(list.empty());
EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
ASSERT_TRUE(buffer.NextRtpHeader());
EXPECT_EQ(kCngPt, buffer.NextRtpHeader()->payloadType);
ASSERT_TRUE(buffer.PeekNextPacket());
EXPECT_EQ(kCngPt, buffer.PeekNextPacket()->payload_type);
EXPECT_FALSE(current_pt); // Current payload type not set.
EXPECT_EQ(rtc::Optional<uint8_t>(kCngPt),
current_cng_pt); // CNG payload type set.
// Insert second packet, which is wide-band speech.
Packet* packet = gen.NextPacket(kPayloadLen);
packet->header.payloadType = kSpeechPt;
packet->payload_type = kSpeechPt;
list.push_back(packet);
// Expect the buffer to flush out the CNG packet, since it does not match the
// new speech sample rate.
@ -429,8 +425,8 @@ TEST(PacketBuffer, CngFirstThenSpeechWithNewSampleRate) {
&current_cng_pt));
EXPECT_TRUE(list.empty());
EXPECT_EQ(1u, buffer.NumPacketsInBuffer());
ASSERT_TRUE(buffer.NextRtpHeader());
EXPECT_EQ(kSpeechPt, buffer.NextRtpHeader()->payloadType);
ASSERT_TRUE(buffer.PeekNextPacket());
EXPECT_EQ(kSpeechPt, buffer.PeekNextPacket()->payload_type);
EXPECT_EQ(rtc::Optional<uint8_t>(kSpeechPt),
current_pt); // Current payload type set.
@ -461,7 +457,7 @@ TEST(PacketBuffer, Failures) {
EXPECT_EQ(PacketBuffer::kBufferEmpty, buffer->NextTimestamp(&temp_ts));
EXPECT_EQ(PacketBuffer::kBufferEmpty,
buffer->NextHigherTimestamp(0, &temp_ts));
EXPECT_EQ(NULL, buffer->NextRtpHeader());
EXPECT_EQ(NULL, buffer->PeekNextPacket());
EXPECT_EQ(NULL, buffer->GetNextPacket(NULL));
EXPECT_EQ(PacketBuffer::kBufferEmpty, buffer->DiscardNextPacket());
EXPECT_EQ(0, buffer->DiscardAllOldPackets(0)); // 0 packets discarded.
@ -516,7 +512,7 @@ TEST(PacketBuffer, ComparePackets) {
EXPECT_FALSE(*a >= *b);
// Testing wrap-around case; 'a' is earlier but has a larger timestamp value.
a->header.timestamp = 0xFFFFFFFF - 10;
a->timestamp = 0xFFFFFFFF - 10;
EXPECT_FALSE(*a == *b);
EXPECT_TRUE(*a != *b);
EXPECT_TRUE(*a < *b);
@ -533,7 +529,7 @@ TEST(PacketBuffer, ComparePackets) {
EXPECT_TRUE(*a >= *a);
// Test equal timestamps but different sequence numbers (0 and 1).
a->header.timestamp = b->header.timestamp;
a->timestamp = b->timestamp;
EXPECT_FALSE(*a == *b);
EXPECT_TRUE(*a != *b);
EXPECT_TRUE(*a < *b);
@ -542,7 +538,7 @@ TEST(PacketBuffer, ComparePackets) {
EXPECT_FALSE(*a >= *b);
// Test equal timestamps but different sequence numbers (32767 and 1).
a->header.sequenceNumber = 0xFFFF;
a->sequence_number = 0xFFFF;
EXPECT_FALSE(*a == *b);
EXPECT_TRUE(*a != *b);
EXPECT_TRUE(*a < *b);
@ -551,7 +547,7 @@ TEST(PacketBuffer, ComparePackets) {
EXPECT_FALSE(*a >= *b);
// Test equal timestamps and sequence numbers, but differing priorities.
a->header.sequenceNumber = b->header.sequenceNumber;
a->sequence_number = b->sequence_number;
a->priority = {1, 0};
b->priority = {0, 0};
// a after b
@ -564,10 +560,10 @@ TEST(PacketBuffer, ComparePackets) {
std::unique_ptr<Packet> c(gen.NextPacket(0)); // SN = 2, TS = 20.
std::unique_ptr<Packet> d(gen.NextPacket(0)); // SN = 3, TS = 20.
c->header.timestamp = b->header.timestamp;
d->header.timestamp = b->header.timestamp;
c->header.sequenceNumber = b->header.sequenceNumber;
d->header.sequenceNumber = b->header.sequenceNumber;
c->timestamp = b->timestamp;
d->timestamp = b->timestamp;
c->sequence_number = b->sequence_number;
d->sequence_number = b->sequence_number;
c->priority = {1, 1};
d->priority = {0, 1};
// c after d

View File

@ -69,14 +69,14 @@ bool RedPayloadSplitter::SplitRed(PacketList* packet_list) {
if (last_block) {
// No more header data to read.
++sum_length; // Account for RED header size of 1 byte.
new_header.timestamp = red_packet->header.timestamp;
new_header.timestamp = red_packet->timestamp;
new_header.payload_length = red_packet->payload.size() - sum_length;
payload_ptr += 1; // Advance to first payload byte.
} else {
// Bits 8 through 21 are timestamp offset.
int timestamp_offset =
(payload_ptr[1] << 6) + ((payload_ptr[2] & 0xFC) >> 2);
new_header.timestamp = red_packet->header.timestamp - timestamp_offset;
new_header.timestamp = red_packet->timestamp - timestamp_offset;
// Bits 22 through 31 are payload length.
new_header.payload_length =
((payload_ptr[2] & 0x03) << 8) + payload_ptr[3];
@ -106,9 +106,9 @@ bool RedPayloadSplitter::SplitRed(PacketList* packet_list) {
}
Packet* new_packet = new Packet;
new_packet->header = red_packet->header;
new_packet->header.timestamp = new_header.timestamp;
new_packet->header.payloadType = new_header.payload_type;
new_packet->timestamp = new_header.timestamp;
new_packet->payload_type = new_header.payload_type;
new_packet->sequence_number = red_packet->sequence_number;
new_packet->priority.red_level =
rtc::checked_cast<int>((new_headers.size() - 1) - i);
new_packet->payload.SetData(payload_ptr, payload_length);
@ -140,7 +140,7 @@ int RedPayloadSplitter::CheckRedPayloads(
int main_payload_type = -1;
int num_deleted_packets = 0;
while (it != packet_list->end()) {
uint8_t this_payload_type = (*it)->header.payloadType;
uint8_t this_payload_type = (*it)->payload_type;
if (!decoder_database.IsDtmf(this_payload_type) &&
!decoder_database.IsComfortNoise(this_payload_type)) {
if (main_payload_type == -1) {

View File

@ -80,9 +80,9 @@ Packet* CreateRedPayload(size_t num_payloads,
int timestamp_offset,
bool embed_opus_fec = false) {
Packet* packet = new Packet;
packet->header.payloadType = kRedPayloadType;
packet->header.timestamp = kBaseTimestamp;
packet->header.sequenceNumber = kSequenceNumber;
packet->payload_type = kRedPayloadType;
packet->timestamp = kBaseTimestamp;
packet->sequence_number = kSequenceNumber;
packet->payload.SetSize((kPayloadLength + 1) +
(num_payloads - 1) *
(kPayloadLength + kRedHeaderLength));
@ -127,9 +127,9 @@ Packet* CreatePacket(uint8_t payload_type,
uint8_t payload_value,
bool opus_fec = false) {
Packet* packet = new Packet;
packet->header.payloadType = payload_type;
packet->header.timestamp = kBaseTimestamp;
packet->header.sequenceNumber = kSequenceNumber;
packet->payload_type = payload_type;
packet->timestamp = kBaseTimestamp;
packet->sequence_number = kSequenceNumber;
packet->payload.SetSize(payload_length);
if (opus_fec) {
CreateOpusFecPayload(packet->payload.data(), packet->payload.size(),
@ -149,9 +149,9 @@ void VerifyPacket(const Packet* packet,
uint8_t payload_value,
Packet::Priority priority) {
EXPECT_EQ(payload_length, packet->payload.size());
EXPECT_EQ(payload_type, packet->header.payloadType);
EXPECT_EQ(sequence_number, packet->header.sequenceNumber);
EXPECT_EQ(timestamp, packet->header.timestamp);
EXPECT_EQ(payload_type, packet->payload_type);
EXPECT_EQ(sequence_number, packet->sequence_number);
EXPECT_EQ(timestamp, packet->timestamp);
EXPECT_EQ(priority, packet->priority);
ASSERT_FALSE(packet->payload.empty());
for (size_t i = 0; i < packet->payload.size(); ++i) {
@ -213,8 +213,8 @@ TEST(RedPayloadSplitter, TwoPacketsOnePayload) {
// Create second packet, with a single RED payload.
packet = CreateRedPayload(1, payload_types, kTimestampOffset);
// Manually change timestamp and sequence number of second packet.
packet->header.timestamp += kTimestampOffset;
packet->header.sequenceNumber++;
packet->timestamp += kTimestampOffset;
packet->sequence_number++;
packet_list.push_back(packet);
RedPayloadSplitter splitter;
EXPECT_TRUE(splitter.SplitRed(&packet_list));
@ -251,8 +251,8 @@ TEST(RedPayloadSplitter, TwoPacketsThreePayloads) {
// Create first packet, with 3 RED payloads.
packet = CreateRedPayload(3, payload_types, kTimestampOffset);
// Manually change timestamp and sequence number of second packet.
packet->header.timestamp += kTimestampOffset;
packet->header.sequenceNumber++;
packet->timestamp += kTimestampOffset;
packet->sequence_number++;
packet_list.push_back(packet);
RedPayloadSplitter splitter;
EXPECT_TRUE(splitter.SplitRed(&packet_list));

View File

@ -23,8 +23,7 @@ void TimestampScaler::ToInternal(Packet* packet) {
if (!packet) {
return;
}
packet->header.timestamp = ToInternal(packet->header.timestamp,
packet->header.payloadType);
packet->timestamp = ToInternal(packet->timestamp, packet->payload_type);
}
void TimestampScaler::ToInternal(PacketList* packet_list) {

View File

@ -181,12 +181,12 @@ TEST(TimestampScaler, TestG722Packet) {
uint32_t external_timestamp = 0xFFFFFFFF - 5;
uint32_t internal_timestamp = external_timestamp;
Packet packet;
packet.header.payloadType = kRtpPayloadType;
packet.payload_type = kRtpPayloadType;
for (; external_timestamp != 5; ++external_timestamp) {
packet.header.timestamp = external_timestamp;
packet.timestamp = external_timestamp;
// Scale to internal timestamp.
scaler.ToInternal(&packet);
EXPECT_EQ(internal_timestamp, packet.header.timestamp);
EXPECT_EQ(internal_timestamp, packet.timestamp);
internal_timestamp += 2;
}
@ -210,18 +210,18 @@ TEST(TimestampScaler, TestG722PacketList) {
uint32_t external_timestamp = 0xFFFFFFFF - 5;
uint32_t internal_timestamp = external_timestamp;
Packet packet1;
packet1.header.payloadType = kRtpPayloadType;
packet1.header.timestamp = external_timestamp;
packet1.payload_type = kRtpPayloadType;
packet1.timestamp = external_timestamp;
Packet packet2;
packet2.header.payloadType = kRtpPayloadType;
packet2.header.timestamp = external_timestamp + 10;
packet2.payload_type = kRtpPayloadType;
packet2.timestamp = external_timestamp + 10;
PacketList packet_list;
packet_list.push_back(&packet1);
packet_list.push_back(&packet2);
scaler.ToInternal(&packet_list);
EXPECT_EQ(internal_timestamp, packet1.header.timestamp);
EXPECT_EQ(internal_timestamp + 20, packet2.header.timestamp);
EXPECT_EQ(internal_timestamp, packet1.timestamp);
EXPECT_EQ(internal_timestamp + 20, packet2.timestamp);
EXPECT_CALL(db, Die()); // Called when database object is deleted.
}