Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1243)

Side by Side Diff: media/formats/webm/webm_cluster_parser_unittest.cc

Issue 239343007: MSE: Make WebMClusterParser hold back buffers at or beyond buffer missing duration (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Always reconstruct text_buffers_map_ from a cleared one in every GetTextBuffers() call. Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW
« media/formats/webm/webm_cluster_parser.h ('K') | « media/formats/webm/webm_cluster_parser.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698