Home | History | Annotate | Download | only in webm
      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