| Index: extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
|
| diff --git a/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a8b769a4421ace00b07782a61c9e5344a614f764
|
| --- /dev/null
|
| +++ b/extensions/renderer/api/display_source/wifi_display/wifi_display_media_packetizer_unittest.cc
|
| @@ -0,0 +1,166 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/big_endian.h"
|
| +#include "extensions/renderer/api/display_source/wifi_display/wifi_display_elementary_stream_packetizer.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace extensions {
|
| +
|
| +namespace {
|
| +
|
| +namespace pes {
|
| +const unsigned kDtsFlag = 0x0040u;
|
| +const unsigned kMarkerFlag = 0x8000u;
|
| +const unsigned kPtsFlag = 0x0080u;
|
| +const size_t kUnitDataAlignment = sizeof(uint32_t);
|
| +}
|
| +
|
| +uint64_t ParseTimeStamp(const uint8_t ts_bytes[5], uint8_t pts_dts_indicator) {
|
| + EXPECT_EQ(pts_dts_indicator, (ts_bytes[0] & 0xF0u) >> 4);
|
| + EXPECT_EQ(0x01u, ts_bytes[0] & 0x01u);
|
| + EXPECT_EQ(0x01u, ts_bytes[2] & 0x01u);
|
| + EXPECT_EQ(0x01u, ts_bytes[4] & 0x01u);
|
| + uint64_t ts = 0u;
|
| + ts = (ts_bytes[0] & 0x0Eu) >> 1;
|
| + ts = (ts << 8) | ts_bytes[1];
|
| + ts = (ts << 7) | ((ts_bytes[2] & 0xFEu) >> 1);
|
| + ts = (ts << 8) | ts_bytes[3];
|
| + ts = (ts << 7) | ((ts_bytes[4] & 0xFEu) >> 1);
|
| + return ts;
|
| +}
|
| +
|
| +class WiFiDisplayElementaryStreamUnitPacketizationTest
|
| + : public testing::TestWithParam<
|
| + testing::tuple<unsigned, base::TimeDelta, base::TimeDelta>> {
|
| + protected:
|
| + static base::TimeTicks SumOrNull(const base::TimeTicks& base,
|
| + const base::TimeDelta& delta) {
|
| + return delta.is_max() ? base::TimeTicks() : base + delta;
|
| + }
|
| +
|
| + WiFiDisplayElementaryStreamUnitPacketizationTest()
|
| + : unit_(testing::get<0>(GetParam())),
|
| + now_(base::TimeTicks::Now()),
|
| + dts_(SumOrNull(now_, testing::get<1>(GetParam()))),
|
| + pts_(SumOrNull(now_, testing::get<2>(GetParam()))) {}
|
| +
|
| + void CheckElementaryStreamPacketHeader(
|
| + const WiFiDisplayElementaryStreamPacket& packet,
|
| + uint8_t stream_id) {
|
| + base::BigEndianReader header_reader(
|
| + reinterpret_cast<const char*>(packet.header().begin()),
|
| + packet.header().size());
|
| + uint8_t parsed_packet_start_code_prefix[3];
|
| + EXPECT_TRUE(
|
| + header_reader.ReadBytes(parsed_packet_start_code_prefix,
|
| + sizeof(parsed_packet_start_code_prefix)));
|
| + EXPECT_EQ(0x00u, parsed_packet_start_code_prefix[0]);
|
| + EXPECT_EQ(0x00u, parsed_packet_start_code_prefix[1]);
|
| + EXPECT_EQ(0x01u, parsed_packet_start_code_prefix[2]);
|
| + uint8_t parsed_stream_id;
|
| + EXPECT_TRUE(header_reader.ReadU8(&parsed_stream_id));
|
| + EXPECT_EQ(stream_id, parsed_stream_id);
|
| + uint16_t parsed_packet_length;
|
| + EXPECT_TRUE(header_reader.ReadU16(&parsed_packet_length));
|
| + size_t packet_length = static_cast<size_t>(header_reader.remaining()) +
|
| + packet.unit_header().size() + packet.unit().size();
|
| + if (packet_length >> 16)
|
| + packet_length = 0u;
|
| + EXPECT_EQ(packet_length, parsed_packet_length);
|
| + uint16_t parsed_flags;
|
| + EXPECT_TRUE(header_reader.ReadU16(&parsed_flags));
|
| + EXPECT_EQ(
|
| + 0u, parsed_flags & ~(pes::kMarkerFlag | pes::kPtsFlag | pes::kDtsFlag));
|
| + const bool parsed_pts_flag = (parsed_flags & pes::kPtsFlag) != 0u;
|
| + const bool parsed_dts_flag = (parsed_flags & pes::kDtsFlag) != 0u;
|
| + EXPECT_EQ(!pts_.is_null(), parsed_pts_flag);
|
| + EXPECT_EQ(!pts_.is_null() && !dts_.is_null(), parsed_dts_flag);
|
| + uint8_t parsed_header_length;
|
| + EXPECT_TRUE(header_reader.ReadU8(&parsed_header_length));
|
| + EXPECT_EQ(header_reader.remaining(), parsed_header_length);
|
| + if (parsed_pts_flag) {
|
| + uint8_t parsed_pts_bytes[5];
|
| + EXPECT_TRUE(
|
| + header_reader.ReadBytes(parsed_pts_bytes, sizeof(parsed_pts_bytes)));
|
| + const uint64_t parsed_pts =
|
| + ParseTimeStamp(parsed_pts_bytes, parsed_dts_flag ? 0x3u : 0x2u);
|
| + if (parsed_dts_flag) {
|
| + uint8_t parsed_dts_bytes[5];
|
| + EXPECT_TRUE(header_reader.ReadBytes(parsed_dts_bytes,
|
| + sizeof(parsed_dts_bytes)));
|
| + const uint64_t parsed_dts = ParseTimeStamp(parsed_dts_bytes, 0x1u);
|
| + EXPECT_EQ(
|
| + static_cast<uint64_t>(90 * (pts_ - dts_).InMicroseconds() / 1000),
|
| + (parsed_pts - parsed_dts) & UINT64_C(0x1FFFFFFFF));
|
| + }
|
| + }
|
| + while (header_reader.remaining() > 0) {
|
| + uint8_t parsed_stuffing_byte;
|
| + EXPECT_TRUE(header_reader.ReadU8(&parsed_stuffing_byte));
|
| + EXPECT_EQ(0xFFu, parsed_stuffing_byte);
|
| + }
|
| + EXPECT_EQ(0, header_reader.remaining());
|
| + }
|
| +
|
| + void CheckElementaryStreamPacketUnitHeader(
|
| + const WiFiDisplayElementaryStreamPacket& packet,
|
| + const uint8_t* unit_header_data,
|
| + size_t unit_header_size) {
|
| + EXPECT_EQ(unit_header_data, packet.unit_header().begin());
|
| + EXPECT_EQ(unit_header_size, packet.unit_header().size());
|
| + }
|
| +
|
| + void CheckElementaryStreamPacketUnit(
|
| + const WiFiDisplayElementaryStreamPacket& packet) {
|
| + EXPECT_EQ(0u, (packet.header().size() + packet.unit_header().size()) %
|
| + pes::kUnitDataAlignment);
|
| + EXPECT_EQ(unit_.data(), packet.unit().begin());
|
| + EXPECT_EQ(unit_.size(), packet.unit().size());
|
| + }
|
| +
|
| + enum { kVideoOnlyUnitSize = 0x8000u }; // Not exact. Be on the safe side.
|
| +
|
| + const std::vector<uint8_t> unit_;
|
| + const base::TimeTicks now_;
|
| + const base::TimeTicks dts_;
|
| + const base::TimeTicks pts_;
|
| +};
|
| +
|
| +TEST_P(WiFiDisplayElementaryStreamUnitPacketizationTest,
|
| + EncodeToElementaryStreamPacket) {
|
| + const size_t kMaxUnitHeaderSize = 4u;
|
| +
|
| + const uint8_t stream_id =
|
| + unit_.size() >= kVideoOnlyUnitSize
|
| + ? WiFiDisplayElementaryStreamPacketizer::kFirstVideoStreamId
|
| + : WiFiDisplayElementaryStreamPacketizer::kFirstAudioStreamId;
|
| +
|
| + WiFiDisplayElementaryStreamPacketizer packetizer;
|
| + uint8_t unit_header_data[kMaxUnitHeaderSize];
|
| + for (size_t unit_header_size = 0u; unit_header_size <= kMaxUnitHeaderSize;
|
| + ++unit_header_size) {
|
| + WiFiDisplayElementaryStreamPacket packet =
|
| + packetizer.EncodeElementaryStreamUnit(stream_id, unit_header_data,
|
| + unit_header_size, unit_.data(),
|
| + unit_.size(), pts_, dts_);
|
| + CheckElementaryStreamPacketHeader(packet, stream_id);
|
| + CheckElementaryStreamPacketUnitHeader(packet, unit_header_data,
|
| + unit_header_size);
|
| + CheckElementaryStreamPacketUnit(packet);
|
| + }
|
| +}
|
| +
|
| +INSTANTIATE_TEST_CASE_P(
|
| + WiFiDisplayElementaryStreamUnitPacketizationTests,
|
| + WiFiDisplayElementaryStreamUnitPacketizationTest,
|
| + testing::Combine(testing::Values(123u, 180u, 0x10000u),
|
| + testing::Values(base::TimeDelta::Max(),
|
| + base::TimeDelta::FromMicroseconds(0)),
|
| + testing::Values(base::TimeDelta::Max(),
|
| + base::TimeDelta::FromMicroseconds(
|
| + 1000 * INT64_C(0x123456789) / 90))));
|
| +
|
| +} // namespace
|
| +} // namespace extensions
|
|
|