|
|
@ -113,6 +113,7 @@ private:
|
|
|
|
const Trex *mTrex;
|
|
|
|
const Trex *mTrex;
|
|
|
|
off64_t mFirstMoofOffset;
|
|
|
|
off64_t mFirstMoofOffset;
|
|
|
|
off64_t mCurrentMoofOffset;
|
|
|
|
off64_t mCurrentMoofOffset;
|
|
|
|
|
|
|
|
off64_t mCurrentMoofSize;
|
|
|
|
off64_t mNextMoofOffset;
|
|
|
|
off64_t mNextMoofOffset;
|
|
|
|
uint32_t mCurrentTime; // in media timescale ticks
|
|
|
|
uint32_t mCurrentTime; // in media timescale ticks
|
|
|
|
int32_t mLastParsedTrackId;
|
|
|
|
int32_t mLastParsedTrackId;
|
|
|
@ -165,8 +166,9 @@ private:
|
|
|
|
status_t parseTrackFragmentRun(off64_t offset, off64_t size);
|
|
|
|
status_t parseTrackFragmentRun(off64_t offset, off64_t size);
|
|
|
|
status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
|
|
|
|
status_t parseSampleAuxiliaryInformationSizes(off64_t offset, off64_t size);
|
|
|
|
status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
|
|
|
|
status_t parseSampleAuxiliaryInformationOffsets(off64_t offset, off64_t size);
|
|
|
|
status_t parseClearEncryptedSizes(off64_t offset, bool isSubsampleEncryption, uint32_t flags);
|
|
|
|
status_t parseClearEncryptedSizes(off64_t offset, bool isSampleEncryption,
|
|
|
|
status_t parseSampleEncryption(off64_t offset);
|
|
|
|
uint32_t flags, off64_t size);
|
|
|
|
|
|
|
|
status_t parseSampleEncryption(off64_t offset, off64_t size);
|
|
|
|
// returns -1 for invalid layer ID
|
|
|
|
// returns -1 for invalid layer ID
|
|
|
|
int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
|
|
|
|
int32_t parseHEVCLayerId(const uint8_t *data, size_t size);
|
|
|
|
|
|
|
|
|
|
|
@ -4859,6 +4861,7 @@ MPEG4Source::MPEG4Source(
|
|
|
|
mTrex(trex),
|
|
|
|
mTrex(trex),
|
|
|
|
mFirstMoofOffset(firstMoofOffset),
|
|
|
|
mFirstMoofOffset(firstMoofOffset),
|
|
|
|
mCurrentMoofOffset(firstMoofOffset),
|
|
|
|
mCurrentMoofOffset(firstMoofOffset),
|
|
|
|
|
|
|
|
mCurrentMoofSize(0),
|
|
|
|
mNextMoofOffset(-1),
|
|
|
|
mNextMoofOffset(-1),
|
|
|
|
mCurrentTime(0),
|
|
|
|
mCurrentTime(0),
|
|
|
|
mDefaultEncryptedByteBlock(0),
|
|
|
|
mDefaultEncryptedByteBlock(0),
|
|
|
@ -5109,6 +5112,9 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
|
|
|
|
case FOURCC("moof"): {
|
|
|
|
case FOURCC("moof"): {
|
|
|
|
off64_t stop_offset = *offset + chunk_size;
|
|
|
|
off64_t stop_offset = *offset + chunk_size;
|
|
|
|
*offset = data_offset;
|
|
|
|
*offset = data_offset;
|
|
|
|
|
|
|
|
if (chunk_type == FOURCC("moof")) {
|
|
|
|
|
|
|
|
mCurrentMoofSize = chunk_data_size;
|
|
|
|
|
|
|
|
}
|
|
|
|
while (*offset < stop_offset) {
|
|
|
|
while (*offset < stop_offset) {
|
|
|
|
status_t err = parseChunk(offset);
|
|
|
|
status_t err = parseChunk(offset);
|
|
|
|
if (err != OK) {
|
|
|
|
if (err != OK) {
|
|
|
@ -5197,7 +5203,7 @@ status_t MPEG4Source::parseChunk(off64_t *offset) {
|
|
|
|
|
|
|
|
|
|
|
|
case FOURCC("senc"): {
|
|
|
|
case FOURCC("senc"): {
|
|
|
|
status_t err;
|
|
|
|
status_t err;
|
|
|
|
if ((err = parseSampleEncryption(data_offset)) != OK) {
|
|
|
|
if ((err = parseSampleEncryption(data_offset, chunk_data_size)) != OK) {
|
|
|
|
return err;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*offset += chunk_size;
|
|
|
|
*offset += chunk_size;
|
|
|
@ -5390,11 +5396,11 @@ status_t MPEG4Source::parseSampleAuxiliaryInformationOffsets(
|
|
|
|
|
|
|
|
|
|
|
|
drmoffset += mCurrentMoofOffset;
|
|
|
|
drmoffset += mCurrentMoofOffset;
|
|
|
|
|
|
|
|
|
|
|
|
return parseClearEncryptedSizes(drmoffset, false, 0);
|
|
|
|
return parseClearEncryptedSizes(drmoffset, false, 0, mCurrentMoofSize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
off64_t offset, bool isSubsampleEncryption, uint32_t flags) {
|
|
|
|
off64_t offset, bool isSampleEncryption, uint32_t flags, off64_t size) {
|
|
|
|
|
|
|
|
|
|
|
|
int32_t ivlength;
|
|
|
|
int32_t ivlength;
|
|
|
|
if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
|
|
|
|
if (!AMediaFormat_getInt32(mFormat, AMEDIAFORMAT_KEY_CRYPTO_DEFAULT_IV_SIZE, &ivlength)) {
|
|
|
@ -5408,11 +5414,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t sampleCount = mCurrentSampleInfoCount;
|
|
|
|
uint32_t sampleCount = mCurrentSampleInfoCount;
|
|
|
|
if (isSubsampleEncryption) {
|
|
|
|
if (isSampleEncryption) {
|
|
|
|
|
|
|
|
if (size < 4) {
|
|
|
|
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (!mDataSource->getUInt32(offset, &sampleCount)) {
|
|
|
|
if (!mDataSource->getUInt32(offset, &sampleCount)) {
|
|
|
|
return ERROR_IO;
|
|
|
|
return ERROR_IO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += 4;
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
size -= 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// read CencSampleAuxiliaryDataFormats
|
|
|
|
// read CencSampleAuxiliaryDataFormats
|
|
|
@ -5427,14 +5437,18 @@ status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memset(smpl->iv, 0, 16);
|
|
|
|
memset(smpl->iv, 0, 16);
|
|
|
|
|
|
|
|
if (size < ivlength) {
|
|
|
|
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
|
|
|
|
if (mDataSource->readAt(offset, smpl->iv, ivlength) != ivlength) {
|
|
|
|
return ERROR_IO;
|
|
|
|
return ERROR_IO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
offset += ivlength;
|
|
|
|
offset += ivlength;
|
|
|
|
|
|
|
|
size -= ivlength;
|
|
|
|
|
|
|
|
|
|
|
|
bool readSubsamples;
|
|
|
|
bool readSubsamples;
|
|
|
|
if (isSubsampleEncryption) {
|
|
|
|
if (isSampleEncryption) {
|
|
|
|
readSubsamples = flags & 2;
|
|
|
|
readSubsamples = flags & 2;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
|
|
|
|
int32_t smplinfosize = mCurrentDefaultSampleInfoSize;
|
|
|
@ -5446,13 +5460,20 @@ status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
|
|
|
|
|
|
|
|
if (readSubsamples) {
|
|
|
|
if (readSubsamples) {
|
|
|
|
uint16_t numsubsamples;
|
|
|
|
uint16_t numsubsamples;
|
|
|
|
|
|
|
|
if (size < 2) {
|
|
|
|
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (!mDataSource->getUInt16(offset, &numsubsamples)) {
|
|
|
|
if (!mDataSource->getUInt16(offset, &numsubsamples)) {
|
|
|
|
return ERROR_IO;
|
|
|
|
return ERROR_IO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += 2;
|
|
|
|
offset += 2;
|
|
|
|
|
|
|
|
size -= 2;
|
|
|
|
for (size_t j = 0; j < numsubsamples; j++) {
|
|
|
|
for (size_t j = 0; j < numsubsamples; j++) {
|
|
|
|
uint16_t numclear;
|
|
|
|
uint16_t numclear;
|
|
|
|
uint32_t numencrypted;
|
|
|
|
uint32_t numencrypted;
|
|
|
|
|
|
|
|
if (size < 6) {
|
|
|
|
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (!mDataSource->getUInt16(offset, &numclear)) {
|
|
|
|
if (!mDataSource->getUInt16(offset, &numclear)) {
|
|
|
|
return ERROR_IO;
|
|
|
|
return ERROR_IO;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -5461,6 +5482,7 @@ status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
return ERROR_IO;
|
|
|
|
return ERROR_IO;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
offset += 4;
|
|
|
|
offset += 4;
|
|
|
|
|
|
|
|
size -= 6;
|
|
|
|
smpl->clearsizes.add(numclear);
|
|
|
|
smpl->clearsizes.add(numclear);
|
|
|
|
smpl->encryptedsizes.add(numencrypted);
|
|
|
|
smpl->encryptedsizes.add(numencrypted);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -5473,12 +5495,15 @@ status_t MPEG4Source::parseClearEncryptedSizes(
|
|
|
|
return OK;
|
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t MPEG4Source::parseSampleEncryption(off64_t offset) {
|
|
|
|
status_t MPEG4Source::parseSampleEncryption(off64_t offset, off64_t chunk_data_size) {
|
|
|
|
uint32_t flags;
|
|
|
|
uint32_t flags;
|
|
|
|
|
|
|
|
if (chunk_data_size < 4) {
|
|
|
|
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
|
|
|
|
if (!mDataSource->getUInt32(offset, &flags)) { // actually version + flags
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
return ERROR_MALFORMED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return parseClearEncryptedSizes(offset + 4, true, flags);
|
|
|
|
return parseClearEncryptedSizes(offset + 4, true, flags, chunk_data_size - 4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
|
|
|
|
status_t MPEG4Source::parseTrackFragmentHeader(off64_t offset, off64_t size) {
|
|
|
|