Bug 1318792 - Adds support for sbgp and sgpd boxes in the traf box r=jya

MozReview-Commit-ID: 7aHEaCTJm22

--HG--
extra : rebase_source : d160d3d64f3848f697e648eae2dafa481800bedd
This commit is contained in:
Jay Harris 2017-01-25 12:10:35 +13:00
parent 7981074791
commit 107910f23e
5 changed files with 258 additions and 1 deletions

View File

@ -360,7 +360,12 @@ MP4TrackDemuxer::GetNextSample()
nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
writer->mCrypto.mMode = mInfo->mCrypto.mMode;
writer->mCrypto.mIVSize = mInfo->mCrypto.mIVSize;
writer->mCrypto.mKeyId.AppendElements(mInfo->mCrypto.mKeyId);
// The length of the key will be zero if no key was specified in the sample
// information, meaning we should fall back to the default key.
if (writer->mCrypto.mKeyId.Length() == 0) {
writer->mCrypto.mKeyId.AppendElements(mInfo->mCrypto.mKeyId);
}
}
return sample.forget();
}

View File

@ -137,6 +137,11 @@ already_AddRefed<MediaRawData> SampleIterator::GetNext()
writer->mCrypto.mValid = true;
writer->mCrypto.mIVSize = ivSize;
CencSampleEncryptionInfoEntry* sampleInfo = GetSampleEncryptionEntry();
if (sampleInfo) {
writer->mCrypto.mKeyId.AppendElements(sampleInfo->mKeyId);
}
if (!reader.ReadArray(writer->mCrypto.mIV, ivSize)) {
return nullptr;
}
@ -164,6 +169,47 @@ already_AddRefed<MediaRawData> SampleIterator::GetNext()
return sample.forget();
}
CencSampleEncryptionInfoEntry* SampleIterator::GetSampleEncryptionEntry()
{
nsTArray<Moof>& moofs = mIndex->mMoofParser->Moofs();
Moof* currentMoof = &moofs[mCurrentMoof];
SampleToGroupEntry* sampleToGroupEntry = nullptr;
uint32_t seen = 0;
for (SampleToGroupEntry& entry : currentMoof->mSampleToGroupEntries) {
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.
if (!sampleToGroupEntry || sampleToGroupEntry->mGroupDescriptionIndex == 0) {
return nullptr;
}
uint32_t group_index = sampleToGroupEntry->mGroupDescriptionIndex;
if (group_index > SampleToGroupEntry::kFragmentGroupDescriptionIndexBase) {
group_index -= SampleToGroupEntry::kFragmentGroupDescriptionIndexBase;
}
// The group_index is one indexed
return group_index > currentMoof->mSampleEncryptionInfoEntries.Length()
? nullptr
: &currentMoof->mSampleEncryptionInfoEntries.ElementAt(group_index - 1);
}
Sample* SampleIterator::Get()
{
if (!mIndex->mMoofParser) {

View File

@ -27,6 +27,8 @@ namespace mp4_demuxer
using namespace stagefright;
using namespace mozilla;
const uint32_t kKeyIdSize = 16;
bool
MoofParser::RebuildFragmentedIndex(
const MediaByteRangeSet& aByteRanges)
@ -486,6 +488,18 @@ Moof::ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, S
} 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.IsValid() && sgpd.mGroupingType == "seig") {
mSampleEncryptionInfoEntries.Clear();
mSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
}
} else if (box.IsType("sbgp")) {
Sbgp sbgp(box);
if (sbgp.IsValid() && sbgp.mGroupingType == "seig") {
mSampleToGroupEntries.Clear();
mSampleToGroupEntries.AppendElements(sbgp.mEntries);
}
} else if (box.IsType("saiz")) {
mSaizs.AppendElement(Saiz(box, aSinf.mDefaultEncryptionType));
} else if (box.IsType("saio")) {
@ -906,5 +920,143 @@ Saio::Saio(Box& aBox, AtomType aDefaultType)
mValid = true;
}
Sbgp::Sbgp(Box& aBox)
{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Sbgp, "Incomplete Box (missing flags)");
return;
}
uint32_t flags = reader->ReadU32();
const uint8_t version = flags >> 24;
flags = flags & 0xffffff;
// Make sure we have enough bytes to read as far as the count.
uint32_t need = (version == 1 ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
if (reader->Remaining() < need) {
LOG(Sbgp, "Incomplete Box (have:%lld, need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
mGroupingType = reader->ReadU32();
if (version == 1) {
mGroupingTypeParam = reader->Read32();
}
uint32_t count = reader->ReadU32();
// Make sure we can read all the entries.
need = sizeof(uint32_t) * 2 * count;
if (reader->Remaining() < need) {
LOG(Sbgp, "Incomplete Box (have:%lld, need:%lld). Failed to read entries",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
for (uint32_t i = 0; i < count; i++) {
uint32_t sampleCount = reader->ReadU32();
uint32_t groupDescriptionIndex = reader->ReadU32();
SampleToGroupEntry entry(sampleCount, groupDescriptionIndex);
mEntries.AppendElement(entry);
}
mValid = true;
}
Sgpd::Sgpd(Box& aBox)
{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Sgpd, "Incomplete Box (missing flags)");
return;
}
uint32_t flags = reader->ReadU32();
const uint8_t version = flags >> 24;
flags = flags & 0xffffff;
uint32_t need = ((flags & 1) ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
if (reader->Remaining() < need) {
LOG(Sgpd, "Incomplete Box (have:%lld need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
mGroupingType = reader->ReadU32();
const uint32_t entrySize = sizeof(uint32_t) + kKeyIdSize;
uint32_t defaultLength = 0;
if (version == 1) {
defaultLength = reader->ReadU32();
if (defaultLength < entrySize && defaultLength != 0) {
return;
}
}
uint32_t count = reader->ReadU32();
// Make sure we have sufficient remaining bytes to read the entries.
need =
count * (sizeof(uint32_t) * (version == 1 && defaultLength == 0 ? 2 : 1) +
kKeyIdSize * sizeof(uint8_t));
if (reader->Remaining() < need) {
LOG(Sgpd, "Incomplete Box (have:%lld need:%lld). Failed to read entries",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
for (uint32_t i = 0; i < count; ++i) {
if (version == 1 && defaultLength == 0) {
uint32_t descriptionLength = reader->ReadU32();
if (descriptionLength < entrySize) {
return;
}
}
CencSampleEncryptionInfoEntry entry;
bool valid = entry.Init(reader);
if (!valid) {
return;
}
mEntries.AppendElement(entry);
}
mValid = true;
}
bool CencSampleEncryptionInfoEntry::Init(BoxReader& aReader)
{
// Skip a reserved byte.
aReader->ReadU8();
uint8_t possiblePatternInfo = aReader->ReadU8();
uint8_t flag = aReader->ReadU8();
mIVSize = aReader->ReadU8();
// Read the key id.
for (uint32_t i = 0; i < kKeyIdSize; ++i) {
mKeyId.AppendElement(aReader->ReadU8());
}
mIsEncrypted = flag != 0;
if (mIsEncrypted) {
if (mIVSize != 8 && mIVSize != 16) {
return false;
}
} else if (mIVSize != 0) {
return false;
}
return true;
}
#undef LOG
}

View File

@ -32,6 +32,9 @@ public:
private:
Sample* Get();
CencSampleEncryptionInfoEntry* GetSampleEncryptionEntry();
void Next();
RefPtr<Index> mIndex;
size_t mCurrentMoof;

View File

@ -17,6 +17,7 @@ typedef int64_t Microseconds;
class Box;
class BoxContext;
class BoxReader;
class Moof;
class Mvhd : public Atom
@ -160,6 +161,53 @@ public:
FallibleTArray<uint64_t> mOffsets;
};
struct SampleToGroupEntry
{
public:
static const uint32_t kTrackGroupDescriptionIndexBase = 0;
static const uint32_t kFragmentGroupDescriptionIndexBase = 0x10000;
SampleToGroupEntry(uint32_t aSampleCount, uint32_t aGroupDescriptionIndex)
: mSampleCount(aSampleCount)
, mGroupDescriptionIndex(aGroupDescriptionIndex)
{
}
uint32_t mSampleCount;
uint32_t mGroupDescriptionIndex;
};
class Sbgp final : public Atom // SampleToGroup box.
{
public:
explicit Sbgp(Box& aBox);
AtomType mGroupingType;
uint32_t mGroupingTypeParam;
nsTArray<SampleToGroupEntry> mEntries;
};
struct CencSampleEncryptionInfoEntry final
{
public:
CencSampleEncryptionInfoEntry() { }
bool Init(BoxReader& aReader);
bool mIsEncrypted = false;
uint8_t mIVSize = 0;
nsTArray<uint8_t> mKeyId;
};
class Sgpd final : public Atom // SampleGroupDescription box.
{
public:
explicit Sgpd(Box& aBox);
AtomType mGroupingType;
nsTArray<CencSampleEncryptionInfoEntry> mEntries;
};
class AuxInfo {
public:
AuxInfo(int64_t aMoofOffset, Saiz& aSaiz, Saio& aSaio);
@ -182,6 +230,9 @@ public:
Interval<Microseconds> mTimeRange;
FallibleTArray<Sample> mIndex;
nsTArray<CencSampleEncryptionInfoEntry> mSampleEncryptionInfoEntries;
nsTArray<SampleToGroupEntry> mSampleToGroupEntries;
nsTArray<Saiz> mSaizs;
nsTArray<Saio> mSaios;