Chromium Code Reviews| Index: media/formats/mp4/track_run_iterator.cc |
| diff --git a/media/formats/mp4/track_run_iterator.cc b/media/formats/mp4/track_run_iterator.cc |
| index c3cb0f337e9544f3a0bea3201924f6df577d2962..aeac5458040333037626515069f0a801cb946f01 100644 |
| --- a/media/formats/mp4/track_run_iterator.cc |
| +++ b/media/formats/mp4/track_run_iterator.cc |
| @@ -5,6 +5,7 @@ |
| #include "media/formats/mp4/track_run_iterator.h" |
| #include <algorithm> |
| +#include <iomanip> |
| #include "media/base/buffers.h" |
| #include "media/formats/mp4/rcheck.h" |
| @@ -18,7 +19,6 @@ struct SampleInfo { |
| int duration; |
| int cts_offset; |
| bool is_keyframe; |
| - bool is_random_access_point; |
| uint32 cenc_group_description_index; |
| }; |
| @@ -89,6 +89,13 @@ TrackRunIterator::TrackRunIterator(const Movie* moov, |
| TrackRunIterator::~TrackRunIterator() {} |
| +static std::string HexFlags(uint32 flags) { |
| + std::stringstream stream; |
| + stream << std::setfill('0') << std::setw(sizeof(uint32)*2) << std::hex |
| + << flags; |
| + return stream.str(); |
| +} |
| + |
| static bool PopulateSampleInfo(const TrackExtends& trex, |
| const TrackFragmentHeader& tfhd, |
| const TrackFragmentRun& trun, |
| @@ -96,6 +103,7 @@ static bool PopulateSampleInfo(const TrackExtends& trex, |
| const uint32 i, |
| SampleInfo* sample_info, |
| const SampleDependsOn sdtp_sample_depends_on, |
| + bool is_audio, |
| const scoped_refptr<MediaLog>& media_log) { |
| if (i < trun.sample_sizes.size()) { |
| sample_info->size = trun.sample_sizes[i]; |
| @@ -123,45 +131,47 @@ static bool PopulateSampleInfo(const TrackExtends& trex, |
| uint32 flags; |
| if (i < trun.sample_flags.size()) { |
| flags = trun.sample_flags[i]; |
| + DVLOG(4) << __FUNCTION__ << " trun sample flags " << HexFlags(flags); |
| } else if (tfhd.has_default_sample_flags) { |
| flags = tfhd.default_sample_flags; |
| + DVLOG(4) << __FUNCTION__ << " tfhd sample flags " << HexFlags(flags); |
| } else { |
| flags = trex.default_sample_flags; |
| + DVLOG(4) << __FUNCTION__ << " trex sample flags " << HexFlags(flags); |
| } |
| SampleDependsOn sample_depends_on = |
| static_cast<SampleDependsOn>((flags >> 24) & 0x3); |
| - |
| - if (sample_depends_on == kSampleDependsOnUnknown) |
| + if (sample_depends_on == kSampleDependsOnUnknown) { |
| sample_depends_on = sdtp_sample_depends_on; |
| + } |
| + DVLOG(4) << __FUNCTION__ << " sample_depends_on " << sample_depends_on; |
| + if (sample_depends_on == kSampleDependsOnReserved) { |
| + MEDIA_LOG(ERROR, media_log) << "Reserved value used in sample dependency" |
| + " info."; |
| + return false; |
| + } |
| - // ISO/IEC 14496-12 Section 8.8.3.1 : The negation of |sample_is_sync_sample| |
| - // provides the same information as the sync sample table [8.6.2]. When |
| - // |sample_is_sync_sample| is true for a sample, it is the same as if the |
| - // sample were not in a movie fragment and marked with an entry in the sync |
| - // sample table (or, if all samples are sync samples, the sync sample table |
| - // were absent). |
| + // Per spec (ISO 14496-12:2012), the definition for a "sync sample" is |
| + // equivalent to the downstream code's "is keyframe" concept. But media exists |
| + // that marks non-key video frames as sync samples (http://crbug.com/507916 |
| + // and http://crbug.com/310712). Hence, for video we additionally check that |
| + // the sample does not depend on others (FFmpeg does to, see mov_read_trun). |
|
wolenetz
2015/08/27 03:01:30
nit: s/to/too/
chcunningham
2015/08/27 18:59:39
Done.
|
| + // Sample dependency is not ignored for audio because encoded audio samples |
| + // can depend on other samples and still be used for random access. Generally |
| + // all audio samples are expected to be sync samples, but we prefer to check |
| + // the flags to catch badly muxed audio (for now anyway ;P). History of |
| + // attempts to get this right discussed in http://crrev.com/1319813002 |
| bool sample_is_sync_sample = !(flags & kSampleIsNonSyncSample); |
| - sample_info->is_random_access_point = sample_is_sync_sample; |
| - |
| - switch (sample_depends_on) { |
| - case kSampleDependsOnUnknown: |
| - sample_info->is_keyframe = sample_is_sync_sample; |
| - break; |
| + bool sample_depends_on_others = sample_depends_on == kSampleDependsOnOthers; |
|
wolenetz
2015/08/27 03:01:30
Hmm. This patch drops the automatic compiler check
chcunningham
2015/08/27 18:59:39
I don't think this is more fragile. There are just
wolenetz
2015/08/28 18:23:37
Acknowledged.
|
| + sample_info->is_keyframe = sample_is_sync_sample && |
| + (!sample_depends_on_others || is_audio); |
| - case kSampleDependsOnOthers: |
| - sample_info->is_keyframe = false; |
| - break; |
| + DVLOG(4) << __FUNCTION__ << " is_kf:" << sample_info->is_keyframe |
| + << " is_sync:" << sample_is_sync_sample |
| + << " deps:" << sample_depends_on_others |
| + << " audio:" << is_audio; |
|
wolenetz
2015/08/27 03:01:30
Do we catch non-keyframe audio buffers in parser,
chcunningham
2015/08/27 18:59:39
We used to (https://b.corp.google.com/issues/12218
wolenetz
2015/08/28 18:23:37
I'll take a look at this (audio frames potentially
|
| - case kSampleDependsOnNoOther: |
| - sample_info->is_keyframe = true; |
| - break; |
| - |
| - case kSampleDependsOnReserved: |
| - MEDIA_LOG(ERROR, media_log) << "Reserved value used in sample dependency" |
| - " info."; |
| - return false; |
| - } |
| return true; |
| } |
| @@ -342,7 +352,7 @@ bool TrackRunIterator::Init(const MovieFragment& moof) { |
| for (size_t k = 0; k < trun.sample_count; k++) { |
| if (!PopulateSampleInfo(*trex, traf.header, trun, edit_list_offset, k, |
| &tri.samples[k], traf.sdtp.sample_depends_on(k), |
| - media_log_)) { |
| + tri.is_audio, media_log_)) { |
| return false; |
| } |
| @@ -523,11 +533,6 @@ bool TrackRunIterator::is_keyframe() const { |
| return sample_itr_->is_keyframe; |
| } |
| -bool TrackRunIterator::is_random_access_point() const { |
| - DCHECK(IsSampleValid()); |
| - return sample_itr_->is_random_access_point; |
| -} |
| - |
| const TrackEncryption& TrackRunIterator::track_encryption() const { |
| if (is_audio()) |
| return audio_description().sinf.info.track_encryption; |