diff options
author | strobe@google.com <strobe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-08 01:33:35 +0000 |
---|---|---|
committer | strobe@google.com <strobe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-08 01:33:35 +0000 |
commit | cbbc13c504ad023a69dcaba56d9064eb77577fa1 (patch) | |
tree | 187f2dad8f5106ef93518de17761ff414488acca /media/mp4 | |
parent | 3422af1d763d8fe33d31863ff1bd1bfe103681a1 (diff) | |
download | chromium_src-cbbc13c504ad023a69dcaba56d9064eb77577fa1.zip chromium_src-cbbc13c504ad023a69dcaba56d9064eb77577fa1.tar.gz chromium_src-cbbc13c504ad023a69dcaba56d9064eb77577fa1.tar.bz2 |
Add initial support for edit lists in MSE BMFF.
BUG=135665
TEST=TrackRunIteratorTest.ReorderingTest
Review URL: https://chromiumcodereview.appspot.com/10832176
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150478 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/mp4')
-rw-r--r-- | media/mp4/mp4_stream_parser.cc | 1 | ||||
-rw-r--r-- | media/mp4/track_run_iterator.cc | 22 | ||||
-rw-r--r-- | media/mp4/track_run_iterator_unittest.cc | 38 |
3 files changed, 56 insertions, 5 deletions
diff --git a/media/mp4/mp4_stream_parser.cc b/media/mp4/mp4_stream_parser.cc index 9c9b750..1aa8c70 100644 --- a/media/mp4/mp4_stream_parser.cc +++ b/media/mp4/mp4_stream_parser.cc @@ -145,7 +145,6 @@ bool MP4StreamParser::ParseBox(bool* err) { bool MP4StreamParser::ParseMoov(BoxReader* reader) { - // TODO(strobe): Respect edit lists. moov_.reset(new Movie); RCHECK(moov_->Parse(reader)); runs_.reset(new TrackRunIterator(moov_.get())); diff --git a/media/mp4/track_run_iterator.cc b/media/mp4/track_run_iterator.cc index 59bc229..073eeee 100644 --- a/media/mp4/track_run_iterator.cc +++ b/media/mp4/track_run_iterator.cc @@ -71,6 +71,7 @@ TrackRunIterator::~TrackRunIterator() {} static void PopulateSampleInfo(const TrackExtends& trex, const TrackFragmentHeader& tfhd, const TrackFragmentRun& trun, + const int64 edit_list_offset, const uint32 i, SampleInfo* sample_info) { if (i < trun.sample_sizes.size()) { @@ -94,6 +95,7 @@ static void PopulateSampleInfo(const TrackExtends& trex, } else { sample_info->cts_offset = 0; } + sample_info->cts_offset += edit_list_offset; uint32 flags; if (i < trun.sample_flags.size()) { @@ -164,6 +166,23 @@ bool TrackRunIterator::Init(const MovieFragment& moof) { RCHECK(desc_idx > 0); // Descriptions are one-indexed in the file desc_idx -= 1; + // Process edit list to remove CTS offset introduced in the presence of + // B-frames (those that contain a single edit with a nonnegative media + // time). Other uses of edit lists are not supported, as they are + // both uncommon and better served by higher-level protocols. + int64 edit_list_offset = 0; + const std::vector<EditListEntry>& edits = trak->edit.list.edits; + if (!edits.empty()) { + if (edits.size() > 1) + DVLOG(1) << "Multi-entry edit box detected; some components ignored."; + + if (edits[0].media_time < 0) { + DVLOG(1) << "Empty edit list entry ignored."; + } else { + edit_list_offset = -edits[0].media_time; + } + } + int64 run_start_dts = traf.decode_time.decode_time; int sample_count_sum = 0; @@ -226,7 +245,8 @@ bool TrackRunIterator::Init(const MovieFragment& moof) { tri.samples.resize(trun.sample_count); for (size_t k = 0; k < trun.sample_count; k++) { - PopulateSampleInfo(*trex, traf.header, trun, k, &tri.samples[k]); + PopulateSampleInfo(*trex, traf.header, trun, edit_list_offset, + k, &tri.samples[k]); run_start_dts += tri.samples[k].duration; } runs_.push_back(tri); diff --git a/media/mp4/track_run_iterator_unittest.cc b/media/mp4/track_run_iterator_unittest.cc index e1c1a03..40385cc 100644 --- a/media/mp4/track_run_iterator_unittest.cc +++ b/media/mp4/track_run_iterator_unittest.cc @@ -261,23 +261,55 @@ TEST_F(TrackRunIteratorTest, MinDecodeTest) { } TEST_F(TrackRunIteratorTest, ReorderingTest) { + // Test frame reordering and edit list support. The frames have the following + // decode timestamps: + // + // 0ms 40ms 120ms 240ms + // | 0 | 1 - | 2 - - | + // + // ...and these composition timestamps, after edit list adjustment: + // + // 0ms 40ms 160ms 240ms + // | 0 | 2 - - | 1 - | + + // Create an edit list with one entry, with an initial start time of 80ms + // (that is, 2 / kVideoTimescale) and a duration of zero (which is treated as + // infinite according to 14496-12:2012). This will cause the first 80ms of the + // media timeline - which will be empty, due to CTS biasing - to be discarded. iter_.reset(new TrackRunIterator(&moov_)); + EditListEntry entry; + entry.segment_duration = 0; + entry.media_time = 2; + entry.media_rate_integer = 1; + entry.media_rate_fraction = 0; + moov_.tracks[1].edit.list.edits.push_back(entry); + + // Add CTS offsets. Without bias, the CTS offsets for the first three frames + // would simply be [0, 3, -2]. Since CTS offsets should be non-negative for + // maximum compatibility, these values are biased up to [2, 5, 0], and the + // extra 80ms is removed via the edit list. MovieFragment moof = CreateFragment(); std::vector<int32>& cts_offsets = moof.tracks[1].runs[0].sample_composition_time_offsets; cts_offsets.resize(10); cts_offsets[0] = 2; - cts_offsets[1] = -1; + cts_offsets[1] = 5; + cts_offsets[2] = 0; moof.tracks[1].decode_time.decode_time = 0; + ASSERT_TRUE(iter_->Init(moof)); iter_->AdvanceRun(); EXPECT_EQ(iter_->dts(), TimeDeltaFromRational(0, kVideoScale)); - EXPECT_EQ(iter_->cts(), TimeDeltaFromRational(2, kVideoScale)); + EXPECT_EQ(iter_->cts(), TimeDeltaFromRational(0, kVideoScale)); EXPECT_EQ(iter_->duration(), TimeDeltaFromRational(1, kVideoScale)); iter_->AdvanceSample(); EXPECT_EQ(iter_->dts(), TimeDeltaFromRational(1, kVideoScale)); - EXPECT_EQ(iter_->cts(), TimeDeltaFromRational(0, kVideoScale)); + EXPECT_EQ(iter_->cts(), TimeDeltaFromRational(4, kVideoScale)); EXPECT_EQ(iter_->duration(), TimeDeltaFromRational(2, kVideoScale)); + iter_->AdvanceSample(); + EXPECT_EQ(iter_->dts(), TimeDeltaFromRational(3, kVideoScale)); + EXPECT_EQ(iter_->cts(), TimeDeltaFromRational(1, kVideoScale)); + EXPECT_EQ(iter_->duration(), TimeDeltaFromRational(3, kVideoScale)); } TEST_F(TrackRunIteratorTest, IgnoreUnknownAuxInfoTest) { |