mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
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:
parent
7981074791
commit
107910f23e
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
: ¤tMoof->mSampleEncryptionInfoEntries.ElementAt(group_index - 1);
|
||||
}
|
||||
|
||||
Sample* SampleIterator::Get()
|
||||
{
|
||||
if (!mIndex->mMoofParser) {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -32,6 +32,9 @@ public:
|
||||
|
||||
private:
|
||||
Sample* Get();
|
||||
|
||||
CencSampleEncryptionInfoEntry* GetSampleEncryptionEntry();
|
||||
|
||||
void Next();
|
||||
RefPtr<Index> mIndex;
|
||||
size_t mCurrentMoof;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user