The second step towards a list based SessionInfo.
Added unittests for most of public functions of SessionInfo. BUG= TEST= Review URL: http://webrtc-codereview.appspot.com/301014 git-svn-id: http://webrtc.googlecode.com/svn/trunk@1166 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -59,13 +59,13 @@ VCMFrameBuffer::SetPreviousFrameLoss()
|
||||
WebRtc_Word32
|
||||
VCMFrameBuffer::GetLowSeqNum() const
|
||||
{
|
||||
return _sessionInfo.GetLowSeqNum();
|
||||
return _sessionInfo.LowSequenceNumber();
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
VCMFrameBuffer::GetHighSeqNum() const
|
||||
{
|
||||
return _sessionInfo.GetHighSeqNum();
|
||||
return _sessionInfo.HighSequenceNumber();
|
||||
}
|
||||
|
||||
int VCMFrameBuffer::PictureId() const {
|
||||
@@ -87,7 +87,7 @@ bool VCMFrameBuffer::NonReference() const {
|
||||
bool
|
||||
VCMFrameBuffer::IsSessionComplete() const
|
||||
{
|
||||
return _sessionInfo.IsSessionComplete();
|
||||
return _sessionInfo.complete();
|
||||
}
|
||||
|
||||
// Insert packet
|
||||
@@ -124,11 +124,6 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs,
|
||||
{
|
||||
return kSizeError;
|
||||
}
|
||||
if ((packet.frameType != kFrameEmpty) &&
|
||||
(!_sessionInfo.HaveStartSeqNumber()))
|
||||
{
|
||||
_sessionInfo.SetStartSeqNumber(packet.seqNum);
|
||||
}
|
||||
if (packet.dataPtr != NULL)
|
||||
{
|
||||
_payloadType = packet.payloadType;
|
||||
@@ -166,14 +161,14 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs,
|
||||
{
|
||||
return kSizeError;
|
||||
}
|
||||
_sessionInfo.UpdateDataPointers(_buffer, prevBuffer);
|
||||
_sessionInfo.UpdateDataPointers(_buffer - prevBuffer);
|
||||
}
|
||||
|
||||
CopyCodecSpecific(&packet.codecSpecificHeader);
|
||||
|
||||
WebRtc_Word64 retVal = _sessionInfo.InsertPacket(packet, _buffer,
|
||||
enableDecodableState,
|
||||
rttMS);
|
||||
int retVal = _sessionInfo.InsertPacket(packet, _buffer,
|
||||
enableDecodableState,
|
||||
rttMS);
|
||||
if (retVal == -1)
|
||||
{
|
||||
return kSizeError;
|
||||
@@ -187,9 +182,9 @@ VCMFrameBuffer::InsertPacket(const VCMPacket& packet, WebRtc_Word64 timeInMs,
|
||||
|
||||
_latestPacketTimeMs = timeInMs;
|
||||
|
||||
if (_sessionInfo.IsSessionComplete()) {
|
||||
if (_sessionInfo.complete()) {
|
||||
return kCompleteSession;
|
||||
} else if (_sessionInfo.IsSessionDecodable()) {
|
||||
} else if (_sessionInfo.decodable()) {
|
||||
SetState(kStateDecodable);
|
||||
return kDecodableSession;
|
||||
} else {
|
||||
@@ -272,11 +267,11 @@ VCMFrameBuffer::MakeSessionDecodable()
|
||||
WebRtc_UWord32 retVal;
|
||||
#ifdef INDEPENDENT_PARTITIONS
|
||||
if (_codec != kVideoCodecVP8) {
|
||||
retVal = _sessionInfo.MakeDecodable(_buffer);
|
||||
retVal = _sessionInfo.MakeDecodable();
|
||||
_length -= retVal;
|
||||
}
|
||||
#else
|
||||
retVal = _sessionInfo.MakeDecodable(_buffer);
|
||||
retVal = _sessionInfo.MakeDecodable();
|
||||
_length -= retVal;
|
||||
#endif
|
||||
}
|
||||
@@ -350,7 +345,7 @@ VCMFrameBuffer::RestructureFrameInformation()
|
||||
{
|
||||
PrepareForDecode();
|
||||
_frameType = ConvertFrameType(_sessionInfo.FrameType());
|
||||
_completeFrame = _sessionInfo.IsSessionComplete();
|
||||
_completeFrame = _sessionInfo.complete();
|
||||
_missingFrame = _sessionInfo.PreviousFrameLoss();
|
||||
}
|
||||
|
||||
@@ -371,14 +366,14 @@ VCMFrameBuffer::ExtractFromStorage(const EncodedVideoData& frameFromStorage)
|
||||
{
|
||||
return VCM_MEMORY;
|
||||
}
|
||||
_sessionInfo.UpdateDataPointers(_buffer, prevBuffer);
|
||||
_sessionInfo.UpdateDataPointers(_buffer - prevBuffer);
|
||||
memcpy(_buffer, frameFromStorage.payloadData, frameFromStorage.payloadSize);
|
||||
_length = frameFromStorage.payloadSize;
|
||||
return VCM_OK;
|
||||
}
|
||||
|
||||
int VCMFrameBuffer::NotDecodablePackets() const {
|
||||
return _sessionInfo.NotDecodablePackets();
|
||||
return _sessionInfo.packets_not_decodable();
|
||||
}
|
||||
|
||||
// Set counted status (as counted by JB or not)
|
||||
@@ -410,7 +405,7 @@ VCMFrameBuffer::GetState(WebRtc_UWord32& timeStamp) const
|
||||
bool
|
||||
VCMFrameBuffer::IsRetransmitted() const
|
||||
{
|
||||
return _sessionInfo.IsRetransmitted();
|
||||
return _sessionInfo.session_nack();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -425,10 +420,10 @@ VCMFrameBuffer::PrepareForDecode()
|
||||
}
|
||||
else
|
||||
{
|
||||
_length = _sessionInfo.PrepareForDecode(_buffer, _codec);
|
||||
_length = _sessionInfo.PrepareForDecode(_buffer);
|
||||
}
|
||||
#else
|
||||
_length = _sessionInfo.PrepareForDecode(_buffer, _codec);
|
||||
_length = _sessionInfo.PrepareForDecode(_buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ enum VCMJitterBufferEnum
|
||||
{
|
||||
kMaxConsecutiveOldFrames = 60,
|
||||
kMaxConsecutiveOldPackets = 300,
|
||||
kMaxPacketsInJitterBuffer = 800,
|
||||
kMaxPacketsInSession = 800,
|
||||
kBufferIncStepSizeBytes = 30000, // >20 packets
|
||||
kMaxJBFrameSizeBytes = 4000000 // sanity don't go above 4Mbyte
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,138 +11,121 @@
|
||||
#ifndef WEBRTC_MODULES_VIDEO_CODING_SESSION_INFO_H_
|
||||
#define WEBRTC_MODULES_VIDEO_CODING_SESSION_INFO_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
#include "module_common_types.h"
|
||||
#include "packet.h"
|
||||
#include <cstddef>
|
||||
#include <list>
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
#include "modules/interface/module_common_types.h"
|
||||
#include "modules/video_coding/main/source/packet.h"
|
||||
#include "typedefs.h" // NOLINT(build/include)
|
||||
|
||||
enum { kMaxVP8Partitions = 9 };
|
||||
namespace webrtc {
|
||||
|
||||
class VCMSessionInfo
|
||||
{
|
||||
public:
|
||||
VCMSessionInfo();
|
||||
virtual ~VCMSessionInfo();
|
||||
class VCMSessionInfo {
|
||||
public:
|
||||
VCMSessionInfo();
|
||||
|
||||
VCMSessionInfo(const VCMSessionInfo& rhs);
|
||||
void UpdateDataPointers(ptrdiff_t address_delta);
|
||||
int ZeroOutSeqNum(int* seq_num_list,
|
||||
int seq_num_list_length);
|
||||
|
||||
void UpdateDataPointers(const WebRtc_UWord8* frame_buffer,
|
||||
const WebRtc_UWord8* prev_buffer_address);
|
||||
// Hybrid version: Zero out seq num for NACK list
|
||||
// Selectively NACK packets.
|
||||
int ZeroOutSeqNumHybrid(int* seq_num_list,
|
||||
int seq_num_list_length,
|
||||
int rtt_ms);
|
||||
void Reset();
|
||||
int InsertPacket(const VCMPacket& packet,
|
||||
uint8_t* frame_buffer,
|
||||
bool enable_decodable_state,
|
||||
int rtt_ms);
|
||||
bool complete() const;
|
||||
bool decodable() const;
|
||||
|
||||
WebRtc_Word32 ZeroOutSeqNum(WebRtc_Word32* list,
|
||||
WebRtc_Word32 numberOfSeqNum);
|
||||
// Hybrid version: Zero out seq num for NACK list
|
||||
// Selectively NACK packets.
|
||||
WebRtc_Word32 ZeroOutSeqNumHybrid(WebRtc_Word32* list,
|
||||
WebRtc_Word32 numberOfSeqNum,
|
||||
WebRtc_UWord32 rttMs);
|
||||
virtual void Reset();
|
||||
// Builds fragmentation headers for VP8, each fragment being a decodable
|
||||
// VP8 partition. Returns the total number of bytes which are decodable. Is
|
||||
// used instead of MakeDecodable for VP8.
|
||||
int BuildVP8FragmentationHeader(uint8_t* frame_buffer,
|
||||
int frame_buffer_length,
|
||||
RTPFragmentationHeader* fragmentation);
|
||||
|
||||
WebRtc_Word64 InsertPacket(const VCMPacket& packet,
|
||||
WebRtc_UWord8* ptrStartOfLayer,
|
||||
bool enableDecodableState,
|
||||
WebRtc_UWord32 rttMs);
|
||||
WebRtc_Word32 InformOfEmptyPacket(const WebRtc_UWord16 seqNum);
|
||||
// Makes the frame decodable. I.e., only contain decodable NALUs. All
|
||||
// non-decodable NALUs will be deleted and packets will be moved to in
|
||||
// memory to remove any empty space.
|
||||
// Returns the number of bytes deleted from the session.
|
||||
int MakeDecodable();
|
||||
int SessionLength() const;
|
||||
bool HaveLastPacket() const;
|
||||
bool session_nack() const;
|
||||
webrtc::FrameType FrameType() const { return frame_type_; }
|
||||
int LowSequenceNumber() const;
|
||||
|
||||
virtual bool IsSessionComplete() const;
|
||||
virtual bool IsSessionDecodable() const;
|
||||
// Returns highest sequence number, media or empty.
|
||||
int HighSequenceNumber() const;
|
||||
int PictureId() const;
|
||||
int TemporalId() const;
|
||||
int Tl0PicId() const;
|
||||
bool NonReference() const;
|
||||
int PrepareForDecode(uint8_t* frame_buffer);
|
||||
void SetPreviousFrameLoss() { previous_frame_loss_ = true; }
|
||||
bool PreviousFrameLoss() const { return previous_frame_loss_; }
|
||||
|
||||
// Builds fragmentation headers for VP8, each fragment being a decodable
|
||||
// VP8 partition. Returns the total number of bytes which are decodable. Is
|
||||
// used instead of MakeDecodable for VP8.
|
||||
int BuildVP8FragmentationHeader(WebRtc_UWord8* frame_buffer,
|
||||
int frame_buffer_length,
|
||||
RTPFragmentationHeader* fragmentation);
|
||||
// The number of packets discarded because the decoder can't make use of
|
||||
// them.
|
||||
int packets_not_decodable() const;
|
||||
|
||||
// Makes the frame decodable. I.e., only contain decodable NALUs. All
|
||||
// non-decodable NALUs will be deleted and packets will be moved to in
|
||||
// memory to remove any empty space.
|
||||
// Returns the number of bytes deleted from the session.
|
||||
WebRtc_UWord32 MakeDecodable(WebRtc_UWord8* ptrStartOfLayer);
|
||||
private:
|
||||
enum { kMaxVP8Partitions = 9 };
|
||||
|
||||
WebRtc_UWord32 GetSessionLength();
|
||||
bool HaveLastPacket() const;
|
||||
bool IsRetransmitted() const;
|
||||
webrtc::FrameType FrameType() const { return _frameType; }
|
||||
typedef std::list<VCMPacket> PacketList;
|
||||
typedef PacketList::iterator PacketIterator;
|
||||
typedef PacketList::const_iterator PacketIteratorConst;
|
||||
typedef PacketList::reverse_iterator ReversePacketIterator;
|
||||
|
||||
virtual WebRtc_Word32 GetHighestPacketIndex();
|
||||
void InformOfEmptyPacket(uint16_t seq_num);
|
||||
|
||||
void SetStartSeqNumber(WebRtc_UWord16 seqNumber);
|
||||
// Finds the packet of the beginning of the next VP8 partition. If
|
||||
// none is found the returned iterator points to |packets_.end()|.
|
||||
// |it| is expected to point to the last packet of the previous partition,
|
||||
// or to the first packet of the frame. |packets_skipped| is incremented
|
||||
// for each packet found which doesn't have the beginning bit set.
|
||||
PacketIterator FindNextPartitionBeginning(PacketIterator it,
|
||||
int* packets_skipped) const;
|
||||
|
||||
bool HaveStartSeqNumber();
|
||||
// Returns an iterator pointing to the last packet of the partition pointed to
|
||||
// by |it|.
|
||||
PacketIterator FindPartitionEnd(PacketIterator it) const;
|
||||
static bool InSequence(const PacketIterator& it,
|
||||
const PacketIterator& prev_it);
|
||||
static int PacketsMissing(const PacketIterator& packet_it,
|
||||
const PacketIterator& prev_packet_it);
|
||||
int InsertBuffer(uint8_t* frame_buffer,
|
||||
PacketIterator packetIterator);
|
||||
void ShiftSubsequentPackets(PacketIterator it, int steps_to_shift);
|
||||
PacketIterator FindNaluEnd(PacketIterator packet_iter) const;
|
||||
// Deletes the data of all packets between |start| and |end|, inclusively.
|
||||
// Note that this function doesn't delete the actual packets.
|
||||
int DeletePacketData(PacketIterator start,
|
||||
PacketIterator end);
|
||||
void UpdateCompleteSession();
|
||||
|
||||
WebRtc_Word32 GetLowSeqNum() const;
|
||||
// returns highest seqNum, media or empty
|
||||
WebRtc_Word32 GetHighSeqNum() const;
|
||||
int PictureId() const;
|
||||
int TemporalId() const;
|
||||
int Tl0PicId() const;
|
||||
bool NonReference() const;
|
||||
// When enabled, determine if session is decodable, i.e. incomplete but
|
||||
// would be sent to the decoder.
|
||||
void UpdateDecodableSession(int rtt_ms);
|
||||
|
||||
WebRtc_UWord32 PrepareForDecode(WebRtc_UWord8* ptrStartOfLayer,
|
||||
VideoCodecType codec);
|
||||
|
||||
void SetPreviousFrameLoss() { _previousFrameLoss = true; }
|
||||
bool PreviousFrameLoss() const { return _previousFrameLoss; }
|
||||
|
||||
// The number of packets discarded because the decoder can't make use of
|
||||
// them.
|
||||
int NotDecodablePackets() const;
|
||||
|
||||
private:
|
||||
// Finds the packet index of the beginning of the next VP8 partition. If
|
||||
// none is found _highestPacketIndex + 1 is returned. packet_index is
|
||||
// expected to be the index of the last decodable packet of the previous
|
||||
// partitions + 1, or 0 for the first partition.
|
||||
int FindNextPartitionBeginning(int packet_index);
|
||||
|
||||
// Finds the packet index of the end of the partition with index
|
||||
// partitionIndex.
|
||||
int FindPartitionEnd(int packet_index) const;
|
||||
static bool InSequence(WebRtc_UWord16 seqNum, WebRtc_UWord16 prevSeqNum);
|
||||
WebRtc_UWord32 InsertBuffer(WebRtc_UWord8* ptrStartOfLayer,
|
||||
WebRtc_Word32 packetIndex,
|
||||
const VCMPacket& packet);
|
||||
void FindNaluBorder(WebRtc_Word32 packetIndex,
|
||||
WebRtc_Word32& startIndex,
|
||||
WebRtc_Word32& endIndex);
|
||||
WebRtc_UWord32 DeletePackets(WebRtc_UWord8* ptrStartOfLayer,
|
||||
WebRtc_Word32 startIndex,
|
||||
WebRtc_Word32 endIndex);
|
||||
void UpdateCompleteSession();
|
||||
// When enabled, determine if session is decodable, i.e. incomplete but
|
||||
// would be sent to the decoder.
|
||||
void UpdateDecodableSession(WebRtc_UWord32 rttMs);
|
||||
// If we have inserted a packet with markerbit into this frame
|
||||
bool _markerBit;
|
||||
// If this session has been NACKed by JB
|
||||
bool _sessionNACK;
|
||||
bool _completeSession;
|
||||
bool _decodableSession;
|
||||
webrtc::FrameType _frameType;
|
||||
bool _previousFrameLoss;
|
||||
// Lowest/Highest packet sequence number in a session
|
||||
WebRtc_Word32 _lowSeqNum;
|
||||
WebRtc_Word32 _highSeqNum;
|
||||
|
||||
// Highest packet index in this frame
|
||||
WebRtc_UWord16 _highestPacketIndex;
|
||||
// Packets in this frame.
|
||||
// TODO(holmer): Replace this with a std::list<VCMPacket*>. Doing that will
|
||||
// make it possible to get rid of _markerBit, _lowSeqNum,
|
||||
// _highSeqNum, _highestPacketIndex, etc.
|
||||
VCMPacket _packets[kMaxPacketsInJitterBuffer];
|
||||
WebRtc_Word32 _emptySeqNumLow;
|
||||
WebRtc_Word32 _emptySeqNumHigh;
|
||||
// Store the sequence number that marks the last media packet
|
||||
WebRtc_Word32 _markerSeqNum;
|
||||
// Number of packets discarded because the decoder can't use them.
|
||||
int _packetsNotDecodable;
|
||||
int _pictureId;
|
||||
// If this session has been NACKed by the jitter buffer.
|
||||
bool session_nack_;
|
||||
bool complete_;
|
||||
bool decodable_;
|
||||
webrtc::FrameType frame_type_;
|
||||
bool previous_frame_loss_;
|
||||
// Packets in this frame.
|
||||
PacketList packets_;
|
||||
int empty_seq_num_low_;
|
||||
int empty_seq_num_high_;
|
||||
// Number of packets discarded because the decoder can't use them.
|
||||
int packets_not_decodable_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_MODULES_VIDEO_CODING_SESSION_INFO_H_
|
||||
#endif // WEBRTC_MODULES_VIDEO_CODING_SESSION_INFO_H_
|
||||
|
||||
@@ -11,63 +11,196 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "module_common_types.h"
|
||||
#include "packet.h"
|
||||
#include "session_info.h"
|
||||
#include "modules/interface/module_common_types.h"
|
||||
#include "modules/video_coding/main/source/packet.h"
|
||||
#include "modules/video_coding/main/source/session_info.h"
|
||||
|
||||
using webrtc::RTPFragmentationHeader;
|
||||
using webrtc::RTPVideoHeaderVP8;
|
||||
using webrtc::VCMPacket;
|
||||
using webrtc::VCMSessionInfo;
|
||||
using webrtc::WebRtcRTPHeader;
|
||||
namespace webrtc {
|
||||
|
||||
enum { kPacketBufferSize = 10 };
|
||||
enum { kFrameBufferSize = 10*kPacketBufferSize };
|
||||
|
||||
class TestVP8MakeDecodable : public ::testing::Test {
|
||||
class TestSessionInfo : public ::testing::Test {
|
||||
protected:
|
||||
enum { kPacketBufferSize = 10 };
|
||||
enum { kFrameBufferSize = 10 * kPacketBufferSize };
|
||||
|
||||
virtual void SetUp() {
|
||||
memset(packet_buffer_, 0, kPacketBufferSize);
|
||||
memset(frame_buffer_, 0, kFrameBufferSize);
|
||||
vp8_header_ = &packet_header_.type.Video.codecHeader.VP8;
|
||||
packet_header_.frameType = webrtc::kVideoFrameDelta;
|
||||
packet_header_.type.Video.codec = webrtc::kRTPVideoVP8;
|
||||
vp8_header_->InitRTPVideoHeaderVP8();
|
||||
fragmentation_.VerifyAndAllocateFragmentationHeader(
|
||||
webrtc::kMaxVP8Partitions);
|
||||
session_.Reset();
|
||||
packet_.Reset();
|
||||
packet_.frameType = kVideoFrameDelta;
|
||||
packet_.sizeBytes = kPacketBufferSize;
|
||||
packet_.dataPtr = packet_buffer_;
|
||||
packet_.seqNum = 0;
|
||||
packet_.timestamp = 0;
|
||||
packet_.bits = false;
|
||||
}
|
||||
|
||||
void FillPacket(WebRtc_UWord8 start_value) {
|
||||
void FillPacket(uint8_t start_value) {
|
||||
for (int i = 0; i < kPacketBufferSize; ++i)
|
||||
packet_buffer_[i] = start_value + i;
|
||||
}
|
||||
|
||||
void VerifyPacket(uint8_t* start_ptr, uint8_t start_value) {
|
||||
for (int j = 0; j < kPacketBufferSize; ++j) {
|
||||
ASSERT_EQ(start_value + j, start_ptr[j]);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t packet_buffer_[kPacketBufferSize];
|
||||
uint8_t frame_buffer_[kFrameBufferSize];
|
||||
VCMSessionInfo session_;
|
||||
VCMPacket packet_;
|
||||
};
|
||||
|
||||
class TestVP8Partitions : public TestSessionInfo {
|
||||
protected:
|
||||
enum { kMaxVP8Partitions = 9 };
|
||||
|
||||
virtual void SetUp() {
|
||||
TestSessionInfo::SetUp();
|
||||
vp8_header_ = &packet_header_.type.Video.codecHeader.VP8;
|
||||
packet_header_.frameType = kVideoFrameDelta;
|
||||
packet_header_.type.Video.codec = kRTPVideoVP8;
|
||||
vp8_header_->InitRTPVideoHeaderVP8();
|
||||
fragmentation_.VerifyAndAllocateFragmentationHeader(kMaxVP8Partitions);
|
||||
}
|
||||
|
||||
bool VerifyPartition(int partition_id,
|
||||
int packets_expected,
|
||||
int start_value) {
|
||||
EXPECT_EQ(static_cast<WebRtc_UWord32>(packets_expected * kPacketBufferSize),
|
||||
EXPECT_EQ(static_cast<uint32_t>(packets_expected * kPacketBufferSize),
|
||||
fragmentation_.fragmentationLength[partition_id]);
|
||||
for (int i = 0; i < packets_expected; ++i) {
|
||||
int packet_index = fragmentation_.fragmentationOffset[partition_id] +
|
||||
i * kPacketBufferSize;
|
||||
for (int j = 0; j < kPacketBufferSize; ++j) {
|
||||
if (packet_index + j > kFrameBufferSize)
|
||||
return false;
|
||||
EXPECT_EQ(start_value + i + j, frame_buffer_[packet_index + j]);
|
||||
}
|
||||
if (packet_index + kPacketBufferSize > kFrameBufferSize)
|
||||
return false;
|
||||
VerifyPacket(frame_buffer_ + packet_index, start_value + i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
WebRtc_UWord8 packet_buffer_[kPacketBufferSize];
|
||||
WebRtc_UWord8 frame_buffer_[kFrameBufferSize];
|
||||
WebRtcRTPHeader packet_header_;
|
||||
VCMSessionInfo session_;
|
||||
RTPVideoHeaderVP8* vp8_header_;
|
||||
RTPFragmentationHeader fragmentation_;
|
||||
WebRtcRTPHeader packet_header_;
|
||||
RTPVideoHeaderVP8* vp8_header_;
|
||||
RTPFragmentationHeader fragmentation_;
|
||||
};
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss) {
|
||||
class TestNalUnits : public TestSessionInfo {
|
||||
protected:
|
||||
virtual void SetUp() {
|
||||
TestSessionInfo::SetUp();
|
||||
packet_.codec = kVideoCodecH264;
|
||||
}
|
||||
|
||||
bool VerifyNalu(int offset, int packets_expected, int start_value) {
|
||||
EXPECT_GE(session_.SessionLength(),
|
||||
packets_expected * kPacketBufferSize);
|
||||
for (int i = 0; i < packets_expected; ++i) {
|
||||
int packet_index = offset * kPacketBufferSize + i * kPacketBufferSize;
|
||||
VerifyPacket(frame_buffer_ + packet_index, start_value + i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TestZeroOutSeqNum : public TestSessionInfo {
|
||||
protected:
|
||||
enum { kMaxSeqNumListLength = 30 };
|
||||
|
||||
virtual void SetUp() {
|
||||
TestSessionInfo::SetUp();
|
||||
seq_num_list_length_ = 0;
|
||||
memset(seq_num_list_, 0, sizeof(seq_num_list_));
|
||||
}
|
||||
|
||||
void BuildSeqNumList(uint16_t low,
|
||||
uint16_t high) {
|
||||
int i = 0;
|
||||
while (low != high + 1) {
|
||||
EXPECT_LT(i, kMaxSeqNumListLength);
|
||||
if (i >= kMaxSeqNumListLength) {
|
||||
seq_num_list_length_ = kMaxSeqNumListLength;
|
||||
return;
|
||||
}
|
||||
seq_num_list_[i] = low;
|
||||
low++;
|
||||
i++;
|
||||
}
|
||||
seq_num_list_length_ = i;
|
||||
}
|
||||
|
||||
void VerifyAll(int value) {
|
||||
for (int i = 0; i < seq_num_list_length_; ++i)
|
||||
EXPECT_EQ(seq_num_list_[i], value);
|
||||
}
|
||||
|
||||
int seq_num_list_[kMaxSeqNumListLength];
|
||||
int seq_num_list_length_;
|
||||
};
|
||||
|
||||
TEST_F(TestSessionInfo, TestSimpleAPIs) {
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.seqNum = 0xFFFE;
|
||||
packet_.sizeBytes = kPacketBufferSize;
|
||||
packet_.frameType = kVideoFrameKey;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(kPacketBufferSize,
|
||||
session_.InsertPacket(packet_, frame_buffer_, false, 0));
|
||||
EXPECT_EQ(false, session_.HaveLastPacket());
|
||||
EXPECT_EQ(kVideoFrameKey, session_.FrameType());
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = true;
|
||||
packet_.seqNum += 1;
|
||||
ASSERT_EQ(kPacketBufferSize,
|
||||
session_.InsertPacket(packet_, frame_buffer_, false, 0));
|
||||
EXPECT_EQ(true, session_.HaveLastPacket());
|
||||
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
||||
EXPECT_EQ(0xFFFE, session_.LowSequenceNumber());
|
||||
|
||||
// Insert empty packet which will be the new high sequence number.
|
||||
// To make things more difficult we will make sure to have a wrap here.
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = true;
|
||||
packet_.seqNum = 2;
|
||||
packet_.sizeBytes = 0;
|
||||
packet_.frameType = kFrameEmpty;
|
||||
ASSERT_EQ(0,
|
||||
session_.InsertPacket(packet_, frame_buffer_, false, 0));
|
||||
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
|
||||
}
|
||||
|
||||
TEST_F(TestSessionInfo, NormalOperation) {
|
||||
packet_.seqNum = 0xFFFF;
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
for (int i = 1; i < 9; ++i) {
|
||||
packet_.seqNum += 1;
|
||||
FillPacket(i);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
}
|
||||
|
||||
packet_.seqNum += 1;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(9);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
EXPECT_EQ(10 * kPacketBufferSize, session_.SessionLength());
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
SCOPED_TRACE("Calling VerifyPacket");
|
||||
VerifyPacket(frame_buffer_ + i * kPacketBufferSize, i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestVP8Partitions, TwoPartitionsOneLoss) {
|
||||
// Partition 0 | Partition 1
|
||||
// [ 0 ] [ 2 ] | [ 3 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -78,7 +211,6 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss) {
|
||||
FillPacket(0);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -106,7 +238,7 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss) {
|
||||
delete packet;
|
||||
|
||||
// One packet should be removed (end of partition 0).
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
2*kPacketBufferSize);
|
||||
@@ -116,7 +248,7 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss) {
|
||||
EXPECT_TRUE(VerifyPartition(1, 1, 3));
|
||||
}
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss2) {
|
||||
TEST_F(TestVP8Partitions, TwoPartitionsOneLoss2) {
|
||||
// Partition 0 | Partition 1
|
||||
// [ 1 ] [ 2 ] | [ 3 ] [ 5 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -127,7 +259,6 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss2) {
|
||||
FillPacket(1);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0)
|
||||
, kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -166,7 +297,7 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss2) {
|
||||
delete packet;
|
||||
|
||||
// One packet should be removed (end of partition 2), 3 left.
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
3*kPacketBufferSize);
|
||||
@@ -174,9 +305,10 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsOneLoss2) {
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 1));
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(1, 1, 3));
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, TwoPartitionsNoLossWrap) {
|
||||
TEST_F(TestVP8Partitions, TwoPartitionsNoLossWrap) {
|
||||
// Partition 0 | Partition 1
|
||||
// [ fffd ] [ fffe ] | [ ffff ] [ 0 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -187,7 +319,6 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsNoLossWrap) {
|
||||
FillPacket(0);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -226,7 +357,7 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsNoLossWrap) {
|
||||
delete packet;
|
||||
|
||||
// No packet should be removed.
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
4*kPacketBufferSize);
|
||||
@@ -234,9 +365,10 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsNoLossWrap) {
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 0));
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(1, 2, 2));
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, TwoPartitionsLossWrap) {
|
||||
TEST_F(TestVP8Partitions, TwoPartitionsLossWrap) {
|
||||
// Partition 0 | Partition 1
|
||||
// [ fffd ] [ fffe ] | [ ffff ] [ 1 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -247,7 +379,6 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsLossWrap) {
|
||||
FillPacket(0);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -286,7 +417,7 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsLossWrap) {
|
||||
delete packet;
|
||||
|
||||
// One packet should be removed from the last partition
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
3*kPacketBufferSize);
|
||||
@@ -294,10 +425,11 @@ TEST_F(TestVP8MakeDecodable, TwoPartitionsLossWrap) {
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 0));
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(1, 1, 2));
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, ThreePartitionsOneMissing) {
|
||||
TEST_F(TestVP8Partitions, ThreePartitionsOneMissing) {
|
||||
// Partition 1 |Partition 2 | Partition 3
|
||||
// [ 1 ] [ 2 ] | | [ 5 ] | [ 6 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -308,7 +440,6 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsOneMissing) {
|
||||
FillPacket(1);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -347,7 +478,7 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsOneMissing) {
|
||||
delete packet;
|
||||
|
||||
// No packet should be removed.
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
4*kPacketBufferSize);
|
||||
@@ -355,9 +486,10 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsOneMissing) {
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 1));
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(2, 2, 5));
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, ThreePartitionsLossInSecond) {
|
||||
TEST_F(TestVP8Partitions, ThreePartitionsLossInSecond) {
|
||||
// Partition 0 |Partition 1 | Partition 2
|
||||
// [ 1 ] [ 2 ] | [ 4 ] [ 5 ] | [ 6 ] [ 7 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -368,7 +500,6 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsLossInSecond) {
|
||||
FillPacket(1);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -429,7 +560,7 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsLossInSecond) {
|
||||
delete packet;
|
||||
|
||||
// 2 partitions left. 2 packets removed from second partition
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
4*kPacketBufferSize);
|
||||
@@ -437,9 +568,10 @@ TEST_F(TestVP8MakeDecodable, ThreePartitionsLossInSecond) {
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 1));
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(2, 2, 6));
|
||||
EXPECT_EQ(2, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestVP8MakeDecodable, AggregationOverTwoPackets) {
|
||||
TEST_F(TestVP8Partitions, AggregationOverTwoPackets) {
|
||||
// Partition 0 | Partition 1 | Partition 2
|
||||
// [ 0 | ] [ 1 ] | [ 2 ]
|
||||
packet_header_.type.Video.isFirstPacket = true;
|
||||
@@ -450,7 +582,6 @@ TEST_F(TestVP8MakeDecodable, AggregationOverTwoPackets) {
|
||||
FillPacket(0);
|
||||
VCMPacket* packet = new VCMPacket(packet_buffer_, kPacketBufferSize,
|
||||
packet_header_);
|
||||
session_.SetStartSeqNumber(packet_header_.header.sequenceNumber);
|
||||
ASSERT_EQ(session_.InsertPacket(*packet, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
@@ -477,11 +608,12 @@ TEST_F(TestVP8MakeDecodable, AggregationOverTwoPackets) {
|
||||
kPacketBufferSize);
|
||||
delete packet;
|
||||
|
||||
// One packet should be removed (end of partition 0).
|
||||
ASSERT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
// No packets removed.
|
||||
EXPECT_EQ(session_.BuildVP8FragmentationHeader(frame_buffer_,
|
||||
kFrameBufferSize,
|
||||
&fragmentation_),
|
||||
3*kPacketBufferSize);
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(0, 2, 0));
|
||||
// This partition is aggregated in partition 0
|
||||
@@ -490,3 +622,338 @@ TEST_F(TestVP8MakeDecodable, AggregationOverTwoPackets) {
|
||||
SCOPED_TRACE("Calling VerifyPartition");
|
||||
EXPECT_TRUE(VerifyPartition(2, 1, 2));
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, OneIsolatedNaluLoss) {
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.completeNALU = kNaluComplete;
|
||||
packet_.seqNum = 0;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluComplete;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(0, session_.MakeDecodable());
|
||||
EXPECT_EQ(2 * kPacketBufferSize, session_.SessionLength());
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
SCOPED_TRACE("Calling VerifyNalu");
|
||||
EXPECT_TRUE(VerifyNalu(0, 1, 0));
|
||||
SCOPED_TRACE("Calling VerifyNalu");
|
||||
EXPECT_TRUE(VerifyNalu(1, 1, 2));
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, LossInMiddleOfNalu) {
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.completeNALU = kNaluComplete;
|
||||
packet_.seqNum = 0;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluEnd;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(kPacketBufferSize, session_.MakeDecodable());
|
||||
EXPECT_EQ(kPacketBufferSize, session_.SessionLength());
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
SCOPED_TRACE("Calling VerifyNalu");
|
||||
EXPECT_TRUE(VerifyNalu(0, 1, 0));
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, StartAndEndOfLastNalUnitLost) {
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.completeNALU = kNaluComplete;
|
||||
packet_.seqNum = 0;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluIncomplete;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(kPacketBufferSize, session_.MakeDecodable());
|
||||
EXPECT_EQ(kPacketBufferSize, session_.SessionLength());
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
SCOPED_TRACE("Calling VerifyNalu");
|
||||
EXPECT_TRUE(VerifyNalu(0, 1, 0));
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, ReorderWrapNoLoss) {
|
||||
packet_.seqNum = 0xFFFF;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluIncomplete;
|
||||
packet_.seqNum += 1;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.completeNALU = kNaluComplete;
|
||||
packet_.seqNum -= 1;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluEnd;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(0, session_.MakeDecodable());
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
EXPECT_EQ(3*kPacketBufferSize, session_.SessionLength());
|
||||
SCOPED_TRACE("Calling VerifyNalu");
|
||||
EXPECT_TRUE(VerifyNalu(0, 1, 0));
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, WrapLosses) {
|
||||
packet_.seqNum = 0xFFFF;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluIncomplete;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluEnd;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(2 * kPacketBufferSize, session_.MakeDecodable());
|
||||
EXPECT_EQ(0, session_.SessionLength());
|
||||
EXPECT_EQ(2, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestNalUnits, ReorderWrapLosses) {
|
||||
packet_.seqNum = 0xFFFF;
|
||||
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluEnd;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.seqNum -= 2;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.completeNALU = kNaluIncomplete;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(2 * kPacketBufferSize, session_.MakeDecodable());
|
||||
EXPECT_EQ(0, session_.SessionLength());
|
||||
EXPECT_EQ(2, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestZeroOutSeqNum, NoLosses) {
|
||||
uint16_t low = 0xFFFF - 5;
|
||||
|
||||
packet_.seqNum = low;
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
for (int i = 1; i < 9; ++i) {
|
||||
packet_.seqNum += 1;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(i + 1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
}
|
||||
|
||||
packet_.seqNum += 1;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(10);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(10 * kPacketBufferSize, session_.SessionLength());
|
||||
BuildSeqNumList(low, packet_.seqNum);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNum(seq_num_list_, seq_num_list_length_));
|
||||
EXPECT_EQ(false, session_.session_nack());
|
||||
SCOPED_TRACE("Calling VerifyAll");
|
||||
VerifyAll(-1);
|
||||
|
||||
BuildSeqNumList(low, packet_.seqNum);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNumHybrid(seq_num_list_,
|
||||
seq_num_list_length_,
|
||||
60));
|
||||
SCOPED_TRACE("Calling VerifyAll");
|
||||
VerifyAll(-1);
|
||||
}
|
||||
|
||||
TEST_F(TestZeroOutSeqNum, FiveLossesSpreadOut) {
|
||||
uint16_t low = 0xFFFF - 5;
|
||||
|
||||
packet_.seqNum = low;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
for (int i = 1; i < 9; ++i) {
|
||||
packet_.seqNum += 1;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(i);
|
||||
if ((i + 1) % 2)
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
}
|
||||
|
||||
packet_.seqNum++; // Simulate loss of last packet.
|
||||
|
||||
EXPECT_EQ(5 * kPacketBufferSize, session_.SessionLength());
|
||||
BuildSeqNumList(low, packet_.seqNum);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNum(seq_num_list_, seq_num_list_length_));
|
||||
for (int i = 0; i < seq_num_list_length_; ++i) {
|
||||
if (i % 2)
|
||||
EXPECT_EQ(static_cast<uint16_t>(low + i), seq_num_list_[i]);
|
||||
else
|
||||
EXPECT_EQ(-1, seq_num_list_[i]);
|
||||
}
|
||||
|
||||
BuildSeqNumList(low, packet_.seqNum);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNumHybrid(seq_num_list_,
|
||||
seq_num_list_length_,
|
||||
60));
|
||||
EXPECT_EQ(true, session_.session_nack());
|
||||
for (int i = 0; i < seq_num_list_length_; ++i) {
|
||||
if (i % 2)
|
||||
EXPECT_EQ(static_cast<uint16_t>(low + i), seq_num_list_[i]);
|
||||
else
|
||||
EXPECT_EQ(-1, seq_num_list_[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TestZeroOutSeqNum, FirstAndLastLost) {
|
||||
uint16_t low = 0xFFFF;
|
||||
|
||||
packet_.seqNum = low + 1;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(0);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(kPacketBufferSize, session_.SessionLength());
|
||||
BuildSeqNumList(low, packet_.seqNum + 1);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNum(seq_num_list_, seq_num_list_length_));
|
||||
EXPECT_EQ(0xFFFF, seq_num_list_[0]);
|
||||
EXPECT_EQ(-1, seq_num_list_[1]);
|
||||
EXPECT_EQ(1, seq_num_list_[2]);
|
||||
|
||||
BuildSeqNumList(low, packet_.seqNum + 1);
|
||||
EXPECT_EQ(0, session_.ZeroOutSeqNumHybrid(seq_num_list_,
|
||||
seq_num_list_length_,
|
||||
60));
|
||||
EXPECT_EQ(true, session_.session_nack());
|
||||
EXPECT_EQ(0xFFFF, seq_num_list_[0]);
|
||||
EXPECT_EQ(-1, seq_num_list_[1]);
|
||||
EXPECT_EQ(1, seq_num_list_[2]);
|
||||
}
|
||||
|
||||
TEST_F(TestSessionInfo, PacketPriorBitsPacketLost) {
|
||||
packet_.seqNum = 0;
|
||||
packet_.codecSpecificHeader.codec = kRTPVideoH263;
|
||||
packet_.bits = true;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(1);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(0, session_.PrepareForDecode(frame_buffer_));
|
||||
EXPECT_EQ(0, session_.SessionLength());
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestSessionInfo, MiddlePacketPriorBitsPacketLost) {
|
||||
packet_.codecSpecificHeader.codec = kRTPVideoH263;
|
||||
packet_.bits = false;
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.seqNum = 0;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.bits = true;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.seqNum += 2;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(2 * kPacketBufferSize, session_.PrepareForDecode(frame_buffer_));
|
||||
EXPECT_EQ(2 * kPacketBufferSize, session_.SessionLength());
|
||||
EXPECT_EQ(1, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
TEST_F(TestSessionInfo, ORingReorderedBitsPackets) {
|
||||
const uint8_t kEndByte = 0x07;
|
||||
const uint8_t kStartByte = 0xF8;
|
||||
packet_.codecSpecificHeader.codec = kRTPVideoH263;
|
||||
packet_.bits = true;
|
||||
packet_.isFirstPacket = false;
|
||||
packet_.seqNum = 1;
|
||||
packet_.markerBit = true;
|
||||
FillPacket(2);
|
||||
packet_buffer_[0] = kStartByte;
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
packet_.bits = false;
|
||||
packet_.isFirstPacket = true;
|
||||
packet_.seqNum = 0;
|
||||
packet_.markerBit = false;
|
||||
FillPacket(1);
|
||||
packet_buffer_[kPacketBufferSize - 1] = kEndByte;
|
||||
ASSERT_EQ(session_.InsertPacket(packet_, frame_buffer_, false, 0),
|
||||
kPacketBufferSize);
|
||||
|
||||
EXPECT_EQ(2 * kPacketBufferSize - 1,
|
||||
session_.PrepareForDecode(frame_buffer_));
|
||||
EXPECT_EQ(2 * kPacketBufferSize - 1, session_.SessionLength());
|
||||
EXPECT_EQ(kStartByte | kEndByte, frame_buffer_[kPacketBufferSize - 1]);
|
||||
EXPECT_EQ(0, session_.packets_not_decodable());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user