| OLD | NEW |
| 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/path_service.h" | 8 #include "base/path_service.h" |
| 9 #include "media/base/media.h" | 9 #include "media/base/media.h" |
| 10 #include "media/base/mock_callback.h" | 10 #include "media/base/mock_callback.h" |
| 11 #include "media/base/mock_ffmpeg.h" | 11 #include "media/base/mock_ffmpeg.h" |
| 12 #include "media/base/mock_filter_host.h" |
| 12 #include "media/filters/chunk_demuxer.h" | 13 #include "media/filters/chunk_demuxer.h" |
| 13 #include "media/filters/chunk_demuxer_client.h" | 14 #include "media/filters/chunk_demuxer_client.h" |
| 14 #include "media/webm/cluster_builder.h" | 15 #include "media/webm/cluster_builder.h" |
| 15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 16 | 17 |
| 18 using ::testing::AnyNumber; |
| 17 using ::testing::InSequence; | 19 using ::testing::InSequence; |
| 18 using ::testing::Return; | 20 using ::testing::Return; |
| 19 using ::testing::SetArgumentPointee; | 21 using ::testing::SetArgumentPointee; |
| 20 using ::testing::NiceMock; | 22 using ::testing::NiceMock; |
| 21 using ::testing::_; | 23 using ::testing::_; |
| 22 | 24 |
| 23 namespace media { | 25 namespace media { |
| 24 | 26 |
| 25 static const uint8 kTracksHeader[] = { | 27 static const uint8 kTracksHeader[] = { |
| 26 0x16, 0x54, 0xAE, 0x6B, // Tracks ID | 28 0x16, 0x54, 0xAE, 0x6B, // Tracks ID |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 memcpy(buf, audio_track_entry.get(), audio_track_entry_size); | 144 memcpy(buf, audio_track_entry.get(), audio_track_entry_size); |
| 143 buf += audio_track_entry_size; | 145 buf += audio_track_entry_size; |
| 144 } | 146 } |
| 145 | 147 |
| 146 if (has_video) { | 148 if (has_video) { |
| 147 memcpy(buf, video_track_entry.get(), video_track_entry_size); | 149 memcpy(buf, video_track_entry.get(), video_track_entry_size); |
| 148 buf += video_track_entry_size; | 150 buf += video_track_entry_size; |
| 149 } | 151 } |
| 150 } | 152 } |
| 151 | 153 |
| 154 void AppendData(const uint8* data, unsigned length) { |
| 155 EXPECT_CALL(mock_filter_host_, SetBufferedBytes(_)).Times(AnyNumber()); |
| 156 EXPECT_CALL(mock_filter_host_, SetBufferedTime(_)).Times(AnyNumber()); |
| 157 EXPECT_CALL(mock_filter_host_, SetNetworkActivity(true)).Times(AnyNumber()); |
| 158 EXPECT_TRUE(demuxer_->AppendData(data, length)); |
| 159 } |
| 160 |
| 152 void AppendInfoTracks(bool has_audio, bool has_video) { | 161 void AppendInfoTracks(bool has_audio, bool has_video) { |
| 153 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) | 162 EXPECT_CALL(mock_ffmpeg_, AVOpenInputFile(_, _, NULL, 0, NULL)) |
| 154 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), | 163 .WillOnce(DoAll(SetArgumentPointee<0>(&format_context_), |
| 155 Return(0))); | 164 Return(0))); |
| 156 | 165 |
| 157 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) | 166 EXPECT_CALL(mock_ffmpeg_, AVFindStreamInfo(&format_context_)) |
| 158 .WillOnce(Return(0)); | 167 .WillOnce(Return(0)); |
| 159 | 168 |
| 160 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); | 169 EXPECT_CALL(mock_ffmpeg_, AVCloseInputFile(&format_context_)); |
| 161 | 170 |
| 162 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_)) | 171 EXPECT_CALL(mock_ffmpeg_, AVRegisterLockManager(_)) |
| 163 .WillRepeatedly(Return(0)); | 172 .WillRepeatedly(Return(0)); |
| 164 | 173 |
| 165 scoped_array<uint8> info_tracks; | 174 scoped_array<uint8> info_tracks; |
| 166 int info_tracks_size = 0; | 175 int info_tracks_size = 0; |
| 167 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size); | 176 CreateInfoTracks(has_audio, has_video, &info_tracks, &info_tracks_size); |
| 168 | 177 |
| 169 SetupAVFormatContext(has_audio, has_video); | 178 SetupAVFormatContext(has_audio, has_video); |
| 170 | 179 |
| 171 demuxer_->AppendData(info_tracks.get(), info_tracks_size); | 180 AppendData(info_tracks.get(), info_tracks_size); |
| 172 } | 181 } |
| 173 | 182 |
| 174 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus, | 183 static void InitDoneCalled(bool* was_called, PipelineStatus expectedStatus, |
| 175 PipelineStatus status) { | 184 PipelineStatus status) { |
| 176 EXPECT_EQ(status, expectedStatus); | 185 EXPECT_EQ(status, expectedStatus); |
| 177 *was_called = true; | 186 *was_called = true; |
| 178 } | 187 } |
| 179 | 188 |
| 180 void InitDemuxer(bool has_audio, bool has_video) { | 189 void InitDemuxer(bool has_audio, bool has_video) { |
| 181 bool init_done_called = false; | 190 bool init_done_called = false; |
| 182 PipelineStatus expectedStatus = | 191 PipelineStatus expectedStatus = |
| 183 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; | 192 (has_audio || has_video) ? PIPELINE_OK : DEMUXER_ERROR_COULD_NOT_OPEN; |
| 184 | 193 |
| 185 EXPECT_CALL(*client_, DemuxerOpened(_)); | 194 EXPECT_CALL(*client_, DemuxerOpened(_)); |
| 186 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled, | 195 demuxer_->Init(base::Bind(&ChunkDemuxerTest::InitDoneCalled, |
| 187 &init_done_called, | 196 &init_done_called, |
| 188 expectedStatus)); | 197 expectedStatus)); |
| 189 | 198 |
| 190 EXPECT_FALSE(init_done_called); | 199 EXPECT_FALSE(init_done_called); |
| 191 | 200 |
| 192 AppendInfoTracks(has_audio, has_video); | 201 AppendInfoTracks(has_audio, has_video); |
| 193 | 202 |
| 194 EXPECT_TRUE(init_done_called); | 203 EXPECT_TRUE(init_done_called); |
| 204 EXPECT_CALL(mock_filter_host_, SetDuration(_)); |
| 205 EXPECT_CALL(mock_filter_host_, SetCurrentReadPosition(_)); |
| 206 demuxer_->set_host(&mock_filter_host_); |
| 195 } | 207 } |
| 196 | 208 |
| 197 void ShutdownDemuxer() { | 209 void ShutdownDemuxer() { |
| 198 if (demuxer_) { | 210 if (demuxer_) { |
| 199 EXPECT_CALL(*client_, DemuxerClosed()); | 211 EXPECT_CALL(*client_, DemuxerClosed()); |
| 200 demuxer_->Shutdown(); | 212 demuxer_->Shutdown(); |
| 201 } | 213 } |
| 202 | 214 |
| 203 if (format_context_.streams) { | 215 if (format_context_.streams) { |
| 204 delete[] format_context_.streams; | 216 delete[] format_context_.streams; |
| 205 format_context_.streams = NULL; | 217 format_context_.streams = NULL; |
| 206 format_context_.nb_streams = 0; | 218 format_context_.nb_streams = 0; |
| 207 } | 219 } |
| 208 } | 220 } |
| 209 | 221 |
| 210 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { | 222 void AddSimpleBlock(ClusterBuilder* cb, int track_num, int64 timecode) { |
| 211 uint8 data[] = { 0x00 }; | 223 uint8 data[] = { 0x00 }; |
| 212 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); | 224 cb->AddSimpleBlock(track_num, timecode, 0, data, sizeof(data)); |
| 213 } | 225 } |
| 214 | 226 |
| 215 MOCK_METHOD1(Checkpoint, void(int id)); | 227 MOCK_METHOD1(Checkpoint, void(int id)); |
| 216 | 228 |
| 217 MockFFmpeg mock_ffmpeg_; | 229 MockFFmpeg mock_ffmpeg_; |
| 230 MockFilterHost mock_filter_host_; |
| 218 | 231 |
| 219 AVFormatContext format_context_; | 232 AVFormatContext format_context_; |
| 220 AVCodecContext codecs_[MAX_CODECS_INDEX]; | 233 AVCodecContext codecs_[MAX_CODECS_INDEX]; |
| 221 AVStream streams_[MAX_CODECS_INDEX]; | 234 AVStream streams_[MAX_CODECS_INDEX]; |
| 222 | 235 |
| 223 scoped_ptr<MockChunkDemuxerClient> client_; | 236 scoped_ptr<MockChunkDemuxerClient> client_; |
| 224 scoped_refptr<ChunkDemuxer> demuxer_; | 237 scoped_refptr<ChunkDemuxer> demuxer_; |
| 225 | 238 |
| 226 private: | 239 private: |
| 227 void SetupAVFormatContext(bool has_audio, bool has_video) { | 240 void SetupAVFormatContext(bool has_audio, bool has_video) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 | 305 |
| 293 EXPECT_CALL(*this, Checkpoint(2)); | 306 EXPECT_CALL(*this, Checkpoint(2)); |
| 294 | 307 |
| 295 ClusterBuilder cb; | 308 ClusterBuilder cb; |
| 296 cb.SetClusterTimecode(0); | 309 cb.SetClusterTimecode(0); |
| 297 AddSimpleBlock(&cb, kVideoTrackNum, 0); | 310 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
| 298 scoped_ptr<Cluster> cluster(cb.Finish()); | 311 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 299 | 312 |
| 300 Checkpoint(1); | 313 Checkpoint(1); |
| 301 | 314 |
| 302 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); | 315 AppendData(cluster->data(), cluster->size()); |
| 303 | 316 |
| 304 Checkpoint(2); | 317 Checkpoint(2); |
| 305 } | 318 } |
| 306 | 319 |
| 307 // Test the case where AppendData() is called before Init(). | 320 // Test the case where AppendData() is called before Init(). |
| 308 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { | 321 TEST_F(ChunkDemuxerTest, TestAppendDataBeforeInit) { |
| 309 scoped_array<uint8> info_tracks; | 322 scoped_array<uint8> info_tracks; |
| 310 int info_tracks_size = 0; | 323 int info_tracks_size = 0; |
| 311 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size); | 324 CreateInfoTracks(true, true, &info_tracks, &info_tracks_size); |
| 312 | 325 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 338 video->Read(base::Bind(&OnReadDone, | 351 video->Read(base::Bind(&OnReadDone, |
| 339 base::TimeDelta::FromMilliseconds(123), | 352 base::TimeDelta::FromMilliseconds(123), |
| 340 &video_read_done)); | 353 &video_read_done)); |
| 341 | 354 |
| 342 ClusterBuilder cb; | 355 ClusterBuilder cb; |
| 343 cb.SetClusterTimecode(0); | 356 cb.SetClusterTimecode(0); |
| 344 AddSimpleBlock(&cb, kAudioTrackNum, 32); | 357 AddSimpleBlock(&cb, kAudioTrackNum, 32); |
| 345 AddSimpleBlock(&cb, kVideoTrackNum, 123); | 358 AddSimpleBlock(&cb, kVideoTrackNum, 123); |
| 346 scoped_ptr<Cluster> cluster(cb.Finish()); | 359 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 347 | 360 |
| 348 EXPECT_TRUE(demuxer_->AppendData(cluster->data(), cluster->size())); | 361 AppendData(cluster->data(), cluster->size()); |
| 349 | 362 |
| 350 EXPECT_TRUE(audio_read_done); | 363 EXPECT_TRUE(audio_read_done); |
| 351 EXPECT_TRUE(video_read_done); | 364 EXPECT_TRUE(video_read_done); |
| 352 } | 365 } |
| 353 | 366 |
| 354 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { | 367 TEST_F(ChunkDemuxerTest, TestOutOfOrderClusters) { |
| 355 InitDemuxer(true, true); | 368 InitDemuxer(true, true); |
| 356 | 369 |
| 357 ClusterBuilder cb; | 370 ClusterBuilder cb; |
| 358 | 371 |
| 359 cb.SetClusterTimecode(10); | 372 cb.SetClusterTimecode(10); |
| 360 AddSimpleBlock(&cb, kAudioTrackNum, 10); | 373 AddSimpleBlock(&cb, kAudioTrackNum, 10); |
| 361 AddSimpleBlock(&cb, kVideoTrackNum, 10); | 374 AddSimpleBlock(&cb, kVideoTrackNum, 10); |
| 362 AddSimpleBlock(&cb, kAudioTrackNum, 33); | 375 AddSimpleBlock(&cb, kAudioTrackNum, 33); |
| 363 AddSimpleBlock(&cb, kVideoTrackNum, 43); | 376 AddSimpleBlock(&cb, kVideoTrackNum, 43); |
| 364 scoped_ptr<Cluster> clusterA(cb.Finish()); | 377 scoped_ptr<Cluster> clusterA(cb.Finish()); |
| 365 | 378 |
| 366 EXPECT_TRUE(demuxer_->AppendData(clusterA->data(), clusterA->size())); | 379 AppendData(clusterA->data(), clusterA->size()); |
| 367 | 380 |
| 368 // Cluster B starts before clusterA and has data | 381 // Cluster B starts before clusterA and has data |
| 369 // that overlaps. | 382 // that overlaps. |
| 370 cb.SetClusterTimecode(5); | 383 cb.SetClusterTimecode(5); |
| 371 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 384 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 372 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 385 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
| 373 AddSimpleBlock(&cb, kAudioTrackNum, 28); | 386 AddSimpleBlock(&cb, kAudioTrackNum, 28); |
| 374 AddSimpleBlock(&cb, kVideoTrackNum, 40); | 387 AddSimpleBlock(&cb, kVideoTrackNum, 40); |
| 375 scoped_ptr<Cluster> clusterB(cb.Finish()); | 388 scoped_ptr<Cluster> clusterB(cb.Finish()); |
| 376 | 389 |
| 377 // Make sure that AppendData() fails because this cluster data | 390 // Make sure that AppendData() fails because this cluster data |
| 378 // is before previous data. | 391 // is before previous data. |
| 379 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | 392 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 393 AppendData(clusterB->data(), clusterB->size()); |
| 380 | 394 |
| 381 // Cluster C starts after clusterA. | 395 // Verify that AppendData() doesn't accept more data now. |
| 382 cb.SetClusterTimecode(56); | 396 cb.SetClusterTimecode(45); |
| 383 AddSimpleBlock(&cb, kAudioTrackNum, 56); | 397 AddSimpleBlock(&cb, kAudioTrackNum, 45); |
| 384 AddSimpleBlock(&cb, kVideoTrackNum, 76); | 398 AddSimpleBlock(&cb, kVideoTrackNum, 45); |
| 385 AddSimpleBlock(&cb, kAudioTrackNum, 79); | |
| 386 AddSimpleBlock(&cb, kVideoTrackNum, 109); | |
| 387 scoped_ptr<Cluster> clusterC(cb.Finish()); | 399 scoped_ptr<Cluster> clusterC(cb.Finish()); |
| 388 | 400 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 } | 401 } |
| 400 | 402 |
| 401 TEST_F(ChunkDemuxerTest, TestInvalidBlockSequences) { | 403 TEST_F(ChunkDemuxerTest, TestNonMonotonicButAboveClusterTimecode) { |
| 402 InitDemuxer(true, true); | 404 InitDemuxer(true, true); |
| 403 | 405 |
| 404 ClusterBuilder cb; | 406 ClusterBuilder cb; |
| 405 | 407 |
| 406 // Test the case where timecode is not monotonically | 408 // Test the case where block timecodes are not monotonically |
| 407 // increasing but stays above the cluster timecode. | 409 // increasing but stay above the cluster timecode. |
| 408 cb.SetClusterTimecode(5); | 410 cb.SetClusterTimecode(5); |
| 409 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 411 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 410 AddSimpleBlock(&cb, kVideoTrackNum, 10); | 412 AddSimpleBlock(&cb, kVideoTrackNum, 10); |
| 411 AddSimpleBlock(&cb, kAudioTrackNum, 7); | 413 AddSimpleBlock(&cb, kAudioTrackNum, 7); |
| 412 AddSimpleBlock(&cb, kVideoTrackNum, 15); | 414 AddSimpleBlock(&cb, kVideoTrackNum, 15); |
| 413 scoped_ptr<Cluster> clusterA(cb.Finish()); | 415 scoped_ptr<Cluster> clusterA(cb.Finish()); |
| 414 | 416 |
| 415 EXPECT_FALSE(demuxer_->AppendData(clusterA->data(), clusterA->size())); | 417 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 418 AppendData(clusterA->data(), clusterA->size()); |
| 416 | 419 |
| 417 // Test timecodes going backwards before cluster timecode. | 420 // Verify that AppendData() doesn't accept more data now. |
| 421 cb.SetClusterTimecode(20); |
| 422 AddSimpleBlock(&cb, kAudioTrackNum, 20); |
| 423 AddSimpleBlock(&cb, kVideoTrackNum, 20); |
| 424 scoped_ptr<Cluster> clusterB(cb.Finish()); |
| 425 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); |
| 426 } |
| 427 |
| 428 TEST_F(ChunkDemuxerTest, TestBackwardsAndBeforeClusterTimecode) { |
| 429 InitDemuxer(true, true); |
| 430 |
| 431 ClusterBuilder cb; |
| 432 |
| 433 // Test timecodes going backwards and including values less than the cluster |
| 434 // timecode. |
| 418 cb.SetClusterTimecode(5); | 435 cb.SetClusterTimecode(5); |
| 419 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 436 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 420 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 437 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
| 421 AddSimpleBlock(&cb, kAudioTrackNum, 3); | 438 AddSimpleBlock(&cb, kAudioTrackNum, 3); |
| 422 AddSimpleBlock(&cb, kVideoTrackNum, 3); | 439 AddSimpleBlock(&cb, kVideoTrackNum, 3); |
| 440 scoped_ptr<Cluster> clusterA(cb.Finish()); |
| 441 |
| 442 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 443 AppendData(clusterA->data(), clusterA->size()); |
| 444 |
| 445 // Verify that AppendData() doesn't accept more data now. |
| 446 cb.SetClusterTimecode(6); |
| 447 AddSimpleBlock(&cb, kAudioTrackNum, 6); |
| 448 AddSimpleBlock(&cb, kVideoTrackNum, 6); |
| 423 scoped_ptr<Cluster> clusterB(cb.Finish()); | 449 scoped_ptr<Cluster> clusterB(cb.Finish()); |
| 450 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); |
| 451 } |
| 424 | 452 |
| 425 EXPECT_FALSE(demuxer_->AppendData(clusterB->data(), clusterB->size())); | 453 |
| 454 TEST_F(ChunkDemuxerTest, TestPerStreamMonotonicallyIncreasingTimestamps) { |
| 455 InitDemuxer(true, true); |
| 456 |
| 457 ClusterBuilder cb; |
| 426 | 458 |
| 427 // Test strict monotonic increasing timestamps on a per stream | 459 // Test strict monotonic increasing timestamps on a per stream |
| 428 // basis. | 460 // basis. |
| 429 cb.SetClusterTimecode(5); | 461 cb.SetClusterTimecode(5); |
| 430 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 462 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 431 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 463 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
| 432 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 464 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 433 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 465 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
| 434 scoped_ptr<Cluster> clusterC(cb.Finish()); | 466 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 435 | 467 |
| 436 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); | 468 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 469 AppendData(cluster->data(), cluster->size()); |
| 470 } |
| 471 |
| 472 TEST_F(ChunkDemuxerTest, TestMonotonicallyIncreasingTimestampsAcrossClusters) { |
| 473 InitDemuxer(true, true); |
| 474 |
| 475 ClusterBuilder cb; |
| 437 | 476 |
| 438 // Test strict monotonic increasing timestamps on a per stream | 477 // Test strict monotonic increasing timestamps on a per stream |
| 439 // basis across clusters. | 478 // basis across clusters. |
| 440 cb.SetClusterTimecode(5); | 479 cb.SetClusterTimecode(5); |
| 441 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 480 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 442 AddSimpleBlock(&cb, kVideoTrackNum, 5); | 481 AddSimpleBlock(&cb, kVideoTrackNum, 5); |
| 443 scoped_ptr<Cluster> clusterD(cb.Finish()); | 482 scoped_ptr<Cluster> clusterA(cb.Finish()); |
| 444 | 483 |
| 445 EXPECT_TRUE(demuxer_->AppendData(clusterD->data(), clusterD->size())); | 484 AppendData(clusterA->data(), clusterA->size()); |
| 446 | 485 |
| 447 cb.SetClusterTimecode(5); | 486 cb.SetClusterTimecode(5); |
| 448 AddSimpleBlock(&cb, kAudioTrackNum, 5); | 487 AddSimpleBlock(&cb, kAudioTrackNum, 5); |
| 449 AddSimpleBlock(&cb, kVideoTrackNum, 7); | 488 AddSimpleBlock(&cb, kVideoTrackNum, 7); |
| 450 scoped_ptr<Cluster> clusterE(cb.Finish()); | 489 scoped_ptr<Cluster> clusterB(cb.Finish()); |
| 451 | 490 |
| 452 EXPECT_FALSE(demuxer_->AppendData(clusterE->data(), clusterE->size())); | 491 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 492 AppendData(clusterB->data(), clusterB->size()); |
| 493 |
| 494 // Verify that AppendData() doesn't accept more data now. |
| 495 cb.SetClusterTimecode(10); |
| 496 AddSimpleBlock(&cb, kAudioTrackNum, 10); |
| 497 AddSimpleBlock(&cb, kVideoTrackNum, 10); |
| 498 scoped_ptr<Cluster> clusterC(cb.Finish()); |
| 499 EXPECT_FALSE(demuxer_->AppendData(clusterC->data(), clusterC->size())); |
| 453 } | 500 } |
| 454 | 501 |
| 455 // Test the case where a cluster is passed to AppendData() before | 502 // Test the case where a cluster is passed to AppendData() before |
| 456 // INFO & TRACKS data. | 503 // INFO & TRACKS data. |
| 457 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { | 504 TEST_F(ChunkDemuxerTest, TestClusterBeforeInfoTracks) { |
| 458 EXPECT_CALL(*client_, DemuxerOpened(_)); | 505 EXPECT_CALL(*client_, DemuxerOpened(_)); |
| 459 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | 506 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); |
| 460 | 507 |
| 461 ClusterBuilder cb; | 508 ClusterBuilder cb; |
| 462 cb.SetClusterTimecode(0); | 509 cb.SetClusterTimecode(0); |
| 463 AddSimpleBlock(&cb, kVideoTrackNum, 0); | 510 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
| 464 scoped_ptr<Cluster> cluster(cb.Finish()); | 511 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 465 | 512 |
| 466 EXPECT_FALSE(demuxer_->AppendData(cluster->data(), cluster->size())); | 513 AppendData(cluster->data(), cluster->size()); |
| 467 } | 514 } |
| 468 | 515 |
| 469 | |
| 470 // Test cases where we get an EndOfStream() call during initialization. | 516 // Test cases where we get an EndOfStream() call during initialization. |
| 471 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { | 517 TEST_F(ChunkDemuxerTest, TestEOSDuringInit) { |
| 472 EXPECT_CALL(*client_, DemuxerOpened(_)); | 518 EXPECT_CALL(*client_, DemuxerOpened(_)); |
| 473 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); | 519 demuxer_->Init(NewExpectedStatusCB(DEMUXER_ERROR_COULD_NOT_OPEN)); |
| 474 demuxer_->EndOfStream(PIPELINE_OK); | 520 demuxer_->EndOfStream(PIPELINE_OK); |
| 475 } | 521 } |
| 522 |
| 523 TEST_F(ChunkDemuxerTest, TestDecodeErrorEndOfStream) { |
| 524 InitDemuxer(true, true); |
| 525 |
| 526 ClusterBuilder cb; |
| 527 cb.SetClusterTimecode(0); |
| 528 AddSimpleBlock(&cb, kAudioTrackNum, 0); |
| 529 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
| 530 AddSimpleBlock(&cb, kAudioTrackNum, 23); |
| 531 AddSimpleBlock(&cb, kVideoTrackNum, 33); |
| 532 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 533 AppendData(cluster->data(), cluster->size()); |
| 534 |
| 535 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_DECODE)); |
| 536 demuxer_->EndOfStream(PIPELINE_ERROR_DECODE); |
| 537 } |
| 538 |
| 539 TEST_F(ChunkDemuxerTest, TestNetworkErrorEndOfStream) { |
| 540 InitDemuxer(true, true); |
| 541 |
| 542 ClusterBuilder cb; |
| 543 cb.SetClusterTimecode(0); |
| 544 AddSimpleBlock(&cb, kAudioTrackNum, 0); |
| 545 AddSimpleBlock(&cb, kVideoTrackNum, 0); |
| 546 AddSimpleBlock(&cb, kAudioTrackNum, 23); |
| 547 AddSimpleBlock(&cb, kVideoTrackNum, 33); |
| 548 scoped_ptr<Cluster> cluster(cb.Finish()); |
| 549 AppendData(cluster->data(), cluster->size()); |
| 550 |
| 551 EXPECT_CALL(mock_filter_host_, SetError(PIPELINE_ERROR_NETWORK)); |
| 552 demuxer_->EndOfStream(PIPELINE_ERROR_NETWORK); |
| 553 } |
| 554 |
| 476 } // namespace media | 555 } // namespace media |
| OLD | NEW |