| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "media/filters/chunk_demuxer.h" | 5 #include "media/filters/chunk_demuxer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 } | 118 } |
| 119 } | 119 } |
| 120 | 120 |
| 121 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { | 121 MATCHER_P(HasTimestamp, timestamp_in_ms, "") { |
| 122 return arg.get() && !arg->end_of_stream() && | 122 return arg.get() && !arg->end_of_stream() && |
| 123 arg->timestamp().InMilliseconds() == timestamp_in_ms; | 123 arg->timestamp().InMilliseconds() == timestamp_in_ms; |
| 124 } | 124 } |
| 125 | 125 |
| 126 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } | 126 MATCHER(IsEndOfStream, "") { return arg.get() && arg->end_of_stream(); } |
| 127 | 127 |
| 128 MATCHER_P(SegmentMissingFrames, frame_types_string, "") { | 128 MATCHER_P(SegmentMissingFrames, track_id, "") { |
| 129 return CONTAINS_STRING(arg, "Media segment did not contain any " + | 129 return CONTAINS_STRING( |
| 130 std::string(frame_types_string) + | 130 arg, "Media segment did not contain any coded frames for track " + |
| 131 " coded frames, mismatching initialization " | 131 std::string(track_id)); |
| 132 "segment. Therefore, MSE coded frame " | |
| 133 "processing may not interoperably detect " | |
| 134 "discontinuities in appended media."); | |
| 135 } | 132 } |
| 136 | 133 |
| 137 MATCHER(StreamParsingFailed, "") { | 134 MATCHER(StreamParsingFailed, "") { |
| 138 return CONTAINS_STRING(arg, "Append: stream parsing failed."); | 135 return CONTAINS_STRING(arg, "Append: stream parsing failed."); |
| 139 } | 136 } |
| 140 | 137 |
| 141 MATCHER_P(FoundStream, stream_type_string, "") { | 138 MATCHER_P(FoundStream, stream_type_string, "") { |
| 142 return CONTAINS_STRING( | 139 return CONTAINS_STRING( |
| 143 arg, "found_" + std::string(stream_type_string) + "_stream") && | 140 arg, "found_" + std::string(stream_type_string) + "_stream") && |
| 144 CONTAINS_STRING(arg, "true"); | 141 CONTAINS_STRING(arg, "true"); |
| 145 } | 142 } |
| 146 | 143 |
| 147 MATCHER_P2(CodecName, stream_type_string, codec_string, "") { | 144 MATCHER_P2(CodecName, stream_type_string, codec_string, "") { |
| 148 return CONTAINS_STRING(arg, | 145 return CONTAINS_STRING(arg, |
| 149 std::string(stream_type_string) + "_codec_name") && | 146 std::string(stream_type_string) + "_codec_name") && |
| 150 CONTAINS_STRING(arg, std::string(codec_string)); | 147 CONTAINS_STRING(arg, std::string(codec_string)); |
| 151 } | 148 } |
| 152 | 149 |
| 153 MATCHER_P2(InitSegmentMismatchesMimeType, | 150 MATCHER_P2(InitSegmentMismatchesMimeType, stream_type, codec_name, "") { |
| 154 track_type_string_with_article, | 151 return CONTAINS_STRING(arg, std::string(stream_type) + " stream codec " + |
| 155 mime_missing_track_type_bool, | 152 std::string(codec_name) + |
| 156 "") { | 153 " doesn't match SourceBuffer codecs."); |
| 157 return CONTAINS_STRING( | 154 } |
| 158 arg, "Initialization segment " + | 155 |
| 159 std::string(mime_missing_track_type_bool ? "has " | 156 MATCHER_P(InitSegmentMissesExpectedTrack, missing_codec, "") { |
| 160 : "does not have ") + | 157 return CONTAINS_STRING(arg, "Initialization segment misses expected " + |
| 161 std::string(track_type_string_with_article) + | 158 std::string(missing_codec) + " track."); |
| 162 " track, but the mimetype " + | |
| 163 std::string(mime_missing_track_type_bool ? "does not specify " | |
| 164 : "specifies ") + | |
| 165 std::string(track_type_string_with_article) + " codec."); | |
| 166 } | 159 } |
| 167 | 160 |
| 168 MATCHER_P2(GeneratedSplice, duration_microseconds, time_microseconds, "") { | 161 MATCHER_P2(GeneratedSplice, duration_microseconds, time_microseconds, "") { |
| 169 return CONTAINS_STRING(arg, "Generated splice of overlap duration " + | 162 return CONTAINS_STRING(arg, "Generated splice of overlap duration " + |
| 170 base::IntToString(duration_microseconds) + | 163 base::IntToString(duration_microseconds) + |
| 171 "us into new buffer at " + | 164 "us into new buffer at " + |
| 172 base::IntToString(time_microseconds) + "us."); | 165 base::IntToString(time_microseconds) + "us."); |
| 173 } | 166 } |
| 174 | 167 |
| 175 MATCHER_P2(SkippingSpliceAtOrBefore, | 168 MATCHER_P2(SkippingSpliceAtOrBefore, |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 | 374 |
| 382 memcpy(buf, info->data(), info->data_size()); | 375 memcpy(buf, info->data(), info->data_size()); |
| 383 buf += info->data_size(); | 376 buf += info->data_size(); |
| 384 | 377 |
| 385 memcpy(buf, kTracksHeader, kTracksHeaderSize); | 378 memcpy(buf, kTracksHeader, kTracksHeaderSize); |
| 386 WriteInt64(buf + kTracksSizeOffset, tracks_element_size); | 379 WriteInt64(buf + kTracksSizeOffset, tracks_element_size); |
| 387 buf += kTracksHeaderSize; | 380 buf += kTracksHeaderSize; |
| 388 | 381 |
| 389 // TODO(xhwang): Simplify this! Probably have test data files that contain | 382 // TODO(xhwang): Simplify this! Probably have test data files that contain |
| 390 // ContentEncodings directly instead of trying to create one at run-time. | 383 // ContentEncodings directly instead of trying to create one at run-time. |
| 391 if (has_audio) { | |
| 392 memcpy(buf, audio_track_entry->data(), | |
| 393 audio_track_entry->data_size()); | |
| 394 if (is_audio_encrypted) { | |
| 395 memcpy(buf + audio_track_entry->data_size(), | |
| 396 audio_content_encodings->data(), | |
| 397 audio_content_encodings->data_size()); | |
| 398 WriteInt64(buf + kAudioTrackSizeOffset, | |
| 399 audio_track_entry->data_size() + | |
| 400 audio_content_encodings->data_size() - | |
| 401 kAudioTrackEntryHeaderSize); | |
| 402 buf += audio_content_encodings->data_size(); | |
| 403 } | |
| 404 buf += audio_track_entry->data_size(); | |
| 405 } | |
| 406 | |
| 407 if (has_video) { | 384 if (has_video) { |
| 408 memcpy(buf, video_track_entry->data(), | 385 memcpy(buf, video_track_entry->data(), |
| 409 video_track_entry->data_size()); | 386 video_track_entry->data_size()); |
| 410 if (is_video_encrypted) { | 387 if (is_video_encrypted) { |
| 411 memcpy(buf + video_track_entry->data_size(), | 388 memcpy(buf + video_track_entry->data_size(), |
| 412 video_content_encodings->data(), | 389 video_content_encodings->data(), |
| 413 video_content_encodings->data_size()); | 390 video_content_encodings->data_size()); |
| 414 WriteInt64(buf + kVideoTrackSizeOffset, | 391 WriteInt64(buf + kVideoTrackSizeOffset, |
| 415 video_track_entry->data_size() + | 392 video_track_entry->data_size() + |
| 416 video_content_encodings->data_size() - | 393 video_content_encodings->data_size() - |
| 417 kVideoTrackEntryHeaderSize); | 394 kVideoTrackEntryHeaderSize); |
| 418 buf += video_content_encodings->data_size(); | 395 buf += video_content_encodings->data_size(); |
| 419 } | 396 } |
| 420 buf += video_track_entry->data_size(); | 397 buf += video_track_entry->data_size(); |
| 421 } | 398 } |
| 422 | 399 |
| 400 if (has_audio) { |
| 401 memcpy(buf, audio_track_entry->data(), audio_track_entry->data_size()); |
| 402 if (is_audio_encrypted) { |
| 403 memcpy(buf + audio_track_entry->data_size(), |
| 404 audio_content_encodings->data(), |
| 405 audio_content_encodings->data_size()); |
| 406 WriteInt64(buf + kAudioTrackSizeOffset, |
| 407 audio_track_entry->data_size() + |
| 408 audio_content_encodings->data_size() - |
| 409 kAudioTrackEntryHeaderSize); |
| 410 buf += audio_content_encodings->data_size(); |
| 411 } |
| 412 buf += audio_track_entry->data_size(); |
| 413 } |
| 414 |
| 423 if (has_text) { | 415 if (has_text) { |
| 424 memcpy(buf, text_track_entry->data(), | 416 memcpy(buf, text_track_entry->data(), |
| 425 text_track_entry->data_size()); | 417 text_track_entry->data_size()); |
| 426 buf += text_track_entry->data_size(); | 418 buf += text_track_entry->data_size(); |
| 427 } | 419 } |
| 428 } | 420 } |
| 429 | 421 |
| 430 ChunkDemuxer::Status AddId() { | 422 ChunkDemuxer::Status AddId() { |
| 431 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); | 423 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); |
| 432 } | 424 } |
| 433 | 425 |
| 434 ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) { | 426 ChunkDemuxer::Status AddId(const std::string& source_id, int stream_flags) { |
| 435 bool has_audio = (stream_flags & HAS_AUDIO) != 0; | 427 bool has_audio = (stream_flags & HAS_AUDIO) != 0; |
| 436 bool has_video = (stream_flags & HAS_VIDEO) != 0; | 428 bool has_video = (stream_flags & HAS_VIDEO) != 0; |
| 437 std::vector<std::string> codecs; | 429 std::string codecs; |
| 438 std::string type; | 430 std::string type; |
| 439 | 431 |
| 440 if (has_audio) { | 432 if (has_audio) { |
| 441 codecs.push_back("vorbis"); | 433 codecs += "vorbis"; |
| 442 type = "audio/webm"; | 434 type = "audio/webm"; |
| 443 } | 435 } |
| 444 | 436 |
| 445 if (has_video) { | 437 if (has_video) { |
| 446 codecs.push_back("vp8"); | 438 if (codecs == "") |
| 439 codecs = "vp8"; |
| 440 else |
| 441 codecs += ",vp8"; |
| 447 type = "video/webm"; | 442 type = "video/webm"; |
| 448 } | 443 } |
| 449 | 444 |
| 450 if (!has_audio && !has_video) { | 445 if (!has_audio && !has_video) { |
| 451 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); | 446 return AddId(kSourceId, HAS_AUDIO | HAS_VIDEO); |
| 452 } | 447 } |
| 453 | 448 |
| 454 ChunkDemuxer::Status status = demuxer_->AddId(source_id, type, codecs); | 449 return AddId(source_id, type, codecs); |
| 450 } |
| 451 |
| 452 ChunkDemuxer::Status AddId(const std::string& source_id, |
| 453 const std::string& mime_type, |
| 454 const std::string& codecs) { |
| 455 ChunkDemuxer::Status status = demuxer_->AddId(source_id, mime_type, codecs); |
| 455 if (status == ChunkDemuxer::kOk) | 456 if (status == ChunkDemuxer::kOk) |
| 456 demuxer_->SetTracksWatcher( | 457 demuxer_->SetTracksWatcher( |
| 457 source_id, base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 458 source_id, base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
| 458 base::Unretained(this))); | 459 base::Unretained(this))); |
| 459 return status; | 460 return status; |
| 460 } | 461 } |
| 461 | 462 |
| 462 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | |
| 463 ChunkDemuxer::Status AddIdForMp2tSource(const std::string& source_id) { | |
| 464 std::vector<std::string> codecs; | |
| 465 std::string type = "video/mp2t"; | |
| 466 codecs.push_back("mp4a.40.2"); | |
| 467 codecs.push_back("avc1.640028"); | |
| 468 ChunkDemuxer::Status status = demuxer_->AddId(source_id, type, codecs); | |
| 469 if (status == ChunkDemuxer::kOk) | |
| 470 demuxer_->SetTracksWatcher( | |
| 471 source_id, base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | |
| 472 base::Unretained(this))); | |
| 473 return status; | |
| 474 } | |
| 475 #endif | |
| 476 | |
| 477 bool AppendData(const uint8_t* data, size_t length) { | 463 bool AppendData(const uint8_t* data, size_t length) { |
| 478 return AppendData(kSourceId, data, length); | 464 return AppendData(kSourceId, data, length); |
| 479 } | 465 } |
| 480 | 466 |
| 481 bool AppendCluster(const std::string& source_id, | 467 bool AppendCluster(const std::string& source_id, |
| 482 std::unique_ptr<Cluster> cluster) { | 468 std::unique_ptr<Cluster> cluster) { |
| 483 return AppendData(source_id, cluster->data(), cluster->size()); | 469 return AppendData(source_id, cluster->data(), cluster->size()); |
| 484 } | 470 } |
| 485 | 471 |
| 486 bool AppendCluster(std::unique_ptr<Cluster> cluster) { | 472 bool AppendCluster(std::unique_ptr<Cluster> cluster) { |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 USE_ALTERNATE_AUDIO_TRACK_ID = 1 << 3, | 797 USE_ALTERNATE_AUDIO_TRACK_ID = 1 << 3, |
| 812 USE_ALTERNATE_VIDEO_TRACK_ID = 1 << 4, | 798 USE_ALTERNATE_VIDEO_TRACK_ID = 1 << 4, |
| 813 USE_ALTERNATE_TEXT_TRACK_ID = 1 << 5, | 799 USE_ALTERNATE_TEXT_TRACK_ID = 1 << 5, |
| 814 }; | 800 }; |
| 815 | 801 |
| 816 bool InitDemuxer(int stream_flags) { | 802 bool InitDemuxer(int stream_flags) { |
| 817 return InitDemuxerWithEncryptionInfo(stream_flags, false, false); | 803 return InitDemuxerWithEncryptionInfo(stream_flags, false, false); |
| 818 } | 804 } |
| 819 | 805 |
| 820 void ExpectInitMediaLogs(int stream_flags) { | 806 void ExpectInitMediaLogs(int stream_flags) { |
| 807 if (stream_flags & HAS_VIDEO) { |
| 808 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 809 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); |
| 810 } |
| 821 if (stream_flags & HAS_AUDIO) { | 811 if (stream_flags & HAS_AUDIO) { |
| 822 EXPECT_MEDIA_LOG(FoundStream("audio")); | 812 EXPECT_MEDIA_LOG(FoundStream("audio")); |
| 823 EXPECT_MEDIA_LOG(CodecName("audio", "vorbis")); | 813 EXPECT_MEDIA_LOG(CodecName("audio", "vorbis")); |
| 824 } | 814 } |
| 825 | |
| 826 if (stream_flags & HAS_VIDEO) { | |
| 827 EXPECT_MEDIA_LOG(FoundStream("video")); | |
| 828 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); | |
| 829 } | |
| 830 } | 815 } |
| 831 | 816 |
| 832 bool InitDemuxerWithEncryptionInfo( | 817 bool InitDemuxerWithEncryptionInfo( |
| 833 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) { | 818 int stream_flags, bool is_audio_encrypted, bool is_video_encrypted) { |
| 834 PipelineStatus expected_status = | 819 PipelineStatus expected_status = |
| 835 (stream_flags != 0) ? PIPELINE_OK : CHUNK_DEMUXER_ERROR_APPEND_FAILED; | 820 (stream_flags != 0) ? PIPELINE_OK : CHUNK_DEMUXER_ERROR_APPEND_FAILED; |
| 836 | 821 |
| 837 base::TimeDelta expected_duration = kNoTimestamp; | 822 base::TimeDelta expected_duration = kNoTimestamp; |
| 838 if (expected_status == PIPELINE_OK) | 823 if (expected_status == PIPELINE_OK) |
| 839 expected_duration = kDefaultDuration(); | 824 expected_duration = kDefaultDuration(); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 857 | 842 |
| 858 // Adding expectations prior to CreateInitDoneCB() here because InSequence | 843 // Adding expectations prior to CreateInitDoneCB() here because InSequence |
| 859 // tests require init segment received before duration set. Also, only | 844 // tests require init segment received before duration set. Also, only |
| 860 // expect an init segment received callback if there is actually a track in | 845 // expect an init segment received callback if there is actually a track in |
| 861 // it. | 846 // it. |
| 862 if (stream_flags != 0) { | 847 if (stream_flags != 0) { |
| 863 ExpectInitMediaLogs(stream_flags); | 848 ExpectInitMediaLogs(stream_flags); |
| 864 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); | 849 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); |
| 865 } else { | 850 } else { |
| 866 // OnNewConfigs() requires at least one audio, video, or text track. | 851 // OnNewConfigs() requires at least one audio, video, or text track. |
| 852 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vorbis")); |
| 853 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vp8")); |
| 867 EXPECT_MEDIA_LOG(StreamParsingFailed()); | 854 EXPECT_MEDIA_LOG(StreamParsingFailed()); |
| 868 } | 855 } |
| 869 | 856 |
| 870 demuxer_->Initialize( | 857 demuxer_->Initialize( |
| 871 &host_, CreateInitDoneCB(expected_duration, expected_status), true); | 858 &host_, CreateInitDoneCB(expected_duration, expected_status), true); |
| 872 | 859 |
| 873 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) | 860 if (AddId(kSourceId, stream_flags) != ChunkDemuxer::kOk) |
| 874 return false; | 861 return false; |
| 875 | 862 |
| 876 return AppendInitSegmentWithEncryptedInfo( | 863 return AppendInitSegmentWithEncryptedInfo( |
| (...skipping 1526 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2403 kSourceId, &tmp, 1, append_window_start_for_next_append_, | 2390 kSourceId, &tmp, 1, append_window_start_for_next_append_, |
| 2404 append_window_end_for_next_append_, ×tamp_offset_map_[kSourceId])); | 2391 append_window_end_for_next_append_, ×tamp_offset_map_[kSourceId])); |
| 2405 } | 2392 } |
| 2406 | 2393 |
| 2407 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) { | 2394 TEST_F(ChunkDemuxerTest, AVHeadersWithAudioOnlyType) { |
| 2408 EXPECT_CALL(*this, DemuxerOpened()); | 2395 EXPECT_CALL(*this, DemuxerOpened()); |
| 2409 demuxer_->Initialize( | 2396 demuxer_->Initialize( |
| 2410 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), | 2397 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), |
| 2411 true); | 2398 true); |
| 2412 | 2399 |
| 2413 std::vector<std::string> codecs(1); | 2400 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", "vorbis"), |
| 2414 codecs[0] = "vorbis"; | |
| 2415 ASSERT_EQ(demuxer_->AddId(kSourceId, "audio/webm", codecs), | |
| 2416 ChunkDemuxer::kOk); | 2401 ChunkDemuxer::kOk); |
| 2417 demuxer_->SetTracksWatcher(kSourceId, | 2402 demuxer_->SetTracksWatcher(kSourceId, |
| 2418 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 2403 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
| 2419 base::Unretained(this))); | 2404 base::Unretained(this))); |
| 2420 | 2405 |
| 2421 // Video track is unexpected per mimetype. | 2406 // Video track is unexpected per mimetype. |
| 2422 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("a video", true)); | 2407 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Video", "vp8")); |
| 2423 EXPECT_MEDIA_LOG(StreamParsingFailed()); | 2408 EXPECT_MEDIA_LOG(StreamParsingFailed()); |
| 2424 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO)); | 2409 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO)); |
| 2425 } | 2410 } |
| 2426 | 2411 |
| 2427 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { | 2412 TEST_F(ChunkDemuxerTest, AVHeadersWithVideoOnlyType) { |
| 2428 EXPECT_CALL(*this, DemuxerOpened()); | 2413 EXPECT_CALL(*this, DemuxerOpened()); |
| 2429 demuxer_->Initialize( | 2414 demuxer_->Initialize( |
| 2430 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), | 2415 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), |
| 2431 true); | 2416 true); |
| 2432 | 2417 |
| 2433 std::vector<std::string> codecs(1); | 2418 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", "vp8"), ChunkDemuxer::kOk); |
| 2434 codecs[0] = "vp8"; | |
| 2435 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), | |
| 2436 ChunkDemuxer::kOk); | |
| 2437 demuxer_->SetTracksWatcher(kSourceId, | 2419 demuxer_->SetTracksWatcher(kSourceId, |
| 2438 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 2420 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
| 2439 base::Unretained(this))); | 2421 base::Unretained(this))); |
| 2440 | 2422 |
| 2441 // Audio track is unexpected per mimetype. | 2423 // Audio track is unexpected per mimetype. |
| 2442 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("an audio", true)); | 2424 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 2425 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); |
| 2426 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("Audio", "vorbis")); |
| 2443 EXPECT_MEDIA_LOG(StreamParsingFailed()); | 2427 EXPECT_MEDIA_LOG(StreamParsingFailed()); |
| 2444 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO)); | 2428 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO | HAS_VIDEO)); |
| 2445 } | 2429 } |
| 2446 | 2430 |
| 2447 TEST_F(ChunkDemuxerTest, AudioOnlyHeaderWithAVType) { | 2431 TEST_F(ChunkDemuxerTest, AudioOnlyHeaderWithAVType) { |
| 2448 EXPECT_CALL(*this, DemuxerOpened()); | 2432 EXPECT_CALL(*this, DemuxerOpened()); |
| 2449 demuxer_->Initialize( | 2433 demuxer_->Initialize( |
| 2450 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), | 2434 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), |
| 2451 true); | 2435 true); |
| 2452 | 2436 |
| 2453 std::vector<std::string> codecs(2); | 2437 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", "vorbis,vp8"), |
| 2454 codecs[0] = "vorbis"; | |
| 2455 codecs[1] = "vp8"; | |
| 2456 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), | |
| 2457 ChunkDemuxer::kOk); | 2438 ChunkDemuxer::kOk); |
| 2458 demuxer_->SetTracksWatcher(kSourceId, | 2439 demuxer_->SetTracksWatcher(kSourceId, |
| 2459 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 2440 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
| 2460 base::Unretained(this))); | 2441 base::Unretained(this))); |
| 2461 | 2442 |
| 2462 // Video track is also expected per mimetype. | 2443 // Video track is also expected per mimetype. |
| 2463 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("a video", false)); | 2444 EXPECT_MEDIA_LOG(FoundStream("audio")); |
| 2445 EXPECT_MEDIA_LOG(CodecName("audio", "vorbis")); |
| 2446 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vp8")); |
| 2464 EXPECT_MEDIA_LOG(StreamParsingFailed()); | 2447 EXPECT_MEDIA_LOG(StreamParsingFailed()); |
| 2465 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO)); | 2448 ASSERT_FALSE(AppendInitSegment(HAS_AUDIO)); |
| 2466 } | 2449 } |
| 2467 | 2450 |
| 2468 TEST_F(ChunkDemuxerTest, VideoOnlyHeaderWithAVType) { | 2451 TEST_F(ChunkDemuxerTest, VideoOnlyHeaderWithAVType) { |
| 2469 EXPECT_CALL(*this, DemuxerOpened()); | 2452 EXPECT_CALL(*this, DemuxerOpened()); |
| 2470 demuxer_->Initialize( | 2453 demuxer_->Initialize( |
| 2471 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), | 2454 &host_, CreateInitDoneCB(kNoTimestamp, CHUNK_DEMUXER_ERROR_APPEND_FAILED), |
| 2472 true); | 2455 true); |
| 2473 | 2456 |
| 2474 std::vector<std::string> codecs(2); | 2457 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", "vorbis,vp8"), |
| 2475 codecs[0] = "vorbis"; | |
| 2476 codecs[1] = "vp8"; | |
| 2477 ASSERT_EQ(demuxer_->AddId(kSourceId, "video/webm", codecs), | |
| 2478 ChunkDemuxer::kOk); | 2458 ChunkDemuxer::kOk); |
| 2479 demuxer_->SetTracksWatcher(kSourceId, | 2459 demuxer_->SetTracksWatcher(kSourceId, |
| 2480 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, | 2460 base::Bind(&ChunkDemuxerTest::InitSegmentReceived, |
| 2481 base::Unretained(this))); | 2461 base::Unretained(this))); |
| 2482 | 2462 |
| 2483 // Audio track is also expected per mimetype. | 2463 // Audio track is also expected per mimetype. |
| 2484 EXPECT_MEDIA_LOG(InitSegmentMismatchesMimeType("an audio", false)); | 2464 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 2465 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); |
| 2466 EXPECT_MEDIA_LOG(InitSegmentMissesExpectedTrack("vorbis")); |
| 2485 EXPECT_MEDIA_LOG(StreamParsingFailed()); | 2467 EXPECT_MEDIA_LOG(StreamParsingFailed()); |
| 2486 ASSERT_FALSE(AppendInitSegment(HAS_VIDEO)); | 2468 ASSERT_FALSE(AppendInitSegment(HAS_VIDEO)); |
| 2487 } | 2469 } |
| 2488 | 2470 |
| 2489 TEST_F(ChunkDemuxerTest, MultipleHeaders) { | 2471 TEST_F(ChunkDemuxerTest, MultipleHeaders) { |
| 2490 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 2472 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 2491 | 2473 |
| 2492 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster())); | 2474 ASSERT_TRUE(AppendCluster(kDefaultFirstCluster())); |
| 2493 | 2475 |
| 2494 // Append another identical initialization segment. | 2476 // Append another identical initialization segment. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2541 TEST_F(ChunkDemuxerTest, AddIdFailures) { | 2523 TEST_F(ChunkDemuxerTest, AddIdFailures) { |
| 2542 EXPECT_CALL(*this, DemuxerOpened()); | 2524 EXPECT_CALL(*this, DemuxerOpened()); |
| 2543 demuxer_->Initialize( | 2525 demuxer_->Initialize( |
| 2544 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); | 2526 &host_, CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
| 2545 | 2527 |
| 2546 std::string audio_id = "audio1"; | 2528 std::string audio_id = "audio1"; |
| 2547 std::string video_id = "video1"; | 2529 std::string video_id = "video1"; |
| 2548 | 2530 |
| 2549 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk); | 2531 ASSERT_EQ(AddId(audio_id, HAS_AUDIO), ChunkDemuxer::kOk); |
| 2550 | 2532 |
| 2551 // Adding an id with audio/video should fail because we already added audio. | |
| 2552 ASSERT_EQ(AddId(), ChunkDemuxer::kReachedIdLimit); | |
| 2553 | |
| 2554 ExpectInitMediaLogs(HAS_AUDIO); | 2533 ExpectInitMediaLogs(HAS_AUDIO); |
| 2555 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); | 2534 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); |
| 2556 ASSERT_TRUE(AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO)); | 2535 ASSERT_TRUE(AppendInitSegmentWithSourceId(audio_id, HAS_AUDIO)); |
| 2557 | 2536 |
| 2558 // Adding an id after append should fail. | 2537 // Adding an id after append should fail. |
| 2559 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit); | 2538 ASSERT_EQ(AddId(video_id, HAS_VIDEO), ChunkDemuxer::kReachedIdLimit); |
| 2560 } | 2539 } |
| 2561 | 2540 |
| 2562 // Test that Read() calls after a RemoveId() return "end of stream" buffers. | 2541 // Test that Read() calls after a RemoveId() return "end of stream" buffers. |
| 2563 TEST_F(ChunkDemuxerTest, RemoveId) { | 2542 TEST_F(ChunkDemuxerTest, RemoveId) { |
| 2564 std::string audio_id = "audio1"; | 2543 std::string audio_id = "audio1"; |
| 2565 std::string video_id = "video1"; | 2544 std::string video_id = "video1"; |
| 2566 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); | 2545 ASSERT_TRUE(InitDemuxerAudioAndVideoSources(audio_id, video_id)); |
| 2567 | 2546 |
| 2568 // Append audio and video data into separate source ids. | 2547 // Append audio and video data into separate source ids. |
| 2569 ASSERT_TRUE(AppendCluster( | 2548 ASSERT_TRUE(AppendCluster( |
| 2570 audio_id, | 2549 audio_id, |
| 2571 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration))); | 2550 GenerateSingleStreamCluster(0, 92, kAudioTrackNum, kAudioBlockDuration))); |
| 2572 ASSERT_TRUE(AppendCluster(video_id, | 2551 ASSERT_TRUE(AppendCluster(video_id, |
| 2573 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, | 2552 GenerateSingleStreamCluster(0, 132, kVideoTrackNum, |
| 2574 kVideoBlockDuration))); | 2553 kVideoBlockDuration))); |
| 2575 | 2554 |
| 2576 // Read() from audio should return normal buffers. | 2555 // Read() from audio should return normal buffers. |
| 2577 GenerateAudioStreamExpectedReads(0, 4); | 2556 GenerateAudioStreamExpectedReads(0, 4); |
| 2578 | 2557 |
| 2558 // Audio stream will become inaccessible after |audio_id| is removed, so save |
| 2559 // it here to read from it after RemoveId. |
| 2560 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 2561 |
| 2579 // Remove the audio id. | 2562 // Remove the audio id. |
| 2580 demuxer_->RemoveId(audio_id); | 2563 demuxer_->RemoveId(audio_id); |
| 2581 | 2564 |
| 2582 // Read() from audio should return "end of stream" buffers. | 2565 // Read() from audio should return "end of stream" buffers. |
| 2583 bool audio_read_done = false; | 2566 bool audio_read_done = false; |
| 2584 ReadAudio(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); | 2567 audio_stream->Read(base::Bind(&OnReadDone_EOSExpected, &audio_read_done)); |
| 2585 base::RunLoop().RunUntilIdle(); | 2568 base::RunLoop().RunUntilIdle(); |
| 2586 EXPECT_TRUE(audio_read_done); | 2569 EXPECT_TRUE(audio_read_done); |
| 2587 | 2570 |
| 2588 // Read() from video should still return normal buffers. | 2571 // Read() from video should still return normal buffers. |
| 2589 GenerateVideoStreamExpectedReads(0, 4); | 2572 GenerateVideoStreamExpectedReads(0, 4); |
| 2590 } | 2573 } |
| 2591 | 2574 |
| 2592 // Test that removing an ID immediately after adding it does not interfere with | 2575 // Test that removing an ID immediately after adding it does not interfere with |
| 2593 // quota for new IDs in the future. | 2576 // quota for new IDs in the future. |
| 2594 TEST_F(ChunkDemuxerTest, RemoveAndAddId) { | 2577 TEST_F(ChunkDemuxerTest, RemoveAndAddId) { |
| (...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3140 | 3123 |
| 3141 #if defined(USE_PROPRIETARY_CODECS) | 3124 #if defined(USE_PROPRIETARY_CODECS) |
| 3142 #if defined(OS_ANDROID) | 3125 #if defined(OS_ANDROID) |
| 3143 if (HasPlatformDecoderSupport()) | 3126 if (HasPlatformDecoderSupport()) |
| 3144 expected = ChunkDemuxer::kOk; | 3127 expected = ChunkDemuxer::kOk; |
| 3145 #else | 3128 #else |
| 3146 expected = ChunkDemuxer::kOk; | 3129 expected = ChunkDemuxer::kOk; |
| 3147 #endif | 3130 #endif |
| 3148 #endif | 3131 #endif |
| 3149 | 3132 |
| 3150 std::vector<std::string> codecs; | 3133 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", "avc1.4D4041"), expected); |
| 3151 codecs.push_back("avc1.4D4041"); | |
| 3152 | |
| 3153 EXPECT_EQ(demuxer_->AddId("source_id", "video/mp4", codecs), expected); | |
| 3154 } | 3134 } |
| 3155 | 3135 |
| 3156 // Test codec ID's that are not compliant with RFC6381, but have been | 3136 // Test codec ID's that are not compliant with RFC6381, but have been |
| 3157 // seen in the wild. | 3137 // seen in the wild. |
| 3158 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) { | 3138 TEST_F(ChunkDemuxerTest, CodecIDsThatAreNotRFC6381Compliant) { |
| 3159 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; | 3139 ChunkDemuxer::Status expected = ChunkDemuxer::kNotSupported; |
| 3160 | 3140 |
| 3161 #if defined(USE_PROPRIETARY_CODECS) | 3141 #if defined(USE_PROPRIETARY_CODECS) |
| 3162 expected = ChunkDemuxer::kOk; | 3142 expected = ChunkDemuxer::kOk; |
| 3163 #endif | 3143 #endif |
| 3164 const char* codec_ids[] = { | 3144 const char* codec_ids[] = { |
| 3165 // GPAC places leading zeros on the audio object type. | 3145 // GPAC places leading zeros on the audio object type. |
| 3166 "mp4a.40.02", | 3146 "mp4a.40.02", |
| 3167 "mp4a.40.05" | 3147 "mp4a.40.05" |
| 3168 }; | 3148 }; |
| 3169 | 3149 |
| 3170 for (size_t i = 0; i < arraysize(codec_ids); ++i) { | 3150 for (size_t i = 0; i < arraysize(codec_ids); ++i) { |
| 3171 std::vector<std::string> codecs; | |
| 3172 codecs.push_back(codec_ids[i]); | |
| 3173 | |
| 3174 ChunkDemuxer::Status result = | 3151 ChunkDemuxer::Status result = |
| 3175 demuxer_->AddId("source_id", "audio/mp4", codecs); | 3152 demuxer_->AddId("source_id", "audio/mp4", codec_ids[i]); |
| 3176 | 3153 |
| 3177 EXPECT_EQ(result, expected) | 3154 EXPECT_EQ(result, expected) |
| 3178 << "Fail to add codec_id '" << codec_ids[i] << "'"; | 3155 << "Fail to add codec_id '" << codec_ids[i] << "'"; |
| 3179 | 3156 |
| 3180 if (result == ChunkDemuxer::kOk) | 3157 if (result == ChunkDemuxer::kOk) |
| 3181 demuxer_->RemoveId("source_id"); | 3158 demuxer_->RemoveId("source_id"); |
| 3182 } | 3159 } |
| 3183 } | 3160 } |
| 3184 | 3161 |
| 3185 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) { | 3162 TEST_F(ChunkDemuxerTest, EndOfStreamStillSetAfterSeek) { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3467 append_window_end_for_next_append_, | 3444 append_window_end_for_next_append_, |
| 3468 ×tamp_offset_map_[kSourceId]); | 3445 ×tamp_offset_map_[kSourceId]); |
| 3469 | 3446 |
| 3470 // After ResetParserState(), parsing should no longer be in the middle of a | 3447 // After ResetParserState(), parsing should no longer be in the middle of a |
| 3471 // media segment. | 3448 // media segment. |
| 3472 ASSERT_FALSE(demuxer_->IsParsingMediaSegment(kSourceId)); | 3449 ASSERT_FALSE(demuxer_->IsParsingMediaSegment(kSourceId)); |
| 3473 } | 3450 } |
| 3474 | 3451 |
| 3475 #if defined(USE_PROPRIETARY_CODECS) | 3452 #if defined(USE_PROPRIETARY_CODECS) |
| 3476 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) | 3453 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) |
| 3454 namespace { |
| 3455 const char* kMp2tMimeType = "video/mp2t"; |
| 3456 const char* kMp2tCodecs = "mp4a.40.2,avc1.640028"; |
| 3457 } |
| 3458 |
| 3477 TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) { | 3459 TEST_F(ChunkDemuxerTest, EmitBuffersDuringAbort) { |
| 3478 EXPECT_CALL(*this, DemuxerOpened()); | 3460 EXPECT_CALL(*this, DemuxerOpened()); |
| 3479 EXPECT_MEDIA_LOG(FoundStream("audio")); | 3461 EXPECT_MEDIA_LOG(FoundStream("audio")); |
| 3480 EXPECT_MEDIA_LOG(CodecName("audio", "aac")); | 3462 EXPECT_MEDIA_LOG(CodecName("audio", "aac")); |
| 3481 EXPECT_MEDIA_LOG(FoundStream("video")); | 3463 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 3482 EXPECT_MEDIA_LOG(CodecName("video", "h264")); | 3464 EXPECT_MEDIA_LOG(CodecName("video", "h264")); |
| 3483 demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK), | 3465 demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK), |
| 3484 true); | 3466 true); |
| 3485 EXPECT_EQ(ChunkDemuxer::kOk, AddIdForMp2tSource(kSourceId)); | 3467 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs)); |
| 3486 | 3468 |
| 3487 // For info: | 3469 // For info: |
| 3488 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode | 3470 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode |
| 3489 // Video: first PES: | 3471 // Video: first PES: |
| 3490 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101] | 3472 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101] |
| 3491 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767] | 3473 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767] |
| 3492 // Audio: first PES: | 3474 // Audio: first PES: |
| 3493 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000] | 3475 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000] |
| 3494 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767] | 3476 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767] |
| 3495 // Video: last PES: | 3477 // Video: last PES: |
| (...skipping 27 matching lines...) Expand all Loading... |
| 3523 } | 3505 } |
| 3524 | 3506 |
| 3525 TEST_F(ChunkDemuxerTest, SeekCompleteDuringAbort) { | 3507 TEST_F(ChunkDemuxerTest, SeekCompleteDuringAbort) { |
| 3526 EXPECT_CALL(*this, DemuxerOpened()); | 3508 EXPECT_CALL(*this, DemuxerOpened()); |
| 3527 EXPECT_MEDIA_LOG(FoundStream("audio")); | 3509 EXPECT_MEDIA_LOG(FoundStream("audio")); |
| 3528 EXPECT_MEDIA_LOG(CodecName("audio", "aac")); | 3510 EXPECT_MEDIA_LOG(CodecName("audio", "aac")); |
| 3529 EXPECT_MEDIA_LOG(FoundStream("video")); | 3511 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 3530 EXPECT_MEDIA_LOG(CodecName("video", "h264")); | 3512 EXPECT_MEDIA_LOG(CodecName("video", "h264")); |
| 3531 demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK), | 3513 demuxer_->Initialize(&host_, CreateInitDoneCB(kInfiniteDuration, PIPELINE_OK), |
| 3532 true); | 3514 true); |
| 3533 EXPECT_EQ(ChunkDemuxer::kOk, AddIdForMp2tSource(kSourceId)); | 3515 EXPECT_EQ(ChunkDemuxer::kOk, AddId(kSourceId, kMp2tMimeType, kMp2tCodecs)); |
| 3534 | 3516 |
| 3535 // For info: | 3517 // For info: |
| 3536 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode | 3518 // DTS/PTS derived using dvbsnoop -s ts -if bear-1280x720.ts -tssubdecode |
| 3537 // Video: first PES: | 3519 // Video: first PES: |
| 3538 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101] | 3520 // PTS: 126912 (0x0001efc0) [= 90 kHz-Timestamp: 0:00:01.4101] |
| 3539 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767] | 3521 // DTS: 123909 (0x0001e405) [= 90 kHz-Timestamp: 0:00:01.3767] |
| 3540 // Audio: first PES: | 3522 // Audio: first PES: |
| 3541 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000] | 3523 // PTS: 126000 (0x0001ec30) [= 90 kHz-Timestamp: 0:00:01.4000] |
| 3542 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767] | 3524 // DTS: 123910 (0x0001e406) [= 90 kHz-Timestamp: 0:00:01.3767] |
| 3543 // Video: last PES: | 3525 // Video: last PES: |
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3810 Seek(seek_time); | 3792 Seek(seek_time); |
| 3811 | 3793 |
| 3812 // Append data to satisfy the seek. | 3794 // Append data to satisfy the seek. |
| 3813 ASSERT_TRUE(AppendCluster(seek_time.InMilliseconds(), 10)); | 3795 ASSERT_TRUE(AppendCluster(seek_time.InMilliseconds(), 10)); |
| 3814 } | 3796 } |
| 3815 | 3797 |
| 3816 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { | 3798 TEST_F(ChunkDemuxerTest, SetMemoryLimitType) { |
| 3817 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 3799 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 3818 | 3800 |
| 3819 // Set different memory limits for audio and video. | 3801 // Set different memory limits for audio and video. |
| 3820 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3802 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3821 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 5 * kBlockSize + 1); | 3803 demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 5 * kBlockSize + 1); |
| 3822 | 3804 |
| 3823 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); | 3805 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1000); |
| 3824 | 3806 |
| 3825 // Append data at the start that can be garbage collected: | 3807 // Append data at the start that can be garbage collected: |
| 3826 AppendMuxedCluster( | 3808 AppendMuxedCluster( |
| 3827 MuxedStreamInfo(kAudioTrackNum, | 3809 MuxedStreamInfo(kAudioTrackNum, |
| 3828 "0K 23K 46K 69K 92K 115K 138K 161K 184K 207K", 23), | 3810 "0K 23K 46K 69K 92K 115K 138K 161K 184K 207K", 23), |
| 3829 MuxedStreamInfo(kVideoTrackNum, "0K 33K 66K 99K 132K", 33)); | 3811 MuxedStreamInfo(kVideoTrackNum, "0K 33K 66K 99K 132K", 33)); |
| 3830 | 3812 |
| 3831 // We should be right at buffer limit, should pass | 3813 // We should be right at buffer limit, should pass |
| (...skipping 16 matching lines...) Expand all Loading... |
| 3848 // We should delete first append, and be exactly at buffer limit | 3830 // We should delete first append, and be exactly at buffer limit |
| 3849 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 0)); | 3831 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 0)); |
| 3850 | 3832 |
| 3851 // Verify that the old data, and nothing more, has been garbage collected. | 3833 // Verify that the old data, and nothing more, has been garbage collected. |
| 3852 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); | 3834 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [1000,1230) }"); |
| 3853 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); | 3835 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [1000,1165) }"); |
| 3854 } | 3836 } |
| 3855 | 3837 |
| 3856 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) { | 3838 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekForward) { |
| 3857 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3839 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3858 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3840 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3859 // Append some data at position 1000ms | 3841 // Append some data at position 1000ms |
| 3860 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); | 3842 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); |
| 3861 CheckExpectedRanges("{ [1000,1230) }"); | 3843 CheckExpectedRanges("{ [1000,1230) }"); |
| 3862 | 3844 |
| 3863 // GC should be able to evict frames in the currently buffered range, since | 3845 // GC should be able to evict frames in the currently buffered range, since |
| 3864 // those frames are earlier than the seek target position. | 3846 // those frames are earlier than the seek target position. |
| 3865 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000); | 3847 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2000); |
| 3866 Seek(seek_time); | 3848 Seek(seek_time); |
| 3867 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); | 3849 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); |
| 3868 | 3850 |
| 3869 // Append data to complete seek operation | 3851 // Append data to complete seek operation |
| 3870 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); | 3852 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); |
| 3871 CheckExpectedRanges("{ [1115,1230) [2000,2115) }"); | 3853 CheckExpectedRanges("{ [1115,1230) [2000,2115) }"); |
| 3872 } | 3854 } |
| 3873 | 3855 |
| 3874 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) { | 3856 TEST_F(ChunkDemuxerTest, GCDuringSeek_SingleRange_SeekBack) { |
| 3875 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3857 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3876 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3858 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3877 // Append some data at position 1000ms | 3859 // Append some data at position 1000ms |
| 3878 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); | 3860 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 10); |
| 3879 CheckExpectedRanges("{ [1000,1230) }"); | 3861 CheckExpectedRanges("{ [1000,1230) }"); |
| 3880 | 3862 |
| 3881 // GC should be able to evict frames in the currently buffered range, since | 3863 // GC should be able to evict frames in the currently buffered range, since |
| 3882 // seek target position has no data and so we should allow some frames to be | 3864 // seek target position has no data and so we should allow some frames to be |
| 3883 // evicted to make space for the upcoming append at seek target position. | 3865 // evicted to make space for the upcoming append at seek target position. |
| 3884 base::TimeDelta seek_time = base::TimeDelta(); | 3866 base::TimeDelta seek_time = base::TimeDelta(); |
| 3885 Seek(seek_time); | 3867 Seek(seek_time); |
| 3886 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); | 3868 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); |
| 3887 | 3869 |
| 3888 // Append data to complete seek operation | 3870 // Append data to complete seek operation |
| 3889 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); | 3871 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); |
| 3890 CheckExpectedRanges("{ [0,115) [1115,1230) }"); | 3872 CheckExpectedRanges("{ [0,115) [1115,1230) }"); |
| 3891 } | 3873 } |
| 3892 | 3874 |
| 3893 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) { | 3875 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekForward) { |
| 3894 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3876 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3895 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3877 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3896 // Append some data at position 1000ms then at 2000ms | 3878 // Append some data at position 1000ms then at 2000ms |
| 3897 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); | 3879 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); |
| 3898 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); | 3880 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); |
| 3899 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); | 3881 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); |
| 3900 | 3882 |
| 3901 // GC should be able to evict frames in the currently buffered ranges, since | 3883 // GC should be able to evict frames in the currently buffered ranges, since |
| 3902 // those frames are earlier than the seek target position. | 3884 // those frames are earlier than the seek target position. |
| 3903 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(3000); | 3885 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(3000); |
| 3904 Seek(seek_time); | 3886 Seek(seek_time); |
| 3905 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); | 3887 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); |
| 3906 | 3888 |
| 3907 // Append data to complete seek operation | 3889 // Append data to complete seek operation |
| 3908 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3000, 5); | 3890 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 3000, 5); |
| 3909 CheckExpectedRanges("{ [2069,2115) [3000,3115) }"); | 3891 CheckExpectedRanges("{ [2069,2115) [3000,3115) }"); |
| 3910 } | 3892 } |
| 3911 | 3893 |
| 3912 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) { | 3894 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween1) { |
| 3913 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3895 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3914 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3896 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3915 // Append some data at position 1000ms then at 2000ms | 3897 // Append some data at position 1000ms then at 2000ms |
| 3916 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); | 3898 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); |
| 3917 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); | 3899 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); |
| 3918 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); | 3900 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); |
| 3919 | 3901 |
| 3920 // GC should be able to evict all frames from the first buffered range, since | 3902 // GC should be able to evict all frames from the first buffered range, since |
| 3921 // those frames are earlier than the seek target position. But there's only 5 | 3903 // those frames are earlier than the seek target position. But there's only 5 |
| 3922 // blocks worth of data in the first range and seek target position has no | 3904 // blocks worth of data in the first range and seek target position has no |
| 3923 // data, so GC proceeds with trying to delete some frames from the back of | 3905 // data, so GC proceeds with trying to delete some frames from the back of |
| 3924 // buffered ranges, that doesn't yield anything, since that's the most | 3906 // buffered ranges, that doesn't yield anything, since that's the most |
| 3925 // recently appended data, so then GC starts removing data from the front of | 3907 // recently appended data, so then GC starts removing data from the front of |
| 3926 // the remaining buffered range (2000ms) to ensure we free up enough space for | 3908 // the remaining buffered range (2000ms) to ensure we free up enough space for |
| 3927 // the upcoming append and allow seek to proceed. | 3909 // the upcoming append and allow seek to proceed. |
| 3928 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1500); | 3910 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(1500); |
| 3929 Seek(seek_time); | 3911 Seek(seek_time); |
| 3930 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); | 3912 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); |
| 3931 | 3913 |
| 3932 // Append data to complete seek operation | 3914 // Append data to complete seek operation |
| 3933 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); | 3915 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); |
| 3934 CheckExpectedRanges("{ [1500,1615) [2069,2115) }"); | 3916 CheckExpectedRanges("{ [1500,1615) [2069,2115) }"); |
| 3935 } | 3917 } |
| 3936 | 3918 |
| 3937 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) { | 3919 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekInbetween2) { |
| 3938 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3920 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3939 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3921 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3940 | 3922 |
| 3941 // Append some data at position 2000ms first, then at 1000ms, so that the last | 3923 // Append some data at position 2000ms first, then at 1000ms, so that the last |
| 3942 // appended data position is in the first buffered range (that matters to the | 3924 // appended data position is in the first buffered range (that matters to the |
| 3943 // GC algorithm since it tries to preserve more recently appended data). | 3925 // GC algorithm since it tries to preserve more recently appended data). |
| 3944 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); | 3926 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); |
| 3945 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); | 3927 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); |
| 3946 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); | 3928 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); |
| 3947 | 3929 |
| 3948 // Now try performing garbage collection without announcing seek first, i.e. | 3930 // Now try performing garbage collection without announcing seek first, i.e. |
| 3949 // without calling Seek(), the GC algorithm should try to preserve data in the | 3931 // without calling Seek(), the GC algorithm should try to preserve data in the |
| 3950 // first range, since that is most recently appended data. | 3932 // first range, since that is most recently appended data. |
| 3951 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2030); | 3933 base::TimeDelta seek_time = base::TimeDelta::FromMilliseconds(2030); |
| 3952 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); | 3934 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 5 * kBlockSize)); |
| 3953 | 3935 |
| 3954 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); | 3936 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1500, 5); |
| 3955 CheckExpectedRanges("{ [1000,1115) [1500,1615) }"); | 3937 CheckExpectedRanges("{ [1000,1115) [1500,1615) }"); |
| 3956 } | 3938 } |
| 3957 | 3939 |
| 3958 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) { | 3940 TEST_F(ChunkDemuxerTest, GCDuringSeek_MultipleRanges_SeekBack) { |
| 3959 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3941 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3960 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 3942 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 3961 // Append some data at position 1000ms then at 2000ms | 3943 // Append some data at position 1000ms then at 2000ms |
| 3962 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); | 3944 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 1000, 5); |
| 3963 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); | 3945 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 2000, 5); |
| 3964 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); | 3946 CheckExpectedRanges("{ [1000,1115) [2000,2115) }"); |
| 3965 | 3947 |
| 3966 // GC should be able to evict frames in the currently buffered ranges, since | 3948 // GC should be able to evict frames in the currently buffered ranges, since |
| 3967 // those frames are earlier than the seek target position. | 3949 // those frames are earlier than the seek target position. |
| 3968 base::TimeDelta seek_time = base::TimeDelta(); | 3950 base::TimeDelta seek_time = base::TimeDelta(); |
| 3969 Seek(seek_time); | 3951 Seek(seek_time); |
| 3970 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); | 3952 EXPECT_TRUE(demuxer_->EvictCodedFrames(kSourceId, seek_time, 8 * kBlockSize)); |
| 3971 | 3953 |
| 3972 // Append data to complete seek operation | 3954 // Append data to complete seek operation |
| 3973 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); | 3955 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 5); |
| 3974 CheckExpectedRanges("{ [0,115) [2069,2115) }"); | 3956 CheckExpectedRanges("{ [0,115) [2069,2115) }"); |
| 3975 } | 3957 } |
| 3976 | 3958 |
| 3977 TEST_F(ChunkDemuxerTest, GCDuringSeek) { | 3959 TEST_F(ChunkDemuxerTest, GCDuringSeek) { |
| 3978 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 3960 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 3979 | 3961 |
| 3980 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); | 3962 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * kBlockSize); |
| 3981 | 3963 |
| 3982 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); | 3964 base::TimeDelta seek_time1 = base::TimeDelta::FromMilliseconds(1000); |
| 3983 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); | 3965 base::TimeDelta seek_time2 = base::TimeDelta::FromMilliseconds(500); |
| 3984 | 3966 |
| 3985 // Initiate a seek to |seek_time1|. | 3967 // Initiate a seek to |seek_time1|. |
| 3986 Seek(seek_time1); | 3968 Seek(seek_time1); |
| 3987 | 3969 |
| 3988 // Append data to satisfy the first seek request. | 3970 // Append data to satisfy the first seek request. |
| 3989 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, | 3971 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, |
| 3990 seek_time1.InMilliseconds(), 5); | 3972 seek_time1.InMilliseconds(), 5); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 4015 // around |seek_time2|, because that's the current playback position, | 3997 // around |seek_time2|, because that's the current playback position, |
| 4016 // and the newly appended range, since this is the most recent append. | 3998 // and the newly appended range, since this is the most recent append. |
| 4017 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); | 3999 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 700, 5); |
| 4018 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0)); | 4000 EXPECT_FALSE(demuxer_->EvictCodedFrames(kSourceId, seek_time2, 0)); |
| 4019 CheckExpectedRanges("{ [500,615) [700,815) }"); | 4001 CheckExpectedRanges("{ [500,615) [700,815) }"); |
| 4020 } | 4002 } |
| 4021 | 4003 |
| 4022 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { | 4004 TEST_F(ChunkDemuxerTest, GCKeepPlayhead) { |
| 4023 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 4005 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 4024 | 4006 |
| 4025 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 5 * kBlockSize); | 4007 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 5 * kBlockSize); |
| 4026 | 4008 |
| 4027 // Append data at the start that can be garbage collected: | 4009 // Append data at the start that can be garbage collected: |
| 4028 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | 4010 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
| 4029 CheckExpectedRanges("{ [0,230) }"); | 4011 CheckExpectedRanges("{ [0,230) }"); |
| 4030 | 4012 |
| 4031 // We expect garbage collection to fail, as we don't want to spontaneously | 4013 // We expect garbage collection to fail, as we don't want to spontaneously |
| 4032 // create gaps in source buffer stream. Gaps could break playback for many | 4014 // create gaps in source buffer stream. Gaps could break playback for many |
| 4033 // clients, who don't bother to check ranges after append. | 4015 // clients, who don't bother to check ranges after append. |
| 4034 EXPECT_FALSE(demuxer_->EvictCodedFrames( | 4016 EXPECT_FALSE(demuxer_->EvictCodedFrames( |
| 4035 kSourceId, base::TimeDelta::FromMilliseconds(0), 0)); | 4017 kSourceId, base::TimeDelta::FromMilliseconds(0), 0)); |
| (...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4414 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4396 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4415 | 4397 |
| 4416 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 0, 4))); | 4398 ASSERT_TRUE(AppendCluster(GenerateCluster(0, 0, 4))); |
| 4417 ASSERT_TRUE(AppendData(kCuesHeader, sizeof(kCuesHeader))); | 4399 ASSERT_TRUE(AppendData(kCuesHeader, sizeof(kCuesHeader))); |
| 4418 ASSERT_TRUE(AppendCluster(GenerateCluster(46, 66, 5))); | 4400 ASSERT_TRUE(AppendCluster(GenerateCluster(46, 66, 5))); |
| 4419 CheckExpectedRanges("{ [0,115) }"); | 4401 CheckExpectedRanges("{ [0,115) }"); |
| 4420 } | 4402 } |
| 4421 | 4403 |
| 4422 TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { | 4404 TEST_F(ChunkDemuxerTest, EvictCodedFramesTest) { |
| 4423 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4405 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4424 demuxer_->SetMemoryLimits(DemuxerStream::AUDIO, 10 * kBlockSize); | 4406 demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, 10 * kBlockSize); |
| 4425 demuxer_->SetMemoryLimits(DemuxerStream::VIDEO, 15 * kBlockSize); | 4407 demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, 15 * kBlockSize); |
| 4426 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 4408 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 4427 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4409 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| 4428 | 4410 |
| 4429 const char* kAudioStreamInfo = "0K 40K 80K 120K 160K 200K 240K 280K"; | 4411 const char* kAudioStreamInfo = "0K 40K 80K 120K 160K 200K 240K 280K"; |
| 4430 const char* kVideoStreamInfo = "0K 10 20K 30 40K 50 60K 70 80K 90 100K " | 4412 const char* kVideoStreamInfo = "0K 10 20K 30 40K 50 60K 70 80K 90 100K " |
| 4431 "110 120K 130 140K"; | 4413 "110 120K 130 140K"; |
| 4432 // Append 8 blocks (80 bytes) of data to audio stream and 15 blocks (150 | 4414 // Append 8 blocks (80 bytes) of data to audio stream and 15 blocks (150 |
| 4433 // bytes) to video stream. | 4415 // bytes) to video stream. |
| 4434 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, kAudioStreamInfo, 40), | 4416 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, kAudioStreamInfo, 40), |
| 4435 MuxedStreamInfo(kVideoTrackNum, kVideoStreamInfo, 10)); | 4417 MuxedStreamInfo(kVideoTrackNum, kVideoStreamInfo, 10)); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 4464 // byte block to stay under 100 bytes memory limit after append | 4446 // byte block to stay under 100 bytes memory limit after append |
| 4465 // 80 - 10 + 28 = 98). | 4447 // 80 - 10 + 28 = 98). |
| 4466 // For video stream 150 + 52 = 202. Video limit is 150 bytes. We need to | 4448 // For video stream 150 + 52 = 202. Video limit is 150 bytes. We need to |
| 4467 // remove at least 6 blocks to stay under limit. | 4449 // remove at least 6 blocks to stay under limit. |
| 4468 CheckExpectedBuffers(audio_stream, "40K 80K 120K 160K 200K 240K 280K"); | 4450 CheckExpectedBuffers(audio_stream, "40K 80K 120K 160K 200K 240K 280K"); |
| 4469 CheckExpectedBuffers(video_stream, "60K 70 80K 90 100K 110 120K 130 140K"); | 4451 CheckExpectedBuffers(video_stream, "60K 70 80K 90 100K 110 120K 130 140K"); |
| 4470 } | 4452 } |
| 4471 | 4453 |
| 4472 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioOnly) { | 4454 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioOnly) { |
| 4473 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 4455 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
| 4474 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio")); | 4456 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); |
| 4475 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4457 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
| 4476 } | 4458 } |
| 4477 | 4459 |
| 4478 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_VideoOnly) { | 4460 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_VideoOnly) { |
| 4479 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 4461 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
| 4480 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4462 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
| 4481 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4463 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
| 4482 } | 4464 } |
| 4483 | 4465 |
| 4484 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioVideo) { | 4466 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioVideo) { |
| 4485 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4467 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4486 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio")); | 4468 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); |
| 4487 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 10); | 4469 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 10); |
| 4488 } | 4470 } |
| 4489 | 4471 |
| 4490 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_AudioVideo) { | 4472 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_AudioVideo) { |
| 4491 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4473 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4492 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4474 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
| 4493 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | 4475 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
| 4494 } | 4476 } |
| 4495 | 4477 |
| 4496 TEST_F(ChunkDemuxerTest, SegmentMissingAudioVideoFrames) { | 4478 TEST_F(ChunkDemuxerTest, SegmentMissingAudioVideoFrames) { |
| 4497 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4479 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4498 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio or video")); | 4480 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
| 4481 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); |
| 4499 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4482 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
| 4500 } | 4483 } |
| 4501 | 4484 |
| 4502 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_FirstSegmentMissingKeyframe) { | 4485 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_FirstSegmentMissingKeyframe) { |
| 4503 // Append V:[n n n][n n K] | 4486 // Append V:[n n n][n n K] |
| 4504 // Expect V: [K] | 4487 // Expect V: [K] |
| 4505 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 4488 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
| 4506 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4489 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| 4507 | 4490 |
| 4508 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(2); | 4491 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(2); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4622 // V: [n n n][n K n] | 4605 // V: [n n n][n K n] |
| 4623 // Expect: | 4606 // Expect: |
| 4624 // A: [K K K][K K K] | 4607 // A: [K K K][K K K] |
| 4625 // V [................K n] (As would occur if there really were a | 4608 // V [................K n] (As would occur if there really were a |
| 4626 // jagged cluster start and not badly muxed clusters as used to | 4609 // jagged cluster start and not badly muxed clusters as used to |
| 4627 // simulate a jagged start in this test.) | 4610 // simulate a jagged start in this test.) |
| 4628 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4611 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4629 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 4612 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 4630 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4613 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| 4631 | 4614 |
| 4632 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4615 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
| 4633 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"), | 4616 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"), |
| 4634 MuxedStreamInfo(kVideoTrackNum, "")); | 4617 MuxedStreamInfo(kVideoTrackNum, "")); |
| 4635 demuxer_->Remove(kSourceId, base::TimeDelta(), | 4618 demuxer_->Remove(kSourceId, base::TimeDelta(), |
| 4636 base::TimeDelta::FromMilliseconds(30)); | 4619 base::TimeDelta::FromMilliseconds(30)); |
| 4637 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"), | 4620 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"), |
| 4638 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10)); | 4621 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10)); |
| 4639 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"), | 4622 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"), |
| 4640 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10)); | 4623 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10)); |
| 4641 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }"); | 4624 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }"); |
| 4642 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,90) }"); | 4625 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,90) }"); |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4737 TEST_F(ChunkDemuxerTest, StreamStatusNotifications) { | 4720 TEST_F(ChunkDemuxerTest, StreamStatusNotifications) { |
| 4738 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4721 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
| 4739 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 4722 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
| 4740 EXPECT_NE(nullptr, audio_stream); | 4723 EXPECT_NE(nullptr, audio_stream); |
| 4741 CheckStreamStatusNotifications(audio_stream); | 4724 CheckStreamStatusNotifications(audio_stream); |
| 4742 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4725 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
| 4743 EXPECT_NE(nullptr, video_stream); | 4726 EXPECT_NE(nullptr, video_stream); |
| 4744 CheckStreamStatusNotifications(video_stream); | 4727 CheckStreamStatusNotifications(video_stream); |
| 4745 } | 4728 } |
| 4746 | 4729 |
| 4730 TEST_F(ChunkDemuxerTest, MultipleIds) { |
| 4731 CreateNewDemuxer(); |
| 4732 EXPECT_CALL(*this, DemuxerOpened()); |
| 4733 EXPECT_CALL(host_, SetDuration(_)).Times(2); |
| 4734 demuxer_->Initialize(&host_, CreateInitDoneCB(kNoTimestamp, PIPELINE_OK), |
| 4735 true); |
| 4736 |
| 4737 const char* kId1 = "id1"; |
| 4738 const char* kId2 = "id2"; |
| 4739 EXPECT_EQ(AddId(kId1, "video/webm", "opus,vp9"), ChunkDemuxer::kOk); |
| 4740 EXPECT_EQ(AddId(kId2, "video/webm", "opus,vp9"), ChunkDemuxer::kOk); |
| 4741 scoped_refptr<DecoderBuffer> data1 = ReadTestDataFile("green-a300hz.webm"); |
| 4742 scoped_refptr<DecoderBuffer> data2 = ReadTestDataFile("red-a500hz.webm"); |
| 4743 |
| 4744 EXPECT_MEDIA_LOG(FoundStream("audio")).Times(2); |
| 4745 EXPECT_MEDIA_LOG(FoundStream("video")).Times(2); |
| 4746 EXPECT_MEDIA_LOG(CodecName("audio", "opus")).Times(2); |
| 4747 EXPECT_MEDIA_LOG(CodecName("video", "vp9")).Times(2); |
| 4748 EXPECT_CALL(*this, InitSegmentReceivedMock(_)).Times(2); |
| 4749 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")).Times(AnyNumber()); |
| 4750 |
| 4751 EXPECT_TRUE(AppendData(kId1, data1->data(), data1->data_size())); |
| 4752 EXPECT_TRUE(AppendData(kId2, data2->data(), data2->data_size())); |
| 4753 CheckExpectedRanges(kId1, "{ [0,12007) }"); |
| 4754 CheckExpectedRanges(kId2, "{ [0,10007) }"); |
| 4755 } |
| 4756 |
| 4757 TEST_F(ChunkDemuxerTest, CompleteInitAfterIdRemoved) { |
| 4758 CreateNewDemuxer(); |
| 4759 EXPECT_CALL(*this, DemuxerOpened()); |
| 4760 demuxer_->Initialize(&host_, |
| 4761 CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
| 4762 |
| 4763 // Add two ids, then remove one of the ids and verify that adding init segment |
| 4764 // only for the remaining id still triggers the InitDoneCB. |
| 4765 const char* kId1 = "id1"; |
| 4766 const char* kId2 = "id2"; |
| 4767 EXPECT_EQ(AddId(kId1, "video/webm", "vp8"), ChunkDemuxer::kOk); |
| 4768 EXPECT_EQ(AddId(kId2, "video/webm", "vp9"), ChunkDemuxer::kOk); |
| 4769 demuxer_->RemoveId(kId2); |
| 4770 |
| 4771 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); |
| 4772 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30)); |
| 4773 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 4774 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); |
| 4775 |
| 4776 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_VIDEO)); |
| 4777 AppendSingleStreamCluster(kId1, kVideoTrackNum, "0K 30 60 90"); |
| 4778 } |
| 4779 |
| 4780 TEST_F(ChunkDemuxerTest, RemovingIdMustRemoveStreams) { |
| 4781 CreateNewDemuxer(); |
| 4782 EXPECT_CALL(*this, DemuxerOpened()); |
| 4783 demuxer_->Initialize(&host_, |
| 4784 CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); |
| 4785 |
| 4786 const char* kId1 = "id1"; |
| 4787 EXPECT_EQ(AddId(kId1, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk); |
| 4788 |
| 4789 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); |
| 4790 EXPECT_MEDIA_LOG(FoundStream("video")); |
| 4791 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); |
| 4792 EXPECT_MEDIA_LOG(FoundStream("audio")); |
| 4793 EXPECT_MEDIA_LOG(CodecName("audio", "vorbis")); |
| 4794 |
| 4795 // Append init segment to ensure demuxer streams get created. |
| 4796 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_AUDIO | HAS_VIDEO)); |
| 4797 EXPECT_NE(nullptr, demuxer_->GetStream(DemuxerStream::AUDIO)); |
| 4798 EXPECT_NE(nullptr, demuxer_->GetStream(DemuxerStream::VIDEO)); |
| 4799 |
| 4800 // Removing the id should remove also the DemuxerStreams. |
| 4801 demuxer_->RemoveId(kId1); |
| 4802 EXPECT_EQ(nullptr, demuxer_->GetStream(DemuxerStream::AUDIO)); |
| 4803 EXPECT_EQ(nullptr, demuxer_->GetStream(DemuxerStream::VIDEO)); |
| 4804 } |
| 4805 |
| 4806 // TODO(servolk): Add a unit test with multiple audio/video tracks using the |
| 4807 // same codec type in a single SourceBuffer/MediaSourceState, when WebM parser |
| 4808 // supports multiple tracks. crbug.com/646900 |
| 4809 |
| 4747 } // namespace media | 4810 } // namespace media |
| OLD | NEW |