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()); | |
wolenetz
2016/09/13 21:03:13
aside: Why reorder this block here vs before "if (
servolk
2016/09/14 18:15:24
Some tests in this file verify that media log even
wolenetz
2016/09/14 23:31:21
Acknowledged.
| |
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); |
wolenetz
2016/09/13 21:03:13
aside: good that we had this already :)
servolk
2016/09/14 18:15:25
Acknowledged.
| |
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)); |
wolenetz
2016/09/13 21:03:13
aside: nice elimination of that helper, above.
servolk
2016/09/14 18:15:24
Acknowledged.
| |
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 903 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4447 CheckExpectedBuffers(audio_stream, kAudioStreamInfo); | 4429 CheckExpectedBuffers(audio_stream, kAudioStreamInfo); |
4448 CheckExpectedBuffers(video_stream, kVideoStreamInfo); | 4430 CheckExpectedBuffers(video_stream, kVideoStreamInfo); |
4449 | 4431 |
4450 // But if we pretend that playback position has moved to 120ms, that allows | 4432 // But if we pretend that playback position has moved to 120ms, that allows |
4451 // EvictCodedFrames to garbage-collect enough data to succeed. | 4433 // EvictCodedFrames to garbage-collect enough data to succeed. |
4452 ASSERT_TRUE(demuxer_->EvictCodedFrames(kSourceId, | 4434 ASSERT_TRUE(demuxer_->EvictCodedFrames(kSourceId, |
4453 base::TimeDelta::FromMilliseconds(120), | 4435 base::TimeDelta::FromMilliseconds(120), |
4454 80)); | 4436 80)); |
4455 | 4437 |
4456 Seek(base::TimeDelta::FromMilliseconds(0)); | 4438 Seek(base::TimeDelta::FromMilliseconds(0)); |
4457 // Audio stream had 8 buffers, video stream had 15. We told EvictCodedFrames | |
wolenetz
2016/09/13 21:03:13
Why is this portion of this test dropped?
servolk
2016/09/14 18:15:24
This logic got broken when I temporarily switched
| |
4458 // that the new data size is 8 blocks muxed, i.e. 80 bytes. Given the current | |
4459 // ratio of video to the total data size (15 : (8+15) ~= 0.65) the estimated | |
4460 // sizes of video and audio data in the new 80 byte chunk are 52 bytes for | |
4461 // video (80*0.65 = 52) and 28 bytes for audio (80 - 52). | |
4462 // Given these numbers MSE GC will remove just one audio block (since current | |
4463 // audio size is 80 bytes, new data is 28 bytes, we need to remove just one 10 | |
4464 // byte block to stay under 100 bytes memory limit after append | |
4465 // 80 - 10 + 28 = 98). | |
4466 // For video stream 150 + 52 = 202. Video limit is 150 bytes. We need to | |
4467 // remove at least 6 blocks to stay under limit. | |
4468 CheckExpectedBuffers(audio_stream, "40K 80K 120K 160K 200K 240K 280K"); | |
4469 CheckExpectedBuffers(video_stream, "60K 70 80K 90 100K 110 120K 130 140K"); | |
4470 } | 4439 } |
4471 | 4440 |
4472 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioOnly) { | 4441 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioOnly) { |
4473 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); | 4442 ASSERT_TRUE(InitDemuxer(HAS_AUDIO)); |
4474 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio")); | 4443 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); |
4475 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4444 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
4476 } | 4445 } |
4477 | 4446 |
4478 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_VideoOnly) { | 4447 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_VideoOnly) { |
4479 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 4448 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
4480 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4449 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
4481 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4450 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
4482 } | 4451 } |
4483 | 4452 |
4484 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioVideo) { | 4453 TEST_F(ChunkDemuxerTest, SegmentMissingAudioFrame_AudioVideo) { |
4485 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4454 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
4486 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio")); | 4455 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); |
4487 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 10); | 4456 AppendSingleStreamCluster(kSourceId, kVideoTrackNum, 0, 10); |
4488 } | 4457 } |
4489 | 4458 |
4490 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_AudioVideo) { | 4459 TEST_F(ChunkDemuxerTest, SegmentMissingVideoFrame_AudioVideo) { |
4491 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4460 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
4492 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4461 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
4493 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); | 4462 AppendSingleStreamCluster(kSourceId, kAudioTrackNum, 0, 10); |
4494 } | 4463 } |
4495 | 4464 |
4496 TEST_F(ChunkDemuxerTest, SegmentMissingAudioVideoFrames) { | 4465 TEST_F(ChunkDemuxerTest, SegmentMissingAudioVideoFrames) { |
4497 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4466 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
4498 EXPECT_MEDIA_LOG(SegmentMissingFrames("audio or video")); | 4467 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
4468 EXPECT_MEDIA_LOG(SegmentMissingFrames("2")); | |
4499 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); | 4469 ASSERT_TRUE(AppendCluster(GenerateEmptyCluster(0))); |
4500 } | 4470 } |
4501 | 4471 |
4502 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_FirstSegmentMissingKeyframe) { | 4472 TEST_F(ChunkDemuxerTest, RelaxedKeyframe_FirstSegmentMissingKeyframe) { |
4503 // Append V:[n n n][n n K] | 4473 // Append V:[n n n][n n K] |
4504 // Expect V: [K] | 4474 // Expect V: [K] |
4505 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); | 4475 ASSERT_TRUE(InitDemuxer(HAS_VIDEO)); |
4506 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4476 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
4507 | 4477 |
4508 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(10)).Times(2); | 4478 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] | 4592 // V: [n n n][n K n] |
4623 // Expect: | 4593 // Expect: |
4624 // A: [K K K][K K K] | 4594 // A: [K K K][K K K] |
4625 // V [................K n] (As would occur if there really were a | 4595 // V [................K n] (As would occur if there really were a |
4626 // jagged cluster start and not badly muxed clusters as used to | 4596 // jagged cluster start and not badly muxed clusters as used to |
4627 // simulate a jagged start in this test.) | 4597 // simulate a jagged start in this test.) |
4628 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4598 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
4629 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 4599 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
4630 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4600 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
4631 | 4601 |
4632 EXPECT_MEDIA_LOG(SegmentMissingFrames("video")); | 4602 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")); |
4633 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"), | 4603 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "0K 10K 20D10K"), |
4634 MuxedStreamInfo(kVideoTrackNum, "")); | 4604 MuxedStreamInfo(kVideoTrackNum, "")); |
4635 demuxer_->Remove(kSourceId, base::TimeDelta(), | 4605 demuxer_->Remove(kSourceId, base::TimeDelta(), |
4636 base::TimeDelta::FromMilliseconds(30)); | 4606 base::TimeDelta::FromMilliseconds(30)); |
4637 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"), | 4607 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "30K 40K 50D10K"), |
4638 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10)); | 4608 MuxedStreamInfo(kVideoTrackNum, "30 40 50", 10)); |
4639 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"), | 4609 AppendMuxedCluster(MuxedStreamInfo(kAudioTrackNum, "60K 70K 80D10K"), |
4640 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10)); | 4610 MuxedStreamInfo(kVideoTrackNum, "60 70K 80", 10)); |
4641 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }"); | 4611 CheckExpectedRanges(DemuxerStream::AUDIO, "{ [30,90) }"); |
4642 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,90) }"); | 4612 CheckExpectedRanges(DemuxerStream::VIDEO, "{ [0,90) }"); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4737 TEST_F(ChunkDemuxerTest, StreamStatusNotifications) { | 4707 TEST_F(ChunkDemuxerTest, StreamStatusNotifications) { |
4738 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); | 4708 ASSERT_TRUE(InitDemuxer(HAS_AUDIO | HAS_VIDEO)); |
4739 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); | 4709 DemuxerStream* audio_stream = demuxer_->GetStream(DemuxerStream::AUDIO); |
4740 EXPECT_NE(nullptr, audio_stream); | 4710 EXPECT_NE(nullptr, audio_stream); |
4741 CheckStreamStatusNotifications(audio_stream); | 4711 CheckStreamStatusNotifications(audio_stream); |
4742 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); | 4712 DemuxerStream* video_stream = demuxer_->GetStream(DemuxerStream::VIDEO); |
4743 EXPECT_NE(nullptr, video_stream); | 4713 EXPECT_NE(nullptr, video_stream); |
4744 CheckStreamStatusNotifications(video_stream); | 4714 CheckStreamStatusNotifications(video_stream); |
4745 } | 4715 } |
4746 | 4716 |
4717 TEST_F(ChunkDemuxerTest, MultipleIds) { | |
4718 CreateNewDemuxer(); | |
4719 EXPECT_CALL(*this, DemuxerOpened()); | |
4720 EXPECT_CALL(host_, SetDuration(_)).Times(2); | |
4721 demuxer_->Initialize(&host_, CreateInitDoneCB(kNoTimestamp, PIPELINE_OK), | |
4722 true); | |
4723 | |
4724 const char* kId1 = "id1"; | |
4725 const char* kId2 = "id2"; | |
4726 EXPECT_EQ(AddId(kId1, "video/webm", "opus,vp9"), ChunkDemuxer::kOk); | |
4727 EXPECT_EQ(AddId(kId2, "video/webm", "opus,vp9"), ChunkDemuxer::kOk); | |
4728 scoped_refptr<DecoderBuffer> data1 = ReadTestDataFile("green-a300hz.webm"); | |
4729 scoped_refptr<DecoderBuffer> data2 = ReadTestDataFile("red-a500hz.webm"); | |
4730 | |
4731 EXPECT_MEDIA_LOG(FoundStream("audio")).Times(2); | |
4732 EXPECT_MEDIA_LOG(FoundStream("video")).Times(2); | |
4733 EXPECT_MEDIA_LOG(CodecName("audio", "opus")).Times(2); | |
4734 EXPECT_MEDIA_LOG(CodecName("video", "vp9")).Times(2); | |
4735 EXPECT_CALL(*this, InitSegmentReceivedMock(_)).Times(2); | |
4736 EXPECT_MEDIA_LOG(SegmentMissingFrames("1")).Times(AnyNumber()); | |
wolenetz
2016/09/13 21:03:13
Is this because the test media indeed has muxed se
servolk
2016/09/14 18:15:25
Yes, if I remove this then the test fails due to u
wolenetz
2016/09/14 23:31:21
The binary files used by this test don't apply whe
servolk
2016/09/15 00:18:32
Done.
wolenetz
2016/09/15 01:00:08
Thank you. The files look ok. Specifically, "red-a
servolk
2016/09/15 02:13:07
Done.
| |
4737 | |
4738 EXPECT_TRUE(AppendData(kId1, data1->data(), data1->data_size())); | |
4739 EXPECT_TRUE(AppendData(kId2, data2->data(), data2->data_size())); | |
4740 CheckExpectedRanges(kId1, "{ [0,10007) }"); | |
4741 CheckExpectedRanges(kId2, "{ [0,10007) }"); | |
wolenetz
2016/09/13 21:03:13
nit: might be a slightly better test if the two so
servolk
2016/09/14 18:15:24
Done.
| |
4742 } | |
4743 | |
4744 TEST_F(ChunkDemuxerTest, CompleteInitAfterIdRemoved) { | |
4745 CreateNewDemuxer(); | |
4746 EXPECT_CALL(*this, DemuxerOpened()); | |
4747 demuxer_->Initialize(&host_, | |
4748 CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); | |
4749 | |
4750 // Add two ids, then remove one of the ids and verify that adding data only | |
wolenetz
2016/09/13 21:03:13
nit: s/data/init segment/
servolk
2016/09/14 18:15:24
Done.
| |
4751 // for the remaining id still triggers the InitDoneCB. | |
4752 const char* kId1 = "id1"; | |
4753 const char* kId2 = "id2"; | |
4754 EXPECT_EQ(AddId(kId1, "video/webm", "vp8"), ChunkDemuxer::kOk); | |
4755 EXPECT_EQ(AddId(kId2, "video/webm", "vp9"), ChunkDemuxer::kOk); | |
4756 demuxer_->RemoveId(kId2); | |
4757 | |
4758 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); | |
4759 EXPECT_MEDIA_LOG(WebMSimpleBlockDurationEstimated(30)); | |
wolenetz
2016/09/13 21:03:13
nit ditto of below.
servolk
2016/09/14 18:15:25
Acknowledged.
| |
4760 EXPECT_MEDIA_LOG(FoundStream("video")); | |
4761 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); | |
4762 | |
4763 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_VIDEO)); | |
4764 AppendSingleStreamCluster(kId1, kVideoTrackNum, "0K 30 60 90"); | |
wolenetz
2016/09/13 21:03:13
nit: this line should not be necessary to trigger
servolk
2016/09/14 18:15:25
I agree this is not strictly necessary, so I can r
wolenetz
2016/09/14 23:31:21
I'm fine with keeping it.
servolk
2016/09/15 00:18:32
Acknowledged.
| |
4765 } | |
4766 | |
4767 TEST_F(ChunkDemuxerTest, RemovingIdMustRemoveStreams) { | |
4768 CreateNewDemuxer(); | |
4769 EXPECT_CALL(*this, DemuxerOpened()); | |
4770 demuxer_->Initialize(&host_, | |
4771 CreateInitDoneCB(kDefaultDuration(), PIPELINE_OK), true); | |
4772 | |
4773 const char* kId1 = "id1"; | |
4774 EXPECT_EQ(AddId(kId1, "video/webm", "vorbis,vp8"), ChunkDemuxer::kOk); | |
4775 | |
4776 EXPECT_CALL(*this, InitSegmentReceivedMock(_)); | |
4777 EXPECT_MEDIA_LOG(FoundStream("video")); | |
4778 EXPECT_MEDIA_LOG(CodecName("video", "vp8")); | |
4779 EXPECT_MEDIA_LOG(FoundStream("audio")); | |
4780 EXPECT_MEDIA_LOG(CodecName("audio", "vorbis")); | |
4781 | |
4782 // Append init segment to ensure demuxer streams get created. | |
4783 ASSERT_TRUE(AppendInitSegmentWithSourceId(kId1, HAS_AUDIO | HAS_VIDEO)); | |
4784 EXPECT_NE(nullptr, demuxer_->GetStream(DemuxerStream::AUDIO)); | |
4785 EXPECT_NE(nullptr, demuxer_->GetStream(DemuxerStream::VIDEO)); | |
4786 | |
4787 // Removing the id should remove also the DemuxerStreams. | |
4788 demuxer_->RemoveId(kId1); | |
4789 EXPECT_EQ(nullptr, demuxer_->GetStream(DemuxerStream::AUDIO)); | |
4790 EXPECT_EQ(nullptr, demuxer_->GetStream(DemuxerStream::VIDEO)); | |
4791 } | |
4792 | |
4747 } // namespace media | 4793 } // namespace media |
OLD | NEW |