mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1066427 - Add Common Encryption support to the MP4 demuxer for non-fragmented MP4 files - r=kentuckyfriedtakahe
This commit is contained in:
parent
ad9da9149f
commit
af6576a9da
@ -358,7 +358,9 @@ MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
|
|||||||
mLastTrack(NULL),
|
mLastTrack(NULL),
|
||||||
mFileMetaData(new MetaData),
|
mFileMetaData(new MetaData),
|
||||||
mFirstSINF(NULL),
|
mFirstSINF(NULL),
|
||||||
mIsDrm(false) {
|
mIsDrm(false),
|
||||||
|
mDrmScheme(0)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MPEG4Extractor::~MPEG4Extractor() {
|
MPEG4Extractor::~MPEG4Extractor() {
|
||||||
@ -956,6 +958,16 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case FOURCC('s', 'c', 'h', 'm'):
|
||||||
|
{
|
||||||
|
if (!mDataSource->getUInt32(data_offset, &mDrmScheme)) {
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset += chunk_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case FOURCC('t', 'e', 'n', 'c'):
|
case FOURCC('t', 'e', 'n', 'c'):
|
||||||
{
|
{
|
||||||
if (chunk_size < 32) {
|
if (chunk_size < 32) {
|
||||||
@ -1431,6 +1443,34 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case FOURCC('s', 'a', 'i', 'z'):
|
||||||
|
{
|
||||||
|
status_t err =
|
||||||
|
mLastTrack->sampleTable->setSampleAuxiliaryInformationSizeParams(
|
||||||
|
data_offset, chunk_data_size, mDrmScheme);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset += chunk_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FOURCC('s', 'a', 'i', 'o'):
|
||||||
|
{
|
||||||
|
status_t err =
|
||||||
|
mLastTrack->sampleTable->setSampleAuxiliaryInformationOffsetParams(
|
||||||
|
data_offset, chunk_data_size, mDrmScheme);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
*offset += chunk_size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// @xyz
|
// @xyz
|
||||||
case FOURCC('\xA9', 'x', 'y', 'z'):
|
case FOURCC('\xA9', 'x', 'y', 'z'):
|
||||||
{
|
{
|
||||||
@ -3407,6 +3447,28 @@ status_t MPEG4Source::read(
|
|||||||
mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
|
mBuffer->meta_data()->setInt32(kKeyIsSyncFrame, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mSampleTable->hasCencInfo()) {
|
||||||
|
Vector<uint16_t> clearSizes;
|
||||||
|
Vector<uint32_t> cipherSizes;
|
||||||
|
uint8_t iv[16];
|
||||||
|
status_t err = mSampleTable->getSampleCencInfo(
|
||||||
|
mCurrentSampleIndex, clearSizes, cipherSizes, iv);
|
||||||
|
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& meta = mBuffer->meta_data();
|
||||||
|
meta->setData(kKeyPlainSizes, 0, clearSizes.array(),
|
||||||
|
clearSizes.size() * sizeof(uint16_t));
|
||||||
|
meta->setData(kKeyEncryptedSizes, 0, cipherSizes.array(),
|
||||||
|
cipherSizes.size() * sizeof(uint32_t));
|
||||||
|
meta->setData(kKeyCryptoIV, 0, iv, sizeof(iv));
|
||||||
|
meta->setInt32(kKeyCryptoDefaultIVSize, mDefaultIVSize);
|
||||||
|
meta->setInt32(kKeyCryptoMode, mCryptoMode);
|
||||||
|
meta->setData(kKeyCryptoKey, 0, mCryptoKey, 16);
|
||||||
|
}
|
||||||
|
|
||||||
++mCurrentSampleIndex;
|
++mCurrentSampleIndex;
|
||||||
|
|
||||||
*out = mBuffer;
|
*out = mBuffer;
|
||||||
|
@ -39,6 +39,8 @@ const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
|
|||||||
// static
|
// static
|
||||||
const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
|
const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
|
||||||
|
|
||||||
|
const uint32_t kAuxTypeCenc = FOURCC('c', 'e', 'n', 'c');
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
struct SampleTable::CompositionDeltaLookup {
|
struct SampleTable::CompositionDeltaLookup {
|
||||||
@ -127,7 +129,11 @@ SampleTable::SampleTable(const sp<DataSource> &source)
|
|||||||
mNumSyncSamples(0),
|
mNumSyncSamples(0),
|
||||||
mSyncSamples(NULL),
|
mSyncSamples(NULL),
|
||||||
mLastSyncSampleIndex(0),
|
mLastSyncSampleIndex(0),
|
||||||
mSampleToChunkEntries(NULL) {
|
mSampleToChunkEntries(NULL),
|
||||||
|
mCencInfo(NULL),
|
||||||
|
mCencInfoCount(0),
|
||||||
|
mCencDefaultSize(0)
|
||||||
|
{
|
||||||
mSampleIterator = new SampleIterator(this);
|
mSampleIterator = new SampleIterator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,6 +156,15 @@ SampleTable::~SampleTable() {
|
|||||||
delete[] mTimeToSample;
|
delete[] mTimeToSample;
|
||||||
mTimeToSample = NULL;
|
mTimeToSample = NULL;
|
||||||
|
|
||||||
|
if (mCencInfo) {
|
||||||
|
for (uint32_t i = 0; i < mCencInfoCount; i++) {
|
||||||
|
if (mCencInfo[i].mSubsamples) {
|
||||||
|
delete[] mCencInfo[i].mSubsamples;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete[] mCencInfo;
|
||||||
|
}
|
||||||
|
|
||||||
delete mSampleIterator;
|
delete mSampleIterator;
|
||||||
mSampleIterator = NULL;
|
mSampleIterator = NULL;
|
||||||
}
|
}
|
||||||
@ -432,6 +447,224 @@ status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
validateCencBoxHeader(
|
||||||
|
sp<DataSource>& data_source, off64_t& data_offset,
|
||||||
|
uint8_t* out_version, uint32_t* out_aux_type) {
|
||||||
|
*out_aux_type = 0;
|
||||||
|
|
||||||
|
if (data_source->readAt(data_offset++, out_version, 1) < 1) {
|
||||||
|
ALOGE("error reading sample aux info header");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t flags;
|
||||||
|
if (!data_source->getUInt24(data_offset, &flags)) {
|
||||||
|
ALOGE("error reading sample aux info flags");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += 3;
|
||||||
|
|
||||||
|
if (flags & 1) {
|
||||||
|
uint32_t aux_type;
|
||||||
|
uint32_t aux_param;
|
||||||
|
if (!data_source->getUInt32(data_offset, &aux_type) ||
|
||||||
|
!data_source->getUInt32(data_offset + 4, &aux_param)) {
|
||||||
|
ALOGE("error reading aux info type");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += 8;
|
||||||
|
*out_aux_type = aux_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SampleTable::setSampleAuxiliaryInformationSizeParams(
|
||||||
|
off64_t data_offset, size_t data_size, uint32_t drm_scheme) {
|
||||||
|
off64_t data_end = data_offset + data_size;
|
||||||
|
|
||||||
|
uint8_t version;
|
||||||
|
uint32_t aux_type;
|
||||||
|
status_t err = validateCencBoxHeader(
|
||||||
|
mDataSource, data_offset, &version, &aux_type);
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aux_type && aux_type != kAuxTypeCenc && drm_scheme != kAuxTypeCenc) {
|
||||||
|
// Quietly skip aux types we don't care about.
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCencSizes.isEmpty() || mCencDefaultSize) {
|
||||||
|
ALOGE("duplicate cenc saiz box");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (version) {
|
||||||
|
ALOGV("unsupported cenc saiz version");
|
||||||
|
return ERROR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDataSource->readAt(
|
||||||
|
data_offset++, &mCencDefaultSize, sizeof(mCencDefaultSize))
|
||||||
|
< sizeof(mCencDefaultSize)) {
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mDataSource->getUInt32(data_offset, &mCencInfoCount)) {
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += 4;
|
||||||
|
|
||||||
|
if (!mCencDefaultSize) {
|
||||||
|
mCencSizes.insertAt(0, 0, mCencInfoCount);
|
||||||
|
if (mDataSource->readAt(
|
||||||
|
data_offset, mCencSizes.editArray(), mCencInfoCount)
|
||||||
|
< mCencInfoCount) {
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += mCencInfoCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(data_offset == data_end);
|
||||||
|
|
||||||
|
return parseSampleCencInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SampleTable::setSampleAuxiliaryInformationOffsetParams(
|
||||||
|
off64_t data_offset, size_t data_size, uint32_t drm_scheme) {
|
||||||
|
off64_t data_end = data_offset + data_size;
|
||||||
|
|
||||||
|
uint8_t version;
|
||||||
|
uint32_t aux_type;
|
||||||
|
status_t err = validateCencBoxHeader(mDataSource, data_offset,
|
||||||
|
&version, &aux_type);
|
||||||
|
if (err != OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aux_type && aux_type != kAuxTypeCenc && drm_scheme != kAuxTypeCenc) {
|
||||||
|
// Quietly skip aux types we don't care about.
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCencOffsets.isEmpty()) {
|
||||||
|
ALOGE("duplicate cenc saio box");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t cencOffsetCount;
|
||||||
|
if (!mDataSource->getUInt32(data_offset, &cencOffsetCount)) {
|
||||||
|
ALOGE("error reading cenc aux info offset count");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += 4;
|
||||||
|
|
||||||
|
mCencOffsets.setCapacity(cencOffsetCount);
|
||||||
|
if (!version) {
|
||||||
|
for (uint32_t i = 0; i < cencOffsetCount; i++) {
|
||||||
|
uint32_t tmp;
|
||||||
|
if (!mDataSource->getUInt32(data_offset, &tmp)) {
|
||||||
|
ALOGE("error reading cenc aux info offsets");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
mCencOffsets.push(tmp);
|
||||||
|
data_offset += 4;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (uint32_t i = 0; i < cencOffsetCount; i++) {
|
||||||
|
if (!mDataSource->getUInt64(data_offset, &mCencOffsets.editItemAt(i))) {
|
||||||
|
ALOGE("error reading cenc aux info offsets");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
data_offset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK(data_offset == data_end);
|
||||||
|
|
||||||
|
return parseSampleCencInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SampleTable::parseSampleCencInfo() {
|
||||||
|
if (!mCencDefaultSize && !mCencInfoCount || mCencOffsets.isEmpty()) {
|
||||||
|
// We don't have all the cenc information we need yet. Quietly fail and
|
||||||
|
// hope we get the data we need later in the track header.
|
||||||
|
ALOGV("Got half of cenc saio/saiz pair. Deferring parse until we get the other half.");
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mCencSizes.isEmpty() && mCencOffsets.size() > 1 &&
|
||||||
|
mCencSizes.size() != mCencOffsets.size()) {
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCencInfo = new SampleCencInfo[mCencInfoCount];
|
||||||
|
for (uint32_t i = 0; i < mCencInfoCount; i++) {
|
||||||
|
mCencInfo[i].mSubsamples = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nextOffset = mCencOffsets[0];
|
||||||
|
for (uint32_t i = 0; i < mCencInfoCount; i++) {
|
||||||
|
uint8_t size = mCencDefaultSize ? mCencDefaultSize : mCencSizes[i];
|
||||||
|
uint64_t offset = mCencOffsets.size() == 1 ? nextOffset : mCencOffsets[i];
|
||||||
|
nextOffset = offset + size;
|
||||||
|
|
||||||
|
auto& info = mCencInfo[i];
|
||||||
|
|
||||||
|
if (size < IV_BYTES) {
|
||||||
|
ALOGE("cenc aux info too small");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDataSource->readAt(offset, info.mIV, IV_BYTES) < IV_BYTES) {
|
||||||
|
ALOGE("couldn't read init vector");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
offset += IV_BYTES;
|
||||||
|
|
||||||
|
if (size == IV_BYTES) {
|
||||||
|
info.mSubsampleCount = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size < IV_BYTES + sizeof(info.mSubsampleCount)) {
|
||||||
|
ALOGE("subsample count overflows sample aux info buffer");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mDataSource->getUInt16(offset, &info.mSubsampleCount)) {
|
||||||
|
ALOGE("error reading sample cenc info subsample count");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
offset += sizeof(info.mSubsampleCount);
|
||||||
|
|
||||||
|
if (size < IV_BYTES + sizeof(info.mSubsampleCount) + info.mSubsampleCount * 6) {
|
||||||
|
ALOGE("subsample descriptions overflow sample aux info buffer");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.mSubsamples = new SampleCencInfo::SubsampleSizes[info.mSubsampleCount];
|
||||||
|
for (uint16_t j = 0; j < info.mSubsampleCount; j++) {
|
||||||
|
auto& subsample = info.mSubsamples[j];
|
||||||
|
if (!mDataSource->getUInt16(offset, &subsample.mClearBytes) ||
|
||||||
|
!mDataSource->getUInt32(offset + sizeof(subsample.mClearBytes),
|
||||||
|
&subsample.mCipherBytes)) {
|
||||||
|
ALOGE("error reading cenc subsample aux info");
|
||||||
|
return ERROR_IO;
|
||||||
|
}
|
||||||
|
offset += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t SampleTable::countChunkOffsets() const {
|
uint32_t SampleTable::countChunkOffsets() const {
|
||||||
return mNumChunkOffsets;
|
return mNumChunkOffsets;
|
||||||
}
|
}
|
||||||
@ -838,6 +1071,31 @@ uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
|
|||||||
return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
|
return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
SampleTable::getSampleCencInfo(
|
||||||
|
uint32_t sample_index, Vector<uint16_t>& clear_sizes,
|
||||||
|
Vector<uint32_t>& cipher_sizes, uint8_t iv[]) {
|
||||||
|
CHECK(clear_sizes.isEmpty() && cipher_sizes.isEmpty());
|
||||||
|
|
||||||
|
if (sample_index >= mCencInfoCount) {
|
||||||
|
ALOGE("cenc info requested for out of range sample index");
|
||||||
|
return ERROR_MALFORMED;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& info = mCencInfo[sample_index];
|
||||||
|
clear_sizes.setCapacity(info.mSubsampleCount);
|
||||||
|
cipher_sizes.setCapacity(info.mSubsampleCount);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < info.mSubsampleCount; i++) {
|
||||||
|
clear_sizes.push(info.mSubsamples[i].mClearBytes);
|
||||||
|
cipher_sizes.push(info.mSubsamples[i].mCipherBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(iv, info.mIV, IV_BYTES);
|
||||||
|
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace stagefright
|
} // namespace stagefright
|
||||||
|
|
||||||
#undef LOG_TAG
|
#undef LOG_TAG
|
||||||
|
@ -131,6 +131,7 @@ private:
|
|||||||
|
|
||||||
bool mIsDrm;
|
bool mIsDrm;
|
||||||
TrackExtends mTrackExtends;
|
TrackExtends mTrackExtends;
|
||||||
|
uint32_t mDrmScheme;
|
||||||
|
|
||||||
status_t parseDrmSINF(off64_t *offset, off64_t data_offset);
|
status_t parseDrmSINF(off64_t *offset, off64_t data_offset);
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <media/stagefright/MediaErrors.h>
|
#include <media/stagefright/MediaErrors.h>
|
||||||
#include <utils/RefBase.h>
|
#include <utils/RefBase.h>
|
||||||
#include <utils/threads.h>
|
#include <utils/threads.h>
|
||||||
|
#include <utils/Vector.h>
|
||||||
|
|
||||||
namespace stagefright {
|
namespace stagefright {
|
||||||
|
|
||||||
@ -53,6 +54,14 @@ public:
|
|||||||
|
|
||||||
status_t setSyncSampleParams(off64_t data_offset, size_t data_size);
|
status_t setSyncSampleParams(off64_t data_offset, size_t data_size);
|
||||||
|
|
||||||
|
status_t setSampleAuxiliaryInformationSizeParams(off64_t aDataOffset,
|
||||||
|
size_t aDataSize,
|
||||||
|
uint32_t aDrmScheme);
|
||||||
|
|
||||||
|
status_t setSampleAuxiliaryInformationOffsetParams(off64_t aDataOffset,
|
||||||
|
size_t aDataSize,
|
||||||
|
uint32_t aDrmScheme);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
uint32_t countChunkOffsets() const;
|
uint32_t countChunkOffsets() const;
|
||||||
@ -84,6 +93,13 @@ public:
|
|||||||
|
|
||||||
status_t findThumbnailSample(uint32_t *sample_index);
|
status_t findThumbnailSample(uint32_t *sample_index);
|
||||||
|
|
||||||
|
bool hasCencInfo() const { return !!mCencInfo; }
|
||||||
|
|
||||||
|
status_t getSampleCencInfo(uint32_t aSampleIndex,
|
||||||
|
Vector<uint16_t>& aClearSizes,
|
||||||
|
Vector<uint32_t>& aCipherSizes,
|
||||||
|
uint8_t aIV[]);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~SampleTable();
|
~SampleTable();
|
||||||
|
|
||||||
@ -137,6 +153,22 @@ private:
|
|||||||
};
|
};
|
||||||
SampleToChunkEntry *mSampleToChunkEntries;
|
SampleToChunkEntry *mSampleToChunkEntries;
|
||||||
|
|
||||||
|
enum { IV_BYTES = 16 };
|
||||||
|
struct SampleCencInfo {
|
||||||
|
uint8_t mIV[IV_BYTES];
|
||||||
|
uint16_t mSubsampleCount;
|
||||||
|
|
||||||
|
struct SubsampleSizes {
|
||||||
|
uint16_t mClearBytes;
|
||||||
|
uint32_t mCipherBytes;
|
||||||
|
} * mSubsamples;
|
||||||
|
} * mCencInfo;
|
||||||
|
uint32_t mCencInfoCount;
|
||||||
|
|
||||||
|
uint8_t mCencDefaultSize;
|
||||||
|
Vector<uint8_t> mCencSizes;
|
||||||
|
Vector<uint64_t> mCencOffsets;
|
||||||
|
|
||||||
friend struct SampleIterator;
|
friend struct SampleIterator;
|
||||||
|
|
||||||
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
|
status_t getSampleSize_l(uint32_t sample_index, size_t *sample_size);
|
||||||
@ -146,6 +178,8 @@ private:
|
|||||||
|
|
||||||
void buildSampleEntriesTable();
|
void buildSampleEntriesTable();
|
||||||
|
|
||||||
|
status_t parseSampleCencInfo();
|
||||||
|
|
||||||
SampleTable(const SampleTable &);
|
SampleTable(const SampleTable &);
|
||||||
SampleTable &operator=(const SampleTable &);
|
SampleTable &operator=(const SampleTable &);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user