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 "MediaData.h"
8 #include "mozilla/ArrayUtils.h"
9 #include "mp4_demuxer/BufferStream.h"
10 #include "mp4_demuxer/MP4Metadata.h"
11 #include "mp4_demuxer/MoofParser.h"
12
13 using namespace mozilla;
14 using namespace mp4_demuxer;
15
16 class TestStream : public Stream
17 {
18 public:
TestStream(const uint8_t * aBuffer,size_t aSize)19 TestStream(const uint8_t* aBuffer, size_t aSize)
20 : mHighestSuccessfulEndOffset(0)
21 , mBuffer(aBuffer)
22 , mSize(aSize)
23 {
24 }
ReadAt(int64_t aOffset,void * aData,size_t aLength,size_t * aBytesRead)25 bool ReadAt(int64_t aOffset, void* aData, size_t aLength,
26 size_t* aBytesRead) override
27 {
28 if (aOffset < 0 || aOffset > static_cast<int64_t>(mSize)) {
29 return false;
30 }
31 // After the test, 0 <= aOffset <= mSize <= SIZE_MAX, so it's safe to cast to size_t.
32 size_t offset = static_cast<size_t>(aOffset);
33 // Don't read past the end (but it's not an error to try).
34 if (aLength > mSize - offset) {
35 aLength = mSize - offset;
36 }
37 // Now, 0 <= offset <= offset + aLength <= mSize <= SIZE_MAX.
38 *aBytesRead = aLength;
39 memcpy(aData, mBuffer + offset, aLength);
40 if (mHighestSuccessfulEndOffset < offset + aLength)
41 {
42 mHighestSuccessfulEndOffset = offset + aLength;
43 }
44 return true;
45 }
CachedReadAt(int64_t aOffset,void * aData,size_t aLength,size_t * aBytesRead)46 bool CachedReadAt(int64_t aOffset, void* aData, size_t aLength,
47 size_t* aBytesRead) override
48 {
49 return ReadAt(aOffset, aData, aLength, aBytesRead);
50 }
Length(int64_t * aLength)51 bool Length(int64_t* aLength) override
52 {
53 *aLength = mSize;
54 return true;
55 }
DiscardBefore(int64_t aOffset)56 void DiscardBefore(int64_t aOffset) override
57 {
58 }
59
60 // Offset past the last character ever read. 0 when nothing read yet.
61 size_t mHighestSuccessfulEndOffset;
62 protected:
~TestStream()63 virtual ~TestStream()
64 {
65 }
66
67 const uint8_t* mBuffer;
68 size_t mSize;
69 };
70
TEST(stagefright_MP4Metadata,EmptyStream)71 TEST(stagefright_MP4Metadata, EmptyStream)
72 {
73 RefPtr<Stream> stream = new TestStream(nullptr, 0);
74
75 EXPECT_FALSE(MP4Metadata::HasCompleteMetadata(stream));
76 RefPtr<MediaByteBuffer> metadataBuffer = MP4Metadata::Metadata(stream);
77 EXPECT_FALSE(metadataBuffer);
78
79 MP4Metadata metadata(stream);
80 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack));
81 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kAudioTrack));
82 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kVideoTrack));
83 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kTextTrack));
84 EXPECT_EQ(0u, metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)));
85 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0));
86 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0));
87 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0));
88 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0));
89 EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0));
90 // We can seek anywhere in any MPEG4.
91 EXPECT_TRUE(metadata.CanSeek());
92 EXPECT_FALSE(metadata.Crypto().valid);
93 }
94
TEST(stagefright_MoofParser,EmptyStream)95 TEST(stagefright_MoofParser, EmptyStream)
96 {
97 RefPtr<Stream> stream = new TestStream(nullptr, 0);
98
99 MoofParser parser(stream, 0, false);
100 EXPECT_EQ(0u, parser.mOffset);
101 EXPECT_TRUE(parser.ReachedEnd());
102
103 MediaByteRangeSet byteRanges;
104 EXPECT_FALSE(parser.RebuildFragmentedIndex(byteRanges));
105
106 EXPECT_TRUE(parser.GetCompositionRange(byteRanges).IsNull());
107 EXPECT_TRUE(parser.mInitRange.IsEmpty());
108 EXPECT_EQ(0u, parser.mOffset);
109 EXPECT_TRUE(parser.ReachedEnd());
110 EXPECT_FALSE(parser.HasMetadata());
111 RefPtr<MediaByteBuffer> metadataBuffer = parser.Metadata();
112 EXPECT_FALSE(metadataBuffer);
113 EXPECT_TRUE(parser.FirstCompleteMediaSegment().IsEmpty());
114 EXPECT_TRUE(parser.FirstCompleteMediaHeader().IsEmpty());
115 }
116
117 nsTArray<uint8_t>
ReadTestFile(const char * aFilename)118 ReadTestFile(const char* aFilename)
119 {
120 if (!aFilename) {
121 return {};
122 }
123 FILE* f = fopen(aFilename, "rb");
124 if (!f) {
125 return {};
126 }
127
128 if (fseek(f, 0, SEEK_END) != 0) {
129 fclose(f);
130 return {};
131 }
132 long position = ftell(f);
133 // I know EOF==-1, so this test is made obsolete by '<0', but I don't want
134 // the code to rely on that.
135 if (position == 0 || position == EOF || position < 0) {
136 fclose(f);
137 return {};
138 }
139 if (fseek(f, 0, SEEK_SET) != 0) {
140 fclose(f);
141 return {};
142 }
143
144 size_t len = static_cast<size_t>(position);
145 nsTArray<uint8_t> buffer(len);
146 buffer.SetLength(len);
147 size_t read = fread(buffer.Elements(), 1, len, f);
148 fclose(f);
149 if (read != len) {
150 return {};
151 }
152
153 return buffer;
154 }
155
156 struct TestFileData
157 {
158 const char* mFilename;
159 uint32_t mNumberVideoTracks;
160 int64_t mVideoDuration; // For first video track, -1 if N/A.
161 int32_t mWidth;
162 int32_t mHeight;
163 uint32_t mNumberAudioTracks;
164 int64_t mAudioDuration; // For first audio track, -1 if N/A.
165 bool mHasCrypto;
166 uint64_t mMoofReachedOffset; // or 0 for the end.
167 bool mValidMoof;
168 bool mHeader;
169 };
170 static const TestFileData testFiles[] = {
171 // filename #V dur w h #A dur crypt off moof headr
172 { "test_case_1156505.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false },
173 { "test_case_1181213.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
174 { "test_case_1181215.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
175 { "test_case_1181220.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
176 { "test_case_1181223.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
177 { "test_case_1181719.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
178 { "test_case_1185230.mp4", 1, 416666,
179 320, 240, 1, 5, false, 0, false, false },
180 { "test_case_1187067.mp4", 1, 80000,
181 160, 90, 0, -1, false, 0, false, false },
182 { "test_case_1200326.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
183 { "test_case_1204580.mp4", 1, 502500,
184 320, 180, 0, -1, false, 0, false, false },
185 { "test_case_1216748.mp4", 0, -1, 0, 0, 0, -1, false, 152, false, false },
186 { "test_case_1296473.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
187 { "test_case_1296532.mp4", 1, 5589333,
188 560, 320, 1, 5589333,
189 true, 0, true, true },
190 { "test_case_1301065.mp4", 0, -1, 0, 0, 1, 100079991719000000,
191 false, 0, false, false },
192 { "test_case_1301065-u32max.mp4", 0, -1, 0, 0, 1, 97391548639,
193 false, 0, false, false },
194 { "test_case_1301065-max-ez.mp4", 0, -1, 0, 0, 1, 209146758205306,
195 false, 0, false, false },
196 { "test_case_1301065-harder.mp4", 0, -1, 0, 0, 1, 209146758205328,
197 false, 0, false, false },
198 { "test_case_1301065-max-ok.mp4", 0, -1, 0, 0, 1, 9223372036854775804,
199 false, 0, false, false },
200 { "test_case_1301065-overfl.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
201 { "test_case_1301065-i64max.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
202 { "test_case_1301065-i64min.mp4", 0, -1, 0, 0, 0, -1, false, 0, false, false },
203 { "test_case_1301065-u64max.mp4", 0, -1, 0, 0, 1, 0, false, 0, false, false },
204 { "test_case_1351094.mp4", 0, -1, 0, 0, 0, -1, false, 0, true, true },
205 };
206
TEST(stagefright_MPEG4Metadata,test_case_mp4)207 TEST(stagefright_MPEG4Metadata, test_case_mp4)
208 {
209 for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
210 nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
211 ASSERT_FALSE(buffer.IsEmpty());
212 RefPtr<Stream> stream = new TestStream(buffer.Elements(), buffer.Length());
213
214 EXPECT_TRUE(MP4Metadata::HasCompleteMetadata(stream));
215 RefPtr<MediaByteBuffer> metadataBuffer = MP4Metadata::Metadata(stream);
216 EXPECT_TRUE(metadataBuffer);
217
218 MP4Metadata metadata(stream);
219 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kUndefinedTrack));
220 EXPECT_EQ(testFiles[test].mNumberAudioTracks,
221 metadata.GetNumberTracks(TrackInfo::kAudioTrack));
222 EXPECT_EQ(testFiles[test].mNumberVideoTracks,
223 metadata.GetNumberTracks(TrackInfo::kVideoTrack));
224 EXPECT_EQ(0u, metadata.GetNumberTracks(TrackInfo::kTextTrack));
225 EXPECT_EQ(0u, metadata.GetNumberTracks(static_cast<TrackInfo::TrackType>(-1)));
226 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kUndefinedTrack, 0));
227 UniquePtr<TrackInfo> trackInfo = metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
228 if (testFiles[test].mNumberVideoTracks == 0) {
229 EXPECT_TRUE(!trackInfo);
230 } else {
231 ASSERT_TRUE(!!trackInfo);
232 const VideoInfo* videoInfo = trackInfo->GetAsVideoInfo();
233 ASSERT_TRUE(!!videoInfo);
234 EXPECT_TRUE(videoInfo->IsValid());
235 EXPECT_TRUE(videoInfo->IsVideo());
236 EXPECT_EQ(testFiles[test].mVideoDuration, videoInfo->mDuration);
237 EXPECT_EQ(testFiles[test].mWidth, videoInfo->mDisplay.width);
238 EXPECT_EQ(testFiles[test].mHeight, videoInfo->mDisplay.height);
239 FallibleTArray<mp4_demuxer::Index::Indice> indices;
240 EXPECT_TRUE(metadata.ReadTrackIndex(indices, videoInfo->mTrackId));
241 for (const mp4_demuxer::Index::Indice& indice : indices) {
242 EXPECT_TRUE(indice.start_offset <= indice.end_offset);
243 EXPECT_TRUE(indice.start_composition <= indice.end_composition);
244 }
245 }
246 trackInfo = metadata.GetTrackInfo(TrackInfo::kAudioTrack, 0);
247 if (testFiles[test].mNumberAudioTracks == 0) {
248 EXPECT_TRUE(!trackInfo);
249 } else {
250 ASSERT_TRUE(!!trackInfo);
251 const AudioInfo* audioInfo = trackInfo->GetAsAudioInfo();
252 ASSERT_TRUE(!!audioInfo);
253 EXPECT_TRUE(audioInfo->IsValid());
254 EXPECT_TRUE(audioInfo->IsAudio());
255 EXPECT_EQ(testFiles[test].mAudioDuration, audioInfo->mDuration);
256 FallibleTArray<mp4_demuxer::Index::Indice> indices;
257 EXPECT_TRUE(metadata.ReadTrackIndex(indices, audioInfo->mTrackId));
258 for (const mp4_demuxer::Index::Indice& indice : indices) {
259 EXPECT_TRUE(indice.start_offset <= indice.end_offset);
260 EXPECT_TRUE(indice.start_composition <= indice.end_composition);
261 }
262 }
263 EXPECT_FALSE(metadata.GetTrackInfo(TrackInfo::kTextTrack, 0));
264 EXPECT_FALSE(metadata.GetTrackInfo(static_cast<TrackInfo::TrackType>(-1), 0));
265 // We can see anywhere in any MPEG4.
266 EXPECT_TRUE(metadata.CanSeek());
267 EXPECT_EQ(testFiles[test].mHasCrypto, metadata.Crypto().valid);
268 }
269 }
270
271 // Bug 1224019: This test produces way to much output, disabling for now.
272 #if 0
273 TEST(stagefright_MPEG4Metadata, test_case_mp4_subsets)
274 {
275 static const size_t step = 1u;
276 for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
277 nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
278 ASSERT_FALSE(buffer.IsEmpty());
279 ASSERT_LE(step, buffer.Length());
280 // Just exercizing the parser starting at different points through the file,
281 // making sure it doesn't crash.
282 // No checks because results would differ for each position.
283 for (size_t offset = 0; offset < buffer.Length() - step; offset += step) {
284 size_t size = buffer.Length() - offset;
285 while (size > 0) {
286 RefPtr<TestStream> stream =
287 new TestStream(buffer.Elements() + offset, size);
288
289 MP4Metadata::HasCompleteMetadata(stream);
290 RefPtr<MediaByteBuffer> metadataBuffer = MP4Metadata::Metadata(stream);
291 MP4Metadata metadata(stream);
292
293 if (stream->mHighestSuccessfulEndOffset <= 0) {
294 // No successful reads -> Cutting down the size won't change anything.
295 break;
296 }
297 if (stream->mHighestSuccessfulEndOffset < size) {
298 // Read up to a point before the end -> Resize down to that point.
299 size = stream->mHighestSuccessfulEndOffset;
300 } else {
301 // Read up to the end (or after?!) -> Just cut 1 byte.
302 size -= 1;
303 }
304 }
305 }
306 }
307 }
308 #endif
309
TEST(stagefright_MoofParser,test_case_mp4)310 TEST(stagefright_MoofParser, test_case_mp4)
311 {
312 for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
313 nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
314 ASSERT_FALSE(buffer.IsEmpty());
315 RefPtr<Stream> stream = new TestStream(buffer.Elements(), buffer.Length());
316
317 MoofParser parser(stream, 0, false);
318 EXPECT_EQ(0u, parser.mOffset);
319 EXPECT_FALSE(parser.ReachedEnd());
320 EXPECT_TRUE(parser.mInitRange.IsEmpty());
321
322 EXPECT_TRUE(parser.HasMetadata());
323 RefPtr<MediaByteBuffer> metadataBuffer = parser.Metadata();
324 EXPECT_TRUE(metadataBuffer);
325
326 EXPECT_FALSE(parser.mInitRange.IsEmpty());
327 const MediaByteRangeSet byteRanges(
328 MediaByteRange(0, int64_t(buffer.Length())));
329 EXPECT_EQ(testFiles[test].mValidMoof,
330 parser.RebuildFragmentedIndex(byteRanges));
331 if (testFiles[test].mMoofReachedOffset == 0) {
332 EXPECT_EQ(buffer.Length(), parser.mOffset);
333 EXPECT_TRUE(parser.ReachedEnd());
334 } else {
335 EXPECT_EQ(testFiles[test].mMoofReachedOffset, parser.mOffset);
336 EXPECT_FALSE(parser.ReachedEnd());
337 }
338
339 EXPECT_FALSE(parser.mInitRange.IsEmpty());
340 EXPECT_TRUE(parser.GetCompositionRange(byteRanges).IsNull());
341 EXPECT_TRUE(parser.FirstCompleteMediaSegment().IsEmpty());
342 EXPECT_EQ(testFiles[test].mHeader,
343 !parser.FirstCompleteMediaHeader().IsEmpty());
344 }
345 }
346
347 // Bug 1224019: This test produces way to much output, disabling for now.
348 #if 0
349 TEST(stagefright_MoofParser, test_case_mp4_subsets)
350 {
351 const size_t step = 1u;
352 for (size_t test = 0; test < ArrayLength(testFiles); ++test) {
353 nsTArray<uint8_t> buffer = ReadTestFile(testFiles[test].mFilename);
354 ASSERT_FALSE(buffer.IsEmpty());
355 ASSERT_LE(step, buffer.Length());
356 // Just exercizing the parser starting at different points through the file,
357 // making sure it doesn't crash.
358 // No checks because results would differ for each position.
359 for (size_t offset = 0; offset < buffer.Length() - step; offset += step) {
360 size_t size = buffer.Length() - offset;
361 while (size > 0) {
362 RefPtr<TestStream> stream =
363 new TestStream(buffer.Elements() + offset, size);
364
365 MoofParser parser(stream, 0, false);
366 MediaByteRangeSet byteRanges;
367 EXPECT_FALSE(parser.RebuildFragmentedIndex(byteRanges));
368 parser.GetCompositionRange(byteRanges);
369 parser.HasMetadata();
370 RefPtr<MediaByteBuffer> metadataBuffer = parser.Metadata();
371 parser.FirstCompleteMediaSegment();
372 parser.FirstCompleteMediaHeader();
373
374 if (stream->mHighestSuccessfulEndOffset <= 0) {
375 // No successful reads -> Cutting down the size won't change anything.
376 break;
377 }
378 if (stream->mHighestSuccessfulEndOffset < size) {
379 // Read up to a point before the end -> Resize down to that point.
380 size = stream->mHighestSuccessfulEndOffset;
381 } else {
382 // Read up to the end (or after?!) -> Just cut 1 byte.
383 size -= 1;
384 }
385 }
386 }
387 }
388 }
389 #endif
390
391 uint8_t media_libstagefright_gtest_video_init_mp4[] = {
392 0x00, 0x00, 0x00, 0x18, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6f, 0x6d,
393 0x00, 0x00, 0x00, 0x01, 0x69, 0x73, 0x6f, 0x6d, 0x61, 0x76, 0x63, 0x31,
394 0x00, 0x00, 0x02, 0xd1, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x6c,
395 0x6d, 0x76, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x49, 0x73, 0xf8,
396 0xc8, 0x4a, 0xc5, 0x7a, 0x00, 0x00, 0x02, 0x58, 0x00, 0x00, 0x00, 0x00,
397 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
398 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
400 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
401 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
402 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
403 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x18,
404 0x69, 0x6f, 0x64, 0x73, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x80, 0x80,
405 0x07, 0x00, 0x4f, 0xff, 0xff, 0x29, 0x15, 0xff, 0x00, 0x00, 0x02, 0x0d,
406 0x74, 0x72, 0x61, 0x6b, 0x00, 0x00, 0x00, 0x5c, 0x74, 0x6b, 0x68, 0x64,
407 0x00, 0x00, 0x00, 0x01, 0xc8, 0x49, 0x73, 0xf8, 0xc8, 0x49, 0x73, 0xf9,
408 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
409 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
410 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
411 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
412 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
413 0x40, 0x00, 0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x01, 0x68, 0x00, 0x00,
414 0x00, 0x00, 0x01, 0xa9, 0x6d, 0x64, 0x69, 0x61, 0x00, 0x00, 0x00, 0x20,
415 0x6d, 0x64, 0x68, 0x64, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x49, 0x73, 0xf8,
416 0xc8, 0x49, 0x73, 0xf9, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0x00, 0x00,
417 0x55, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x68, 0x64, 0x6c, 0x72,
418 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0x69, 0x64, 0x65,
419 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420 0x47, 0x50, 0x41, 0x43, 0x20, 0x49, 0x53, 0x4f, 0x20, 0x56, 0x69, 0x64,
421 0x65, 0x6f, 0x20, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x00, 0x00,
422 0x00, 0x00, 0x01, 0x49, 0x6d, 0x69, 0x6e, 0x66, 0x00, 0x00, 0x00, 0x14,
423 0x76, 0x6d, 0x68, 0x64, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
424 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x64, 0x69, 0x6e, 0x66,
425 0x00, 0x00, 0x00, 0x1c, 0x64, 0x72, 0x65, 0x66, 0x00, 0x00, 0x00, 0x00,
426 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x0c, 0x75, 0x72, 0x6c, 0x20,
427 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x09, 0x73, 0x74, 0x62, 0x6c,
428 0x00, 0x00, 0x00, 0xad, 0x73, 0x74, 0x73, 0x64, 0x00, 0x00, 0x00, 0x00,
429 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x9d, 0x61, 0x76, 0x63, 0x31,
430 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
431 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432 0x02, 0x80, 0x01, 0x68, 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00,
433 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
434 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
435 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
436 0x00, 0x00, 0x00, 0x18, 0xff, 0xff, 0x00, 0x00, 0x00, 0x33, 0x61, 0x76,
437 0x63, 0x43, 0x01, 0x64, 0x00, 0x1f, 0xff, 0xe1, 0x00, 0x1b, 0x67, 0x64,
438 0x00, 0x1f, 0xac, 0x2c, 0xc5, 0x02, 0x80, 0xbf, 0xe5, 0xc0, 0x44, 0x00,
439 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0xf2, 0x3c, 0x60, 0xc6,
440 0x58, 0x01, 0x00, 0x05, 0x68, 0xe9, 0x2b, 0x2c, 0x8b, 0x00, 0x00, 0x00,
441 0x14, 0x62, 0x74, 0x72, 0x74, 0x00, 0x01, 0x5a, 0xc2, 0x00, 0x24, 0x74,
442 0x38, 0x00, 0x09, 0x22, 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x74,
443 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444 0x10, 0x63, 0x74, 0x74, 0x73, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x73, 0x63, 0x00, 0x00, 0x00,
446 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x73, 0x74, 0x73,
447 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
448 0x00, 0x00, 0x00, 0x00, 0x10, 0x73, 0x74, 0x63, 0x6f, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6d, 0x76, 0x65,
450 0x78, 0x00, 0x00, 0x00, 0x10, 0x6d, 0x65, 0x68, 0x64, 0x00, 0x00, 0x00,
451 0x00, 0x00, 0x05, 0x76, 0x18, 0x00, 0x00, 0x00, 0x20, 0x74, 0x72, 0x65,
452 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
453 0x01, 0x00, 0x00, 0x03, 0xe8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
454 0x00
455 };
456
457 const uint32_t media_libstagefright_gtest_video_init_mp4_len = 745;
458
TEST(stagefright_MP4Metadata,EmptyCTTS)459 TEST(stagefright_MP4Metadata, EmptyCTTS)
460 {
461 RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer(media_libstagefright_gtest_video_init_mp4_len);
462 buffer->AppendElements(media_libstagefright_gtest_video_init_mp4, media_libstagefright_gtest_video_init_mp4_len);
463 RefPtr<BufferStream> stream = new BufferStream(buffer);
464
465 EXPECT_TRUE(MP4Metadata::HasCompleteMetadata(stream));
466 RefPtr<MediaByteBuffer> metadataBuffer = MP4Metadata::Metadata(stream);
467 EXPECT_TRUE(metadataBuffer);
468
469 MP4Metadata metadata(stream);
470
471 EXPECT_EQ(1u, metadata.GetNumberTracks(TrackInfo::kVideoTrack));
472 mozilla::UniquePtr<mozilla::TrackInfo> track =
473 metadata.GetTrackInfo(TrackInfo::kVideoTrack, 0);
474 EXPECT_TRUE(track != nullptr);
475 // We can seek anywhere in any MPEG4.
476 EXPECT_TRUE(metadata.CanSeek());
477 EXPECT_FALSE(metadata.Crypto().valid);
478 }
479
480