OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <algorithm> | 5 #include <algorithm> |
6 #include <cstdlib> | 6 #include <cstdlib> |
7 | 7 |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "media/base/decrypt_config.h" | 10 #include "media/base/decrypt_config.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 cb.SetClusterTimecode(0); | 110 cb.SetClusterTimecode(0); |
111 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write); | 111 cb.AddSimpleBlock(kVideoTrackNum, 0, 0, kEncryptedFrame, bytes_to_write); |
112 return cb.Finish(); | 112 return cb.Finish(); |
113 } | 113 } |
114 | 114 |
115 static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, | 115 static bool VerifyBuffers(const WebMClusterParser::BufferQueue& audio_buffers, |
116 const WebMClusterParser::BufferQueue& video_buffers, | 116 const WebMClusterParser::BufferQueue& video_buffers, |
117 const WebMClusterParser::BufferQueue& text_buffers, | 117 const WebMClusterParser::BufferQueue& text_buffers, |
118 const BlockInfo* block_info, | 118 const BlockInfo* block_info, |
119 int block_count) { | 119 int block_count) { |
120 int buffer_count = audio_buffers.size() + video_buffers.size() + | |
121 text_buffers.size(); | |
122 EXPECT_EQ(block_count, buffer_count); | |
acolwell GONE FROM CHROMIUM
2014/04/23 22:36:39
nit: put this in a DVLOG below since this conditio
wolenetz
2014/04/25 20:04:21
Done.
| |
123 if (block_count != buffer_count) | |
124 return false; | |
125 | |
120 size_t audio_offset = 0; | 126 size_t audio_offset = 0; |
121 size_t video_offset = 0; | 127 size_t video_offset = 0; |
122 size_t text_offset = 0; | 128 size_t text_offset = 0; |
123 for (int i = 0; i < block_count; i++) { | 129 for (int i = 0; i < block_count; i++) { |
124 const WebMClusterParser::BufferQueue* buffers = NULL; | 130 const WebMClusterParser::BufferQueue* buffers = NULL; |
125 size_t* offset; | 131 size_t* offset; |
126 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN; | 132 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN; |
127 | 133 |
128 if (block_info[i].track_num == kAudioTrackNum) { | 134 if (block_info[i].track_num == kAudioTrackNum) { |
129 buffers = &audio_buffers; | 135 buffers = &audio_buffers; |
130 offset = &audio_offset; | 136 offset = &audio_offset; |
131 expected_type = DemuxerStream::AUDIO; | 137 expected_type = DemuxerStream::AUDIO; |
132 } else if (block_info[i].track_num == kVideoTrackNum) { | 138 } else if (block_info[i].track_num == kVideoTrackNum) { |
133 buffers = &video_buffers; | 139 buffers = &video_buffers; |
134 offset = &video_offset; | 140 offset = &video_offset; |
135 expected_type = DemuxerStream::VIDEO; | 141 expected_type = DemuxerStream::VIDEO; |
136 } else if (block_info[i].track_num == kTextTrackNum) { | 142 } else if (block_info[i].track_num == kTextTrackNum) { |
137 buffers = &text_buffers; | 143 buffers = &text_buffers; |
138 offset = &text_offset; | 144 offset = &text_offset; |
139 expected_type = DemuxerStream::TEXT; | 145 expected_type = DemuxerStream::TEXT; |
140 } else { | 146 } else { |
141 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; | 147 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; |
142 return false; | 148 return false; |
143 } | 149 } |
144 | 150 |
151 EXPECT_LT(*offset, buffers->size()); | |
acolwell GONE FROM CHROMIUM
2014/04/23 22:36:39
ditto
wolenetz
2014/04/25 20:04:21
Done.
| |
145 if (*offset >= buffers->size()) | 152 if (*offset >= buffers->size()) |
146 return false; | 153 return false; |
147 | 154 |
148 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; | 155 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; |
149 | 156 |
150 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); | 157 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); |
151 EXPECT_EQ(std::abs(block_info[i].duration), | 158 EXPECT_EQ(std::abs(block_info[i].duration), |
152 buffer->duration().InMilliseconds()); | 159 buffer->duration().InMilliseconds()); |
153 EXPECT_EQ(expected_type, buffer->type()); | 160 EXPECT_EQ(expected_type, buffer->type()); |
154 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); | 161 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
260 std::string(), | 267 std::string(), |
261 LogCB())); | 268 LogCB())); |
262 } | 269 } |
263 | 270 |
264 scoped_ptr<WebMClusterParser> parser_; | 271 scoped_ptr<WebMClusterParser> parser_; |
265 | 272 |
266 private: | 273 private: |
267 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); | 274 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); |
268 }; | 275 }; |
269 | 276 |
277 TEST_F(WebMClusterParserTest, HeldBackBufferHoldsBackAllTracks) { | |
278 // If a buffer is missing duration and is being held back, then all other | |
279 // tracks' buffers that have same or higher (decode) timestamp should be held | |
280 // back too to keep the timestamps emitted for a cluster monotonically | |
281 // non-decreasing and in same order as parsed. | |
282 InSequence s; | |
283 | |
284 // Reset the parser to have 3 tracks: text, video (no default frame duration), | |
285 // and audio (with a default frame duration). | |
286 TextTracks text_tracks; | |
287 text_tracks.insert(std::make_pair(TextTracks::key_type(kTextTrackNum), | |
288 TextTrackConfig(kTextSubtitles, "", "", | |
289 ""))); | |
290 base::TimeDelta default_audio_duration = | |
291 base::TimeDelta::FromMilliseconds(kTestAudioFrameDefaultDurationInMs); | |
292 ASSERT_GE(default_audio_duration, base::TimeDelta()); | |
293 ASSERT_NE(kNoTimestamp(), default_audio_duration); | |
294 parser_.reset(new WebMClusterParser(kTimecodeScale, | |
295 kAudioTrackNum, | |
296 default_audio_duration, | |
297 kVideoTrackNum, | |
298 kNoTimestamp(), | |
299 text_tracks, | |
300 std::set<int64>(), | |
301 std::string(), | |
302 std::string(), | |
303 LogCB())); | |
304 | |
305 const BlockInfo kBlockInfo[] = { | |
306 { kVideoTrackNum, 0, 33, true }, | |
307 { kAudioTrackNum, 0, 23, false }, | |
308 { kTextTrackNum, 10, 42, false }, | |
309 { kAudioTrackNum, 23, kTestAudioFrameDefaultDurationInMs, true }, | |
310 { kVideoTrackNum, 33, 33, true }, | |
311 { kAudioTrackNum, 36, kTestAudioFrameDefaultDurationInMs, true }, | |
312 { kVideoTrackNum, 66, 33, true }, | |
313 { kAudioTrackNum, 70, kTestAudioFrameDefaultDurationInMs, true }, | |
314 { kAudioTrackNum, 83, kTestAudioFrameDefaultDurationInMs, true }, | |
315 }; | |
316 | |
317 const int kExpectedBuffersOnPartialCluster[] = { | |
318 0, // Video simple block without DefaultDuration should be held back | |
319 0, // Audio buffer ready, but not emitted because its TS >= held back video | |
320 0, // Text buffer ready, but not emitted because its TS >= held back video | |
321 0, // 2nd audio buffer ready, also not emitted for same reason as first | |
322 4, // All previous buffers emitted, 2nd video held back with no duration | |
323 4, // 2nd video still has no duration, 3rd audio ready but not emitted | |
324 6, // All previous buffers emitted, 3rd video held back with no duration | |
325 6, // 3rd video still has no duration, 4th audio ready but not emitted | |
326 9, // Cluster end emits all buffers and 3rd video's duration is estimated | |
327 }; | |
328 | |
329 ASSERT_EQ(arraysize(kBlockInfo), arraysize(kExpectedBuffersOnPartialCluster)); | |
330 int block_count = arraysize(kBlockInfo); | |
331 | |
332 // Iteratively create a cluster containing the first N+1 blocks and parse all | |
333 // but the last byte of the cluster (except when N==|block_count|, just parse | |
334 // the whole cluster). Verify that the corresponding entry in | |
335 // |kExpectedBuffersOnPartialCluster| identifies the exact subset of | |
336 // |kBlockInfo| returned by the parser. | |
337 for (int i = 0; i < block_count; ++i) { | |
338 if (i > 0) | |
339 parser_->Reset(); | |
340 // Since we don't know exactly the offsets of each block in the full | |
341 // cluster, build a cluster with exactly one additional block so that | |
342 // parse of all but one byte should deterministically parse all but the | |
343 // last full block. Don't |exceed block_count| blocks though. | |
344 int blocks_in_cluster = std::min(i + 2, block_count); | |
345 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, | |
346 blocks_in_cluster)); | |
347 // Parse all but the last byte unless we need to parse the full cluster. | |
348 bool parse_full_cluster = i == (block_count - 1); | |
349 int result = parser_->Parse(cluster->data(), parse_full_cluster ? | |
350 cluster->size() : cluster->size() - 1); | |
351 if (parse_full_cluster) { | |
352 DVLOG(1) << "Verifying parse result of full cluster of " | |
353 << blocks_in_cluster << " blocks"; | |
354 EXPECT_EQ(cluster->size(), result); | |
355 } else { | |
356 DVLOG(1) << "Verifying parse result of cluster of " | |
357 << blocks_in_cluster << " blocks with last block incomplete"; | |
358 EXPECT_GT(cluster->size(), result); | |
359 EXPECT_LT(0, result); | |
360 } | |
361 | |
362 EXPECT_TRUE(VerifyBuffers(parser_, kBlockInfo, | |
363 kExpectedBuffersOnPartialCluster[i])); | |
364 } | |
365 } | |
366 | |
270 TEST_F(WebMClusterParserTest, Reset) { | 367 TEST_F(WebMClusterParserTest, Reset) { |
271 InSequence s; | 368 InSequence s; |
272 | 369 |
273 int block_count = arraysize(kDefaultBlockInfo); | 370 int block_count = arraysize(kDefaultBlockInfo); |
274 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); | 371 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); |
275 | 372 |
276 // Send slightly less than the full cluster so all but the last block is | 373 // Send slightly less than the full cluster so all but the last block is |
277 // parsed. | 374 // parsed. |
278 int result = parser_->Parse(cluster->data(), cluster->size() - 1); | 375 int result = parser_->Parse(cluster->data(), cluster->size() - 1); |
279 EXPECT_GT(result, 0); | 376 EXPECT_GT(result, 0); |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
846 }; | 943 }; |
847 | 944 |
848 int block_count = arraysize(kBlockInfo); | 945 int block_count = arraysize(kBlockInfo); |
849 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); | 946 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
850 int result = parser_->Parse(cluster->data(), cluster->size()); | 947 int result = parser_->Parse(cluster->data(), cluster->size()); |
851 EXPECT_EQ(cluster->size(), result); | 948 EXPECT_EQ(cluster->size(), result); |
852 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); | 949 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
853 } | 950 } |
854 | 951 |
855 } // namespace media | 952 } // namespace media |
OLD | NEW |