TestContainerParser.cpp (5633B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include <gtest/gtest.h> 7 #include <stdint.h> 8 9 #include "ContainerParser.h" 10 #include "mozilla/gtest/MozAssertions.h" 11 12 using namespace mozilla; 13 using TimeUnit = mozilla::media::TimeUnit; 14 15 TEST(ContainerParser, MIMETypes) 16 { 17 const char* containerTypes[] = {"video/webm", "audio/webm", "video/mp4", 18 "audio/mp4", "audio/aac"}; 19 UniquePtr<ContainerParser> parser; 20 for (size_t i = 0; i < std::size(containerTypes); ++i) { 21 Maybe<MediaContainerType> containerType = 22 MakeMediaContainerType(containerTypes[i]); 23 ASSERT_TRUE(containerType.isSome()); 24 parser = ContainerParser::CreateForMIMEType(*containerType); 25 ASSERT_NE(parser, nullptr); 26 } 27 } 28 29 already_AddRefed<MediaByteBuffer> make_adts_header() { 30 const uint8_t test[] = {0xff, 0xf1, 0x50, 0x80, 0x03, 0x1f, 0xfc}; 31 RefPtr<MediaByteBuffer> buffer(new MediaByteBuffer); 32 buffer->AppendElements(test, std::size(test)); 33 return buffer.forget(); 34 } 35 36 TEST(ContainerParser, ADTSHeader) 37 { 38 UniquePtr<ContainerParser> parser; 39 parser = ContainerParser::CreateForMIMEType( 40 MediaContainerType(MEDIAMIMETYPE("audio/aac"))); 41 ASSERT_NE(parser, nullptr); 42 43 // Audio data should have no gaps. 44 EXPECT_EQ(parser->GetRoundingError(), 0); 45 46 // Test a valid header. 47 RefPtr<MediaByteBuffer> header = make_adts_header(); 48 EXPECT_NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header))); 49 50 // Test variations. 51 uint8_t save = header->ElementAt(1); 52 for (uint8_t i = 1; i < 3; ++i) { 53 // Set non-zero layer. 54 header->ReplaceElementAt(1, (header->ElementAt(1) & 0xf9) | (i << 1)); 55 EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header)))) 56 << "Accepted non-zero layer in header."; 57 } 58 header->ReplaceElementAt(1, save); 59 save = header->ElementAt(2); 60 header->ReplaceElementAt(2, (header->ElementAt(2) & 0x3b) | (15 << 2)); 61 EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header)))) 62 << "Accepted explicit frequency in header."; 63 header->ReplaceElementAt(2, save); 64 65 // Test a short header. 66 header->SetLength(6); 67 EXPECT_FALSE(NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header)))) 68 << "Accepted too-short header."; 69 EXPECT_FALSE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(MediaSpan(header)))) 70 << "Found media segment when there was just a partial header."; 71 72 // Test a header with short data. 73 header = make_adts_header(); 74 header->AppendElements(1); 75 EXPECT_TRUE(NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header)))) 76 << "Rejected a valid header."; 77 EXPECT_TRUE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(MediaSpan(header)))) 78 << "Rejected a one-byte media segment."; 79 80 // Test parse results. 81 header = make_adts_header(); 82 EXPECT_FALSE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(MediaSpan(header)))) 83 << "Found media segment when there was just a header."; 84 TimeUnit start; 85 TimeUnit end; 86 EXPECT_TRUE(NS_FAILED( 87 parser->ParseStartAndEndTimestamps(MediaSpan(header), start, end))); 88 89 EXPECT_TRUE(parser->HasInitData()); 90 EXPECT_TRUE(parser->HasCompleteInitData()); 91 MediaByteBuffer* init = parser->InitData(); 92 ASSERT_NE(init, nullptr); 93 EXPECT_EQ(init->Length(), header->Length()); 94 95 EXPECT_EQ(parser->InitSegmentRange(), 96 MediaByteRange(0, int64_t(header->Length()))); 97 // Media segment range should be empty here. 98 EXPECT_EQ(parser->MediaHeaderRange(), MediaByteRange()); 99 EXPECT_EQ(parser->MediaSegmentRange(), MediaByteRange()); 100 } 101 102 TEST(ContainerParser, ADTSBlankMedia) 103 { 104 UniquePtr<ContainerParser> parser; 105 parser = ContainerParser::CreateForMIMEType( 106 MediaContainerType(MEDIAMIMETYPE("audio/aac"))); 107 ASSERT_NE(parser, nullptr); 108 109 // Audio data should have no gaps. 110 EXPECT_EQ(parser->GetRoundingError(), 0); 111 112 // Test the header only. 113 RefPtr<MediaByteBuffer> header = make_adts_header(); 114 EXPECT_NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header))); 115 116 // Test with the correct length of (invalid) frame data. 117 size_t header_length = header->Length(); 118 size_t data_length = 24; 119 size_t frame_length = header_length + data_length; 120 header->AppendElements(data_length); 121 EXPECT_TRUE(NS_SUCCEEDED(parser->IsInitSegmentPresent(MediaSpan(header)))) 122 << "Rejected a valid header."; 123 EXPECT_TRUE(NS_SUCCEEDED(parser->IsMediaSegmentPresent(MediaSpan(header)))) 124 << "Rejected a full (but zeroed) media segment."; 125 TimeUnit start; 126 TimeUnit end; 127 // We don't report timestamps from ADTS. 128 EXPECT_TRUE(NS_FAILED( 129 parser->ParseStartAndEndTimestamps(MediaSpan(header), start, end))); 130 EXPECT_TRUE(start.IsZero()); 131 EXPECT_TRUE(end.IsZero()); 132 133 // Verify the parser calculated header and packet data boundaries. 134 EXPECT_TRUE(parser->HasInitData()); 135 EXPECT_TRUE(parser->HasCompleteInitData()); 136 MediaByteBuffer* init = parser->InitData(); 137 ASSERT_NE(init, nullptr); 138 EXPECT_EQ(init->Length(), header_length) 139 << "Found incorrect init segment length."; 140 EXPECT_EQ(parser->InitSegmentRange(), 141 MediaByteRange(0, int64_t(header_length))); 142 // In ADTS the Media Header is the same as the Media Segment. 143 MediaByteRange expected_media = 144 MediaByteRange(int64_t(header_length), int64_t(frame_length)); 145 EXPECT_EQ(parser->MediaHeaderRange(), expected_media); 146 EXPECT_EQ(parser->MediaSegmentRange(), expected_media); 147 }