Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(815)

Side by Side Diff: media/formats/webm/webm_cluster_parser_unittest.cc

Issue 238273002: Adds WebMClusterParserTest coverage for duration default/estimation/fallback logic (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix lint errors Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« media/formats/webm/cluster_builder.cc ('K') | « media/formats/webm/webm_cluster_parser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698