Revert 224458 "Enabling MediaStreamInfoBarTest.DenyingCameraDoes..."
[chromium-blink-merge.git] / media / webm / webm_cluster_parser_unittest.cc
blob5c5837fa8660e3e61baf57df95da3da1081767f6
1 // Copyright (c) 2012 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.
5 #include <algorithm>
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "media/base/decrypt_config.h"
10 #include "media/webm/cluster_builder.h"
11 #include "media/webm/webm_cluster_parser.h"
12 #include "media/webm/webm_constants.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using ::testing::InSequence;
17 using ::testing::Return;
18 using ::testing::_;
20 namespace media {
22 enum {
23 kTimecodeScale = 1000000, // Timecode scale for millisecond timestamps.
24 kAudioTrackNum = 1,
25 kVideoTrackNum = 2,
26 kTextTrackNum = 3,
29 struct BlockInfo {
30 int track_num;
31 int timestamp;
32 int duration;
33 bool use_simple_block;
36 static const BlockInfo kDefaultBlockInfo[] = {
37 { kAudioTrackNum, 0, 23, true },
38 { kAudioTrackNum, 23, 23, true },
39 { kVideoTrackNum, 33, 34, true },
40 { kAudioTrackNum, 46, 23, true },
41 { kVideoTrackNum, 67, 33, false },
42 { kAudioTrackNum, 69, 23, false },
43 { kVideoTrackNum, 100, 33, false },
46 static const uint8 kEncryptedFrame[] = {
47 0x01, // Block is encrypted
48 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 // IV
51 static scoped_ptr<Cluster> CreateCluster(int timecode,
52 const BlockInfo* block_info,
53 int block_count) {
54 ClusterBuilder cb;
55 cb.SetClusterTimecode(0);
57 for (int i = 0; i < block_count; i++) {
58 uint8 data[] = { 0x00 };
59 if (block_info[i].use_simple_block) {
60 cb.AddSimpleBlock(block_info[i].track_num,
61 block_info[i].timestamp,
62 0, data, sizeof(data));
63 continue;
66 CHECK_GE(block_info[i].duration, 0);
67 cb.AddBlockGroup(block_info[i].track_num,
68 block_info[i].timestamp,
69 block_info[i].duration,
70 0, data, sizeof(data));
73 return cb.Finish();
76 // Creates a Cluster with one encrypted Block. |bytes_to_write| is number of
77 // bytes of the encrypted frame to write.
78 static scoped_ptr<Cluster> CreateEncryptedCluster(int bytes_to_write) {
79 CHECK_GT(bytes_to_write, 0);
80 CHECK_LE(bytes_to_write, static_cast<int>(sizeof(kEncryptedFrame)));
82 ClusterBuilder cb;
83 cb.SetClusterTimecode(0);
84 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write);
85 return cb.Finish();
88 static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers,
89 const WebMClusterParser::BufferQueue& video_buffers,
90 const WebMClusterParser::BufferQueue& text_buffers,
91 const BlockInfo* block_info,
92 int block_count) {
93 size_t audio_offset = 0;
94 size_t video_offset = 0;
95 size_t text_offset = 0;
96 for (int i = 0; i < block_count; i++) {
97 const WebMClusterParser::BufferQueue* buffers = NULL;
98 size_t* offset;
100 if (block_info[i].track_num == kAudioTrackNum) {
101 buffers = &audio_buffers;
102 offset = &audio_offset;
103 } else if (block_info[i].track_num == kVideoTrackNum) {
104 buffers = &video_buffers;
105 offset = &video_offset;
106 } else if (block_info[i].track_num == kTextTrackNum) {
107 buffers = &text_buffers;
108 offset = &text_offset;
109 } else {
110 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num;
111 return false;
114 if (*offset >= buffers->size())
115 return false;
117 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++];
120 EXPECT_EQ(buffer->timestamp().InMilliseconds(), block_info[i].timestamp);
122 if (!block_info[i].use_simple_block)
123 EXPECT_NE(buffer->duration(), kNoTimestamp());
125 if (buffer->duration() != kNoTimestamp())
126 EXPECT_EQ(buffer->duration().InMilliseconds(), block_info[i].duration);
129 return true;
132 static bool VerifyBuffers(const scoped_ptr<WebMClusterParser>& parser,
133 const BlockInfo* block_info,
134 int block_count) {
135 typedef WebMClusterParser::TextTrackIterator TextTrackIterator;
136 TextTrackIterator text_it = parser->CreateTextTrackIterator();
138 int text_track_num;
139 const WebMClusterParser::BufferQueue* text_buffers;
141 while (text_it(&text_track_num, &text_buffers))
142 break;
144 const WebMClusterParser::BufferQueue no_text_buffers;
146 if (text_buffers == NULL)
147 text_buffers = &no_text_buffers;
149 return VerifyBuffers(parser->audio_buffers(),
150 parser->video_buffers(),
151 *text_buffers,
152 block_info,
153 block_count);
156 static bool VerifyTextBuffers(
157 const scoped_ptr<WebMClusterParser>& parser,
158 const BlockInfo* block_info_ptr,
159 int block_count,
160 int text_track_num,
161 const WebMClusterParser::BufferQueue& text_buffers) {
162 const BlockInfo* const block_info_end = block_info_ptr + block_count;
164 typedef WebMClusterParser::BufferQueue::const_iterator TextBufferIter;
165 TextBufferIter buffer_iter = text_buffers.begin();
166 const TextBufferIter buffer_end = text_buffers.end();
168 while (block_info_ptr != block_info_end) {
169 const BlockInfo& block_info = *block_info_ptr++;
171 if (block_info.track_num != text_track_num)
172 continue;
174 EXPECT_FALSE(block_info.use_simple_block);
175 EXPECT_FALSE(buffer_iter == buffer_end);
177 const scoped_refptr<StreamParserBuffer> buffer = *buffer_iter++;
178 EXPECT_EQ(buffer->timestamp().InMilliseconds(), block_info.timestamp);
179 EXPECT_EQ(buffer->duration().InMilliseconds(), block_info.duration);
182 EXPECT_TRUE(buffer_iter == buffer_end);
183 return true;
186 static bool VerifyEncryptedBuffer(
187 scoped_refptr<StreamParserBuffer> buffer) {
188 EXPECT_TRUE(buffer->decrypt_config());
189 EXPECT_EQ(static_cast<unsigned long>(DecryptConfig::kDecryptionKeySize),
190 buffer->decrypt_config()->iv().length());
191 const uint8* data = buffer->data();
192 return data[0] & kWebMFlagEncryptedFrame;
195 static void AppendToEnd(const WebMClusterParser::BufferQueue& src,
196 WebMClusterParser::BufferQueue* dest) {
197 for (WebMClusterParser::BufferQueue::const_iterator itr = src.begin();
198 itr != src.end(); ++itr) {
199 dest->push_back(*itr);
203 class WebMClusterParserTest : public testing::Test {
204 public:
205 WebMClusterParserTest()
206 : parser_(new WebMClusterParser(kTimecodeScale,
207 kAudioTrackNum,
208 kVideoTrackNum,
209 WebMTracksParser::TextTracks(),
210 std::set<int64>(),
211 std::string(),
212 std::string(),
213 LogCB())) {}
215 protected:
216 scoped_ptr<WebMClusterParser> parser_;
219 TEST_F(WebMClusterParserTest, Reset) {
220 InSequence s;
222 int block_count = arraysize(kDefaultBlockInfo);
223 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
225 // Send slightly less than the full cluster so all but the last block is
226 // parsed.
227 int result = parser_->Parse(cluster->data(), cluster->size() - 1);
228 EXPECT_GT(result, 0);
229 EXPECT_LT(result, cluster->size());
231 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count - 1));
232 parser_->Reset();
234 // Now parse a whole cluster to verify that all the blocks will get parsed.
235 result = parser_->Parse(cluster->data(), cluster->size());
236 EXPECT_EQ(result, cluster->size());
237 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
240 TEST_F(WebMClusterParserTest, ParseClusterWithSingleCall) {
241 int block_count = arraysize(kDefaultBlockInfo);
242 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
244 int result = parser_->Parse(cluster->data(), cluster->size());
245 EXPECT_EQ(cluster->size(), result);
246 ASSERT_TRUE(VerifyBuffers(parser_, kDefaultBlockInfo, block_count));
249 TEST_F(WebMClusterParserTest, ParseClusterWithMultipleCalls) {
250 int block_count = arraysize(kDefaultBlockInfo);
251 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count));
253 WebMClusterParser::BufferQueue audio_buffers;
254 WebMClusterParser::BufferQueue video_buffers;
255 const WebMClusterParser::BufferQueue no_text_buffers;
257 const uint8* data = cluster->data();
258 int size = cluster->size();
259 int default_parse_size = 3;
260 int parse_size = std::min(default_parse_size, size);
262 while (size > 0) {
263 int result = parser_->Parse(data, parse_size);
264 ASSERT_GE(result, 0);
265 ASSERT_LE(result, parse_size);
267 if (result == 0) {
268 // The parser needs more data so increase the parse_size a little.
269 parse_size += default_parse_size;
270 parse_size = std::min(parse_size, size);
271 continue;
274 AppendToEnd(parser_->audio_buffers(), &audio_buffers);
275 AppendToEnd(parser_->video_buffers(), &video_buffers);
277 parse_size = default_parse_size;
279 data += result;
280 size -= result;
282 ASSERT_TRUE(VerifyBuffers(audio_buffers, video_buffers,
283 no_text_buffers, kDefaultBlockInfo,
284 block_count));
287 // Verify that both BlockGroups with the BlockDuration before the Block
288 // and BlockGroups with the BlockDuration after the Block are supported
289 // correctly.
290 // Note: Raw bytes are use here because ClusterBuilder only generates
291 // one of these scenarios.
292 TEST_F(WebMClusterParserTest, ParseBlockGroup) {
293 const BlockInfo kBlockInfo[] = {
294 { kAudioTrackNum, 0, 23, false },
295 { kVideoTrackNum, 33, 34, false },
297 int block_count = arraysize(kBlockInfo);
299 const uint8 kClusterData[] = {
300 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
301 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
302 // BlockGroup with BlockDuration before Block.
303 0xA0, 0x8A, // BlockGroup(size=10)
304 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
305 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
306 // BlockGroup with BlockDuration after Block.
307 0xA0, 0x8A, // BlockGroup(size=10)
308 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
309 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
311 const int kClusterSize = sizeof(kClusterData);
313 int result = parser_->Parse(kClusterData, kClusterSize);
314 EXPECT_EQ(result, kClusterSize);
315 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
318 TEST_F(WebMClusterParserTest, ParseSimpleBlockAndBlockGroupMixture) {
319 const BlockInfo kBlockInfo[] = {
320 { kAudioTrackNum, 0, 23, true },
321 { kAudioTrackNum, 23, 23, false },
322 { kVideoTrackNum, 33, 34, true },
323 { kAudioTrackNum, 46, 23, false },
324 { kVideoTrackNum, 67, 33, false },
326 int block_count = arraysize(kBlockInfo);
327 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count));
329 int result = parser_->Parse(cluster->data(), cluster->size());
330 EXPECT_EQ(cluster->size(), result);
331 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count));
334 TEST_F(WebMClusterParserTest, IgnoredTracks) {
335 std::set<int64> ignored_tracks;
336 ignored_tracks.insert(kTextTrackNum);
338 parser_.reset(new WebMClusterParser(kTimecodeScale,
339 kAudioTrackNum,
340 kVideoTrackNum,
341 WebMTracksParser::TextTracks(),
342 ignored_tracks,
343 std::string(),
344 std::string(),
345 LogCB()));
347 const BlockInfo kInputBlockInfo[] = {
348 { kAudioTrackNum, 0, 23, true },
349 { kAudioTrackNum, 23, 23, true },
350 { kVideoTrackNum, 33, 33, true },
351 { kTextTrackNum, 33, 99, true },
352 { kAudioTrackNum, 46, 23, true },
353 { kVideoTrackNum, 67, 33, true },
355 int input_block_count = arraysize(kInputBlockInfo);
357 const BlockInfo kOutputBlockInfo[] = {
358 { kAudioTrackNum, 0, 23, true },
359 { kAudioTrackNum, 23, 23, true },
360 { kVideoTrackNum, 33, 33, true },
361 { kAudioTrackNum, 46, 23, true },
362 { kVideoTrackNum, 67, 33, true },
364 int output_block_count = arraysize(kOutputBlockInfo);
366 scoped_ptr<Cluster> cluster(
367 CreateCluster(0, kInputBlockInfo, input_block_count));
369 int result = parser_->Parse(cluster->data(), cluster->size());
370 EXPECT_EQ(cluster->size(), result);
371 ASSERT_TRUE(VerifyBuffers(parser_, kOutputBlockInfo, output_block_count));
374 TEST_F(WebMClusterParserTest, ParseTextTracks) {
375 typedef WebMTracksParser::TextTracks TextTracks;
376 TextTracks text_tracks;
377 WebMTracksParser::TextTrackInfo text_track_info;
379 text_track_info.kind = kTextSubtitles;
380 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
381 text_track_info));
383 parser_.reset(new WebMClusterParser(kTimecodeScale,
384 kAudioTrackNum,
385 kVideoTrackNum,
386 text_tracks,
387 std::set<int64>(),
388 std::string(),
389 std::string(),
390 LogCB()));
392 const BlockInfo kInputBlockInfo[] = {
393 { kAudioTrackNum, 0, 23, true },
394 { kAudioTrackNum, 23, 23, true },
395 { kVideoTrackNum, 33, 33, true },
396 { kTextTrackNum, 33, 42, false },
397 { kAudioTrackNum, 46, 23, true },
398 { kTextTrackNum, 55, 44, false },
399 { kVideoTrackNum, 67, 33, true },
401 int input_block_count = arraysize(kInputBlockInfo);
403 scoped_ptr<Cluster> cluster(
404 CreateCluster(0, kInputBlockInfo, input_block_count));
406 int result = parser_->Parse(cluster->data(), cluster->size());
407 EXPECT_EQ(cluster->size(), result);
408 ASSERT_TRUE(VerifyBuffers(parser_, kInputBlockInfo, input_block_count));
411 TEST_F(WebMClusterParserTest, TextTracksSimpleBlock) {
412 typedef WebMTracksParser::TextTracks TextTracks;
413 TextTracks text_tracks;
414 WebMTracksParser::TextTrackInfo text_track_info;
416 text_track_info.kind = kTextSubtitles;
417 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum),
418 text_track_info));
420 parser_.reset(new WebMClusterParser(kTimecodeScale,
421 kAudioTrackNum,
422 kVideoTrackNum,
423 text_tracks,
424 std::set<int64>(),
425 std::string(),
426 std::string(),
427 LogCB()));
429 const BlockInfo kInputBlockInfo[] = {
430 { kTextTrackNum, 33, 42, true },
432 int input_block_count = arraysize(kInputBlockInfo);
434 scoped_ptr<Cluster> cluster(
435 CreateCluster(0, kInputBlockInfo, input_block_count));
437 int result = parser_->Parse(cluster->data(), cluster->size());
438 EXPECT_LT(result, 0);
441 TEST_F(WebMClusterParserTest, ParseMultipleTextTracks) {
442 typedef WebMTracksParser::TextTracks TextTracks;
443 TextTracks text_tracks;
444 WebMTracksParser::TextTrackInfo text_track_info;
446 const int kSubtitleTextTrackNum = kTextTrackNum;
447 const int kCaptionTextTrackNum = kTextTrackNum + 1;
449 text_track_info.kind = kTextSubtitles;
450 text_tracks.insert(std::make_pair(TextTracks::key_type(kSubtitleTextTrackNum),
451 text_track_info));
453 text_track_info.kind = kTextCaptions;
454 text_tracks.insert(std::make_pair(TextTracks::key_type(kCaptionTextTrackNum),
455 text_track_info));
457 parser_.reset(new WebMClusterParser(kTimecodeScale,
458 kAudioTrackNum,
459 kVideoTrackNum,
460 text_tracks,
461 std::set<int64>(),
462 std::string(),
463 std::string(),
464 LogCB()));
466 const BlockInfo kInputBlockInfo[] = {
467 { kAudioTrackNum, 0, 23, true },
468 { kAudioTrackNum, 23, 23, true },
469 { kVideoTrackNum, 33, 33, true },
470 { kSubtitleTextTrackNum, 33, 42, false },
471 { kAudioTrackNum, 46, 23, true },
472 { kCaptionTextTrackNum, 55, 44, false },
473 { kVideoTrackNum, 67, 33, true },
474 { kSubtitleTextTrackNum, 67, 33, false },
476 int input_block_count = arraysize(kInputBlockInfo);
478 scoped_ptr<Cluster> cluster(
479 CreateCluster(0, kInputBlockInfo, input_block_count));
481 int result = parser_->Parse(cluster->data(), cluster->size());
482 EXPECT_EQ(cluster->size(), result);
484 WebMClusterParser::TextTrackIterator text_it =
485 parser_->CreateTextTrackIterator();
487 int text_track_num;
488 const WebMClusterParser::BufferQueue* text_buffers;
490 while (text_it(&text_track_num, &text_buffers)) {
491 const WebMTracksParser::TextTracks::const_iterator find_result =
492 text_tracks.find(text_track_num);
493 ASSERT_TRUE(find_result != text_tracks.end());
494 ASSERT_TRUE(VerifyTextBuffers(parser_, kInputBlockInfo, input_block_count,
495 text_track_num, *text_buffers));
499 TEST_F(WebMClusterParserTest, ParseEncryptedBlock) {
500 scoped_ptr<Cluster> cluster(CreateEncryptedCluster(sizeof(kEncryptedFrame)));
502 parser_.reset(new WebMClusterParser(kTimecodeScale,
503 kAudioTrackNum,
504 kVideoTrackNum,
505 WebMTracksParser::TextTracks(),
506 std::set<int64>(),
507 std::string(),
508 "video_key_id",
509 LogCB()));
510 int result = parser_->Parse(cluster->data(), cluster->size());
511 EXPECT_EQ(cluster->size(), result);
512 ASSERT_EQ(1UL, parser_->video_buffers().size());
513 scoped_refptr<StreamParserBuffer> buffer = parser_->video_buffers()[0];
514 EXPECT_TRUE(VerifyEncryptedBuffer(buffer));
517 TEST_F(WebMClusterParserTest, ParseBadEncryptedBlock) {
518 scoped_ptr<Cluster> cluster(
519 CreateEncryptedCluster(sizeof(kEncryptedFrame) - 1));
521 parser_.reset(new WebMClusterParser(kTimecodeScale,
522 kAudioTrackNum,
523 kVideoTrackNum,
524 WebMTracksParser::TextTracks(),
525 std::set<int64>(),
526 std::string(),
527 "video_key_id",
528 LogCB()));
529 int result = parser_->Parse(cluster->data(), cluster->size());
530 EXPECT_EQ(-1, result);
533 } // namespace media