| 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 |