TestWebMBuffered.cpp (7593B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <stdio.h> 8 9 #include "WebMBufferedParser.h" 10 #include "gtest/gtest.h" 11 #include "nsTArray.h" 12 13 using namespace mozilla; 14 15 std::ostream& operator<<(std::ostream& aStream, nsresult aResult) { 16 return aStream << GetStaticErrorName(aResult); 17 } 18 19 namespace mozilla { 20 std::ostream& operator<<(std::ostream& aStream, const MediaResult& aResult) { 21 aStream << aResult.Code(); 22 if (!aResult.Message().IsEmpty()) { 23 aStream << " (" << aResult.Message() << ")"; 24 } 25 return aStream; 26 } 27 } // namespace mozilla 28 29 // "test.webm" contains 8 SimpleBlocks in a single Cluster. The blocks with 30 // timecodes 100000000 and are 133000000 skipped by WebMBufferedParser 31 // because they occur after a block with timecode 160000000 and the parser 32 // expects in-order timecodes per the WebM spec. The remaining 6 33 // SimpleBlocks have the following attributes: 34 static const uint64_t gTimecodes[] = {66000000, 160000000, 166000000, 35 200000000, 233000000, 320000000}; 36 static const int64_t gEndOffsets[] = {466, 737, 1209, 1345, 1508, 1980}; 37 38 TEST(WebMBuffered, BasicTests) 39 { 40 WebMBufferedParser parser(0); 41 42 nsTArray<WebMTimeDataOffset> mapping; 43 EXPECT_EQ(parser.Append(nullptr, 0, mapping), NS_OK); 44 EXPECT_TRUE(mapping.IsEmpty()); 45 EXPECT_EQ(parser.mStartOffset, 0); 46 EXPECT_EQ(parser.mCurrentOffset, 0); 47 48 unsigned char buf[] = {0x1a, 0x45, 0xdf, 0xa3}; 49 EXPECT_EQ(parser.Append(buf, std::size(buf), mapping), NS_OK); 50 EXPECT_TRUE(mapping.IsEmpty()); 51 EXPECT_EQ(parser.mStartOffset, 0); 52 EXPECT_EQ(parser.mCurrentOffset, 4); 53 } 54 55 static void ReadFile(const char* aPath, nsTArray<uint8_t>& aBuffer) { 56 FILE* f = fopen(aPath, "rb"); 57 ASSERT_NE(f, (FILE*)nullptr); 58 59 int r = fseek(f, 0, SEEK_END); 60 ASSERT_EQ(r, 0); 61 62 long size = ftell(f); 63 ASSERT_NE(size, -1); 64 aBuffer.SetLength(size); 65 66 r = fseek(f, 0, SEEK_SET); 67 ASSERT_EQ(r, 0); 68 69 size_t got = fread(aBuffer.Elements(), 1, size, f); 70 ASSERT_EQ(got, size_t(size)); 71 72 r = fclose(f); 73 ASSERT_EQ(r, 0); 74 } 75 76 TEST(WebMBuffered, RealData) 77 { 78 WebMBufferedParser parser(0); 79 80 nsTArray<uint8_t> webmData; 81 ReadFile("test.webm", webmData); 82 83 nsTArray<WebMTimeDataOffset> mapping; 84 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 85 NS_OK); 86 EXPECT_EQ(mapping.Length(), 6u); 87 EXPECT_EQ(parser.mStartOffset, 0); 88 EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length())); 89 EXPECT_EQ(parser.GetTimecodeScale(), 500000u); 90 91 for (uint32_t i = 0; i < mapping.Length(); ++i) { 92 EXPECT_EQ(mapping[i].mEndOffset, gEndOffsets[i]); 93 EXPECT_EQ(mapping[i].mSyncOffset, 326); 94 EXPECT_EQ(mapping[i].mTimecode, gTimecodes[i]); 95 } 96 } 97 98 TEST(WebMBuffered, RealDataAppend) 99 { 100 WebMBufferedParser parser(0); 101 nsTArray<WebMTimeDataOffset> mapping; 102 103 nsTArray<uint8_t> webmData; 104 ReadFile("test.webm", webmData); 105 106 uint32_t arrayEntries = mapping.Length(); 107 size_t offset = 0; 108 while (offset < webmData.Length()) { 109 EXPECT_EQ(parser.Append(webmData.Elements() + offset, 1, mapping), NS_OK); 110 offset += 1; 111 EXPECT_EQ(parser.mCurrentOffset, int64_t(offset)); 112 if (mapping.Length() != arrayEntries) { 113 arrayEntries = mapping.Length(); 114 ASSERT_LE(arrayEntries, 6u); 115 uint32_t i = arrayEntries - 1; 116 EXPECT_EQ(mapping[i].mEndOffset, gEndOffsets[i]); 117 EXPECT_EQ(mapping[i].mSyncOffset, 326); 118 EXPECT_EQ(mapping[i].mTimecode, gTimecodes[i]); 119 EXPECT_EQ(parser.GetTimecodeScale(), 500000u); 120 } 121 } 122 EXPECT_EQ(mapping.Length(), 6u); 123 EXPECT_EQ(parser.mStartOffset, 0); 124 EXPECT_EQ(parser.mCurrentOffset, int64_t(webmData.Length())); 125 EXPECT_EQ(parser.GetTimecodeScale(), 500000u); 126 127 for (uint32_t i = 0; i < mapping.Length(); ++i) { 128 EXPECT_EQ(mapping[i].mEndOffset, gEndOffsets[i]); 129 EXPECT_EQ(mapping[i].mSyncOffset, 326); 130 EXPECT_EQ(mapping[i].mTimecode, gTimecodes[i]); 131 } 132 } 133 134 TEST(WebMBuffered, InvalidEBMLMaxIdLength) 135 { 136 WebMBufferedParser parser(0); 137 138 nsTArray<uint8_t> webmData; 139 // This file contains EBMLMaxIdLength=3, but a Segment element (and maybe 140 // others) whose Id VInt has length 4. 141 ReadFile("test_InvalidElementId.webm", webmData); 142 143 nsTArray<WebMTimeDataOffset> mapping; 144 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 145 NS_ERROR_FAILURE); 146 } 147 148 TEST(WebMBuffered, InvalidLargeElementIdLength) 149 { 150 WebMBufferedParser parser(0); 151 152 nsTArray<uint8_t> webmData; 153 // This file contains EBMLMaxIdLength=4, but a dummy element whose Id VInt has 154 // length 5. 155 ReadFile("test_InvalidLargeElementId.webm", webmData); 156 157 nsTArray<WebMTimeDataOffset> mapping; 158 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 159 NS_ERROR_FAILURE); 160 } 161 162 TEST(WebMBuffered, InvalidSmallEBMLMaxIdLength) 163 { 164 WebMBufferedParser parser(0); 165 166 nsTArray<uint8_t> webmData; 167 // This file contains EBMLMaxIdLength=3. 168 // Per draft-ietf-cellar-matroska-13 EBMLMaxIdLength MUST be 4. But element 169 // ids can also be between 1 and 5 octets long. 5 only if EBMLMaxIdLength 170 // specifies it. At least 3 is too short. 171 ReadFile("test_InvalidSmallEBMLMaxIdLength.webm", webmData); 172 173 nsTArray<WebMTimeDataOffset> mapping; 174 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 175 NS_ERROR_FAILURE); 176 } 177 178 TEST(WebMBuffered, ValidLargeEBMLMaxIdLength) 179 { 180 WebMBufferedParser parser(0); 181 182 nsTArray<uint8_t> webmData; 183 // This file contains EBMLMaxIdLength=5 and a dummy element with a 5 octet 184 // long id. Per draft-ietf-cellar-matroska-13 EBMLMaxIdLength MUST be 4. But 185 // element ids can also be between 1 and 5 octets long. 5 only if 186 // EBMLMaxIdLength specifies it. We better tolerate this. 187 ReadFile("test_ValidLargeEBMLMaxIdLength.webm", webmData); 188 189 nsTArray<WebMTimeDataOffset> mapping; 190 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 191 NS_OK); 192 } 193 194 TEST(WebMBuffered, InvalidLargeEBMLMaxIdLength) 195 { 196 WebMBufferedParser parser(0); 197 198 nsTArray<uint8_t> webmData; 199 // This file contains EBMLMaxIdLength=6. 200 // Per draft-ietf-cellar-matroska-13 EBMLMaxIdLength MUST be 4. But 201 // element ids can also be between 1 and 5 octets long. 5 only if 202 // EBMLMaxIdLength specifies it. At least 6 is too long. 203 ReadFile("test_InvalidLargeEBMLMaxIdLength.webm", webmData); 204 205 nsTArray<WebMTimeDataOffset> mapping; 206 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 207 NS_ERROR_FAILURE); 208 } 209 210 TEST(WebMBuffered, ValidSmallEBMLMaxSizeLength) 211 { 212 WebMBufferedParser parser(0); 213 214 nsTArray<uint8_t> webmData; 215 // This file contains EBMLMaxSizeLength=7 and no element with an element size 216 // longer than 7 bytes. 217 ReadFile("test_ValidSmallEBMLMaxSizeLength.webm", webmData); 218 219 nsTArray<WebMTimeDataOffset> mapping; 220 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 221 NS_OK); 222 } 223 224 TEST(WebMBuffered, InvalidEBMLMaxSizeLength) 225 { 226 WebMBufferedParser parser(0); 227 228 nsTArray<uint8_t> webmData; 229 // This file contains EBMLMaxSizeLength=7, but the Segment element size VInt 230 // has length 8. 231 ReadFile("test_InvalidElementSize.webm", webmData); 232 233 nsTArray<WebMTimeDataOffset> mapping; 234 EXPECT_EQ(parser.Append(webmData.Elements(), webmData.Length(), mapping), 235 NS_ERROR_FAILURE); 236 }