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.
7 #include "base/logging.h"
8 #include "media/webm/cluster_builder.h"
9 #include "media/webm/webm_cluster_parser.h"
10 #include "media/webm/webm_constants.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using ::testing::InSequence
;
15 using ::testing::Return
;
21 kTimecodeScale
= 1000000, // Timecode scale for millisecond timestamps.
30 bool use_simple_block
;
33 const BlockInfo kDefaultBlockInfo
[] = {
34 { kAudioTrackNum
, 0, 23, true },
35 { kAudioTrackNum
, 23, 23, true },
36 { kVideoTrackNum
, 33, 34, true },
37 { kAudioTrackNum
, 46, 23, true },
38 { kVideoTrackNum
, 67, 33, false },
39 { kAudioTrackNum
, 69, 23, false },
40 { kVideoTrackNum
, 100, 33, false },
43 static scoped_ptr
<Cluster
> CreateCluster(int timecode
,
44 const BlockInfo
* block_info
,
47 cb
.SetClusterTimecode(0);
49 for (int i
= 0; i
< block_count
; i
++) {
50 uint8 data
[] = { 0x00 };
51 if (block_info
[i
].use_simple_block
) {
52 cb
.AddSimpleBlock(block_info
[i
].track_num
,
53 block_info
[i
].timestamp
,
54 0, data
, sizeof(data
));
58 CHECK_GE(block_info
[i
].duration
, 0);
59 cb
.AddBlockGroup(block_info
[i
].track_num
,
60 block_info
[i
].timestamp
,
61 block_info
[i
].duration
,
62 0, data
, sizeof(data
));
68 static bool VerifyBuffers(const WebMClusterParser::BufferQueue
& audio_buffers
,
69 const WebMClusterParser::BufferQueue
& video_buffers
,
70 const BlockInfo
* block_info
,
72 size_t audio_offset
= 0;
73 size_t video_offset
= 0;
74 for (int i
= 0; i
< block_count
; i
++) {
75 const WebMClusterParser::BufferQueue
* buffers
= NULL
;
78 if (block_info
[i
].track_num
== kAudioTrackNum
) {
79 buffers
= &audio_buffers
;
80 offset
= &audio_offset
;
81 } else if (block_info
[i
].track_num
== kVideoTrackNum
) {
82 buffers
= &video_buffers
;
83 offset
= &video_offset
;
85 LOG(ERROR
) << "Unexpected track number " << block_info
[i
].track_num
;
89 if (*offset
>= buffers
->size())
92 scoped_refptr
<StreamParserBuffer
> buffer
= (*buffers
)[(*offset
)++];
95 EXPECT_EQ(buffer
->GetTimestamp().InMilliseconds(), block_info
[i
].timestamp
);
97 if (!block_info
[i
].use_simple_block
)
98 EXPECT_NE(buffer
->GetDuration(), kNoTimestamp());
100 if (buffer
->GetDuration() != kNoTimestamp())
101 EXPECT_EQ(buffer
->GetDuration().InMilliseconds(), block_info
[i
].duration
);
107 static bool VerifyBuffers(const scoped_ptr
<WebMClusterParser
>& parser
,
108 const BlockInfo
* block_info
,
110 return VerifyBuffers(parser
->audio_buffers(),
111 parser
->video_buffers(),
116 static void AppendToEnd(const WebMClusterParser::BufferQueue
& src
,
117 WebMClusterParser::BufferQueue
* dest
) {
118 for (WebMClusterParser::BufferQueue::const_iterator itr
= src
.begin();
119 itr
!= src
.end(); ++itr
) {
120 dest
->push_back(*itr
);
124 class WebMClusterParserTest
: public testing::Test
{
126 WebMClusterParserTest()
127 : parser_(new WebMClusterParser(kTimecodeScale
,
128 kAudioTrackNum
, kVideoTrackNum
,
133 scoped_ptr
<WebMClusterParser
> parser_
;
136 TEST_F(WebMClusterParserTest
, TestReset
) {
139 int block_count
= arraysize(kDefaultBlockInfo
);
140 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
142 // Send slightly less than the full cluster so all but the last block is
144 int result
= parser_
->Parse(cluster
->data(), cluster
->size() - 1);
145 EXPECT_GT(result
, 0);
146 EXPECT_LT(result
, cluster
->size());
148 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
- 1));
151 // Now parse a whole cluster to verify that all the blocks will get parsed.
152 result
= parser_
->Parse(cluster
->data(), cluster
->size());
153 EXPECT_EQ(result
, cluster
->size());
154 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
157 TEST_F(WebMClusterParserTest
, ParseClusterWithSingleCall
) {
158 int block_count
= arraysize(kDefaultBlockInfo
);
159 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
161 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
162 EXPECT_EQ(cluster
->size(), result
);
163 ASSERT_TRUE(VerifyBuffers(parser_
, kDefaultBlockInfo
, block_count
));
166 TEST_F(WebMClusterParserTest
, ParseClusterWithMultipleCalls
) {
167 int block_count
= arraysize(kDefaultBlockInfo
);
168 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kDefaultBlockInfo
, block_count
));
170 WebMClusterParser::BufferQueue audio_buffers
;
171 WebMClusterParser::BufferQueue video_buffers
;
173 const uint8
* data
= cluster
->data();
174 int size
= cluster
->size();
175 int default_parse_size
= 3;
176 int parse_size
= std::min(default_parse_size
, size
);
179 int result
= parser_
->Parse(data
, parse_size
);
180 ASSERT_GE(result
, 0);
181 ASSERT_LE(result
, parse_size
);
184 // The parser needs more data so increase the parse_size a little.
185 parse_size
+= default_parse_size
;
186 parse_size
= std::min(parse_size
, size
);
190 AppendToEnd(parser_
->audio_buffers(), &audio_buffers
);
191 AppendToEnd(parser_
->video_buffers(), &video_buffers
);
193 parse_size
= default_parse_size
;
198 ASSERT_TRUE(VerifyBuffers(audio_buffers
, video_buffers
, kDefaultBlockInfo
,
202 // Verify that both BlockGroups with the BlockDuration before the Block
203 // and BlockGroups with the BlockDuration after the Block are supported
205 // Note: Raw bytes are use here because ClusterBuilder only generates
206 // one of these scenarios.
207 TEST_F(WebMClusterParserTest
, ParseBlockGroup
) {
208 const BlockInfo kBlockInfo
[] = {
209 { kAudioTrackNum
, 0, 23, false },
210 { kVideoTrackNum
, 33, 34, false },
212 int block_count
= arraysize(kBlockInfo
);
214 const uint8 kClusterData
[] = {
215 0x1F, 0x43, 0xB6, 0x75, 0x9B, // Cluster(size=27)
216 0xE7, 0x81, 0x00, // Timecode(size=1, value=0)
217 // BlockGroup with BlockDuration before Block.
218 0xA0, 0x8A, // BlockGroup(size=10)
219 0x9B, 0x81, 0x17, // BlockDuration(size=1, value=23)
220 0xA1, 0x85, 0x81, 0x00, 0x00, 0x00, 0xaa, // Block(size=5, track=1, ts=0)
221 // BlockGroup with BlockDuration after Block.
222 0xA0, 0x8A, // BlockGroup(size=10)
223 0xA1, 0x85, 0x82, 0x00, 0x21, 0x00, 0x55, // Block(size=5, track=2, ts=33)
224 0x9B, 0x81, 0x22, // BlockDuration(size=1, value=34)
226 const int kClusterSize
= sizeof(kClusterData
);
228 int result
= parser_
->Parse(kClusterData
, kClusterSize
);
229 EXPECT_EQ(result
, kClusterSize
);
230 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));
233 TEST_F(WebMClusterParserTest
, ParseSimpleBlockAndBlockGroupMixture
) {
234 const BlockInfo kBlockInfo
[] = {
235 { kAudioTrackNum
, 0, 23, true },
236 { kAudioTrackNum
, 23, 23, false },
237 { kVideoTrackNum
, 33, 34, true },
238 { kAudioTrackNum
, 46, 23, false },
239 { kVideoTrackNum
, 67, 33, false },
241 int block_count
= arraysize(kBlockInfo
);
242 scoped_ptr
<Cluster
> cluster(CreateCluster(0, kBlockInfo
, block_count
));
244 int result
= parser_
->Parse(cluster
->data(), cluster
->size());
245 EXPECT_EQ(cluster
->size(), result
);
246 ASSERT_TRUE(VerifyBuffers(parser_
, kBlockInfo
, block_count
));