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 if (block_count != buffer_count) { |
| 123 DVLOG(1) << __FUNCTION__ << " : block_count (" << block_count |
| 124 << ") mismatches buffer_count (" << buffer_count << ")"; |
| 125 return false; |
| 126 } |
| 127 |
120 size_t audio_offset = 0; | 128 size_t audio_offset = 0; |
121 size_t video_offset = 0; | 129 size_t video_offset = 0; |
122 size_t text_offset = 0; | 130 size_t text_offset = 0; |
123 for (int i = 0; i < block_count; i++) { | 131 for (int i = 0; i < block_count; i++) { |
124 const WebMClusterParser::BufferQueue* buffers = NULL; | 132 const WebMClusterParser::BufferQueue* buffers = NULL; |
125 size_t* offset; | 133 size_t* offset; |
126 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN; | 134 StreamParserBuffer::Type expected_type = DemuxerStream::UNKNOWN; |
127 | 135 |
128 if (block_info[i].track_num == kAudioTrackNum) { | 136 if (block_info[i].track_num == kAudioTrackNum) { |
129 buffers = &audio_buffers; | 137 buffers = &audio_buffers; |
130 offset = &audio_offset; | 138 offset = &audio_offset; |
131 expected_type = DemuxerStream::AUDIO; | 139 expected_type = DemuxerStream::AUDIO; |
132 } else if (block_info[i].track_num == kVideoTrackNum) { | 140 } else if (block_info[i].track_num == kVideoTrackNum) { |
133 buffers = &video_buffers; | 141 buffers = &video_buffers; |
134 offset = &video_offset; | 142 offset = &video_offset; |
135 expected_type = DemuxerStream::VIDEO; | 143 expected_type = DemuxerStream::VIDEO; |
136 } else if (block_info[i].track_num == kTextTrackNum) { | 144 } else if (block_info[i].track_num == kTextTrackNum) { |
137 buffers = &text_buffers; | 145 buffers = &text_buffers; |
138 offset = &text_offset; | 146 offset = &text_offset; |
139 expected_type = DemuxerStream::TEXT; | 147 expected_type = DemuxerStream::TEXT; |
140 } else { | 148 } else { |
141 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; | 149 LOG(ERROR) << "Unexpected track number " << block_info[i].track_num; |
142 return false; | 150 return false; |
143 } | 151 } |
144 | 152 |
145 if (*offset >= buffers->size()) | 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"; |
146 return false; | 157 return false; |
| 158 } |
147 | 159 |
148 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; | 160 scoped_refptr<StreamParserBuffer> buffer = (*buffers)[(*offset)++]; |
149 | 161 |
150 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); | 162 EXPECT_EQ(block_info[i].timestamp, buffer->timestamp().InMilliseconds()); |
151 EXPECT_EQ(std::abs(block_info[i].duration), | 163 EXPECT_EQ(std::abs(block_info[i].duration), |
152 buffer->duration().InMilliseconds()); | 164 buffer->duration().InMilliseconds()); |
153 EXPECT_EQ(expected_type, buffer->type()); | 165 EXPECT_EQ(expected_type, buffer->type()); |
154 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); | 166 EXPECT_EQ(block_info[i].track_num, buffer->track_id()); |
155 } | 167 } |
156 | 168 |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 std::string(), | 272 std::string(), |
261 LogCB())); | 273 LogCB())); |
262 } | 274 } |
263 | 275 |
264 scoped_ptr<WebMClusterParser> parser_; | 276 scoped_ptr<WebMClusterParser> parser_; |
265 | 277 |
266 private: | 278 private: |
267 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); | 279 DISALLOW_COPY_AND_ASSIGN(WebMClusterParserTest); |
268 }; | 280 }; |
269 | 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 |
270 TEST_F(WebMClusterParserTest, Reset) { | 372 TEST_F(WebMClusterParserTest, Reset) { |
271 InSequence s; | 373 InSequence s; |
272 | 374 |
273 int block_count = arraysize(kDefaultBlockInfo); | 375 int block_count = arraysize(kDefaultBlockInfo); |
274 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); | 376 scoped_ptr<Cluster> cluster(CreateCluster(0, kDefaultBlockInfo, block_count)); |
275 | 377 |
276 // Send slightly less than the full cluster so all but the last block is | 378 // Send slightly less than the full cluster so all but the last block is |
277 // parsed. | 379 // parsed. |
278 int result = parser_->Parse(cluster->data(), cluster->size() - 1); | 380 int result = parser_->Parse(cluster->data(), cluster->size() - 1); |
279 EXPECT_GT(result, 0); | 381 EXPECT_GT(result, 0); |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
846 }; | 948 }; |
847 | 949 |
848 int block_count = arraysize(kBlockInfo); | 950 int block_count = arraysize(kBlockInfo); |
849 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); | 951 scoped_ptr<Cluster> cluster(CreateCluster(0, kBlockInfo, block_count)); |
850 int result = parser_->Parse(cluster->data(), cluster->size()); | 952 int result = parser_->Parse(cluster->data(), cluster->size()); |
851 EXPECT_EQ(cluster->size(), result); | 953 EXPECT_EQ(cluster->size(), result); |
852 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); | 954 ASSERT_TRUE(VerifyBuffers(parser_, kBlockInfo, block_count)); |
853 } | 955 } |
854 | 956 |
855 } // namespace media | 957 } // namespace media |
OLD | NEW |