OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
| 6 #include <cstdlib> |
6 | 7 |
7 #include "base/bind.h" | 8 #include "base/bind.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "media/base/decrypt_config.h" | 10 #include "media/base/decrypt_config.h" |
10 #include "media/formats/webm/cluster_builder.h" | 11 #include "media/formats/webm/cluster_builder.h" |
11 #include "media/formats/webm/webm_cluster_parser.h" | 12 #include "media/formats/webm/webm_cluster_parser.h" |
12 #include "media/formats/webm/webm_constants.h" | 13 #include "media/formats/webm/webm_constants.h" |
13 #include "testing/gmock/include/gmock/gmock.h" | 14 #include "testing/gmock/include/gmock/gmock.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 | 16 |
16 using ::testing::InSequence; | 17 using ::testing::InSequence; |
17 using ::testing::Return; | 18 using ::testing::Return; |
18 using ::testing::_; | 19 using ::testing::_; |
19 | 20 |
20 namespace media { | 21 namespace media { |
21 | 22 |
| 23 typedef WebMTracksParser::TextTracks TextTracks; |
| 24 |
22 enum { | 25 enum { |
23 kTimecodeScale = 1000000, // Timecode scale for millisecond timestamps. | 26 kTimecodeScale = 1000000, // Timecode scale for millisecond timestamps. |
24 kAudioTrackNum = 1, | 27 kAudioTrackNum = 1, |
25 kVideoTrackNum = 2, | 28 kVideoTrackNum = 2, |
26 kTextTrackNum = 3, | 29 kTextTrackNum = 3, |
| 30 kTestAudioFrameDefaultDurationInMs = 13, |
| 31 kTestVideoFrameDefaultDurationInMs = 17 |
27 }; | 32 }; |
28 | 33 |
| 34 COMPILE_ASSERT( |
| 35 static_cast<int>(kTestAudioFrameDefaultDurationInMs) != |
| 36 static_cast<int>(WebMClusterParser::kDefaultAudioBufferDurationInMs), |
| 37 test_default_is_same_as_estimation_fallback_audio_duration); |
| 38 COMPILE_ASSERT( |
| 39 static_cast<int>(kTestVideoFrameDefaultDurationInMs) != |
| 40 static_cast<int>(WebMClusterParser::kDefaultVideoBufferDurationInMs), |
| 41 test_default_is_same_as_estimation_fallback_video_duration); |
| 42 |
29 struct BlockInfo { | 43 struct BlockInfo { |
30 int track_num; | 44 int track_num; |
31 int timestamp; | 45 int timestamp; |
| 46 |
| 47 // Negative value is allowed only for block groups (not simple blocks) and |
| 48 // directs CreateCluster() to exclude BlockDuration entry from the cluster for |
| 49 // this BlockGroup. The absolute value is used for parser verification. |
| 50 // For simple blocks, this value must be non-negative, and is used only for |
| 51 // parser verification. |
32 int duration; | 52 int duration; |
33 bool use_simple_block; | 53 bool use_simple_block; |
34 }; | 54 }; |
35 | 55 |
36 static const BlockInfo kDefaultBlockInfo[] = { | 56 static const BlockInfo kDefaultBlockInfo[] = { |
37 { kAudioTrackNum, 0, 23, true }, | 57 { kAudioTrackNum, 0, 23, true }, |
38 { kAudioTrackNum, 23, 23, true }, | 58 { kAudioTrackNum, 23, 23, true }, |
39 { kVideoTrackNum, 33, 34, true }, // Assumes not using DefaultDuration | 59 { kVideoTrackNum, 33, 34, true }, // Assumes not using DefaultDuration |
40 { kAudioTrackNum, 46, 23, true }, | 60 { kAudioTrackNum, 46, 23, true }, |
41 { kVideoTrackNum, 67, 33, false }, | 61 { kVideoTrackNum, 67, 33, false }, |
42 { kAudioTrackNum, 69, 23, false }, | 62 { kAudioTrackNum, 69, 23, false }, |
43 { kVideoTrackNum, 100, 33, false }, | 63 { kVideoTrackNum, 100, 33, false }, |
44 }; | 64 }; |
45 | 65 |
46 static const uint8 kEncryptedFrame[] = { | 66 static const uint8 kEncryptedFrame[] = { |
47 0x01, // Block is encrypted | 67 0x01, // Block is encrypted |
48 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV | 68 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV |
49 }; | 69 }; |
50 | 70 |
51 static scoped_ptr<Cluster> CreateCluster(int timecode, | 71 static scoped_ptr<Cluster> CreateCluster(int timecode, |
52 const BlockInfo* block_info, | 72 const BlockInfo* block_info, |
53 int block_count) { | 73 int block_count) { |
54 ClusterBuilder cb; | 74 ClusterBuilder cb; |
55 cb.SetClusterTimecode(0); | 75 cb.SetClusterTimecode(0); |
56 | 76 |
57 for (int i = 0; i < block_count; i++) { | 77 for (int i = 0; i < block_count; i++) { |
58 uint8 data[] = { 0x00 }; | 78 uint8 data[] = { 0x00 }; |
59 if (block_info[i].use_simple_block) { | 79 if (block_info[i].use_simple_block) { |
| 80 CHECK_GE(block_info[i].duration, 0); |
60 cb.AddSimpleBlock(block_info[i].track_num, | 81 cb.AddSimpleBlock(block_info[i].track_num, |
61 block_info[i].timestamp, | 82 block_info[i].timestamp, |
62 0, data, sizeof(data)); | 83 0, data, sizeof(data)); |
63 continue; | 84 continue; |
64 } | 85 } |
65 | 86 |
66 CHECK_GE(block_info[i].duration, 0); | 87 if (block_info[i].duration < 0) { |
| 88 cb.AddBlockGroupWithoutBlockDuration(block_info[i].track_num, |
| 89 block_info[i].timestamp, |
| 90 0, data, sizeof(data)); |
| 91 continue; |
| 92 } |
| 93 |
67 cb.AddBlockGroup(block_info[i].track_num, | 94 cb.AddBlockGroup(block_info[i].track_num, |
68 block_info[i].timestamp, | 95 block_info[i].timestamp, |
69 block_info[i].duration, | 96 block_info[i].duration, |
70 0, data, sizeof(data)); | 97 0, data, sizeof(data)); |
71 } | 98 } |
72 | 99 |
73 return cb.Finish(); | 100 return cb.Finish(); |
74 } | 101 } |
75 | 102 |
76 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of | 103 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; | 141 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; |
115 return false; | 142 return false; |
116 } | 143 } |
117 | 144 |
118 if (*offset >= buffers->size()) | 145 if (*offset >= buffers->size()) |
119 return false; | 146 return false; |
120 | 147 |
121 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; | 148 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; |
122 | 149 |
123 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); | 150 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); |
124 EXPECT_EQ(block_info[i].duration, buffer->duration().InMilliseconds()); | 151 EXPECT_EQ(std::abs(block_info[i].duration), |
| 152 buffer->duration().InMilliseconds()); |
125 EXPECT_EQ(expected_type, buffer->type()); | 153 EXPECT_EQ(expected_type, buffer->type()); |
126 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); | 154 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); |
127 } | 155 } |
128 | 156 |
129 return true; | 157 return true; |
130 } | 158 } |
131 | 159 |
132 static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser, | 160 static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser, |
133 const BlockInfo* block_info, | 161 const BlockInfo* block_info, |
134 int block_count) { | 162 int block_count) { |
(...skipping 29 matching lines...) Expand all Loading... |
164 const BlockInfo& block_info = *block_info_ptr++; | 192 const BlockInfo& block_info = *block_info_ptr++; |
165 | 193 |
166 if (block_info.track_num != text_track_num) | 194 if (block_info.track_num != text_track_num) |
167 continue; | 195 continue; |
168 | 196 |
169 EXPECT_FALSE(block_info.use_simple_block); | 197 EXPECT_FALSE(block_info.use_simple_block); |
170 EXPECT_FALSE(buffer_iter == buffer_end); | 198 EXPECT_FALSE(buffer_iter == buffer_end); |
171 | 199 |
172 const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++; | 200 const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++; |
173 EXPECT_EQ(block_info.timestamp, buffer->timestamp().InMilliseconds()); | 201 EXPECT_EQ(block_info.timestamp, buffer->timestamp().InMilliseconds()); |
174 EXPECT_EQ(block_info.duration, buffer->duration().InMilliseconds()); | 202 EXPECT_EQ(std::abs(block_info.duration), |
| 203 buffer->duration().InMilliseconds()); |
175 EXPECT_EQ(DemuxerStream::TEXT, buffer->type()); | 204 EXPECT_EQ(DemuxerStream::TEXT, buffer->type()); |
176 EXPECT_EQ(text_track_num, buffer->track_id()); | 205 EXPECT_EQ(text_track_num, buffer->track_id()); |
177 } | 206 } |
178 | 207 |
179 EXPECT_TRUE(buffer_iter == buffer_end); | 208 EXPECT_TRUE(buffer_iter == buffer_end); |
180 return true; | 209 return true; |
181 } | 210 } |
182 | 211 |
183 static void VerifyEncryptedBuffer( | 212 static void VerifyEncryptedBuffer( |
184 scoped_refptr<StreamParserBuffer> buffer) { | 213 scoped_refptr<StreamParserBuffer> buffer) { |
(...skipping 11 matching lines...) Expand all Loading... |
196 } | 225 } |
197 | 226 |
198 class WebMClusterParserTest : public testing::Test { | 227 class WebMClusterParserTest : public testing::Test { |
199 public: | 228 public: |
200 WebMClusterParserTest() | 229 WebMClusterParserTest() |
201 : parser_(new WebMClusterParser(kTimecodeScale, | 230 : parser_(new WebMClusterParser(kTimecodeScale, |
202 kAudioTrackNum, | 231 kAudioTrackNum, |
203 kNoTimestamp(), | 232 kNoTimestamp(), |
204 kVideoTrackNum, | 233 kVideoTrackNum, |
205 kNoTimestamp(), | 234 kNoTimestamp(), |
206 WebMTracksParser::TextTracks(), | 235 TextTracks(), |
207 std::set<int64>(), | 236 std::set<int64>(), |
208 std::string(), | 237 std::string(), |
209 std::string(), | 238 std::string(), |
210 LogCB())) {} | 239 LogCB())) {} |
211 | 240 |
212 protected: | 241 protected: |
| 242 void ResetParserToHaveDefaultDurations() { |
| 243 base::TimeDelta default_audio_duration = base::TimeDelta::FromMilliseconds( |
| 244 kTestAudioFrameDefaultDurationInMs); |
| 245 base::TimeDelta default_video_duration = base::TimeDelta::FromMilliseconds( |
| 246 kTestVideoFrameDefaultDurationInMs); |
| 247 ASSERT_GE(default_audio_duration, base::TimeDelta()); |
| 248 ASSERT_GE(default_video_duration, base::TimeDelta()); |
| 249 ASSERT_NE(kNoTimestamp(), default_audio_duration); |
| 250 ASSERT_NE(kNoTimestamp(), default_video_duration); |
| 251 |
| 252 parser_.reset(new WebMClusterParser(kTimecodeScale, |
| 253 kAudioTrackNum, |
| 254 default_audio_duration, |
| 255 kVideoTrackNum, |
| 256 default_video_duration, |
| 257 TextTracks(), |
| 258 std::set<int64>(), |
| 259 std::string(), |
| 260 std::string(), |
| 261 LogCB())); |
| 262 } |
| 263 |
213 scoped_ptr<WebMClusterParser> parser_; | 264 scoped_ptr<WebMClusterParser> parser_; |
| 265 |
| 266 private: |
| 267 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); |
214 }; | 268 }; |
215 | 269 |
216 TEST_F(WebMClusterParserTest, Reset) { | 270 TEST_F(WebMClusterParserTest, Reset) { |
217 InSequence s; | 271 InSequence s; |
218 | 272 |
219 int block_count = arraysize(kDefaultBlockInfo); | 273 int block_count = arraysize(kDefaultBlockInfo); |
220 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); | 274 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); |
221 | 275 |
222 // Send slightly less than the full cluster so all but the last block is | 276 // Send slightly less than the full cluster so all but the last block is |
223 // parsed. | 277 // parsed. |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 | 384 |
331 TEST_F(WebMClusterParserTest, IgnoredTracks) { | 385 TEST_F(WebMClusterParserTest, IgnoredTracks) { |
332 std::set<int64> ignored_tracks; | 386 std::set<int64> ignored_tracks; |
333 ignored_tracks.insert(kTextTrackNum); | 387 ignored_tracks.insert(kTextTrackNum); |
334 | 388 |
335 parser_.reset(new WebMClusterParser(kTimecodeScale, | 389 parser_.reset(new WebMClusterParser(kTimecodeScale, |
336 kAudioTrackNum, | 390 kAudioTrackNum, |
337 kNoTimestamp(), | 391 kNoTimestamp(), |
338 kVideoTrackNum, | 392 kVideoTrackNum, |
339 kNoTimestamp(), | 393 kNoTimestamp(), |
340 WebMTracksParser::TextTracks(), | 394 TextTracks(), |
341 ignored_tracks, | 395 ignored_tracks, |
342 std::string(), | 396 std::string(), |
343 std::string(), | 397 std::string(), |
344 LogCB())); | 398 LogCB())); |
345 | 399 |
346 const BlockInfo kInputBlockInfo[] = { | 400 const BlockInfo kInputBlockInfo[] = { |
347 { kAudioTrackNum, 0, 23, true }, | 401 { kAudioTrackNum, 0, 23, true }, |
348 { kAudioTrackNum, 23, 23, true }, | 402 { kAudioTrackNum, 23, 23, true }, |
349 { kVideoTrackNum, 33, 34, true }, | 403 { kVideoTrackNum, 33, 34, true }, |
350 { kTextTrackNum, 33, 99, true }, | 404 { kTextTrackNum, 33, 99, true }, |
(...skipping 13 matching lines...) Expand all Loading... |
364 | 418 |
365 scoped_ptr<Cluster> cluster( | 419 scoped_ptr<Cluster> cluster( |
366 CreateCluster(0, kInputBlockInfo, input_block_count)); | 420 CreateCluster(0, kInputBlockInfo, input_block_count)); |
367 | 421 |
368 int result = parser_->Parse(cluster->data(), cluster->size()); | 422 int result = parser_->Parse(cluster->data(), cluster->size()); |
369 EXPECT_EQ(cluster->size(), result); | 423 EXPECT_EQ(cluster->size(), result); |
370 ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count)); | 424 ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count)); |
371 } | 425 } |
372 | 426 |
373 TEST_F(WebMClusterParserTest, ParseTextTracks) { | 427 TEST_F(WebMClusterParserTest, ParseTextTracks) { |
374 typedef WebMTracksParser::TextTracks TextTracks; | |
375 TextTracks text_tracks; | 428 TextTracks text_tracks; |
376 | 429 |
377 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), | 430 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), |
378 TextTrackConfig(kTextSubtitles, "", "", | 431 TextTrackConfig(kTextSubtitles, "", "", |
379 ""))); | 432 ""))); |
380 | 433 |
381 parser_.reset(new WebMClusterParser(kTimecodeScale, | 434 parser_.reset(new WebMClusterParser(kTimecodeScale, |
382 kAudioTrackNum, | 435 kAudioTrackNum, |
383 kNoTimestamp(), | 436 kNoTimestamp(), |
384 kVideoTrackNum, | 437 kVideoTrackNum, |
(...skipping 17 matching lines...) Expand all Loading... |
402 | 455 |
403 scoped_ptr<Cluster> cluster( | 456 scoped_ptr<Cluster> cluster( |
404 CreateCluster(0, kInputBlockInfo, input_block_count)); | 457 CreateCluster(0, kInputBlockInfo, input_block_count)); |
405 | 458 |
406 int result = parser_->Parse(cluster->data(), cluster->size()); | 459 int result = parser_->Parse(cluster->data(), cluster->size()); |
407 EXPECT_EQ(cluster->size(), result); | 460 EXPECT_EQ(cluster->size(), result); |
408 ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count)); | 461 ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count)); |
409 } | 462 } |
410 | 463 |
411 TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) { | 464 TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) { |
412 typedef WebMTracksParser::TextTracks TextTracks; | 465 TextTracks text_tracks; |
413 WebMTracksParser::TextTracks text_tracks; | |
414 | 466 |
415 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), | 467 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), |
416 TextTrackConfig(kTextSubtitles, "", "", | 468 TextTrackConfig(kTextSubtitles, "", "", |
417 ""))); | 469 ""))); |
418 | 470 |
419 parser_.reset(new WebMClusterParser(kTimecodeScale, | 471 parser_.reset(new WebMClusterParser(kTimecodeScale, |
420 kAudioTrackNum, | 472 kAudioTrackNum, |
421 kNoTimestamp(), | 473 kNoTimestamp(), |
422 kVideoTrackNum, | 474 kVideoTrackNum, |
423 kNoTimestamp(), | 475 kNoTimestamp(), |
424 text_tracks, | 476 text_tracks, |
425 std::set<int64>(), | 477 std::set<int64>(), |
426 std::string(), | 478 std::string(), |
427 std::string(), | 479 std::string(), |
428 LogCB())); | 480 LogCB())); |
429 | 481 |
430 const BlockInfo kInputBlockInfo[] = { | 482 const BlockInfo kInputBlockInfo[] = { |
431 { kTextTrackNum, 33, 42, true }, | 483 { kTextTrackNum, 33, 42, true }, |
432 }; | 484 }; |
433 int input_block_count = arraysize(kInputBlockInfo); | 485 int input_block_count = arraysize(kInputBlockInfo); |
434 | 486 |
435 scoped_ptr<Cluster> cluster( | 487 scoped_ptr<Cluster> cluster( |
436 CreateCluster(0, kInputBlockInfo, input_block_count)); | 488 CreateCluster(0, kInputBlockInfo, input_block_count)); |
437 | 489 |
438 int result = parser_->Parse(cluster->data(), cluster->size()); | 490 int result = parser_->Parse(cluster->data(), cluster->size()); |
439 EXPECT_LT(result, 0); | 491 EXPECT_LT(result, 0); |
440 } | 492 } |
441 | 493 |
442 TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) { | 494 TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) { |
443 typedef WebMTracksParser::TextTracks TextTracks; | |
444 TextTracks text_tracks; | 495 TextTracks text_tracks; |
445 | 496 |
446 const int kSubtitleTextTrackNum = kTextTrackNum; | 497 const int kSubtitleTextTrackNum = kTextTrackNum; |
447 const int kCaptionTextTrackNum = kTextTrackNum + 1; | 498 const int kCaptionTextTrackNum = kTextTrackNum + 1; |
448 | 499 |
449 text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum), | 500 text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum), |
450 TextTrackConfig(kTextSubtitles, "", "", | 501 TextTrackConfig(kTextSubtitles, "", "", |
451 ""))); | 502 ""))); |
452 | 503 |
453 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum), | 504 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum), |
(...skipping 28 matching lines...) Expand all Loading... |
482 | 533 |
483 int result = parser_->Parse(cluster->data(), cluster->size()); | 534 int result = parser_->Parse(cluster->data(), cluster->size()); |
484 EXPECT_EQ(cluster->size(), result); | 535 EXPECT_EQ(cluster->size(), result); |
485 | 536 |
486 const WebMClusterParser::TextBufferQueueMap& text_map = | 537 const WebMClusterParser::TextBufferQueueMap& text_map = |
487 parser_->GetTextBuffers(); | 538 parser_->GetTextBuffers(); |
488 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr = | 539 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr = |
489 text_map.begin(); | 540 text_map.begin(); |
490 itr != text_map.end(); | 541 itr != text_map.end(); |
491 ++itr) { | 542 ++itr) { |
492 const WebMTracksParser::TextTracks::const_iterator find_result = | 543 const TextTracks::const_iterator find_result = |
493 text_tracks.find(itr->first); | 544 text_tracks.find(itr->first); |
494 ASSERT_TRUE(find_result != text_tracks.end()); | 545 ASSERT_TRUE(find_result != text_tracks.end()); |
495 ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count, | 546 ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count, |
496 itr->first, itr->second)); | 547 itr->first, itr->second)); |
497 } | 548 } |
498 } | 549 } |
499 | 550 |
500 TEST_F(WebMClusterParserTest, ParseEncryptedBlock) { | 551 TEST_F(WebMClusterParserTest, ParseEncryptedBlock) { |
501 scoped_ptr<Cluster> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame))); | 552 scoped_ptr<Cluster> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame))); |
502 | 553 |
503 parser_.reset(new WebMClusterParser(kTimecodeScale, | 554 parser_.reset(new WebMClusterParser(kTimecodeScale, |
504 kAudioTrackNum, | 555 kAudioTrackNum, |
505 kNoTimestamp(), | 556 kNoTimestamp(), |
506 kVideoTrackNum, | 557 kVideoTrackNum, |
507 kNoTimestamp(), | 558 kNoTimestamp(), |
508 WebMTracksParser::TextTracks(), | 559 TextTracks(), |
509 std::set<int64>(), | 560 std::set<int64>(), |
510 std::string(), | 561 std::string(), |
511 "video_key_id", | 562 "video_key_id", |
512 LogCB())); | 563 LogCB())); |
513 int result = parser_->Parse(cluster->data(), cluster->size()); | 564 int result = parser_->Parse(cluster->data(), cluster->size()); |
514 EXPECT_EQ(cluster->size(), result); | 565 EXPECT_EQ(cluster->size(), result); |
515 ASSERT_EQ(1UL, parser_->GetVideoBuffers().size()); | 566 ASSERT_EQ(1UL, parser_->GetVideoBuffers().size()); |
516 scoped_refptr<StreamParserBuffer> buffer = parser_->GetVideoBuffers()[0]; | 567 scoped_refptr<StreamParserBuffer> buffer = parser_->GetVideoBuffers()[0]; |
517 VerifyEncryptedBuffer(buffer); | 568 VerifyEncryptedBuffer(buffer); |
518 } | 569 } |
519 | 570 |
520 TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) { | 571 TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) { |
521 scoped_ptr<Cluster> cluster( | 572 scoped_ptr<Cluster> cluster( |
522 CreateEncryptedCluster(sizeof(kEncryptedFrame) - 1)); | 573 CreateEncryptedCluster(sizeof(kEncryptedFrame) - 1)); |
523 | 574 |
524 parser_.reset(new WebMClusterParser(kTimecodeScale, | 575 parser_.reset(new WebMClusterParser(kTimecodeScale, |
525 kAudioTrackNum, | 576 kAudioTrackNum, |
526 kNoTimestamp(), | 577 kNoTimestamp(), |
527 kVideoTrackNum, | 578 kVideoTrackNum, |
528 kNoTimestamp(), | 579 kNoTimestamp(), |
529 WebMTracksParser::TextTracks(), | 580 TextTracks(), |
530 std::set<int64>(), | 581 std::set<int64>(), |
531 std::string(), | 582 std::string(), |
532 "video_key_id", | 583 "video_key_id", |
533 LogCB())); | 584 LogCB())); |
534 int result = parser_->Parse(cluster->data(), cluster->size()); | 585 int result = parser_->Parse(cluster->data(), cluster->size()); |
535 EXPECT_EQ(-1, result); | 586 EXPECT_EQ(-1, result); |
536 } | 587 } |
537 | 588 |
538 TEST_F(WebMClusterParserTest, ParseInvalidZeroSizedCluster) { | 589 TEST_F(WebMClusterParserTest, ParseInvalidZeroSizedCluster) { |
539 const uint8 kBuffer[] = { | 590 const uint8 kBuffer[] = { |
540 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) | 591 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) |
541 }; | 592 }; |
542 | 593 |
543 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); | 594 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); |
544 } | 595 } |
545 | 596 |
546 TEST_F(WebMClusterParserTest, ParseInvalidUnknownButActuallyZeroSizedCluster) { | 597 TEST_F(WebMClusterParserTest, ParseInvalidUnknownButActuallyZeroSizedCluster) { |
547 const uint8 kBuffer[] = { | 598 const uint8 kBuffer[] = { |
548 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown") | 599 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown") |
549 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5) | 600 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5) |
550 }; | 601 }; |
551 | 602 |
552 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); | 603 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); |
553 } | 604 } |
554 | 605 |
| 606 TEST_F(WebMClusterParserTest, ParseInvalidTextBlockGroupWithoutDuration) { |
| 607 // Text track frames must have explicitly specified BlockGroup BlockDurations. |
| 608 TextTracks text_tracks; |
| 609 |
| 610 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), |
| 611 TextTrackConfig(kTextSubtitles, "", "", |
| 612 ""))); |
| 613 |
| 614 parser_.reset(new WebMClusterParser(kTimecodeScale, |
| 615 kAudioTrackNum, |
| 616 kNoTimestamp(), |
| 617 kVideoTrackNum, |
| 618 kNoTimestamp(), |
| 619 text_tracks, |
| 620 std::set<int64>(), |
| 621 std::string(), |
| 622 std::string(), |
| 623 LogCB())); |
| 624 |
| 625 const BlockInfo kBlockInfo[] = { |
| 626 { kTextTrackNum, 33, -42, false }, |
| 627 }; |
| 628 int block_count = arraysize(kBlockInfo); |
| 629 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| 630 int result = parser_->Parse(cluster->data(), cluster->size()); |
| 631 EXPECT_LT(result, 0); |
| 632 } |
| 633 |
| 634 TEST_F(WebMClusterParserTest, ParseWithDefaultDurationsSimpleBlocks) { |
| 635 InSequence s; |
| 636 ResetParserToHaveDefaultDurations(); |
| 637 |
| 638 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23); |
| 639 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33); |
| 640 |
| 641 const BlockInfo kBlockInfo[] = { |
| 642 { kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true }, |
| 643 { kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true }, |
| 644 { kVideoTrackNum, 33, kTestVideoFrameDefaultDurationInMs, true }, |
| 645 { kAudioTrackNum, 46, kTestAudioFrameDefaultDurationInMs, true }, |
| 646 { kVideoTrackNum, 67, kTestVideoFrameDefaultDurationInMs, true }, |
| 647 { kAudioTrackNum, 69, kTestAudioFrameDefaultDurationInMs, true }, |
| 648 { kVideoTrackNum, 100, kTestVideoFrameDefaultDurationInMs, true }, |
| 649 }; |
| 650 |
| 651 int block_count = arraysize(kBlockInfo); |
| 652 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| 653 |
| 654 // Send slightly less than the full cluster so all but the last block is |
| 655 // parsed. Though all the blocks are simple blocks, none should be held aside |
| 656 // for duration estimation prior to end of cluster detection because all the |
| 657 // tracks have DefaultDurations. |
| 658 int result = parser_->Parse(cluster->data(), cluster->size() - 1); |
| 659 EXPECT_GT(result, 0); |
| 660 EXPECT_LT(result, cluster->size()); |
| 661 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1)); |
| 662 |
| 663 parser_->Reset(); |
| 664 |
| 665 // Now parse a whole cluster to verify that all the blocks will get parsed. |
| 666 result = parser_->Parse(cluster->data(), cluster->size()); |
| 667 EXPECT_EQ(cluster->size(), result); |
| 668 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
| 669 } |
| 670 |
| 671 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) { |
| 672 InSequence s; |
| 673 |
| 674 // Absent DefaultDuration information, SimpleBlock durations are derived from |
| 675 // inter-buffer track timestamp delta if within the cluster, and are estimated |
| 676 // as the lowest non-zero duration seen so far if the last buffer in the track |
| 677 // in the cluster (independently for each track in the cluster). |
| 678 const BlockInfo kBlockInfo1[] = { |
| 679 { kAudioTrackNum, 0, 23, true }, |
| 680 { kAudioTrackNum, 23, 22, true }, |
| 681 { kVideoTrackNum, 33, 33, true }, |
| 682 { kAudioTrackNum, 45, 23, true }, |
| 683 { kVideoTrackNum, 66, 34, true }, |
| 684 { kAudioTrackNum, 68, 22, true }, // Estimated from minimum audio dur |
| 685 { kVideoTrackNum, 100, 33, true }, // Estimated from minimum video dur |
| 686 }; |
| 687 |
| 688 int block_count1 = arraysize(kBlockInfo1); |
| 689 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1)); |
| 690 |
| 691 // Send slightly less than the first full cluster so all but the last video |
| 692 // block is parsed. Verify the last fully parsed audio and video buffer are |
| 693 // both missing from the result (parser should hold them aside for duration |
| 694 // estimation prior to end of cluster detection in the absence of |
| 695 // DefaultDurations.) |
| 696 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1); |
| 697 EXPECT_GT(result, 0); |
| 698 EXPECT_LT(result, cluster1->size()); |
| 699 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3)); |
| 700 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size()); |
| 701 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size()); |
| 702 |
| 703 parser_->Reset(); |
| 704 |
| 705 // Now parse the full first cluster and verify all the blocks are parsed. |
| 706 result = parser_->Parse(cluster1->data(), cluster1->size()); |
| 707 EXPECT_EQ(cluster1->size(), result); |
| 708 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1)); |
| 709 |
| 710 // Verify that the estimated frame duration is tracked across clusters for |
| 711 // each track. |
| 712 const BlockInfo kBlockInfo2[] = { |
| 713 { kAudioTrackNum, 200, 22, true }, // Estimate carries over across clusters |
| 714 { kVideoTrackNum, 201, 33, true }, // Estimate carries over across clusters |
| 715 }; |
| 716 |
| 717 int block_count2 = arraysize(kBlockInfo2); |
| 718 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2)); |
| 719 result = parser_->Parse(cluster2->data(), cluster2->size()); |
| 720 EXPECT_EQ(cluster2->size(), result); |
| 721 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2)); |
| 722 } |
| 723 |
| 724 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) { |
| 725 InSequence s; |
| 726 |
| 727 // Absent DefaultDuration and BlockDuration information, BlockGroup block |
| 728 // durations are derived from inter-buffer track timestamp delta if within the |
| 729 // cluster, and are estimated as the lowest non-zero duration seen so far if |
| 730 // the last buffer in the track in the cluster (independently for each track |
| 731 // in the cluster). |
| 732 const BlockInfo kBlockInfo1[] = { |
| 733 { kAudioTrackNum, 0, -23, false }, |
| 734 { kAudioTrackNum, 23, -22, false }, |
| 735 { kVideoTrackNum, 33, -33, false }, |
| 736 { kAudioTrackNum, 45, -23, false }, |
| 737 { kVideoTrackNum, 66, -34, false }, |
| 738 { kAudioTrackNum, 68, -22, false }, // Estimated from minimum audio dur |
| 739 { kVideoTrackNum, 100, -33, false }, // Estimated from minimum video dur |
| 740 }; |
| 741 |
| 742 int block_count1 = arraysize(kBlockInfo1); |
| 743 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1)); |
| 744 |
| 745 // Send slightly less than the first full cluster so all but the last video |
| 746 // block is parsed. Verify the last fully parsed audio and video buffer are |
| 747 // both missing from the result (parser should hold them aside for duration |
| 748 // estimation prior to end of cluster detection in the absence of |
| 749 // DefaultDurations.) |
| 750 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1); |
| 751 EXPECT_GT(result, 0); |
| 752 EXPECT_LT(result, cluster1->size()); |
| 753 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3)); |
| 754 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size()); |
| 755 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size()); |
| 756 |
| 757 parser_->Reset(); |
| 758 |
| 759 // Now parse the full first cluster and verify all the blocks are parsed. |
| 760 result = parser_->Parse(cluster1->data(), cluster1->size()); |
| 761 EXPECT_EQ(cluster1->size(), result); |
| 762 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1)); |
| 763 |
| 764 // Verify that the estimated frame duration is tracked across clusters for |
| 765 // each track. |
| 766 const BlockInfo kBlockInfo2[] = { |
| 767 { kAudioTrackNum, 200, -22, false }, |
| 768 { kVideoTrackNum, 201, -33, false }, |
| 769 }; |
| 770 |
| 771 int block_count2 = arraysize(kBlockInfo2); |
| 772 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2)); |
| 773 result = parser_->Parse(cluster2->data(), cluster2->size()); |
| 774 EXPECT_EQ(cluster2->size(), result); |
| 775 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2)); |
| 776 } |
| 777 |
| 778 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433. |
| 779 TEST_F(WebMClusterParserTest, |
| 780 ParseWithDefaultDurationsBlockGroupsWithoutDurations) { |
| 781 InSequence s; |
| 782 ResetParserToHaveDefaultDurations(); |
| 783 |
| 784 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23); |
| 785 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33); |
| 786 |
| 787 const BlockInfo kBlockInfo[] = { |
| 788 { kAudioTrackNum, 0, -kTestAudioFrameDefaultDurationInMs, false }, |
| 789 { kAudioTrackNum, 23, -kTestAudioFrameDefaultDurationInMs, false }, |
| 790 { kVideoTrackNum, 33, -kTestVideoFrameDefaultDurationInMs, false }, |
| 791 { kAudioTrackNum, 46, -kTestAudioFrameDefaultDurationInMs, false }, |
| 792 { kVideoTrackNum, 67, -kTestVideoFrameDefaultDurationInMs, false }, |
| 793 { kAudioTrackNum, 69, -kTestAudioFrameDefaultDurationInMs, false }, |
| 794 { kVideoTrackNum, 100, -kTestVideoFrameDefaultDurationInMs, false }, |
| 795 }; |
| 796 |
| 797 int block_count = arraysize(kBlockInfo); |
| 798 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| 799 |
| 800 // Send slightly less than the full cluster so all but the last block is |
| 801 // parsed. None should be held aside for duration estimation prior to end of |
| 802 // cluster detection because all the tracks have DefaultDurations. |
| 803 int result = parser_->Parse(cluster->data(), cluster->size() - 1); |
| 804 EXPECT_GT(result, 0); |
| 805 EXPECT_LT(result, cluster->size()); |
| 806 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1)); |
| 807 |
| 808 parser_->Reset(); |
| 809 |
| 810 // Now parse a whole cluster to verify that all the blocks will get parsed. |
| 811 result = parser_->Parse(cluster->data(), cluster->size()); |
| 812 EXPECT_EQ(cluster->size(), result); |
| 813 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
| 814 } |
| 815 |
| 816 TEST_F(WebMClusterParserTest, |
| 817 ParseDegenerateClusterYieldsHardcodedEstimatedDurations) { |
| 818 const BlockInfo kBlockInfo[] = { |
| 819 { |
| 820 kAudioTrackNum, |
| 821 0, |
| 822 WebMClusterParser::kDefaultAudioBufferDurationInMs, |
| 823 true |
| 824 }, { |
| 825 kVideoTrackNum, |
| 826 0, |
| 827 WebMClusterParser::kDefaultVideoBufferDurationInMs, |
| 828 true |
| 829 }, |
| 830 }; |
| 831 |
| 832 int block_count = arraysize(kBlockInfo); |
| 833 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| 834 int result = parser_->Parse(cluster->data(), cluster->size()); |
| 835 EXPECT_EQ(cluster->size(), result); |
| 836 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
| 837 } |
| 838 |
| 839 TEST_F(WebMClusterParserTest, |
| 840 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations) { |
| 841 ResetParserToHaveDefaultDurations(); |
| 842 |
| 843 const BlockInfo kBlockInfo[] = { |
| 844 { kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true }, |
| 845 { kVideoTrackNum, 0, kTestVideoFrameDefaultDurationInMs, true }, |
| 846 }; |
| 847 |
| 848 int block_count = arraysize(kBlockInfo); |
| 849 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
| 850 int result = parser_->Parse(cluster->data(), cluster->size()); |
| 851 EXPECT_EQ(cluster->size(), result); |
| 852 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
| 853 } |
| 854 |
555 } // namespace media | 855 } // namespace media |
OLD | NEW |