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