Commit cbbc13c5 authored by strobe@google.com's avatar strobe@google.com

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
parent 3422af1d
......@@ -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()));
......
......@@ -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);
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment