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 3 // found in the LICENSE file. 4 5 #include <algorithm> 6 #include <cstdlib> 7 8 #include "base/bind.h" 9 #include "base/logging.h" 10 #include "media/base/decrypt_config.h" 11 #include "media/formats/webm/cluster_builder.h" 12 #include "media/formats/webm/webm_cluster_parser.h" 13 #include "media/formats/webm/webm_constants.h" 14 #include "testing/gmock/include/gmock/gmock.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 using ::testing::InSequence; 18 using ::testing::Return; 19 using ::testing::_; 20 21 namespace media { 22 23 typedef WebMTracksParser::TextTracks TextTracks; 24 25 enum { 26 kTimecodeScale = 1000000, // Timecode scale for millisecond timestamps. 27 kAudioTrackNum = 1, 28 kVideoTrackNum = 2, 29 kTextTrackNum = 3, 30 kTestAudioFrameDefaultDurationInMs = 13, 31 kTestVideoFrameDefaultDurationInMs = 17 32 }; 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 43 struct BlockInfo { 44 int track_num; 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. 52 int duration; 53 bool use_simple_block; 54 }; 55 56 static const BlockInfo kDefaultBlockInfo[] = { 57 { kAudioTrackNum, 0, 23, true }, 58 { kAudioTrackNum, 23, 23, true }, 59 { kVideoTrackNum, 33, 34, true }, // Assumes not using DefaultDuration 60 { kAudioTrackNum, 46, 23, true }, 61 { kVideoTrackNum, 67, 33, false }, 62 { kAudioTrackNum, 69, 23, false }, 63 { kVideoTrackNum, 100, 33, false }, 64 }; 65 66 static const uint8 kEncryptedFrame[] = { 67 0x01, // Block is encrypted 68 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV 69 }; 70 71 static scoped_ptr<Cluster> CreateCluster(int timecode, 72 const BlockInfo* block_info, 73 int block_count) { 74 ClusterBuilder cb; 75 cb.SetClusterTimecode(0); 76 77 for (int i = 0; i < block_count; i++) { 78 uint8 data[] = { 0x00 }; 79 if (block_info[i].use_simple_block) { 80 CHECK_GE(block_info[i].duration, 0); 81 cb.AddSimpleBlock(block_info[i].track_num, 82 block_info[i].timestamp, 83 0, data, sizeof(data)); 84 continue; 85 } 86 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 94 cb.AddBlockGroup(block_info[i].track_num, 95 block_info[i].timestamp, 96 block_info[i].duration, 97 0, data, sizeof(data)); 98 } 99 100 return cb.Finish(); 101 } 102 103 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of 104 // bytes of the encrypted frame to write. 105 static scoped_ptr<Cluster> CreateEncryptedCluster(int bytes_to_write) { 106 CHECK_GT(bytes_to_write, 0); 107 CHECK_LE(bytes_to_write, static_cast<int>(sizeof(kEncryptedFrame))); 108 109 ClusterBuilder cb; 110 cb.SetClusterTimecode(0); 111 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write); 112 return cb.Finish(); 113 } 114 115 static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, 116 const WebMClusterParser::BufferQueue& video_buffers, 117 const WebMClusterParser::BufferQueue& text_buffers, 118 const BlockInfo* block_info, 119 int block_count) { 120 int buffer_count = audio_buffers.size() + video_buffers.size() + 121 text_buffers.size(); 122 if (block_count != buffer_count) { 123 DVLOG(1) << __FUNCTION__ << " : block_count (" << block_count 124 << ") mismatches buffer_count (" << buffer_count << ")"; 125 return false; 126 } 127 128 size_t audio_offset = 0; 129 size_t video_offset = 0; 130 size_t text_offset = 0; 131 for (int i = 0; i < block_count; i++) { 132 const WebMClusterParser::BufferQueue* buffers = NULL; 133 size_t* offset; 134 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN; 135 136 if (block_info[i].track_num == kAudioTrackNum) { 137 buffers = &audio_buffers; 138 offset = &audio_offset; 139 expected_type = DemuxerStream::AUDIO; 140 } else if (block_info[i].track_num == kVideoTrackNum) { 141 buffers = &video_buffers; 142 offset = &video_offset; 143 expected_type = DemuxerStream::VIDEO; 144 } else if (block_info[i].track_num == kTextTrackNum) { 145 buffers = &text_buffers; 146 offset = &text_offset; 147 expected_type = DemuxerStream::TEXT; 148 } else { 149 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; 150 return false; 151 } 152 153 if (*offset >= buffers->size()) { 154 DVLOG(1) << __FUNCTION__ << " : Too few buffers (" << buffers->size() 155 << ") for track_num (" << block_info[i].track_num 156 << "), expected at least " << *offset + 1 << " buffers"; 157 return false; 158 } 159 160 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; 161 162 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); 163 EXPECT_EQ(std::abs(block_info[i].duration), 164 buffer->duration().InMilliseconds()); 165 EXPECT_EQ(expected_type, buffer->type()); 166 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); 167 } 168 169 return true; 170 } 171 172 static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser, 173 const BlockInfo* block_info, 174 int block_count) { 175 const WebMClusterParser::TextBufferQueueMap& text_map = 176 parser->GetTextBuffers(); 177 const WebMClusterParser::BufferQueue* text_buffers; 178 const WebMClusterParser::BufferQueue no_text_buffers; 179 if (!text_map.empty()) 180 text_buffers = &(text_map.rbegin()->second); 181 else 182 text_buffers = &no_text_buffers; 183 184 return VerifyBuffers(parser->GetAudioBuffers(), 185 parser->GetVideoBuffers(), 186 *text_buffers, 187 block_info, 188 block_count); 189 } 190 191 static bool VerifyTextBuffers( 192 const scoped_ptr<WebMClusterParser>& parser, 193 const BlockInfo* block_info_ptr, 194 int block_count, 195 int text_track_num, 196 const WebMClusterParser::BufferQueue& text_buffers) { 197 const BlockInfo* const block_info_end = block_info_ptr + block_count; 198 199 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter; 200 TextBufferIter buffer_iter = text_buffers.begin(); 201 const TextBufferIter buffer_end = text_buffers.end(); 202 203 while (block_info_ptr != block_info_end) { 204 const BlockInfo& block_info = *block_info_ptr++; 205 206 if (block_info.track_num != text_track_num) 207 continue; 208 209 EXPECT_FALSE(block_info.use_simple_block); 210 EXPECT_FALSE(buffer_iter == buffer_end); 211 212 const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++; 213 EXPECT_EQ(block_info.timestamp, buffer->timestamp().InMilliseconds()); 214 EXPECT_EQ(std::abs(block_info.duration), 215 buffer->duration().InMilliseconds()); 216 EXPECT_EQ(DemuxerStream::TEXT, buffer->type()); 217 EXPECT_EQ(text_track_num, buffer->track_id()); 218 } 219 220 EXPECT_TRUE(buffer_iter == buffer_end); 221 return true; 222 } 223 224 static void VerifyEncryptedBuffer( 225 scoped_refptr<StreamParserBuffer> buffer) { 226 EXPECT_TRUE(buffer->decrypt_config()); 227 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize), 228 buffer->decrypt_config()->iv().length()); 229 } 230 231 static void AppendToEnd(const WebMClusterParser::BufferQueue& src, 232 WebMClusterParser::BufferQueue* dest) { 233 for (WebMClusterParser::BufferQueue::const_iterator itr = src.begin(); 234 itr != src.end(); ++itr) { 235 dest->push_back(*itr); 236 } 237 } 238 239 class WebMClusterParserTest : public testing::Test { 240 public: 241 WebMClusterParserTest() 242 : parser_(new WebMClusterParser(kTimecodeScale, 243 kAudioTrackNum, 244 kNoTimestamp(), 245 kVideoTrackNum, 246 kNoTimestamp(), 247 TextTracks(), 248 std::set<int64>(), 249 std::string(), 250 std::string(), 251 LogCB())) {} 252 253 protected: 254 void ResetParserToHaveDefaultDurations() { 255 base::TimeDelta default_audio_duration = base::TimeDelta::FromMilliseconds( 256 kTestAudioFrameDefaultDurationInMs); 257 base::TimeDelta default_video_duration = base::TimeDelta::FromMilliseconds( 258 kTestVideoFrameDefaultDurationInMs); 259 ASSERT_GE(default_audio_duration, base::TimeDelta()); 260 ASSERT_GE(default_video_duration, base::TimeDelta()); 261 ASSERT_NE(kNoTimestamp(), default_audio_duration); 262 ASSERT_NE(kNoTimestamp(), default_video_duration); 263 264 parser_.reset(new WebMClusterParser(kTimecodeScale, 265 kAudioTrackNum, 266 default_audio_duration, 267 kVideoTrackNum, 268 default_video_duration, 269 TextTracks(), 270 std::set<int64>(), 271 std::string(), 272 std::string(), 273 LogCB())); 274 } 275 276 scoped_ptr<WebMClusterParser> parser_; 277 278 private: 279 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); 280 }; 281 282 TEST_F(WebMClusterParserTest, HeldBackBufferHoldsBackAllTracks) { 283 // If a buffer is missing duration and is being held back, then all other 284 // tracks' buffers that have same or higher (decode) timestamp should be held 285 // back too to keep the timestamps emitted for a cluster monotonically 286 // non-decreasing and in same order as parsed. 287 InSequence s; 288 289 // Reset the parser to have 3 tracks: text, video (no default frame duration), 290 // and audio (with a default frame duration). 291 TextTracks text_tracks; 292 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), 293 TextTrackConfig(kTextSubtitles, "", "", 294 ""))); 295 base::TimeDelta default_audio_duration = 296 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs); 297 ASSERT_GE(default_audio_duration, base::TimeDelta()); 298 ASSERT_NE(kNoTimestamp(), default_audio_duration); 299 parser_.reset(new WebMClusterParser(kTimecodeScale, 300 kAudioTrackNum, 301 default_audio_duration, 302 kVideoTrackNum, 303 kNoTimestamp(), 304 text_tracks, 305 std::set<int64>(), 306 std::string(), 307 std::string(), 308 LogCB())); 309 310 const BlockInfo kBlockInfo[] = { 311 { kVideoTrackNum, 0, 33, true }, 312 { kAudioTrackNum, 0, 23, false }, 313 { kTextTrackNum, 10, 42, false }, 314 { kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true }, 315 { kVideoTrackNum, 33, 33, true }, 316 { kAudioTrackNum, 36, kTestAudioFrameDefaultDurationInMs, true }, 317 { kVideoTrackNum, 66, 33, true }, 318 { kAudioTrackNum, 70, kTestAudioFrameDefaultDurationInMs, true }, 319 { kAudioTrackNum, 83, kTestAudioFrameDefaultDurationInMs, true }, 320 }; 321 322 const int kExpectedBuffersOnPartialCluster[] = { 323 0, // Video simple block without DefaultDuration should be held back 324 0, // Audio buffer ready, but not emitted because its TS >= held back video 325 0, // Text buffer ready, but not emitted because its TS >= held back video 326 0, // 2nd audio buffer ready, also not emitted for same reason as first 327 4, // All previous buffers emitted, 2nd video held back with no duration 328 4, // 2nd video still has no duration, 3rd audio ready but not emitted 329 6, // All previous buffers emitted, 3rd video held back with no duration 330 6, // 3rd video still has no duration, 4th audio ready but not emitted 331 9, // Cluster end emits all buffers and 3rd video's duration is estimated 332 }; 333 334 ASSERT_EQ(arraysize(kBlockInfo), arraysize(kExpectedBuffersOnPartialCluster)); 335 int block_count = arraysize(kBlockInfo); 336 337 // Iteratively create a cluster containing the first N+1 blocks and parse all 338 // but the last byte of the cluster (except when N==|block_count|, just parse 339 // the whole cluster). Verify that the corresponding entry in 340 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of 341 // |kBlockInfo| returned by the parser. 342 for (int i = 0; i < block_count; ++i) { 343 if (i > 0) 344 parser_->Reset(); 345 // Since we don't know exactly the offsets of each block in the full 346 // cluster, build a cluster with exactly one additional block so that 347 // parse of all but one byte should deterministically parse all but the 348 // last full block. Don't |exceed block_count| blocks though. 349 int blocks_in_cluster = std::min(i + 2, block_count); 350 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, 351 blocks_in_cluster)); 352 // Parse all but the last byte unless we need to parse the full cluster. 353 bool parse_full_cluster = i == (block_count - 1); 354 int result = parser_->Parse(cluster->data(), parse_full_cluster ? 355 cluster->size() : cluster->size() - 1); 356 if (parse_full_cluster) { 357 DVLOG(1) << "Verifying parse result of full cluster of " 358 << blocks_in_cluster << " blocks"; 359 EXPECT_EQ(cluster->size(), result); 360 } else { 361 DVLOG(1) << "Verifying parse result of cluster of " 362 << blocks_in_cluster << " blocks with last block incomplete"; 363 EXPECT_GT(cluster->size(), result); 364 EXPECT_LT(0, result); 365 } 366 367 EXPECT_TRUE(VerifyBuffers(parser_, kBlockInfo, 368 kExpectedBuffersOnPartialCluster[i])); 369 } 370 } 371 372 TEST_F(WebMClusterParserTest, Reset) { 373 InSequence s; 374 375 int block_count = arraysize(kDefaultBlockInfo); 376 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); 377 378 // Send slightly less than the full cluster so all but the last block is 379 // parsed. 380 int result = parser_->Parse(cluster->data(), cluster->size() - 1); 381 EXPECT_GT(result, 0); 382 EXPECT_LT(result, cluster->size()); 383 384 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count - 1)); 385 parser_->Reset(); 386 387 // Now parse a whole cluster to verify that all the blocks will get parsed. 388 result = parser_->Parse(cluster->data(), cluster->size()); 389 EXPECT_EQ(cluster->size(), result); 390 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count)); 391 } 392 393 TEST_F(WebMClusterParserTest, ParseClusterWithSingleCall) { 394 int block_count = arraysize(kDefaultBlockInfo); 395 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); 396 397 int result = parser_->Parse(cluster->data(), cluster->size()); 398 EXPECT_EQ(cluster->size(), result); 399 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count)); 400 } 401 402 TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) { 403 int block_count = arraysize(kDefaultBlockInfo); 404 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); 405 406 WebMClusterParser::BufferQueue audio_buffers; 407 WebMClusterParser::BufferQueue video_buffers; 408 const WebMClusterParser::BufferQueue no_text_buffers; 409 410 const uint8* data = cluster->data(); 411 int size = cluster->size(); 412 int default_parse_size = 3; 413 int parse_size = std::min(default_parse_size, size); 414 415 while (size > 0) { 416 int result = parser_->Parse(data, parse_size); 417 ASSERT_GE(result, 0); 418 ASSERT_LE(result, parse_size); 419 420 if (result == 0) { 421 // The parser needs more data so increase the parse_size a little. 422 parse_size += default_parse_size; 423 parse_size = std::min(parse_size, size); 424 continue; 425 } 426 427 AppendToEnd(parser_->GetAudioBuffers(), &audio_buffers); 428 AppendToEnd(parser_->GetVideoBuffers(), &video_buffers); 429 430 parse_size = default_parse_size; 431 432 data += result; 433 size -= result; 434 } 435 ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers, 436 no_text_buffers, kDefaultBlockInfo, 437 block_count)); 438 } 439 440 // Verify that both BlockGroups with the BlockDuration before the Block 441 // and BlockGroups with the BlockDuration after the Block are supported 442 // correctly. 443 // Note: Raw bytes are use here because ClusterBuilder only generates 444 // one of these scenarios. 445 TEST_F(WebMClusterParserTest, ParseBlockGroup) { 446 const BlockInfo kBlockInfo[] = { 447 { kAudioTrackNum, 0, 23, false }, 448 { kVideoTrackNum, 33, 34, false }, 449 }; 450 int block_count = arraysize(kBlockInfo); 451 452 const uint8 kClusterData[] = { 453 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27) 454 0xE7, 0x81, 0x00, // Timecode(size=1, value=0) 455 // BlockGroup with BlockDuration before Block. 456 0xA0, 0x8A, // BlockGroup(size=10) 457 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23) 458 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0) 459 // BlockGroup with BlockDuration after Block. 460 0xA0, 0x8A, // BlockGroup(size=10) 461 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33) 462 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34) 463 }; 464 const int kClusterSize = sizeof(kClusterData); 465 466 int result = parser_->Parse(kClusterData, kClusterSize); 467 EXPECT_EQ(kClusterSize, result); 468 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 469 } 470 471 TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) { 472 const BlockInfo kBlockInfo[] = { 473 { kAudioTrackNum, 0, 23, true }, 474 { kAudioTrackNum, 23, 23, false }, 475 { kVideoTrackNum, 33, 34, true }, 476 { kAudioTrackNum, 46, 23, false }, 477 { kVideoTrackNum, 67, 33, false }, 478 }; 479 int block_count = arraysize(kBlockInfo); 480 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 481 482 int result = parser_->Parse(cluster->data(), cluster->size()); 483 EXPECT_EQ(cluster->size(), result); 484 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 485 } 486 487 TEST_F(WebMClusterParserTest, IgnoredTracks) { 488 std::set<int64> ignored_tracks; 489 ignored_tracks.insert(kTextTrackNum); 490 491 parser_.reset(new WebMClusterParser(kTimecodeScale, 492 kAudioTrackNum, 493 kNoTimestamp(), 494 kVideoTrackNum, 495 kNoTimestamp(), 496 TextTracks(), 497 ignored_tracks, 498 std::string(), 499 std::string(), 500 LogCB())); 501 502 const BlockInfo kInputBlockInfo[] = { 503 { kAudioTrackNum, 0, 23, true }, 504 { kAudioTrackNum, 23, 23, true }, 505 { kVideoTrackNum, 33, 34, true }, 506 { kTextTrackNum, 33, 99, true }, 507 { kAudioTrackNum, 46, 23, true }, 508 { kVideoTrackNum, 67, 34, true }, 509 }; 510 int input_block_count = arraysize(kInputBlockInfo); 511 512 const BlockInfo kOutputBlockInfo[] = { 513 { kAudioTrackNum, 0, 23, true }, 514 { kAudioTrackNum, 23, 23, true }, 515 { kVideoTrackNum, 33, 34, true }, 516 { kAudioTrackNum, 46, 23, true }, 517 { kVideoTrackNum, 67, 34, true }, 518 }; 519 int output_block_count = arraysize(kOutputBlockInfo); 520 521 scoped_ptr<Cluster> cluster( 522 CreateCluster(0, kInputBlockInfo, input_block_count)); 523 524 int result = parser_->Parse(cluster->data(), cluster->size()); 525 EXPECT_EQ(cluster->size(), result); 526 ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count)); 527 } 528 529 TEST_F(WebMClusterParserTest, ParseTextTracks) { 530 TextTracks text_tracks; 531 532 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), 533 TextTrackConfig(kTextSubtitles, "", "", 534 ""))); 535 536 parser_.reset(new WebMClusterParser(kTimecodeScale, 537 kAudioTrackNum, 538 kNoTimestamp(), 539 kVideoTrackNum, 540 kNoTimestamp(), 541 text_tracks, 542 std::set<int64>(), 543 std::string(), 544 std::string(), 545 LogCB())); 546 547 const BlockInfo kInputBlockInfo[] = { 548 { kAudioTrackNum, 0, 23, true }, 549 { kAudioTrackNum, 23, 23, true }, 550 { kVideoTrackNum, 33, 34, true }, 551 { kTextTrackNum, 33, 42, false }, 552 { kAudioTrackNum, 46, 23, true }, 553 { kTextTrackNum, 55, 44, false }, 554 { kVideoTrackNum, 67, 34, true }, 555 }; 556 int input_block_count = arraysize(kInputBlockInfo); 557 558 scoped_ptr<Cluster> cluster( 559 CreateCluster(0, kInputBlockInfo, input_block_count)); 560 561 int result = parser_->Parse(cluster->data(), cluster->size()); 562 EXPECT_EQ(cluster->size(), result); 563 ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count)); 564 } 565 566 TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) { 567 TextTracks text_tracks; 568 569 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), 570 TextTrackConfig(kTextSubtitles, "", "", 571 ""))); 572 573 parser_.reset(new WebMClusterParser(kTimecodeScale, 574 kAudioTrackNum, 575 kNoTimestamp(), 576 kVideoTrackNum, 577 kNoTimestamp(), 578 text_tracks, 579 std::set<int64>(), 580 std::string(), 581 std::string(), 582 LogCB())); 583 584 const BlockInfo kInputBlockInfo[] = { 585 { kTextTrackNum, 33, 42, true }, 586 }; 587 int input_block_count = arraysize(kInputBlockInfo); 588 589 scoped_ptr<Cluster> cluster( 590 CreateCluster(0, kInputBlockInfo, input_block_count)); 591 592 int result = parser_->Parse(cluster->data(), cluster->size()); 593 EXPECT_LT(result, 0); 594 } 595 596 TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) { 597 TextTracks text_tracks; 598 599 const int kSubtitleTextTrackNum = kTextTrackNum; 600 const int kCaptionTextTrackNum = kTextTrackNum + 1; 601 602 text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum), 603 TextTrackConfig(kTextSubtitles, "", "", 604 ""))); 605 606 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum), 607 TextTrackConfig(kTextCaptions, "", "", 608 ""))); 609 610 parser_.reset(new WebMClusterParser(kTimecodeScale, 611 kAudioTrackNum, 612 kNoTimestamp(), 613 kVideoTrackNum, 614 kNoTimestamp(), 615 text_tracks, 616 std::set<int64>(), 617 std::string(), 618 std::string(), 619 LogCB())); 620 621 const BlockInfo kInputBlockInfo[] = { 622 { kAudioTrackNum, 0, 23, true }, 623 { kAudioTrackNum, 23, 23, true }, 624 { kVideoTrackNum, 33, 34, true }, 625 { kSubtitleTextTrackNum, 33, 42, false }, 626 { kAudioTrackNum, 46, 23, true }, 627 { kCaptionTextTrackNum, 55, 44, false }, 628 { kVideoTrackNum, 67, 34, true }, 629 { kSubtitleTextTrackNum, 67, 33, false }, 630 }; 631 int input_block_count = arraysize(kInputBlockInfo); 632 633 scoped_ptr<Cluster> cluster( 634 CreateCluster(0, kInputBlockInfo, input_block_count)); 635 636 int result = parser_->Parse(cluster->data(), cluster->size()); 637 EXPECT_EQ(cluster->size(), result); 638 639 const WebMClusterParser::TextBufferQueueMap& text_map = 640 parser_->GetTextBuffers(); 641 for (WebMClusterParser::TextBufferQueueMap::const_iterator itr = 642 text_map.begin(); 643 itr != text_map.end(); 644 ++itr) { 645 const TextTracks::const_iterator find_result = 646 text_tracks.find(itr->first); 647 ASSERT_TRUE(find_result != text_tracks.end()); 648 ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count, 649 itr->first, itr->second)); 650 } 651 } 652 653 TEST_F(WebMClusterParserTest, ParseEncryptedBlock) { 654 scoped_ptr<Cluster> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame))); 655 656 parser_.reset(new WebMClusterParser(kTimecodeScale, 657 kAudioTrackNum, 658 kNoTimestamp(), 659 kVideoTrackNum, 660 kNoTimestamp(), 661 TextTracks(), 662 std::set<int64>(), 663 std::string(), 664 "video_key_id", 665 LogCB())); 666 int result = parser_->Parse(cluster->data(), cluster->size()); 667 EXPECT_EQ(cluster->size(), result); 668 ASSERT_EQ(1UL, parser_->GetVideoBuffers().size()); 669 scoped_refptr<StreamParserBuffer> buffer = parser_->GetVideoBuffers()[0]; 670 VerifyEncryptedBuffer(buffer); 671 } 672 673 TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) { 674 scoped_ptr<Cluster> cluster( 675 CreateEncryptedCluster(sizeof(kEncryptedFrame) - 1)); 676 677 parser_.reset(new WebMClusterParser(kTimecodeScale, 678 kAudioTrackNum, 679 kNoTimestamp(), 680 kVideoTrackNum, 681 kNoTimestamp(), 682 TextTracks(), 683 std::set<int64>(), 684 std::string(), 685 "video_key_id", 686 LogCB())); 687 int result = parser_->Parse(cluster->data(), cluster->size()); 688 EXPECT_EQ(-1, result); 689 } 690 691 TEST_F(WebMClusterParserTest, ParseInvalidZeroSizedCluster) { 692 const uint8 kBuffer[] = { 693 0x1F, 0x43, 0xB6, 0x75, 0x80, // CLUSTER (size = 0) 694 }; 695 696 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); 697 } 698 699 TEST_F(WebMClusterParserTest, ParseInvalidUnknownButActuallyZeroSizedCluster) { 700 const uint8 kBuffer[] = { 701 0x1F, 0x43, 0xB6, 0x75, 0xFF, // CLUSTER (size = "unknown") 702 0x1F, 0x43, 0xB6, 0x75, 0x85, // CLUSTER (size = 5) 703 }; 704 705 EXPECT_EQ(-1, parser_->Parse(kBuffer, sizeof(kBuffer))); 706 } 707 708 TEST_F(WebMClusterParserTest, ParseInvalidTextBlockGroupWithoutDuration) { 709 // Text track frames must have explicitly specified BlockGroup BlockDurations. 710 TextTracks text_tracks; 711 712 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), 713 TextTrackConfig(kTextSubtitles, "", "", 714 ""))); 715 716 parser_.reset(new WebMClusterParser(kTimecodeScale, 717 kAudioTrackNum, 718 kNoTimestamp(), 719 kVideoTrackNum, 720 kNoTimestamp(), 721 text_tracks, 722 std::set<int64>(), 723 std::string(), 724 std::string(), 725 LogCB())); 726 727 const BlockInfo kBlockInfo[] = { 728 { kTextTrackNum, 33, -42, false }, 729 }; 730 int block_count = arraysize(kBlockInfo); 731 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 732 int result = parser_->Parse(cluster->data(), cluster->size()); 733 EXPECT_LT(result, 0); 734 } 735 736 TEST_F(WebMClusterParserTest, ParseWithDefaultDurationsSimpleBlocks) { 737 InSequence s; 738 ResetParserToHaveDefaultDurations(); 739 740 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23); 741 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33); 742 743 const BlockInfo kBlockInfo[] = { 744 { kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true }, 745 { kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true }, 746 { kVideoTrackNum, 33, kTestVideoFrameDefaultDurationInMs, true }, 747 { kAudioTrackNum, 46, kTestAudioFrameDefaultDurationInMs, true }, 748 { kVideoTrackNum, 67, kTestVideoFrameDefaultDurationInMs, true }, 749 { kAudioTrackNum, 69, kTestAudioFrameDefaultDurationInMs, true }, 750 { kVideoTrackNum, 100, kTestVideoFrameDefaultDurationInMs, true }, 751 }; 752 753 int block_count = arraysize(kBlockInfo); 754 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 755 756 // Send slightly less than the full cluster so all but the last block is 757 // parsed. Though all the blocks are simple blocks, none should be held aside 758 // for duration estimation prior to end of cluster detection because all the 759 // tracks have DefaultDurations. 760 int result = parser_->Parse(cluster->data(), cluster->size() - 1); 761 EXPECT_GT(result, 0); 762 EXPECT_LT(result, cluster->size()); 763 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1)); 764 765 parser_->Reset(); 766 767 // Now parse a whole cluster to verify that all the blocks will get parsed. 768 result = parser_->Parse(cluster->data(), cluster->size()); 769 EXPECT_EQ(cluster->size(), result); 770 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 771 } 772 773 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsSimpleBlocks) { 774 InSequence s; 775 776 // Absent DefaultDuration information, SimpleBlock durations are derived from 777 // inter-buffer track timestamp delta if within the cluster, and are estimated 778 // as the lowest non-zero duration seen so far if the last buffer in the track 779 // in the cluster (independently for each track in the cluster). 780 const BlockInfo kBlockInfo1[] = { 781 { kAudioTrackNum, 0, 23, true }, 782 { kAudioTrackNum, 23, 22, true }, 783 { kVideoTrackNum, 33, 33, true }, 784 { kAudioTrackNum, 45, 23, true }, 785 { kVideoTrackNum, 66, 34, true }, 786 { kAudioTrackNum, 68, 22, true }, // Estimated from minimum audio dur 787 { kVideoTrackNum, 100, 33, true }, // Estimated from minimum video dur 788 }; 789 790 int block_count1 = arraysize(kBlockInfo1); 791 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1)); 792 793 // Send slightly less than the first full cluster so all but the last video 794 // block is parsed. Verify the last fully parsed audio and video buffer are 795 // both missing from the result (parser should hold them aside for duration 796 // estimation prior to end of cluster detection in the absence of 797 // DefaultDurations.) 798 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1); 799 EXPECT_GT(result, 0); 800 EXPECT_LT(result, cluster1->size()); 801 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3)); 802 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size()); 803 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size()); 804 805 parser_->Reset(); 806 807 // Now parse the full first cluster and verify all the blocks are parsed. 808 result = parser_->Parse(cluster1->data(), cluster1->size()); 809 EXPECT_EQ(cluster1->size(), result); 810 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1)); 811 812 // Verify that the estimated frame duration is tracked across clusters for 813 // each track. 814 const BlockInfo kBlockInfo2[] = { 815 { kAudioTrackNum, 200, 22, true }, // Estimate carries over across clusters 816 { kVideoTrackNum, 201, 33, true }, // Estimate carries over across clusters 817 }; 818 819 int block_count2 = arraysize(kBlockInfo2); 820 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2)); 821 result = parser_->Parse(cluster2->data(), cluster2->size()); 822 EXPECT_EQ(cluster2->size(), result); 823 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2)); 824 } 825 826 TEST_F(WebMClusterParserTest, ParseWithoutAnyDurationsBlockGroups) { 827 InSequence s; 828 829 // Absent DefaultDuration and BlockDuration information, BlockGroup block 830 // durations are derived from inter-buffer track timestamp delta if within the 831 // cluster, and are estimated as the lowest non-zero duration seen so far if 832 // the last buffer in the track in the cluster (independently for each track 833 // in the cluster). 834 const BlockInfo kBlockInfo1[] = { 835 { kAudioTrackNum, 0, -23, false }, 836 { kAudioTrackNum, 23, -22, false }, 837 { kVideoTrackNum, 33, -33, false }, 838 { kAudioTrackNum, 45, -23, false }, 839 { kVideoTrackNum, 66, -34, false }, 840 { kAudioTrackNum, 68, -22, false }, // Estimated from minimum audio dur 841 { kVideoTrackNum, 100, -33, false }, // Estimated from minimum video dur 842 }; 843 844 int block_count1 = arraysize(kBlockInfo1); 845 scoped_ptr<Cluster> cluster1(CreateCluster(0, kBlockInfo1, block_count1)); 846 847 // Send slightly less than the first full cluster so all but the last video 848 // block is parsed. Verify the last fully parsed audio and video buffer are 849 // both missing from the result (parser should hold them aside for duration 850 // estimation prior to end of cluster detection in the absence of 851 // DefaultDurations.) 852 int result = parser_->Parse(cluster1->data(), cluster1->size() - 1); 853 EXPECT_GT(result, 0); 854 EXPECT_LT(result, cluster1->size()); 855 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1 - 3)); 856 EXPECT_EQ(3UL, parser_->GetAudioBuffers().size()); 857 EXPECT_EQ(1UL, parser_->GetVideoBuffers().size()); 858 859 parser_->Reset(); 860 861 // Now parse the full first cluster and verify all the blocks are parsed. 862 result = parser_->Parse(cluster1->data(), cluster1->size()); 863 EXPECT_EQ(cluster1->size(), result); 864 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo1, block_count1)); 865 866 // Verify that the estimated frame duration is tracked across clusters for 867 // each track. 868 const BlockInfo kBlockInfo2[] = { 869 { kAudioTrackNum, 200, -22, false }, 870 { kVideoTrackNum, 201, -33, false }, 871 }; 872 873 int block_count2 = arraysize(kBlockInfo2); 874 scoped_ptr<Cluster> cluster2(CreateCluster(0, kBlockInfo2, block_count2)); 875 result = parser_->Parse(cluster2->data(), cluster2->size()); 876 EXPECT_EQ(cluster2->size(), result); 877 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo2, block_count2)); 878 } 879 880 // TODO(wolenetz): Is parser behavior correct? See http://crbug.com/363433. 881 TEST_F(WebMClusterParserTest, 882 ParseWithDefaultDurationsBlockGroupsWithoutDurations) { 883 InSequence s; 884 ResetParserToHaveDefaultDurations(); 885 886 EXPECT_LT(kTestAudioFrameDefaultDurationInMs, 23); 887 EXPECT_LT(kTestVideoFrameDefaultDurationInMs, 33); 888 889 const BlockInfo kBlockInfo[] = { 890 { kAudioTrackNum, 0, -kTestAudioFrameDefaultDurationInMs, false }, 891 { kAudioTrackNum, 23, -kTestAudioFrameDefaultDurationInMs, false }, 892 { kVideoTrackNum, 33, -kTestVideoFrameDefaultDurationInMs, false }, 893 { kAudioTrackNum, 46, -kTestAudioFrameDefaultDurationInMs, false }, 894 { kVideoTrackNum, 67, -kTestVideoFrameDefaultDurationInMs, false }, 895 { kAudioTrackNum, 69, -kTestAudioFrameDefaultDurationInMs, false }, 896 { kVideoTrackNum, 100, -kTestVideoFrameDefaultDurationInMs, false }, 897 }; 898 899 int block_count = arraysize(kBlockInfo); 900 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 901 902 // Send slightly less than the full cluster so all but the last block is 903 // parsed. None should be held aside for duration estimation prior to end of 904 // cluster detection because all the tracks have DefaultDurations. 905 int result = parser_->Parse(cluster->data(), cluster->size() - 1); 906 EXPECT_GT(result, 0); 907 EXPECT_LT(result, cluster->size()); 908 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count - 1)); 909 910 parser_->Reset(); 911 912 // Now parse a whole cluster to verify that all the blocks will get parsed. 913 result = parser_->Parse(cluster->data(), cluster->size()); 914 EXPECT_EQ(cluster->size(), result); 915 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 916 } 917 918 TEST_F(WebMClusterParserTest, 919 ParseDegenerateClusterYieldsHardcodedEstimatedDurations) { 920 const BlockInfo kBlockInfo[] = { 921 { 922 kAudioTrackNum, 923 0, 924 WebMClusterParser::kDefaultAudioBufferDurationInMs, 925 true 926 }, { 927 kVideoTrackNum, 928 0, 929 WebMClusterParser::kDefaultVideoBufferDurationInMs, 930 true 931 }, 932 }; 933 934 int block_count = arraysize(kBlockInfo); 935 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 936 int result = parser_->Parse(cluster->data(), cluster->size()); 937 EXPECT_EQ(cluster->size(), result); 938 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 939 } 940 941 TEST_F(WebMClusterParserTest, 942 ParseDegenerateClusterWithDefaultDurationsYieldsDefaultDurations) { 943 ResetParserToHaveDefaultDurations(); 944 945 const BlockInfo kBlockInfo[] = { 946 { kAudioTrackNum, 0, kTestAudioFrameDefaultDurationInMs, true }, 947 { kVideoTrackNum, 0, kTestVideoFrameDefaultDurationInMs, true }, 948 }; 949 950 int block_count = arraysize(kBlockInfo); 951 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); 952 int result = parser_->Parse(cluster->data(), cluster->size()); 953 EXPECT_EQ(cluster->size(), result); 954 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); 955 } 956 957 } // namespace media 958