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

Side by Side Diff: media/filters/chunk_demuxer_unittest.cc

Issue 7538027: Make ChunkDemuxer error handling more consistent and robust. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix unittests. Created 9 years, 4 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 (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "base/base_paths.h" 5 #include "base/base_paths.h"
6 #include "base/bind.h" 6 #include "base/bind.h"
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/message_loop.h"
8 #include "base/path_service.h" 9 #include "base/path_service.h"
9 #include "media/base/media.h" 10 #include "media/base/media.h"
10 #include "media/base/mock_callback.h" 11 #include "media/base/mock_callback.h"
11 #include "media/base/mock_ffmpeg.h" 12 #include "media/base/mock_ffmpeg.h"
13 #include "media/base/mock_filter_host.h"
12 #include "media/filters/chunk_demuxer.h" 14 #include "media/filters/chunk_demuxer.h"
13 #include "media/filters/chunk_demuxer_client.h" 15 #include "media/filters/chunk_demuxer_client.h"
14 #include "media/webm/cluster_builder.h" 16 #include "media/webm/cluster_builder.h"
15 #include "testing/gtest/include/gtest/gtest.h" 17 #include "testing/gtest/include/gtest/gtest.h"
16 18
19 using ::testing::AnyNumber;
17 using ::testing::InSequence; 20 using ::testing::InSequence;
18 using ::testing::Return; 21 using ::testing::Return;
19 using ::testing::SetArgumentPointee; 22 using ::testing::SetArgumentPointee;
20 using ::testing::NiceMock; 23 using ::testing::NiceMock;
21 using ::testing::_; 24 using ::testing::_;
22 25
23 namespace media { 26 namespace media {
24 27
25 static const uint8 kTracksHeader[] = { 28 static const uint8 kTracksHeader[] = {
26 0x16, 0x54, 0xAE, 0x6B, // Tracks ID 29 0x16, 0x54, 0xAE, 0x6B, // Tracks ID
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 codecs_[VIDEO].width = 320; 68 codecs_[VIDEO].width = 320;
66 codecs_[VIDEO].height = 240; 69 codecs_[VIDEO].height = 240;
67 70
68 codecs_[AUDIO].codec_type = AVMEDIA_TYPE_AUDIO; 71 codecs_[AUDIO].codec_type = AVMEDIA_TYPE_AUDIO;
69 codecs_[AUDIO].codec_id = CODEC_ID_VORBIS; 72 codecs_[AUDIO].codec_id = CODEC_ID_VORBIS;
70 codecs_[AUDIO].channels = 2; 73 codecs_[AUDIO].channels = 2;
71 codecs_[AUDIO].sample_rate = 44100; 74 codecs_[AUDIO].sample_rate = 44100;
72 } 75 }
73 76
74 virtual ~ChunkDemuxerTest() { 77 virtual ~ChunkDemuxerTest() {
78 message_loop_.RunAllPending();
Ami GONE FROM CHROMIUM 2011/08/03 21:06:02 This makes me worry. Why do you have it?
acolwell GONE FROM CHROMIUM 2011/08/03 22:08:11 It was just catching the error on EndOfStream() ca
75 ShutdownDemuxer(); 79 ShutdownDemuxer();
76 } 80 }
77 81
78 void ReadFile(const std::string& name, scoped_array<uint8>* buffer, 82 void ReadFile(const std::string& name, scoped_array<uint8>* buffer,
79 int* size) { 83 int* size) {
80 FilePath file_path; 84 FilePath file_path;
81 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path)); 85 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &file_path));
82 file_path = file_path.Append(FILE_PATH_LITERAL("media")) 86 file_path = file_path.Append(FILE_PATH_LITERAL("media"))
83 .Append(FILE_PATH_LITERAL("test")) 87 .Append(FILE_PATH_LITERAL("test"))
84 .Append(FILE_PATH_LITERAL("data")) 88 .Append(FILE_PATH_LITERAL("data"))
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 memcpy(buf, audio_track_entry.get(), audio_track_entry_size); 146 memcpy(buf, audio_track_entry.get(), audio_track_entry_size);
143 buf += audio_track_entry_size; 147 buf += audio_track_entry_size;
144 } 148 }
145 149
146 if (has_video) { 150 if (has_video) {
147 memcpy(buf, video_track_entry.get(), video_track_entry_size); 151 memcpy(buf, video_track_entry.get(), video_track_entry_size);
148 buf += video_track_entry_size; 152 buf += video_track_entry_size;
149 } 153 }
150 } 154 }
151 155
156 void AppendData(const uint8* data, unsigned length) {
157 EXPECT_CALL(mock_filter_host_, SetBufferedBytes(_)).Times(AnyNumber());
158 EXPECT_CALL(mock_filter_host_, SetBufferedTime(_)).Times(AnyNumber());
159 EXPECT_CALL(mock_filter_host_, SetNetworkActivity(true)).Times(AnyNumber());
Ami GONE FROM CHROMIUM 2011/08/03 21:06:02 Ugh to the above three lines, and the other green
acolwell GONE FROM CHROMIUM 2011/08/03 22:08:11 Yes. Yes I can...These are on the must die list al
160 EXPECT_TRUE(demuxer_->AppendData(data, length));
161 message_loop_.RunAllPending();
162 }
163
152 void AppendInfoTracks(bool has_audio, bool has_video) { 164 void AppendInfoTracks(bool has_audio, bool has_video) {
153 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) 165 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL))
154 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), 166 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_),
155 Return(0))); 167 Return(0)));
156 168
157 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) 169 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_))
158 .WillOnce(Return(0)); 170 .WillOnce(Return(0));
159 171
160 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); 172 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_));
161 173
162 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_)) 174 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_))
163 .WillRepeatedly(Return(0)); 175 .WillRepeatedly(Return(0));
164 176
165 scoped_array<uint8> info_tracks; 177 scoped_array<uint8> info_tracks;
166 int info_tracks_size = 0; 178 int info_tracks_size = 0;
167 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size); 179 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size);
168 180
169 SetupAVFormatContext(has_audio, has_video); 181 SetupAVFormatContext(has_audio, has_video);
170 182
171 demuxer_->AppendData(info_tracks.get(), info_tracks_size); 183 AppendData(info_tracks.get(), info_tracks_size);
172 } 184 }
173 185
174 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus, 186 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus,
175 PipelineStatus status) { 187 PipelineStatus status) {
176 EXPECT_EQ(status, expectedStatus); 188 EXPECT_EQ(status, expectedStatus);
177 *was_called = true; 189 *was_called = true;
178 } 190 }
179 191
180 void InitDemuxer(bool has_audio, bool has_video) { 192 void InitDemuxer(bool has_audio, bool has_video) {
181 bool init_done_called = false; 193 bool init_done_called = false;
182 PipelineStatus expectedStatus = 194 PipelineStatus expectedStatus =
183 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; 195 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN;
184 196
185 EXPECT_CALL(*client_, DemuxerOpened(_)); 197 EXPECT_CALL(*client_, DemuxerOpened(_));
186 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled, 198 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled,
187 &init_done_called, 199 &init_done_called,
188 expectedStatus)); 200 expectedStatus));
189 201
190 EXPECT_FALSE(init_done_called); 202 EXPECT_FALSE(init_done_called);
191 203
192 AppendInfoTracks(has_audio, has_video); 204 AppendInfoTracks(has_audio, has_video);
193 205
194 EXPECT_TRUE(init_done_called); 206 EXPECT_TRUE(init_done_called);
207 EXPECT_CALL(mock_filter_host_, SetDuration(_));
208 EXPECT_CALL(mock_filter_host_, SetCurrentReadPosition(_));
209 demuxer_->set_host(&mock_filter_host_);
195 } 210 }
196 211
197 void ShutdownDemuxer() { 212 void ShutdownDemuxer() {
198 if (demuxer_) { 213 if (demuxer_) {
199 EXPECT_CALL(*client_, DemuxerClosed()); 214 EXPECT_CALL(*client_, DemuxerClosed());
200 demuxer_->Shutdown(); 215 demuxer_->Shutdown();
201 } 216 }
202 217
203 if (format_context_.streams) { 218 if (format_context_.streams) {
204 delete[] format_context_.streams; 219 delete[] format_context_.streams;
205 format_context_.streams = NULL; 220 format_context_.streams = NULL;
206 format_context_.nb_streams = 0; 221 format_context_.nb_streams = 0;
207 } 222 }
208 } 223 }
209 224
210 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { 225 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) {
211 uint8 data[] = { 0x00 }; 226 uint8 data[] = { 0x00 };
212 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); 227 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data));
213 } 228 }
214 229
215 MOCK_METHOD1(Checkpoint, void(int id)); 230 MOCK_METHOD1(Checkpoint, void(int id));
216 231
232 MessageLoop message_loop_;
Ami GONE FROM CHROMIUM 2011/08/03 21:06:02 I don't get where this is populated, only drained.
acolwell GONE FROM CHROMIUM 2011/08/03 22:08:11 The constructor is magical and initializes the thr
Ami GONE FROM CHROMIUM 2011/08/03 23:41:35 Per offline convo, I think you can avoid ML entire
acolwell GONE FROM CHROMIUM 2011/08/04 00:22:16 Removed
217 MockFFmpeg mock_ffmpeg_; 233 MockFFmpeg mock_ffmpeg_;
234 MockFilterHost mock_filter_host_;
218 235
219 AVFormatContext format_context_; 236 AVFormatContext format_context_;
220 AVCodecContext codecs_[MAX_CODECS_INDEX]; 237 AVCodecContext codecs_[MAX_CODECS_INDEX];
221 AVStream streams_[MAX_CODECS_INDEX]; 238 AVStream streams_[MAX_CODECS_INDEX];
222 239
223 scoped_ptr<MockChunkDemuxerClient> client_; 240 scoped_ptr<MockChunkDemuxerClient> client_;
224 scoped_refptr<ChunkDemuxer> demuxer_; 241 scoped_refptr<ChunkDemuxer> demuxer_;
225 242
226 private: 243 private:
227 void SetupAVFormatContext(bool has_audio, bool has_video) { 244 void SetupAVFormatContext(bool has_audio, bool has_video) {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 309
293 EXPECT_CALL(*this, Checkpoint(2)); 310 EXPECT_CALL(*this, Checkpoint(2));
294 311
295 ClusterBuilder cb; 312 ClusterBuilder cb;
296 cb.SetClusterTimecode(0); 313 cb.SetClusterTimecode(0);
297 AddSimpleBlock(&cb, kVideoTrackNum, 0); 314 AddSimpleBlock(&cb, kVideoTrackNum, 0);
298 scoped_ptr<Cluster> cluster(cb.Finish()); 315 scoped_ptr<Cluster> cluster(cb.Finish());
299 316
300 Checkpoint(1); 317 Checkpoint(1);
301 318
302 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); 319 AppendData(cluster->data(), cluster->size());
303 320
304 Checkpoint(2); 321 Checkpoint(2);
305 } 322 }
306 323
307 // Test the case where AppendData() is called before Init(). 324 // Test the case where AppendData() is called before Init().
308 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { 325 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) {
309 scoped_array<uint8> info_tracks; 326 scoped_array<uint8> info_tracks;
310 int info_tracks_size = 0; 327 int info_tracks_size = 0;
311 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size); 328 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size);
312 329
(...skipping 25 matching lines...) Expand all
338 video->Read(base::Bind(&OnReadDone, 355 video->Read(base::Bind(&OnReadDone,
339 base::TimeDelta::FromMilliseconds(123), 356 base::TimeDelta::FromMilliseconds(123),
340 &video_read_done)); 357 &video_read_done));
341 358
342 ClusterBuilder cb; 359 ClusterBuilder cb;
343 cb.SetClusterTimecode(0); 360 cb.SetClusterTimecode(0);
344 AddSimpleBlock(&cb, kAudioTrackNum, 32); 361 AddSimpleBlock(&cb, kAudioTrackNum, 32);
345 AddSimpleBlock(&cb, kVideoTrackNum, 123); 362 AddSimpleBlock(&cb, kVideoTrackNum, 123);
346 scoped_ptr<Cluster> cluster(cb.Finish()); 363 scoped_ptr<Cluster> cluster(cb.Finish());
347 364
348 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); 365 AppendData(cluster->data(), cluster->size());
349 366
350 EXPECT_TRUE(audio_read_done); 367 EXPECT_TRUE(audio_read_done);
351 EXPECT_TRUE(video_read_done); 368 EXPECT_TRUE(video_read_done);
352 } 369 }
353 370
354 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { 371 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) {
355 InitDemuxer(true, true); 372 InitDemuxer(true, true);
356 373
357 ClusterBuilder cb; 374 ClusterBuilder cb;
358 375
359 cb.SetClusterTimecode(10); 376 cb.SetClusterTimecode(10);
360 AddSimpleBlock(&cb, kAudioTrackNum, 10); 377 AddSimpleBlock(&cb, kAudioTrackNum, 10);
361 AddSimpleBlock(&cb, kVideoTrackNum, 10); 378 AddSimpleBlock(&cb, kVideoTrackNum, 10);
362 AddSimpleBlock(&cb, kAudioTrackNum, 33); 379 AddSimpleBlock(&cb, kAudioTrackNum, 33);
363 AddSimpleBlock(&cb, kVideoTrackNum, 43); 380 AddSimpleBlock(&cb, kVideoTrackNum, 43);
364 scoped_ptr<Cluster> clusterA(cb.Finish()); 381 scoped_ptr<Cluster> clusterA(cb.Finish());
365 382
366 EXPECT_TRUE(demuxer_->AppendData(clusterA->data(), clusterA->size())); 383 AppendData(clusterA->data(), clusterA->size());
367 384
368 // Cluster B starts before clusterA and has data 385 // Cluster B starts before clusterA and has data
369 // that overlaps. 386 // that overlaps.
370 cb.SetClusterTimecode(5); 387 cb.SetClusterTimecode(5);
371 AddSimpleBlock(&cb, kAudioTrackNum, 5); 388 AddSimpleBlock(&cb, kAudioTrackNum, 5);
372 AddSimpleBlock(&cb, kVideoTrackNum, 7); 389 AddSimpleBlock(&cb, kVideoTrackNum, 7);
373 AddSimpleBlock(&cb, kAudioTrackNum, 28); 390 AddSimpleBlock(&cb, kAudioTrackNum, 28);
374 AddSimpleBlock(&cb, kVideoTrackNum, 40); 391 AddSimpleBlock(&cb, kVideoTrackNum, 40);
375 scoped_ptr<Cluster> clusterB(cb.Finish()); 392 scoped_ptr<Cluster> clusterB(cb.Finish());
376 393
377 // Make sure that AppendData() fails because this cluster data 394 // Make sure that AppendData() fails because this cluster data
378 // is before previous data. 395 // is before previous data.
379 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); 396 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
397 AppendData(clusterB->data(), clusterB->size());
380 398
381 // Cluster C starts after clusterA. 399 // Verify that AppendData() doesn't accept more data now.
382 cb.SetClusterTimecode(56); 400 cb.SetClusterTimecode(45);
383 AddSimpleBlock(&cb, kAudioTrackNum, 56); 401 AddSimpleBlock(&cb, kAudioTrackNum, 45);
384 AddSimpleBlock(&cb, kVideoTrackNum, 76); 402 AddSimpleBlock(&cb, kVideoTrackNum, 45);
385 AddSimpleBlock(&cb, kAudioTrackNum, 79);
386 AddSimpleBlock(&cb, kVideoTrackNum, 109);
387 scoped_ptr<Cluster> clusterC(cb.Finish()); 403 scoped_ptr<Cluster> clusterC(cb.Finish());
388 404 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size()));
389 // Verify that clusterC is accepted.
390 EXPECT_TRUE(demuxer_->AppendData(clusterC->data(), clusterC->size()));
391
392 // Flush and try clusterB again.
393 demuxer_->FlushData();
394 EXPECT_TRUE(demuxer_->AppendData(clusterB->data(), clusterB->size()));
395
396 // Following that with clusterC should work too since it doesn't
397 // overlap with clusterB.
398 EXPECT_TRUE(demuxer_->AppendData(clusterC->data(), clusterC->size()));
399 } 405 }
400 406
401 TEST_F(ChunkDemuxerTest, TestInvalidBlockSequences) { 407 TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) {
402 InitDemuxer(true, true); 408 InitDemuxer(true, true);
403 409
404 ClusterBuilder cb; 410 ClusterBuilder cb;
405 411
406 // Test the case where timecode is not monotonically 412 // Test the case where block timecodes are not monotonically
407 // increasing but stays above the cluster timecode. 413 // increasing but stay above the cluster timecode.
408 cb.SetClusterTimecode(5); 414 cb.SetClusterTimecode(5);
409 AddSimpleBlock(&cb, kAudioTrackNum, 5); 415 AddSimpleBlock(&cb, kAudioTrackNum, 5);
410 AddSimpleBlock(&cb, kVideoTrackNum, 10); 416 AddSimpleBlock(&cb, kVideoTrackNum, 10);
411 AddSimpleBlock(&cb, kAudioTrackNum, 7); 417 AddSimpleBlock(&cb, kAudioTrackNum, 7);
412 AddSimpleBlock(&cb, kVideoTrackNum, 15); 418 AddSimpleBlock(&cb, kVideoTrackNum, 15);
413 scoped_ptr<Cluster> clusterA(cb.Finish()); 419 scoped_ptr<Cluster> clusterA(cb.Finish());
414 420
415 EXPECT_FALSE(demuxer_->AppendData(clusterA->data(), clusterA->size())); 421 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
422 AppendData(clusterA->data(), clusterA->size());
416 423
417 // Test timecodes going backwards before cluster timecode. 424 // Verify that AppendData() doesn't accept more data now.
425 cb.SetClusterTimecode(20);
426 AddSimpleBlock(&cb, kAudioTrackNum, 20);
427 AddSimpleBlock(&cb, kVideoTrackNum, 20);
428 scoped_ptr<Cluster> clusterB(cb.Finish());
429 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size()));
430 }
431
432 TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) {
433 InitDemuxer(true, true);
434
435 ClusterBuilder cb;
436
437 // Test timecodes going backwards and including values less than the cluster
438 // timecode.
418 cb.SetClusterTimecode(5); 439 cb.SetClusterTimecode(5);
419 AddSimpleBlock(&cb, kAudioTrackNum, 5); 440 AddSimpleBlock(&cb, kAudioTrackNum, 5);
420 AddSimpleBlock(&cb, kVideoTrackNum, 5); 441 AddSimpleBlock(&cb, kVideoTrackNum, 5);
421 AddSimpleBlock(&cb, kAudioTrackNum, 3); 442 AddSimpleBlock(&cb, kAudioTrackNum, 3);
422 AddSimpleBlock(&cb, kVideoTrackNum, 3); 443 AddSimpleBlock(&cb, kVideoTrackNum, 3);
444 scoped_ptr<Cluster> clusterA(cb.Finish());
445
446 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
447 AppendData(clusterA->data(), clusterA->size());
448
449 // Verify that AppendData() doesn't accept more data now.
450 cb.SetClusterTimecode(6);
451 AddSimpleBlock(&cb, kAudioTrackNum, 6);
452 AddSimpleBlock(&cb, kVideoTrackNum, 6);
423 scoped_ptr<Cluster> clusterB(cb.Finish()); 453 scoped_ptr<Cluster> clusterB(cb.Finish());
454 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size()));
455 }
424 456
425 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); 457
458 TEST_F(ChunkDemuxerTest, TestPerStreamMonotonicallyIncreasingTimestamps) {
459 InitDemuxer(true, true);
460
461 ClusterBuilder cb;
426 462
427 // Test strict monotonic increasing timestamps on a per stream 463 // Test strict monotonic increasing timestamps on a per stream
428 // basis. 464 // basis.
429 cb.SetClusterTimecode(5); 465 cb.SetClusterTimecode(5);
430 AddSimpleBlock(&cb, kAudioTrackNum, 5); 466 AddSimpleBlock(&cb, kAudioTrackNum, 5);
431 AddSimpleBlock(&cb, kVideoTrackNum, 5); 467 AddSimpleBlock(&cb, kVideoTrackNum, 5);
432 AddSimpleBlock(&cb, kAudioTrackNum, 5); 468 AddSimpleBlock(&cb, kAudioTrackNum, 5);
433 AddSimpleBlock(&cb, kVideoTrackNum, 7); 469 AddSimpleBlock(&cb, kVideoTrackNum, 7);
434 scoped_ptr<Cluster> clusterC(cb.Finish()); 470 scoped_ptr<Cluster> cluster(cb.Finish());
435 471
436 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); 472 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
473 AppendData(cluster->data(), cluster->size());
474 }
475
476 TEST_F(ChunkDemuxerTest, TestMonotonicallyIncreasingTimestampsAcrossClusters) {
477 InitDemuxer(true, true);
478
479 ClusterBuilder cb;
437 480
438 // Test strict monotonic increasing timestamps on a per stream 481 // Test strict monotonic increasing timestamps on a per stream
439 // basis across clusters. 482 // basis across clusters.
440 cb.SetClusterTimecode(5); 483 cb.SetClusterTimecode(5);
441 AddSimpleBlock(&cb, kAudioTrackNum, 5); 484 AddSimpleBlock(&cb, kAudioTrackNum, 5);
442 AddSimpleBlock(&cb, kVideoTrackNum, 5); 485 AddSimpleBlock(&cb, kVideoTrackNum, 5);
443 scoped_ptr<Cluster> clusterD(cb.Finish()); 486 scoped_ptr<Cluster> clusterA(cb.Finish());
444 487
445 EXPECT_TRUE(demuxer_->AppendData(clusterD->data(), clusterD->size())); 488 AppendData(clusterA->data(), clusterA->size());
446 489
447 cb.SetClusterTimecode(5); 490 cb.SetClusterTimecode(5);
448 AddSimpleBlock(&cb, kAudioTrackNum, 5); 491 AddSimpleBlock(&cb, kAudioTrackNum, 5);
449 AddSimpleBlock(&cb, kVideoTrackNum, 7); 492 AddSimpleBlock(&cb, kVideoTrackNum, 7);
450 scoped_ptr<Cluster> clusterE(cb.Finish()); 493 scoped_ptr<Cluster> clusterB(cb.Finish());
451 494
452 EXPECT_FALSE(demuxer_->AppendData(clusterE->data(), clusterE->size())); 495 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
496 AppendData(clusterB->data(), clusterB->size());
497
498 // Verify that AppendData() doesn't accept more data now.
499 cb.SetClusterTimecode(10);
500 AddSimpleBlock(&cb, kAudioTrackNum, 10);
501 AddSimpleBlock(&cb, kVideoTrackNum, 10);
502 scoped_ptr<Cluster> clusterC(cb.Finish());
503 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size()));
453 } 504 }
454 505
455 // Test the case where a cluster is passed to AppendData() before 506 // Test the case where a cluster is passed to AppendData() before
456 // INFO & TRACKS data. 507 // INFO & TRACKS data.
457 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { 508 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) {
458 EXPECT_CALL(*client_, DemuxerOpened(_)); 509 EXPECT_CALL(*client_, DemuxerOpened(_));
459 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); 510 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
460 511
461 ClusterBuilder cb; 512 ClusterBuilder cb;
462 cb.SetClusterTimecode(0); 513 cb.SetClusterTimecode(0);
463 AddSimpleBlock(&cb, kVideoTrackNum, 0); 514 AddSimpleBlock(&cb, kVideoTrackNum, 0);
464 scoped_ptr<Cluster> cluster(cb.Finish()); 515 scoped_ptr<Cluster> cluster(cb.Finish());
465 516
466 EXPECT_FALSE(demuxer_->AppendData(cluster->data(), cluster->size())); 517 AppendData(cluster->data(), cluster->size());
467 } 518 }
468 519
469
470 // Test cases where we get an EndOfStream() call during initialization. 520 // Test cases where we get an EndOfStream() call during initialization.
471 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { 521 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) {
472 EXPECT_CALL(*client_, DemuxerOpened(_)); 522 EXPECT_CALL(*client_, DemuxerOpened(_));
473 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); 523 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN));
474 demuxer_->EndOfStream(PIPELINE_OK); 524 demuxer_->EndOfStream(PIPELINE_OK);
475 } 525 }
526
527 TEST_F(ChunkDemuxerTest, TestDecodeErrorEndOfStream) {
528 InitDemuxer(true, true);
529
530 ClusterBuilder cb;
531 cb.SetClusterTimecode(0);
532 AddSimpleBlock(&cb, kAudioTrackNum, 0);
533 AddSimpleBlock(&cb, kVideoTrackNum, 0);
534 AddSimpleBlock(&cb, kAudioTrackNum, 23);
535 AddSimpleBlock(&cb, kVideoTrackNum, 33);
536 scoped_ptr<Cluster> cluster(cb.Finish());
537 AppendData(cluster->data(), cluster->size());
538
539 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE));
540 demuxer_->EndOfStream(PIPELINE_ERROR_DECODE);
541 }
542
543 TEST_F(ChunkDemuxerTest, TestNetworkErrorEndOfStream) {
544 InitDemuxer(true, true);
545
546 ClusterBuilder cb;
547 cb.SetClusterTimecode(0);
548 AddSimpleBlock(&cb, kAudioTrackNum, 0);
549 AddSimpleBlock(&cb, kVideoTrackNum, 0);
550 AddSimpleBlock(&cb, kAudioTrackNum, 23);
551 AddSimpleBlock(&cb, kVideoTrackNum, 33);
552 scoped_ptr<Cluster> cluster(cb.Finish());
553 AppendData(cluster->data(), cluster->size());
554
555 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_NETWORK));
556 demuxer_->EndOfStream(PIPELINE_ERROR_NETWORK);
557 }
558
476 } // namespace media 559 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698