OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/basictypes.h" | 5 #include "base/basictypes.h" |
6 #include "base/logging.h" | 6 #include "base/logging.h" |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/string_split.h" | 8 #include "base/strings/string_split.h" |
9 #include "media/formats/mp4/box_definitions.h" | 9 #include "media/formats/mp4/box_definitions.h" |
10 #include "media/formats/mp4/rcheck.h" | 10 #include "media/formats/mp4/rcheck.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 moov_.tracks[0].media.header.timescale = kAudioScale; | 66 moov_.tracks[0].media.header.timescale = kAudioScale; |
67 SampleDescription& desc1 = | 67 SampleDescription& desc1 = |
68 moov_.tracks[0].media.information.sample_table.description; | 68 moov_.tracks[0].media.information.sample_table.description; |
69 AudioSampleEntry aud_desc; | 69 AudioSampleEntry aud_desc; |
70 aud_desc.format = FOURCC_MP4A; | 70 aud_desc.format = FOURCC_MP4A; |
71 aud_desc.sinf.info.track_encryption.is_encrypted = false; | 71 aud_desc.sinf.info.track_encryption.is_encrypted = false; |
72 desc1.type = kAudio; | 72 desc1.type = kAudio; |
73 desc1.audio_entries.push_back(aud_desc); | 73 desc1.audio_entries.push_back(aud_desc); |
74 moov_.extends.tracks[0].track_id = 1; | 74 moov_.extends.tracks[0].track_id = 1; |
75 moov_.extends.tracks[0].default_sample_description_index = 1; | 75 moov_.extends.tracks[0].default_sample_description_index = 1; |
76 moov_.tracks[0].media.information.sample_table.sync_sample.is_present = | |
77 false; | |
78 moov_.tracks[1].header.track_id = 2; | 76 moov_.tracks[1].header.track_id = 2; |
79 moov_.tracks[1].media.header.timescale = kVideoScale; | 77 moov_.tracks[1].media.header.timescale = kVideoScale; |
80 SampleDescription& desc2 = | 78 SampleDescription& desc2 = |
81 moov_.tracks[1].media.information.sample_table.description; | 79 moov_.tracks[1].media.information.sample_table.description; |
82 VideoSampleEntry vid_desc; | 80 VideoSampleEntry vid_desc; |
83 vid_desc.format = FOURCC_AVC1; | 81 vid_desc.format = FOURCC_AVC1; |
84 vid_desc.sinf.info.track_encryption.is_encrypted = false; | 82 vid_desc.sinf.info.track_encryption.is_encrypted = false; |
85 desc2.type = kVideo; | 83 desc2.type = kVideo; |
86 desc2.video_entries.push_back(vid_desc); | 84 desc2.video_entries.push_back(vid_desc); |
87 moov_.extends.tracks[1].track_id = 2; | 85 moov_.extends.tracks[1].track_id = 2; |
88 moov_.extends.tracks[1].default_sample_description_index = 1; | 86 moov_.extends.tracks[1].default_sample_description_index = 1; |
89 SyncSample& video_sync_sample = | |
90 moov_.tracks[1].media.information.sample_table.sync_sample; | |
91 video_sync_sample.is_present = true; | |
92 video_sync_sample.entries.resize(1); | |
93 video_sync_sample.entries[0] = 0; | |
94 | 87 |
95 moov_.tracks[2].header.track_id = 3; | 88 moov_.tracks[2].header.track_id = 3; |
96 moov_.tracks[2].media.information.sample_table.description.type = kHint; | 89 moov_.tracks[2].media.information.sample_table.description.type = kHint; |
97 } | 90 } |
98 | 91 |
99 uint32 ToSampleFlags(const std::string& str) { | 92 uint32 ToSampleFlags(const std::string& str) { |
100 CHECK_EQ(str.length(), 2u); | 93 CHECK_EQ(str.length(), 2u); |
101 | 94 |
102 SampleDependsOn sample_depends_on = kSampleDependsOnReserved; | 95 SampleDependsOn sample_depends_on = kSampleDependsOnReserved; |
103 bool is_non_sync_sample = false; | 96 bool is_non_sync_sample = false; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
163 trun->sample_flags[i] = ToSampleFlags(flags_data[i]); | 156 trun->sample_flags[i] = ToSampleFlags(flags_data[i]); |
164 } | 157 } |
165 | 158 |
166 std::string KeyframeAndRAPInfo(TrackRunIterator* iter) { | 159 std::string KeyframeAndRAPInfo(TrackRunIterator* iter) { |
167 CHECK(iter->IsRunValid()); | 160 CHECK(iter->IsRunValid()); |
168 std::stringstream ss; | 161 std::stringstream ss; |
169 ss << iter->track_id(); | 162 ss << iter->track_id(); |
170 | 163 |
171 while (iter->IsSampleValid()) { | 164 while (iter->IsSampleValid()) { |
172 ss << " " << (iter->is_keyframe() ? "K" : "P"); | 165 ss << " " << (iter->is_keyframe() ? "K" : "P"); |
173 if (iter->is_random_access_point()) | |
174 ss << "R"; | |
175 iter->AdvanceSample(); | 166 iter->AdvanceSample(); |
176 } | 167 } |
177 | 168 |
178 return ss.str(); | 169 return ss.str(); |
179 } | 170 } |
180 | 171 |
181 MovieFragment CreateFragment() { | 172 MovieFragment CreateFragment() { |
182 MovieFragment moof; | 173 MovieFragment moof; |
183 moof.tracks.resize(2); | 174 moof.tracks.resize(2); |
184 moof.tracks[0].decode_time.decode_time = 0; | 175 moof.tracks[0].decode_time.decode_time = 0; |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 // Ensure that keyframes are flagged correctly in the face of BMFF boxes which | 365 // Ensure that keyframes are flagged correctly in the face of BMFF boxes which |
375 // explicitly specify the flags for the first sample in a run and rely on | 366 // explicitly specify the flags for the first sample in a run and rely on |
376 // defaults for all subsequent samples | 367 // defaults for all subsequent samples |
377 iter_.reset(new TrackRunIterator(&moov_, media_log_)); | 368 iter_.reset(new TrackRunIterator(&moov_, media_log_)); |
378 MovieFragment moof = CreateFragment(); | 369 MovieFragment moof = CreateFragment(); |
379 moof.tracks[1].header.has_default_sample_flags = true; | 370 moof.tracks[1].header.has_default_sample_flags = true; |
380 moof.tracks[1].header.default_sample_flags = ToSampleFlags("UN"); | 371 moof.tracks[1].header.default_sample_flags = ToSampleFlags("UN"); |
381 SetFlagsOnSamples("US", &moof.tracks[1].runs[0]); | 372 SetFlagsOnSamples("US", &moof.tracks[1].runs[0]); |
382 | 373 |
383 ASSERT_TRUE(iter_->Init(moof)); | 374 ASSERT_TRUE(iter_->Init(moof)); |
384 EXPECT_EQ("1 KR KR KR KR KR KR KR KR KR KR", KeyframeAndRAPInfo(iter_.get())); | 375 EXPECT_EQ("1 K K K K K K K K K K", KeyframeAndRAPInfo(iter_.get())); |
385 | 376 |
386 iter_->AdvanceRun(); | 377 iter_->AdvanceRun(); |
387 EXPECT_EQ("2 KR P P P P P P P P P", KeyframeAndRAPInfo(iter_.get())); | 378 EXPECT_EQ("2 K P P P P P P P P P", KeyframeAndRAPInfo(iter_.get())); |
388 } | 379 } |
389 | 380 |
390 // Verify that parsing fails if a reserved value is in the sample flags. | 381 // Verify that parsing fails if a reserved value is in the sample flags. |
391 TEST_F(TrackRunIteratorTest, SampleInfoTest_ReservedInSampleFlags) { | 382 TEST_F(TrackRunIteratorTest, SampleInfoTest_ReservedInSampleFlags) { |
392 iter_.reset(new TrackRunIterator(&moov_, media_log_)); | 383 iter_.reset(new TrackRunIterator(&moov_, media_log_)); |
393 MovieFragment moof = CreateFragment(); | 384 MovieFragment moof = CreateFragment(); |
394 // Change the "depends on" field on one of the samples to a | 385 // Change the "depends on" field on one of the samples to a |
395 // reserved value. | 386 // reserved value. |
396 moof.tracks[1].runs[0].sample_flags[0] = ToSampleFlags("RS"); | 387 moof.tracks[1].runs[0].sample_flags[0] = ToSampleFlags("RS"); |
397 ASSERT_FALSE(iter_->Init(moof)); | 388 ASSERT_FALSE(iter_->Init(moof)); |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
665 EXPECT_EQ(iter_->GetMaxClearOffset(), 101); | 656 EXPECT_EQ(iter_->GetMaxClearOffset(), 101); |
666 iter_->AdvanceRun(); | 657 iter_->AdvanceRun(); |
667 EXPECT_EQ(iter_->track_id(), 1u); | 658 EXPECT_EQ(iter_->track_id(), 1u); |
668 EXPECT_EQ(iter_->aux_info_offset(), 201); | 659 EXPECT_EQ(iter_->aux_info_offset(), 201); |
669 EXPECT_EQ(iter_->sample_offset(), 10000); | 660 EXPECT_EQ(iter_->sample_offset(), 10000); |
670 EXPECT_EQ(iter_->GetMaxClearOffset(), 201); | 661 EXPECT_EQ(iter_->GetMaxClearOffset(), 201); |
671 EXPECT_TRUE(iter_->CacheAuxInfo(kAuxInfo, arraysize(kAuxInfo))); | 662 EXPECT_TRUE(iter_->CacheAuxInfo(kAuxInfo, arraysize(kAuxInfo))); |
672 EXPECT_EQ(iter_->GetMaxClearOffset(), 10000); | 663 EXPECT_EQ(iter_->GetMaxClearOffset(), 10000); |
673 } | 664 } |
674 | 665 |
675 TEST_F(TrackRunIteratorTest, MissingAndEmptyStss) { | 666 TEST_F(TrackRunIteratorTest, KeyFrameFlagCombinations) { |
| 667 // Setup both audio and video tracks to each have 6 samples covering all the |
| 668 // combinations of mp4 "sync sample" and "depends on" relationships. |
676 MovieFragment moof = CreateFragment(); | 669 MovieFragment moof = CreateFragment(); |
677 | |
678 // Setup track 0 to not have an stss box, which means that all samples should | |
679 // be marked as random access points unless the kSampleIsNonSyncSample flag is | |
680 // set in the sample flags. | |
681 moov_.tracks[0].media.information.sample_table.sync_sample.is_present = false; | |
682 moov_.tracks[0].media.information.sample_table.sync_sample.entries.resize(0); | |
683 moof.tracks[0].runs.resize(1); | 670 moof.tracks[0].runs.resize(1); |
| 671 moof.tracks[1].runs.resize(1); |
684 moof.tracks[0].runs[0].sample_count = 6; | 672 moof.tracks[0].runs[0].sample_count = 6; |
685 moof.tracks[0].runs[0].data_offset = 100; | 673 moof.tracks[1].runs[0].sample_count = 6; |
686 SetFlagsOnSamples("US UN OS ON NS NN", &moof.tracks[0].runs[0]); | 674 SetFlagsOnSamples("US UN OS ON NS NN", &moof.tracks[0].runs[0]); |
687 | |
688 // Setup track 1 to have an stss box with no entries, which normally means | |
689 // that none of the samples should be random access points. If the | |
690 // kSampleIsNonSyncSample flag is NOT set though, the sample should be | |
691 // considered a random access point. | |
692 moov_.tracks[1].media.information.sample_table.sync_sample.is_present = true; | |
693 moov_.tracks[1].media.information.sample_table.sync_sample.entries.resize(0); | |
694 moof.tracks[1].runs.resize(1); | |
695 moof.tracks[1].runs[0].sample_count = 6; | |
696 moof.tracks[1].runs[0].data_offset = 200; | |
697 SetFlagsOnSamples("US UN OS ON NS NN", &moof.tracks[1].runs[0]); | 675 SetFlagsOnSamples("US UN OS ON NS NN", &moof.tracks[1].runs[0]); |
698 | |
699 iter_.reset(new TrackRunIterator(&moov_, media_log_)); | 676 iter_.reset(new TrackRunIterator(&moov_, media_log_)); |
700 | 677 |
701 ASSERT_TRUE(iter_->Init(moof)); | 678 ASSERT_TRUE(iter_->Init(moof)); |
702 EXPECT_TRUE(iter_->IsRunValid()); | 679 EXPECT_TRUE(iter_->IsRunValid()); |
703 | 680 |
704 // Verify that all samples except for the ones that have the | 681 // Keyframes should be marked according to downstream's expectations that |
705 // kSampleIsNonSyncSample flag set are marked as random access points. | 682 // keyframes serve as points of random access for seeking. |
706 EXPECT_EQ("1 KR P PR P KR K", KeyframeAndRAPInfo(iter_.get())); | 683 |
| 684 // For audio, any sync sample should be marked as a key frame. Whether a |
| 685 // sample "depends on" other samples is not considered. Unlike video samples, |
| 686 // audio samples are often marked as depending on other samples but are still |
| 687 // workable for random access. While we allow for parsing of audio samples |
| 688 // that are non-sync samples, we generally expect all audio samples to be sync |
| 689 // samples and downstream will log and discard any non-sync audio samples. |
| 690 EXPECT_EQ("1 K P K P K P", KeyframeAndRAPInfo(iter_.get())); |
707 | 691 |
708 iter_->AdvanceRun(); | 692 iter_->AdvanceRun(); |
709 | 693 |
710 // Verify that nothing is marked as a random access point. | 694 // For video, any key frame should be both a sync sample and have no known |
711 EXPECT_EQ("2 KR P PR P KR K", KeyframeAndRAPInfo(iter_.get())); | 695 // dependents. Ideally, a video sync sample should always be marked as having |
| 696 // no dependents, but we occasionally encounter media where all samples are |
| 697 // marked "sync" and we must rely on combining the two flags to pick out the |
| 698 // true key frames. See http://crbug.com/310712 and http://crbug.com/507916. |
| 699 // Realiably knowing the keyframes for video is also critical to SPS PPS |
| 700 // insertion. |
| 701 EXPECT_EQ("2 K P P P K P", KeyframeAndRAPInfo(iter_.get())); |
712 } | 702 } |
713 | 703 |
714 | |
715 } // namespace mp4 | 704 } // namespace mp4 |
716 } // namespace media | 705 } // namespace media |
OLD | NEW |