Loading include/media/stagefright/DataSource.h +60 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ #define DATA_SOURCE_H_ #include <sys/types.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MediaErrors.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> Loading Loading @@ -58,6 +58,20 @@ public: bool getUInt32(off64_t offset, uint32_t *x); bool getUInt64(off64_t offset, uint64_t *x); // Reads in "count" entries of type T into vector *x. // Returns true if "count" entries can be read. // If fewer than "count" entries can be read, return false. In this case, // the output vector *x will still have those entries that were read. Call // x->size() to obtain the number of entries read. // The optional parameter chunkSize specifies how many entries should be // read from the data source at one time into a temporary buffer. Increasing // chunkSize can improve the performance at the cost of extra memory usage. // The default value for chunkSize is set to read at least 4k bytes at a // time, depending on sizeof(T). template <typename T> bool getVector(off64_t offset, Vector<T>* x, size_t count, size_t chunkSize = (4095 / sizeof(T)) + 1); // May return ERROR_UNSUPPORTED. virtual status_t getSize(off64_t *size); Loading Loading @@ -108,6 +122,51 @@ private: DataSource &operator=(const DataSource &); }; template <typename T> bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, size_t chunkSize) { x->clear(); if (chunkSize == 0) { return false; } if (count == 0) { return true; } T tmp[chunkSize]; ssize_t numBytesRead; size_t numBytesPerChunk = chunkSize * sizeof(T); size_t i; for (i = 0; i + chunkSize < count; i += chunkSize) { // This loops is executed when more than chunkSize records need to be // read. numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk); if (numBytesRead == -1) { // If readAt() returns -1, there is an error. return false; } if (numBytesRead < numBytesPerChunk) { // This case is triggered when the stream ends before the whole // chunk is read. x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); return false; } x->appendArray(tmp, chunkSize); offset += numBytesPerChunk; } // There are (count - i) more records to read. // Right now, (count - i) <= chunkSize. // We do the same thing as above, but with chunkSize replaced by count - i. numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T)); if (numBytesRead == -1) { return false; } x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); return x->size() == count; } } // namespace android #endif // DATA_SOURCE_H_ media/libstagefright/SampleTable.cpp +19 −15 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ SampleTable::SampleTable(const sp<DataSource> &source) mDefaultSampleSize(0), mNumSampleSizes(0), mTimeToSampleCount(0), mTimeToSample(NULL), mTimeToSample(), mSampleTimeEntries(NULL), mCompositionTimeDeltaEntries(NULL), mNumCompositionTimeDeltaEntries(0), Loading Loading @@ -151,9 +151,6 @@ SampleTable::~SampleTable() { delete[] mSampleTimeEntries; mSampleTimeEntries = NULL; delete[] mTimeToSample; mTimeToSample = NULL; delete mSampleIterator; mSampleIterator = NULL; } Loading @@ -162,7 +159,7 @@ bool SampleTable::isValid() const { return mChunkOffsetOffset >= 0 && mSampleToChunkOffset >= 0 && mSampleSizeOffset >= 0 && mTimeToSample != NULL; && !mTimeToSample.empty(); } status_t SampleTable::setChunkOffsetParams( Loading Loading @@ -326,7 +323,7 @@ status_t SampleTable::setSampleSizeParams( status_t SampleTable::setTimeToSampleParams( off64_t data_offset, size_t data_size) { if (mTimeToSample != NULL || data_size < 8) { if (!mTimeToSample.empty() || data_size < 8) { return ERROR_MALFORMED; } Loading @@ -342,22 +339,29 @@ status_t SampleTable::setTimeToSampleParams( } mTimeToSampleCount = U32_AT(&header[4]); uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); if (allocSize > SIZE_MAX) { if ((uint64_t)mTimeToSampleCount > (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) { // Choose this bound because // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one // time-to-sample entry in the time-to-sample table. // 2) mTimeToSampleCount is the number of entries of the time-to-sample // table. // 3) We hope that the table size does not exceed UINT32_MAX. ALOGE(" Error: Time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } mTimeToSample = new uint32_t[mTimeToSampleCount * 2]; size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2; if (mDataSource->readAt( data_offset + 8, mTimeToSample, size) < (ssize_t)size) { // Note: At this point, we know that mTimeToSampleCount * 2 will not // overflow because of the above condition. if (!mDataSource->getVector(data_offset + 8, &mTimeToSample, mTimeToSampleCount * 2)) { ALOGE(" Error: Incomplete data read for time-to-sample table."); return ERROR_IO; } for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) { mTimeToSample[i] = ntohl(mTimeToSample[i]); for (size_t i = 0; i < mTimeToSample.size(); ++i) { mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]); } return OK; } Loading media/libstagefright/include/SampleTable.h +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <media/stagefright/MediaErrors.h> #include <utils/RefBase.h> #include <utils/threads.h> #include <utils/Vector.h> namespace android { Loading Loading @@ -109,7 +110,7 @@ private: uint32_t mNumSampleSizes; uint32_t mTimeToSampleCount; uint32_t *mTimeToSample; Vector<uint32_t> mTimeToSample; struct SampleTimeEntry { uint32_t mSampleIndex; Loading Loading
include/media/stagefright/DataSource.h +60 −1 Original line number Diff line number Diff line Loading @@ -19,7 +19,7 @@ #define DATA_SOURCE_H_ #include <sys/types.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/MediaErrors.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> Loading Loading @@ -58,6 +58,20 @@ public: bool getUInt32(off64_t offset, uint32_t *x); bool getUInt64(off64_t offset, uint64_t *x); // Reads in "count" entries of type T into vector *x. // Returns true if "count" entries can be read. // If fewer than "count" entries can be read, return false. In this case, // the output vector *x will still have those entries that were read. Call // x->size() to obtain the number of entries read. // The optional parameter chunkSize specifies how many entries should be // read from the data source at one time into a temporary buffer. Increasing // chunkSize can improve the performance at the cost of extra memory usage. // The default value for chunkSize is set to read at least 4k bytes at a // time, depending on sizeof(T). template <typename T> bool getVector(off64_t offset, Vector<T>* x, size_t count, size_t chunkSize = (4095 / sizeof(T)) + 1); // May return ERROR_UNSUPPORTED. virtual status_t getSize(off64_t *size); Loading Loading @@ -108,6 +122,51 @@ private: DataSource &operator=(const DataSource &); }; template <typename T> bool DataSource::getVector(off64_t offset, Vector<T>* x, size_t count, size_t chunkSize) { x->clear(); if (chunkSize == 0) { return false; } if (count == 0) { return true; } T tmp[chunkSize]; ssize_t numBytesRead; size_t numBytesPerChunk = chunkSize * sizeof(T); size_t i; for (i = 0; i + chunkSize < count; i += chunkSize) { // This loops is executed when more than chunkSize records need to be // read. numBytesRead = this->readAt(offset, (void*)&tmp, numBytesPerChunk); if (numBytesRead == -1) { // If readAt() returns -1, there is an error. return false; } if (numBytesRead < numBytesPerChunk) { // This case is triggered when the stream ends before the whole // chunk is read. x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); return false; } x->appendArray(tmp, chunkSize); offset += numBytesPerChunk; } // There are (count - i) more records to read. // Right now, (count - i) <= chunkSize. // We do the same thing as above, but with chunkSize replaced by count - i. numBytesRead = this->readAt(offset, (void*)&tmp, (count - i) * sizeof(T)); if (numBytesRead == -1) { return false; } x->appendArray(tmp, (size_t)numBytesRead / sizeof(T)); return x->size() == count; } } // namespace android #endif // DATA_SOURCE_H_
media/libstagefright/SampleTable.cpp +19 −15 Original line number Diff line number Diff line Loading @@ -122,7 +122,7 @@ SampleTable::SampleTable(const sp<DataSource> &source) mDefaultSampleSize(0), mNumSampleSizes(0), mTimeToSampleCount(0), mTimeToSample(NULL), mTimeToSample(), mSampleTimeEntries(NULL), mCompositionTimeDeltaEntries(NULL), mNumCompositionTimeDeltaEntries(0), Loading Loading @@ -151,9 +151,6 @@ SampleTable::~SampleTable() { delete[] mSampleTimeEntries; mSampleTimeEntries = NULL; delete[] mTimeToSample; mTimeToSample = NULL; delete mSampleIterator; mSampleIterator = NULL; } Loading @@ -162,7 +159,7 @@ bool SampleTable::isValid() const { return mChunkOffsetOffset >= 0 && mSampleToChunkOffset >= 0 && mSampleSizeOffset >= 0 && mTimeToSample != NULL; && !mTimeToSample.empty(); } status_t SampleTable::setChunkOffsetParams( Loading Loading @@ -326,7 +323,7 @@ status_t SampleTable::setSampleSizeParams( status_t SampleTable::setTimeToSampleParams( off64_t data_offset, size_t data_size) { if (mTimeToSample != NULL || data_size < 8) { if (!mTimeToSample.empty() || data_size < 8) { return ERROR_MALFORMED; } Loading @@ -342,22 +339,29 @@ status_t SampleTable::setTimeToSampleParams( } mTimeToSampleCount = U32_AT(&header[4]); uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t); if (allocSize > SIZE_MAX) { if ((uint64_t)mTimeToSampleCount > (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) { // Choose this bound because // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one // time-to-sample entry in the time-to-sample table. // 2) mTimeToSampleCount is the number of entries of the time-to-sample // table. // 3) We hope that the table size does not exceed UINT32_MAX. ALOGE(" Error: Time-to-sample table size too large."); return ERROR_OUT_OF_RANGE; } mTimeToSample = new uint32_t[mTimeToSampleCount * 2]; size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2; if (mDataSource->readAt( data_offset + 8, mTimeToSample, size) < (ssize_t)size) { // Note: At this point, we know that mTimeToSampleCount * 2 will not // overflow because of the above condition. if (!mDataSource->getVector(data_offset + 8, &mTimeToSample, mTimeToSampleCount * 2)) { ALOGE(" Error: Incomplete data read for time-to-sample table."); return ERROR_IO; } for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) { mTimeToSample[i] = ntohl(mTimeToSample[i]); for (size_t i = 0; i < mTimeToSample.size(); ++i) { mTimeToSample.editItemAt(i) = ntohl(mTimeToSample[i]); } return OK; } Loading
media/libstagefright/include/SampleTable.h +2 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <media/stagefright/MediaErrors.h> #include <utils/RefBase.h> #include <utils/threads.h> #include <utils/Vector.h> namespace android { Loading Loading @@ -109,7 +110,7 @@ private: uint32_t mNumSampleSizes; uint32_t mTimeToSampleCount; uint32_t *mTimeToSample; Vector<uint32_t> mTimeToSample; struct SampleTimeEntry { uint32_t mSampleIndex; Loading