Bug 1318792 - Adds support for sbgp and sgpd boxes occuring in the sampletable r?cpearce
MozReview-Commit-ID: AWroyPEf4rD
--- a/dom/media/fmp4/MP4Demuxer.cpp
+++ b/dom/media/fmp4/MP4Demuxer.cpp
@@ -351,22 +351,25 @@ MP4TrackDemuxer::GetNextSample()
// We could reject the sample now, however demuxer errors are fatal.
// So we keep the invalid frame, relying on the H264 decoder to
// handle the error later.
// TODO: make demuxer errors non-fatal.
break;
}
}
}
+
if (sample->mCrypto.mValid) {
nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
writer->mCrypto.mMode = mInfo->mCrypto.mMode;
- writer->mCrypto.mIVSize = mInfo->mCrypto.mIVSize;
+ // Only use the default key parsed from the moov if we haven't already got
+ // one from the sample group description.
if (writer->mCrypto.mKeyId.Length() == 0) {
+ writer->mCrypto.mIVSize = mInfo->mCrypto.mIVSize;
writer->mCrypto.mKeyId.AppendElements(mInfo->mCrypto.mKeyId);
}
}
return sample.forget();
}
RefPtr<MP4TrackDemuxer::SamplesPromise>
MP4TrackDemuxer::GetSamples(int32_t aNumSamples)
--- a/media/libstagefright/binding/Index.cpp
+++ b/media/libstagefright/binding/Index.cpp
@@ -136,16 +136,17 @@ already_AddRefed<MediaRawData> SampleIte
ByteReader reader(cenc);
writer->mCrypto.mValid = true;
writer->mCrypto.mIVSize = ivSize;
nsTArray<uint8_t> keyIdArray;
CencSampleEncryptionInfoEntry* sampleInfo = GetSampleEncryptionEntry();
if (sampleInfo) {
+ writer->mCrypto.mIVSize = sampleInfo->mIVSize;
keyIdArray.AppendElements(sampleInfo->mKeyId);
}
writer->mCrypto.mKeyId = keyIdArray;
if (!reader.ReadArray(writer->mCrypto.mIV, ivSize)) {
return nullptr;
}
@@ -174,50 +175,66 @@ already_AddRefed<MediaRawData> SampleIte
}
CencSampleEncryptionInfoEntry* SampleIterator::GetSampleEncryptionEntry()
{
nsTArray<Moof>& moofs = mIndex->mMoofParser->Moofs();
Moof* currentMoof = &moofs[mCurrentMoof];
SampleToGroupEntry* sampleToGroupEntry = nullptr;
+ // Default to using the sample to group entries for the fragment, otherwise
+ // fall back to the sample to group entries for the track.
+ nsTArray<SampleToGroupEntry>* sampleToGroupEntries =
+ currentMoof->mFragmentSampleToGroupEntries.Length() != 0
+ ? ¤tMoof->mFragmentSampleToGroupEntries
+ : &mIndex->mMoofParser->mTrackSampleToGroupEntries;
+
uint32_t seen = 0;
- for (uint32_t i = 0; i < currentMoof->mSampleToGroupEntries.Length(); ++i) {
- SampleToGroupEntry* entry = ¤tMoof->mSampleToGroupEntries.ElementAt(i);
+ for (uint32_t i = 0; i < sampleToGroupEntries->Length(); ++i) {
+ SampleToGroupEntry* entry = &sampleToGroupEntries->ElementAt(i);
if (seen + entry->mSampleCount > mCurrentSample) {
sampleToGroupEntry = entry;
break;
}
seen += entry->mSampleCount;
}
// ISO-14496-12 Section 8.9.2.3 and 8.9.4 : group description index
// (1) ranges from 1 to the number of sample group entries in the track
// level SampleGroupDescription Box, or (2) takes the value 0 to
// indicate that this sample is a member of no group, in this case, the
// sample is associated with the default values specified in
// TrackEncryption Box, or (3) starts at 0x10001, i.e. the index value
// 1, with the value 1 in the top 16 bits, to reference fragment-local
// SampleGroupDescription Box.
+ // According to the spec, ISO-14496-12, the sum of the sample counts in this
+ // box should be equal to the total number of samples, and, if less, the
+ // reader should behave as if an extra SampleToGroupEntry existed, with
+ // groupDescriptionIndex 0.
if (!sampleToGroupEntry || sampleToGroupEntry->mGroupDescriptionIndex == 0) {
return nullptr;
}
- uint32_t group_index = sampleToGroupEntry->mGroupDescriptionIndex;
+ nsTArray<CencSampleEncryptionInfoEntry>* entries = &mIndex->mMoofParser->mTrackSampleEncryptionInfoEntries;
+
+ uint32_t groupIndex = sampleToGroupEntry->mGroupDescriptionIndex;
- if (group_index > SampleToGroupEntry::kFragmentGroupDescriptionIndexBase) {
- group_index -= SampleToGroupEntry::kFragmentGroupDescriptionIndexBase;
+ // If the first bit is set to a one, then we should use the sample group
+ // descriptions from the fragment.
+ if (groupIndex > SampleToGroupEntry::kFragmentGroupDescriptionIndexBase) {
+ groupIndex -= SampleToGroupEntry::kFragmentGroupDescriptionIndexBase;
+ entries = ¤tMoof->mFragmentSampleEncryptionInfoEntries;
}
- // The group_index is one indexed
- return group_index > currentMoof->mSampleEncryptionInfoEntries.Length()
+ // The group_index is one based.
+ return groupIndex > entries->Length()
? nullptr
- : ¤tMoof->mSampleEncryptionInfoEntries.ElementAt(group_index - 1);
+ : &entries->ElementAt(groupIndex - 1);
}
Sample* SampleIterator::Get()
{
if (!mIndex->mMoofParser) {
MOZ_ASSERT(!mCurrentMoof);
return mCurrentSample < mIndex->mIndex.Length()
? &mIndex->mIndex[mCurrentSample]
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -312,16 +312,28 @@ MoofParser::ParseMinf(Box& aBox)
}
void
MoofParser::ParseStbl(Box& aBox)
{
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("stsd")) {
ParseStsd(box);
+ } else if (box.IsType("sgpd")) {
+ Sgpd sgpd(box);
+ if (sgpd.mGroupingType == "seig") {
+ mTrackSampleEncryptionInfoEntries.Clear();
+ mTrackSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
+ }
+ } else if (box.IsType("sbgp")) {
+ Sbgp sbgp(box);
+ if (sbgp.mGroupingType == "seig") {
+ mTrackSampleToGroupEntries.Clear();
+ mTrackSampleToGroupEntries.AppendElements(sbgp.mEntries);
+ }
}
}
}
void
MoofParser::ParseStsd(Box& aBox)
{
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
@@ -477,33 +489,34 @@ Moof::ProcessCenc()
}
void
Moof::ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, uint64_t* aDecodeTime, bool aIsAudio)
{
MOZ_ASSERT(aDecodeTime);
Tfhd tfhd(aTrex);
Tfdt tfdt;
+
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("tfhd")) {
tfhd = Tfhd(box, aTrex);
} else if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
if (box.IsType("tfdt")) {
tfdt = Tfdt(box);
} else if (box.IsType("sgpd")) {
Sgpd sgpd(box);
if (sgpd.mGroupingType == "seig") {
- mSampleEncryptionInfoEntries.Clear();
- mSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
+ mFragmentSampleEncryptionInfoEntries.Clear();
+ mFragmentSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
}
} else if (box.IsType("sbgp")) {
Sbgp sbgp(box);
if (sbgp.mGroupingType == "seig") {
- mSampleToGroupEntries.Clear();
- mSampleToGroupEntries.AppendElements(sbgp.mEntries);
+ mFragmentSampleToGroupEntries.Clear();
+ mFragmentSampleToGroupEntries.AppendElements(sbgp.mEntries);
}
} else if (box.IsType("saiz")) {
mSaizs.AppendElement(Saiz(box, aSinf.mDefaultEncryptionType));
} else if (box.IsType("saio")) {
mSaios.AppendElement(Saio(box, aSinf.mDefaultEncryptionType));
}
}
}
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -222,18 +222,18 @@ public:
bool GetAuxInfo(AtomType aType, nsTArray<MediaByteRange>* aByteRanges);
void FixRounding(const Moof& aMoof);
mozilla::MediaByteRange mRange;
mozilla::MediaByteRange mMdatRange;
Interval<Microseconds> mTimeRange;
FallibleTArray<Sample> mIndex;
- nsTArray<CencSampleEncryptionInfoEntry> mSampleEncryptionInfoEntries;
- nsTArray<SampleToGroupEntry> mSampleToGroupEntries;
+ nsTArray<CencSampleEncryptionInfoEntry> mFragmentSampleEncryptionInfoEntries;
+ nsTArray<SampleToGroupEntry> mFragmentSampleToGroupEntries;
nsTArray<Saiz> mSaizs;
nsTArray<Saio> mSaios;
private:
// aDecodeTime is updated to the end of the parsed TRAF on return.
void ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, uint64_t* aDecodeTime, bool aIsAudio);
// aDecodeTime is updated to the end of the parsed TRUN on return.
@@ -285,16 +285,20 @@ public:
uint64_t mOffset;
nsTArray<uint64_t> mMoofOffsets;
Mvhd mMvhd;
Mdhd mMdhd;
Trex mTrex;
Tfdt mTfdt;
Edts mEdts;
Sinf mSinf;
+
+ nsTArray<CencSampleEncryptionInfoEntry> mTrackSampleEncryptionInfoEntries;
+ nsTArray<SampleToGroupEntry> mTrackSampleToGroupEntries;
+
nsTArray<Moof>& Moofs() { return mMoofs; }
private:
void ScanForMetadata(mozilla::MediaByteRange& aFtyp,
mozilla::MediaByteRange& aMoov);
nsTArray<Moof> mMoofs;
nsTArray<MediaByteRange> mMediaRanges;
bool mIsAudio;
uint64_t mLastDecodeTime;