1*103e46e4SHarish Mahendrakar // Copyright (c) 2016 The WebM project authors. All Rights Reserved.
2*103e46e4SHarish Mahendrakar //
3*103e46e4SHarish Mahendrakar // Use of this source code is governed by a BSD-style license
4*103e46e4SHarish Mahendrakar // that can be found in the LICENSE file in the root of the source
5*103e46e4SHarish Mahendrakar // tree. An additional intellectual property rights grant can be found
6*103e46e4SHarish Mahendrakar // in the file PATENTS. All contributing project authors may
7*103e46e4SHarish Mahendrakar // be found in the AUTHORS file in the root of the source tree.
8*103e46e4SHarish Mahendrakar #include "m2ts/webm2pes.h"
9*103e46e4SHarish Mahendrakar
10*103e46e4SHarish Mahendrakar #include <cstddef>
11*103e46e4SHarish Mahendrakar #include <cstdint>
12*103e46e4SHarish Mahendrakar #include <cstdio>
13*103e46e4SHarish Mahendrakar #include <cstring>
14*103e46e4SHarish Mahendrakar #include <limits>
15*103e46e4SHarish Mahendrakar #include <string>
16*103e46e4SHarish Mahendrakar #include <vector>
17*103e46e4SHarish Mahendrakar
18*103e46e4SHarish Mahendrakar #include "gtest/gtest.h"
19*103e46e4SHarish Mahendrakar
20*103e46e4SHarish Mahendrakar #include "common/file_util.h"
21*103e46e4SHarish Mahendrakar #include "common/libwebm_util.h"
22*103e46e4SHarish Mahendrakar #include "m2ts/vpxpes_parser.h"
23*103e46e4SHarish Mahendrakar #include "testing/test_util.h"
24*103e46e4SHarish Mahendrakar
25*103e46e4SHarish Mahendrakar namespace {
26*103e46e4SHarish Mahendrakar
27*103e46e4SHarish Mahendrakar class Webm2PesTests : public ::testing::Test {
28*103e46e4SHarish Mahendrakar public:
29*103e46e4SHarish Mahendrakar // Constants for validating known values from input data.
30*103e46e4SHarish Mahendrakar const std::uint8_t kMinVideoStreamId = 0xE0;
31*103e46e4SHarish Mahendrakar const std::uint8_t kMaxVideoStreamId = 0xEF;
32*103e46e4SHarish Mahendrakar const int kPesHeaderSize = 6;
33*103e46e4SHarish Mahendrakar const int kPesOptionalHeaderStartOffset = kPesHeaderSize;
34*103e46e4SHarish Mahendrakar const int kPesOptionalHeaderSize = 9;
35*103e46e4SHarish Mahendrakar const int kPesOptionalHeaderMarkerValue = 0x2;
36*103e46e4SHarish Mahendrakar const int kWebm2PesOptHeaderRemainingSize = 6;
37*103e46e4SHarish Mahendrakar const int kBcmvHeaderSize = 10;
38*103e46e4SHarish Mahendrakar
39*103e46e4SHarish Mahendrakar Webm2PesTests() = default;
40*103e46e4SHarish Mahendrakar ~Webm2PesTests() = default;
41*103e46e4SHarish Mahendrakar
CreateAndLoadTestInput()42*103e46e4SHarish Mahendrakar void CreateAndLoadTestInput() {
43*103e46e4SHarish Mahendrakar libwebm::Webm2Pes converter(input_file_name_, temp_file_name_.name());
44*103e46e4SHarish Mahendrakar ASSERT_TRUE(converter.ConvertToFile());
45*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser_.Open(pes_file_name()));
46*103e46e4SHarish Mahendrakar }
47*103e46e4SHarish Mahendrakar
VerifyPacketStartCode(const libwebm::VpxPesParser::PesHeader & header)48*103e46e4SHarish Mahendrakar bool VerifyPacketStartCode(const libwebm::VpxPesParser::PesHeader& header) {
49*103e46e4SHarish Mahendrakar // PES packets all start with the byte sequence 0x0 0x0 0x1.
50*103e46e4SHarish Mahendrakar if (header.start_code[0] != 0 || header.start_code[1] != 0 ||
51*103e46e4SHarish Mahendrakar header.start_code[2] != 1) {
52*103e46e4SHarish Mahendrakar return false;
53*103e46e4SHarish Mahendrakar }
54*103e46e4SHarish Mahendrakar return true;
55*103e46e4SHarish Mahendrakar }
56*103e46e4SHarish Mahendrakar
pes_file_name() const57*103e46e4SHarish Mahendrakar const std::string& pes_file_name() const { return temp_file_name_.name(); }
parser()58*103e46e4SHarish Mahendrakar libwebm::VpxPesParser* parser() { return &parser_; }
59*103e46e4SHarish Mahendrakar
60*103e46e4SHarish Mahendrakar private:
61*103e46e4SHarish Mahendrakar const libwebm::TempFileDeleter temp_file_name_;
62*103e46e4SHarish Mahendrakar const std::string input_file_name_ =
63*103e46e4SHarish Mahendrakar test::GetTestFilePath("bbb_480p_vp9_opus_1second.webm");
64*103e46e4SHarish Mahendrakar libwebm::VpxPesParser parser_;
65*103e46e4SHarish Mahendrakar };
66*103e46e4SHarish Mahendrakar
TEST_F(Webm2PesTests,CreatePesFile)67*103e46e4SHarish Mahendrakar TEST_F(Webm2PesTests, CreatePesFile) { CreateAndLoadTestInput(); }
68*103e46e4SHarish Mahendrakar
TEST_F(Webm2PesTests,CanParseFirstPacket)69*103e46e4SHarish Mahendrakar TEST_F(Webm2PesTests, CanParseFirstPacket) {
70*103e46e4SHarish Mahendrakar CreateAndLoadTestInput();
71*103e46e4SHarish Mahendrakar libwebm::VpxPesParser::PesHeader header;
72*103e46e4SHarish Mahendrakar libwebm::VideoFrame frame;
73*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser()->ParseNextPacket(&header, &frame));
74*103e46e4SHarish Mahendrakar EXPECT_TRUE(VerifyPacketStartCode(header));
75*103e46e4SHarish Mahendrakar
76*103e46e4SHarish Mahendrakar // 9 bytes: PES optional header
77*103e46e4SHarish Mahendrakar // 10 bytes: BCMV Header
78*103e46e4SHarish Mahendrakar // 83 bytes: frame
79*103e46e4SHarish Mahendrakar // 102 bytes total in packet length field:
80*103e46e4SHarish Mahendrakar const std::size_t kPesPayloadLength = 102;
81*103e46e4SHarish Mahendrakar EXPECT_EQ(kPesPayloadLength, header.packet_length);
82*103e46e4SHarish Mahendrakar
83*103e46e4SHarish Mahendrakar EXPECT_GE(header.stream_id, kMinVideoStreamId);
84*103e46e4SHarish Mahendrakar EXPECT_LE(header.stream_id, kMaxVideoStreamId);
85*103e46e4SHarish Mahendrakar
86*103e46e4SHarish Mahendrakar // Test PesOptionalHeader values.
87*103e46e4SHarish Mahendrakar EXPECT_EQ(kPesOptionalHeaderMarkerValue, header.opt_header.marker);
88*103e46e4SHarish Mahendrakar EXPECT_EQ(kWebm2PesOptHeaderRemainingSize, header.opt_header.remaining_size);
89*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.scrambling);
90*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.priority);
91*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.data_alignment);
92*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.copyright);
93*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.original);
94*103e46e4SHarish Mahendrakar EXPECT_EQ(1, header.opt_header.has_pts);
95*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.has_dts);
96*103e46e4SHarish Mahendrakar EXPECT_EQ(0, header.opt_header.unused_fields);
97*103e46e4SHarish Mahendrakar
98*103e46e4SHarish Mahendrakar // Test the BCMV header.
99*103e46e4SHarish Mahendrakar // Note: The length field of the BCMV header includes its own length.
100*103e46e4SHarish Mahendrakar const std::size_t kBcmvBaseLength = 10;
101*103e46e4SHarish Mahendrakar const std::size_t kFirstFrameLength = 83;
102*103e46e4SHarish Mahendrakar const libwebm::VpxPesParser::BcmvHeader kFirstBcmvHeader(kFirstFrameLength +
103*103e46e4SHarish Mahendrakar kBcmvBaseLength);
104*103e46e4SHarish Mahendrakar EXPECT_TRUE(header.bcmv_header.Valid());
105*103e46e4SHarish Mahendrakar EXPECT_EQ(kFirstBcmvHeader, header.bcmv_header);
106*103e46e4SHarish Mahendrakar
107*103e46e4SHarish Mahendrakar // Parse the next packet to confirm correct parse and consumption of payload.
108*103e46e4SHarish Mahendrakar EXPECT_TRUE(parser()->ParseNextPacket(&header, &frame));
109*103e46e4SHarish Mahendrakar }
110*103e46e4SHarish Mahendrakar
TEST_F(Webm2PesTests,CanMuxLargeBuffers)111*103e46e4SHarish Mahendrakar TEST_F(Webm2PesTests, CanMuxLargeBuffers) {
112*103e46e4SHarish Mahendrakar const std::size_t kBufferSize = 100 * 1024;
113*103e46e4SHarish Mahendrakar const std::int64_t kFakeTimestamp = libwebm::kNanosecondsPerSecond;
114*103e46e4SHarish Mahendrakar libwebm::VideoFrame fake_frame(kFakeTimestamp, libwebm::VideoFrame::kVP9);
115*103e46e4SHarish Mahendrakar ASSERT_TRUE(fake_frame.Init(kBufferSize));
116*103e46e4SHarish Mahendrakar std::memset(fake_frame.buffer().data.get(), 0x80, kBufferSize);
117*103e46e4SHarish Mahendrakar ASSERT_TRUE(fake_frame.SetBufferLength(kBufferSize));
118*103e46e4SHarish Mahendrakar libwebm::PacketDataBuffer pes_packet_buffer;
119*103e46e4SHarish Mahendrakar ASSERT_TRUE(
120*103e46e4SHarish Mahendrakar libwebm::Webm2Pes::WritePesPacket(fake_frame, &pes_packet_buffer));
121*103e46e4SHarish Mahendrakar
122*103e46e4SHarish Mahendrakar // TODO(tomfinegan): Change VpxPesParser so it can read from a buffer, and get
123*103e46e4SHarish Mahendrakar // rid of this extra step.
124*103e46e4SHarish Mahendrakar libwebm::FilePtr pes_file(std::fopen(pes_file_name().c_str(), "wb"),
125*103e46e4SHarish Mahendrakar libwebm::FILEDeleter());
126*103e46e4SHarish Mahendrakar ASSERT_EQ(pes_packet_buffer.size(),
127*103e46e4SHarish Mahendrakar fwrite(&pes_packet_buffer[0], 1, pes_packet_buffer.size(),
128*103e46e4SHarish Mahendrakar pes_file.get()));
129*103e46e4SHarish Mahendrakar fclose(pes_file.get());
130*103e46e4SHarish Mahendrakar pes_file.release();
131*103e46e4SHarish Mahendrakar
132*103e46e4SHarish Mahendrakar libwebm::VpxPesParser parser;
133*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser.Open(pes_file_name()));
134*103e46e4SHarish Mahendrakar libwebm::VpxPesParser::PesHeader header;
135*103e46e4SHarish Mahendrakar libwebm::VideoFrame parsed_frame;
136*103e46e4SHarish Mahendrakar ASSERT_TRUE(parser.ParseNextPacket(&header, &parsed_frame));
137*103e46e4SHarish Mahendrakar EXPECT_EQ(fake_frame.nanosecond_pts(), parsed_frame.nanosecond_pts());
138*103e46e4SHarish Mahendrakar EXPECT_EQ(fake_frame.buffer().length, parsed_frame.buffer().length);
139*103e46e4SHarish Mahendrakar EXPECT_EQ(0, std::memcmp(fake_frame.buffer().data.get(),
140*103e46e4SHarish Mahendrakar parsed_frame.buffer().data.get(), kBufferSize));
141*103e46e4SHarish Mahendrakar }
142*103e46e4SHarish Mahendrakar
TEST_F(Webm2PesTests,ParserConsumesAllInput)143*103e46e4SHarish Mahendrakar TEST_F(Webm2PesTests, ParserConsumesAllInput) {
144*103e46e4SHarish Mahendrakar CreateAndLoadTestInput();
145*103e46e4SHarish Mahendrakar libwebm::VpxPesParser::PesHeader header;
146*103e46e4SHarish Mahendrakar libwebm::VideoFrame frame;
147*103e46e4SHarish Mahendrakar while (parser()->ParseNextPacket(&header, &frame) == true) {
148*103e46e4SHarish Mahendrakar EXPECT_TRUE(VerifyPacketStartCode(header));
149*103e46e4SHarish Mahendrakar }
150*103e46e4SHarish Mahendrakar EXPECT_EQ(0, parser()->BytesAvailable());
151*103e46e4SHarish Mahendrakar }
152*103e46e4SHarish Mahendrakar
153*103e46e4SHarish Mahendrakar } // namespace
154*103e46e4SHarish Mahendrakar
main(int argc,char * argv[])155*103e46e4SHarish Mahendrakar int main(int argc, char* argv[]) {
156*103e46e4SHarish Mahendrakar ::testing::InitGoogleTest(&argc, argv);
157*103e46e4SHarish Mahendrakar return RUN_ALL_TESTS();
158*103e46e4SHarish Mahendrakar }
159