blob: d43af778e38063ddf91ecd048b506346ac139d42 [file] [log] [blame]
/*
* Copyright (c) 2017 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 <algorithm>
#include <limits>
#include <memory>
#include <vector>
#include "api/array_view.h"
#include "modules/include/module_common_types.h"
#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
#include "modules/rtp_rtcp/source/byte_io.h"
#include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::testing::Each;
using ::testing::ElementsAreArray;
using ::testing::Le;
using ::testing::SizeIs;
using ::testing::Contains;
constexpr RtpPacketizer::PayloadSizeLimits kNoSizeLimits;
std::vector<int> NextPacketFillPayloadSizes(RtpPacketizerGeneric* packetizer) {
RtpPacketToSend packet(nullptr);
std::vector<int> result;
while (packetizer->NextPacket(&packet)) {
result.push_back(packet.payload_size());
}
return result;
}
TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSize) {
const size_t kPayloadSize = 50;
const uint8_t kPayload[kPayloadSize] = {};
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader(),
VideoFrameType::kVideoFrameKey);
std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
}
TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSize) {
const size_t kPayloadSize = 50;
const uint8_t kPayload[kPayloadSize] = {};
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
RtpPacketizerGeneric packetizer(kPayload, limits, RTPVideoHeader(),
VideoFrameType::kVideoFrameKey);
std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
// With kPayloadSize > max_payload_len^2, there should be packets that use
// all the payload, otherwise it is possible to use less packets.
EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
}
TEST(RtpPacketizerVideoGeneric, WritesExtendedHeaderWhenPictureIdIsSet) {
const size_t kPayloadSize = 13;
const uint8_t kPayload[kPayloadSize] = {};
RTPVideoHeader rtp_video_header;
rtp_video_header.generic.emplace().frame_id = 37;
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header,
VideoFrameType::kVideoFrameKey);
RtpPacketToSend packet(nullptr);
ASSERT_TRUE(packetizer.NextPacket(&packet));
rtc::ArrayView<const uint8_t> payload = packet.payload();
EXPECT_EQ(payload.size(), 3 + kPayloadSize);
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
// Frame id is 37.
EXPECT_EQ(0u, payload[1]);
EXPECT_EQ(37u, payload[2]);
}
TEST(RtpPacketizerVideoGeneric, RespectsMaxPayloadSizeWithExtendedHeader) {
const int kPayloadSize = 50;
const uint8_t kPayload[kPayloadSize] = {};
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
RTPVideoHeader rtp_video_header;
rtp_video_header.generic.emplace().frame_id = 37;
RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header,
VideoFrameType::kVideoFrameKey);
std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
EXPECT_THAT(payload_sizes, Each(Le(limits.max_payload_len)));
}
TEST(RtpPacketizerVideoGeneric, UsesMaxPayloadSizeWithExtendedHeader) {
const int kPayloadSize = 50;
const uint8_t kPayload[kPayloadSize] = {};
RtpPacketizer::PayloadSizeLimits limits;
limits.max_payload_len = 6;
RTPVideoHeader rtp_video_header;
rtp_video_header.generic.emplace().frame_id = 37;
RtpPacketizerGeneric packetizer(kPayload, limits, rtp_video_header,
VideoFrameType::kVideoFrameKey);
std::vector<int> payload_sizes = NextPacketFillPayloadSizes(&packetizer);
// With kPayloadSize > max_payload_len^2, there should be packets that use
// all the payload, otherwise it is possible to use less packets.
EXPECT_THAT(payload_sizes, Contains(limits.max_payload_len));
}
TEST(RtpPacketizerVideoGeneric, FrameIdOver15bitsWrapsAround) {
const int kPayloadSize = 13;
const uint8_t kPayload[kPayloadSize] = {};
RTPVideoHeader rtp_video_header;
rtp_video_header.generic.emplace().frame_id = 0x8137;
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, rtp_video_header,
VideoFrameType::kVideoFrameKey);
RtpPacketToSend packet(nullptr);
ASSERT_TRUE(packetizer.NextPacket(&packet));
rtc::ArrayView<const uint8_t> payload = packet.payload();
EXPECT_TRUE(payload[0] & 0x04); // Extended header bit is set.
// Frame id is 0x137.
EXPECT_EQ(0x01u, payload[1]);
EXPECT_EQ(0x37u, payload[2]);
}
TEST(RtpPacketizerVideoGeneric, NoFrameIdDoesNotWriteExtendedHeader) {
const int kPayloadSize = 13;
const uint8_t kPayload[kPayloadSize] = {};
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits, RTPVideoHeader(),
VideoFrameType::kVideoFrameKey);
RtpPacketToSend packet(nullptr);
ASSERT_TRUE(packetizer.NextPacket(&packet));
rtc::ArrayView<const uint8_t> payload = packet.payload();
EXPECT_FALSE(payload[0] & 0x04);
}
TEST(RtpPacketizerVideoGeneric, DoesNotWriteHeaderForRawPayload) {
const uint8_t kPayload[] = {0x05, 0x25, 0x52};
RtpPacketizerGeneric packetizer(kPayload, kNoSizeLimits);
RtpPacketToSend packet(nullptr);
ASSERT_TRUE(packetizer.NextPacket(&packet));
rtc::ArrayView<const uint8_t> payload = packet.payload();
EXPECT_THAT(payload, ElementsAreArray(kPayload));
}
TEST(RtpDepacketizerVideoGeneric, NonExtendedHeaderNoFrameId) {
const size_t kPayloadLen = 1;
uint8_t payload[kPayloadLen] = {0x01};
RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/true);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
EXPECT_FALSE(parsed_payload.video_header().generic);
}
TEST(RtpDepacketizerVideoGeneric, ExtendedHeaderParsesFrameId) {
const size_t kPayloadLen = 3;
uint8_t payload[kPayloadLen] = {0x05, 0x13, 0x37};
RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/true);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, payload, kPayloadLen);
ASSERT_TRUE(parsed_payload.video_header().generic);
EXPECT_EQ(0x1337, parsed_payload.video_header().generic->frame_id);
}
TEST(RtpDepacketizerVideoGeneric, DoesNotParseHeaderForRawPayload) {
const uint8_t kPayload[] = {0x05, 0x25, 0x52};
const size_t kPayloadLen = sizeof(kPayload);
RtpDepacketizerGeneric depacketizer(/*generic_header_enabled=*/false);
RtpDepacketizer::ParsedPayload parsed_payload;
depacketizer.Parse(&parsed_payload, kPayload, kPayloadLen);
EXPECT_FALSE(parsed_payload.video_header().generic);
EXPECT_THAT(rtc::MakeArrayView<const uint8_t>(parsed_payload.payload,
parsed_payload.payload_length),
ElementsAreArray(kPayload));
}
} // namespace
} // namespace webrtc