webrtc/modules/video_coding/session_info_unittest.cc
Magnus Jedvert 2234121cfb VCMPacket: Set VCMNaluCompleteness for generic codecs
We previously always set VCMNaluCompleteness to kNaluComplete for
kVideoCodecGeneric, which seems wrong. This CL fixes that and also
cleans up the code a bit. The logic for VP8, VP9, and H264
should be exactly preserved. This CL also updates the test to use
kVideoCodecGeneric instead of kVideoCodecUnknown. kVideoCodecUnknown
has no purpose and should be removed.

Bug: webrtc:9516
Change-Id: Ib8d2bf6a04d41b91c5774531f3a669edce3c6cb2
Reviewed-on: https://webrtc-review.googlesource.com/88181
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Commit-Queue: Magnus Jedvert <magjed@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#23933}
2018-07-11 13:22:59 +00:00

559 lines
19 KiB
C++

/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <string.h>
#include "modules/include/module_common_types.h"
#include "modules/video_coding/packet.h"
#include "modules/video_coding/session_info.h"
#include "test/gtest.h"
namespace webrtc {
class TestSessionInfo : public ::testing::Test {
protected:
virtual void SetUp() {
memset(packet_buffer_, 0, sizeof(packet_buffer_));
memset(frame_buffer_, 0, sizeof(frame_buffer_));
session_.Reset();
packet_.frameType = kVideoFrameDelta;
packet_.sizeBytes = packet_buffer_size();
packet_.dataPtr = packet_buffer_;
packet_.seqNum = 0;
packet_.timestamp = 0;
frame_data.rtt_ms = 0;
frame_data.rolling_average_packets_per_frame = -1;
}
void FillPacket(uint8_t start_value) {
for (size_t i = 0; i < packet_buffer_size(); ++i)
packet_buffer_[i] = start_value + i;
}
void VerifyPacket(uint8_t* start_ptr, uint8_t start_value) {
for (size_t j = 0; j < packet_buffer_size(); ++j) {
ASSERT_EQ(start_value + j, start_ptr[j]);
}
}
size_t packet_buffer_size() const {
return sizeof(packet_buffer_) / sizeof(packet_buffer_[0]);
}
size_t frame_buffer_size() const {
return sizeof(frame_buffer_) / sizeof(frame_buffer_[0]);
}
enum { kPacketBufferSize = 10 };
uint8_t packet_buffer_[kPacketBufferSize];
uint8_t frame_buffer_[10 * kPacketBufferSize];
VCMSessionInfo session_;
VCMPacket packet_;
FrameData frame_data;
};
class TestNalUnits : public TestSessionInfo {
protected:
virtual void SetUp() {
TestSessionInfo::SetUp();
packet_.codec = kVideoCodecVP8;
}
bool VerifyNalu(int offset, int packets_expected, int start_value) {
EXPECT_GE(session_.SessionLength(),
packets_expected * packet_buffer_size());
for (int i = 0; i < packets_expected; ++i) {
int packet_index = (offset + i) * packet_buffer_size();
VerifyPacket(frame_buffer_ + packet_index, start_value + i);
}
return true;
}
};
class TestNackList : public TestSessionInfo {
protected:
static const size_t 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) {
size_t 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_.is_first_packet_in_frame = true;
packet_.seqNum = 0xFFFE;
packet_.sizeBytes = packet_buffer_size();
packet_.frameType = kVideoFrameKey;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_FALSE(session_.HaveLastPacket());
EXPECT_EQ(kVideoFrameKey, session_.FrameType());
packet_.is_first_packet_in_frame = false;
packet_.markerBit = true;
packet_.seqNum += 1;
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_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_.is_first_packet_in_frame = false;
packet_.markerBit = true;
packet_.seqNum = 2;
packet_.sizeBytes = 0;
packet_.frameType = kEmptyFrame;
EXPECT_EQ(
0, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
EXPECT_EQ(packet_.seqNum, session_.HighSequenceNumber());
}
TEST_F(TestSessionInfo, NormalOperation) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = false;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
for (int i = 1; i < 9; ++i) {
packet_.seqNum += 1;
FillPacket(i);
ASSERT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kNoErrors, frame_data)));
}
packet_.seqNum += 1;
packet_.markerBit = true;
FillPacket(9);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(10 * packet_buffer_size(), session_.SessionLength());
for (int i = 0; i < 10; ++i) {
SCOPED_TRACE("Calling VerifyPacket");
VerifyPacket(frame_buffer_ + i * packet_buffer_size(), i);
}
}
TEST_F(TestSessionInfo, ErrorsEqualDecodableState) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(3);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kWithErrors, frame_data)));
EXPECT_TRUE(session_.decodable());
}
TEST_F(TestSessionInfo, SelectiveDecodableState) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
frame_data.rolling_average_packets_per_frame = 11;
frame_data.rtt_ms = 150;
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
EXPECT_FALSE(session_.decodable());
packet_.seqNum -= 1;
FillPacket(0);
packet_.is_first_packet_in_frame = true;
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
EXPECT_TRUE(session_.decodable());
packet_.is_first_packet_in_frame = false;
packet_.seqNum += 1;
for (int i = 2; i < 8; ++i) {
packet_.seqNum += 1;
FillPacket(i);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
EXPECT_TRUE(session_.decodable());
}
packet_.seqNum += 1;
FillPacket(8);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(
packet_, frame_buffer_, kSelectiveErrors, frame_data)));
EXPECT_TRUE(session_.decodable());
}
TEST_F(TestSessionInfo, OutOfBoundsPackets1PacketFrame) {
packet_.seqNum = 0x0001;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0004;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
packet_.seqNum = 0x0000;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
}
TEST_F(TestSessionInfo, SetMarkerBitOnce) {
packet_.seqNum = 0x0005;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
++packet_.seqNum;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
}
TEST_F(TestSessionInfo, OutOfBoundsPacketsBase) {
// Allow packets in the range 5-6.
packet_.seqNum = 0x0005;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
// Insert an older packet with a first packet set.
packet_.seqNum = 0x0004;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
packet_.seqNum = 0x0006;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0008;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
}
TEST_F(TestSessionInfo, OutOfBoundsPacketsWrap) {
packet_.seqNum = 0xFFFE;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0004;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0002;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
ASSERT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0xFFF0;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
packet_.seqNum = 0x0006;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
}
TEST_F(TestSessionInfo, OutOfBoundsOutOfOrder) {
// Insert out of bound regular packets, and then the first and last packet.
// Verify that correct bounds are maintained.
packet_.seqNum = 0x0003;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
// Insert an older packet with a first packet set.
packet_.seqNum = 0x0005;
packet_.is_first_packet_in_frame = true;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0004;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
packet_.seqNum = 0x0010;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0008;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = true;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum = 0x0009;
packet_.is_first_packet_in_frame = false;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(
-3, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
}
TEST_F(TestNalUnits, OnlyReceivedEmptyPacket) {
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluComplete;
packet_.frameType = kEmptyFrame;
packet_.sizeBytes = 0;
packet_.seqNum = 0;
packet_.markerBit = false;
EXPECT_EQ(
0, session_.InsertPacket(packet_, frame_buffer_, kNoErrors, frame_data));
EXPECT_EQ(0U, session_.MakeDecodable());
EXPECT_EQ(0U, session_.SessionLength());
}
TEST_F(TestNalUnits, OneIsolatedNaluLoss) {
packet_.is_first_packet_in_frame = true;
packet_.completeNALU = kNaluComplete;
packet_.seqNum = 0;
packet_.markerBit = false;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluComplete;
packet_.seqNum += 2;
packet_.markerBit = true;
FillPacket(2);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(0U, session_.MakeDecodable());
EXPECT_EQ(2 * packet_buffer_size(), session_.SessionLength());
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_.is_first_packet_in_frame = true;
packet_.completeNALU = kNaluComplete;
packet_.seqNum = 0;
packet_.markerBit = false;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluEnd;
packet_.seqNum += 2;
packet_.markerBit = true;
FillPacket(2);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
SCOPED_TRACE("Calling VerifyNalu");
EXPECT_TRUE(VerifyNalu(0, 1, 0));
}
TEST_F(TestNalUnits, StartAndEndOfLastNalUnitLost) {
packet_.is_first_packet_in_frame = true;
packet_.completeNALU = kNaluComplete;
packet_.seqNum = 0;
packet_.markerBit = false;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluIncomplete;
packet_.seqNum += 2;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(packet_buffer_size(), session_.MakeDecodable());
EXPECT_EQ(packet_buffer_size(), session_.SessionLength());
SCOPED_TRACE("Calling VerifyNalu");
EXPECT_TRUE(VerifyNalu(0, 1, 0));
}
TEST_F(TestNalUnits, ReorderWrapNoLoss) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluIncomplete;
packet_.seqNum += 1;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = true;
packet_.completeNALU = kNaluComplete;
packet_.seqNum -= 1;
packet_.markerBit = false;
FillPacket(0);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluEnd;
packet_.seqNum += 2;
packet_.markerBit = true;
FillPacket(2);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(0U, session_.MakeDecodable());
EXPECT_EQ(3 * packet_buffer_size(), session_.SessionLength());
SCOPED_TRACE("Calling VerifyNalu");
EXPECT_TRUE(VerifyNalu(0, 1, 0));
}
TEST_F(TestNalUnits, WrapLosses) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluIncomplete;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluEnd;
packet_.seqNum += 2;
packet_.markerBit = true;
FillPacket(2);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
EXPECT_EQ(0U, session_.SessionLength());
}
TEST_F(TestNalUnits, ReorderWrapLosses) {
packet_.seqNum = 0xFFFF;
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluEnd;
packet_.seqNum += 2;
packet_.markerBit = true;
FillPacket(2);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
packet_.seqNum -= 2;
packet_.is_first_packet_in_frame = false;
packet_.completeNALU = kNaluIncomplete;
packet_.markerBit = false;
FillPacket(1);
EXPECT_EQ(packet_buffer_size(),
static_cast<size_t>(session_.InsertPacket(packet_, frame_buffer_,
kNoErrors, frame_data)));
EXPECT_EQ(2 * packet_buffer_size(), session_.MakeDecodable());
EXPECT_EQ(0U, session_.SessionLength());
}
} // namespace webrtc