Loading include/media/mediametadataretriever.h +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ enum { METADATA_KEY_IS_DRM = 22, METADATA_KEY_LOCATION = 23, METADATA_KEY_VIDEO_ROTATION = 24, METADATA_KEY_CAPTURE_FRAMERATE = 25, // Add more here... }; Loading include/media/stagefright/MetaData.h +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ enum { kKeyCompilation = 'cpil', // cstring kKeyLocation = 'loc ', // cstring kKeyTimeScale = 'tmsl', // int32_t kKeyCaptureFramerate = 'capF', // float (capture fps) // video profile and level kKeyVideoProfile = 'vprf', // int32_t Loading media/libstagefright/MPEG4Extractor.cpp +151 −20 Original line number Diff line number Diff line Loading @@ -739,6 +739,16 @@ static bool underMetaDataPath(const Vector<uint32_t> &path) { && path[3] == FOURCC('i', 'l', 's', 't'); } static bool underQTMetaPath(const Vector<uint32_t> &path, int32_t depth) { return path.size() >= 2 && path[0] == FOURCC('m', 'o', 'o', 'v') && path[1] == FOURCC('m', 'e', 't', 'a') && (depth == 2 || (depth == 3 && (path[2] == FOURCC('i', 'l', 's', 't') || path[2] == FOURCC('k', 'e', 'y', 's')))); } // Given a time in seconds since Jan 1 1904, produce a human-readable string. static void convertTimeToDate(int64_t time_1904, String8 *s) { time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); Loading Loading @@ -1732,6 +1742,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('m', 'e', 't', 'a'): { off64_t stop_offset = *offset + chunk_size; *offset = data_offset; bool isParsingMetaKeys = underQTMetaPath(mPath, 2); if (!isParsingMetaKeys) { uint8_t buffer[4]; if (chunk_data_size < (off64_t)sizeof(buffer)) { *offset += chunk_size; Loading @@ -1754,9 +1768,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { *offset += chunk_size; return OK; } *offset += sizeof(buffer); } off64_t stop_offset = *offset + chunk_size; *offset = data_offset + sizeof(buffer); while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading Loading @@ -1920,6 +1934,16 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } case FOURCC('k', 'e', 'y', 's'): { *offset += chunk_size; if (underQTMetaPath(mPath, 3)) { parseQTMetaKey(data_offset, chunk_data_size); } break; } case FOURCC('t', 'r', 'e', 'x'): { *offset += chunk_size; Loading Loading @@ -2050,6 +2074,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { default: { // check if we're parsing 'ilst' for meta keys // if so, treat type as a number (key-id). if (underQTMetaPath(mPath, 3)) { parseQTMetaVal(chunk_type, data_offset, chunk_data_size); } *offset += chunk_size; break; } Loading Loading @@ -2180,7 +2210,108 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { return OK; } status_t MPEG4Extractor::parseQTMetaKey(off64_t offset, size_t size) { if (size < 8) { return ERROR_MALFORMED; } uint32_t count; if (!mDataSource->getUInt32(offset + 4, &count)) { return ERROR_MALFORMED; } if (mMetaKeyMap.size() > 0) { ALOGW("'keys' atom seen again, discarding existing entries"); mMetaKeyMap.clear(); } off64_t keyOffset = offset + 8; off64_t stopOffset = offset + size; for (size_t i = 1; i <= count; i++) { if (keyOffset + 8 > stopOffset) { return ERROR_MALFORMED; } uint32_t keySize; if (!mDataSource->getUInt32(keyOffset, &keySize) || keySize < 8 || keyOffset + keySize > stopOffset) { return ERROR_MALFORMED; } uint32_t type; if (!mDataSource->getUInt32(keyOffset + 4, &type) || type != FOURCC('m', 'd', 't', 'a')) { return ERROR_MALFORMED; } keySize -= 8; keyOffset += 8; sp<ABuffer> keyData = new ABuffer(keySize); if (keyData->data() == NULL) { return ERROR_MALFORMED; } if (mDataSource->readAt( keyOffset, keyData->data(), keySize) < (ssize_t) keySize) { return ERROR_MALFORMED; } AString key((const char *)keyData->data(), keySize); mMetaKeyMap.add(i, key); keyOffset += keySize; } return OK; } status_t MPEG4Extractor::parseQTMetaVal( int32_t keyId, off64_t offset, size_t size) { ssize_t index = mMetaKeyMap.indexOfKey(keyId); if (index < 0) { // corresponding key is not present, ignore return ERROR_MALFORMED; } if (size <= 16) { return ERROR_MALFORMED; } uint32_t dataSize; if (!mDataSource->getUInt32(offset, &dataSize) || dataSize > size || dataSize <= 16) { return ERROR_MALFORMED; } uint32_t atomFourCC; if (!mDataSource->getUInt32(offset + 4, &atomFourCC) || atomFourCC != FOURCC('d', 'a', 't', 'a')) { return ERROR_MALFORMED; } uint32_t dataType; if (!mDataSource->getUInt32(offset + 8, &dataType) || ((dataType & 0xff000000) != 0)) { // not well-known type return ERROR_MALFORMED; } dataSize -= 16; offset += 16; if (dataType == 23 && dataSize >= 4) { // BE Float32 uint32_t val; if (!mDataSource->getUInt32(offset, &val)) { return ERROR_MALFORMED; } if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) { mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val); } } else { // add more keys if needed ALOGV("ignoring key: type %d, size %d", dataType, dataSize); } return OK; } status_t MPEG4Extractor::parseTrackHeader( off64_t data_offset, off64_t data_size) { Loading media/libstagefright/StagefrightMetadataRetriever.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,12 @@ void StagefrightMetadataRetriever::parseMetaData() { mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); float captureFps; if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) { sprintf(tmp, "%f", captureFps); mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp)); } bool hasAudio = false; bool hasVideo = false; int32_t videoWidth = -1; Loading media/libstagefright/include/MPEG4Extractor.h +4 −0 Original line number Diff line number Diff line Loading @@ -104,11 +104,15 @@ private: String8 mLastCommentName; String8 mLastCommentData; KeyedVector<uint32_t, AString> mMetaKeyMap; status_t readMetaData(); status_t parseChunk(off64_t *offset, int depth); status_t parseITunesMetaData(off64_t offset, size_t size); status_t parse3GPPMetaData(off64_t offset, size_t size, int depth); void parseID3v2MetaData(off64_t offset); status_t parseQTMetaKey(off64_t data_offset, size_t data_size); status_t parseQTMetaVal(int32_t keyId, off64_t data_offset, size_t data_size); status_t updateAudioTrackInfoFromESDS_MPEG4Audio( const void *esds_data, size_t esds_size); Loading Loading
include/media/mediametadataretriever.h +1 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,7 @@ enum { METADATA_KEY_IS_DRM = 22, METADATA_KEY_LOCATION = 23, METADATA_KEY_VIDEO_ROTATION = 24, METADATA_KEY_CAPTURE_FRAMERATE = 25, // Add more here... }; Loading
include/media/stagefright/MetaData.h +1 −0 Original line number Diff line number Diff line Loading @@ -98,6 +98,7 @@ enum { kKeyCompilation = 'cpil', // cstring kKeyLocation = 'loc ', // cstring kKeyTimeScale = 'tmsl', // int32_t kKeyCaptureFramerate = 'capF', // float (capture fps) // video profile and level kKeyVideoProfile = 'vprf', // int32_t Loading
media/libstagefright/MPEG4Extractor.cpp +151 −20 Original line number Diff line number Diff line Loading @@ -739,6 +739,16 @@ static bool underMetaDataPath(const Vector<uint32_t> &path) { && path[3] == FOURCC('i', 'l', 's', 't'); } static bool underQTMetaPath(const Vector<uint32_t> &path, int32_t depth) { return path.size() >= 2 && path[0] == FOURCC('m', 'o', 'o', 'v') && path[1] == FOURCC('m', 'e', 't', 'a') && (depth == 2 || (depth == 3 && (path[2] == FOURCC('i', 'l', 's', 't') || path[2] == FOURCC('k', 'e', 'y', 's')))); } // Given a time in seconds since Jan 1 1904, produce a human-readable string. static void convertTimeToDate(int64_t time_1904, String8 *s) { time_t time_1970 = time_1904 - (((66 * 365 + 17) * 24) * 3600); Loading Loading @@ -1732,6 +1742,10 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('m', 'e', 't', 'a'): { off64_t stop_offset = *offset + chunk_size; *offset = data_offset; bool isParsingMetaKeys = underQTMetaPath(mPath, 2); if (!isParsingMetaKeys) { uint8_t buffer[4]; if (chunk_data_size < (off64_t)sizeof(buffer)) { *offset += chunk_size; Loading @@ -1754,9 +1768,9 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { *offset += chunk_size; return OK; } *offset += sizeof(buffer); } off64_t stop_offset = *offset + chunk_size; *offset = data_offset + sizeof(buffer); while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading Loading @@ -1920,6 +1934,16 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { break; } case FOURCC('k', 'e', 'y', 's'): { *offset += chunk_size; if (underQTMetaPath(mPath, 3)) { parseQTMetaKey(data_offset, chunk_data_size); } break; } case FOURCC('t', 'r', 'e', 'x'): { *offset += chunk_size; Loading Loading @@ -2050,6 +2074,12 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { default: { // check if we're parsing 'ilst' for meta keys // if so, treat type as a number (key-id). if (underQTMetaPath(mPath, 3)) { parseQTMetaVal(chunk_type, data_offset, chunk_data_size); } *offset += chunk_size; break; } Loading Loading @@ -2180,7 +2210,108 @@ status_t MPEG4Extractor::parseSegmentIndex(off64_t offset, size_t size) { return OK; } status_t MPEG4Extractor::parseQTMetaKey(off64_t offset, size_t size) { if (size < 8) { return ERROR_MALFORMED; } uint32_t count; if (!mDataSource->getUInt32(offset + 4, &count)) { return ERROR_MALFORMED; } if (mMetaKeyMap.size() > 0) { ALOGW("'keys' atom seen again, discarding existing entries"); mMetaKeyMap.clear(); } off64_t keyOffset = offset + 8; off64_t stopOffset = offset + size; for (size_t i = 1; i <= count; i++) { if (keyOffset + 8 > stopOffset) { return ERROR_MALFORMED; } uint32_t keySize; if (!mDataSource->getUInt32(keyOffset, &keySize) || keySize < 8 || keyOffset + keySize > stopOffset) { return ERROR_MALFORMED; } uint32_t type; if (!mDataSource->getUInt32(keyOffset + 4, &type) || type != FOURCC('m', 'd', 't', 'a')) { return ERROR_MALFORMED; } keySize -= 8; keyOffset += 8; sp<ABuffer> keyData = new ABuffer(keySize); if (keyData->data() == NULL) { return ERROR_MALFORMED; } if (mDataSource->readAt( keyOffset, keyData->data(), keySize) < (ssize_t) keySize) { return ERROR_MALFORMED; } AString key((const char *)keyData->data(), keySize); mMetaKeyMap.add(i, key); keyOffset += keySize; } return OK; } status_t MPEG4Extractor::parseQTMetaVal( int32_t keyId, off64_t offset, size_t size) { ssize_t index = mMetaKeyMap.indexOfKey(keyId); if (index < 0) { // corresponding key is not present, ignore return ERROR_MALFORMED; } if (size <= 16) { return ERROR_MALFORMED; } uint32_t dataSize; if (!mDataSource->getUInt32(offset, &dataSize) || dataSize > size || dataSize <= 16) { return ERROR_MALFORMED; } uint32_t atomFourCC; if (!mDataSource->getUInt32(offset + 4, &atomFourCC) || atomFourCC != FOURCC('d', 'a', 't', 'a')) { return ERROR_MALFORMED; } uint32_t dataType; if (!mDataSource->getUInt32(offset + 8, &dataType) || ((dataType & 0xff000000) != 0)) { // not well-known type return ERROR_MALFORMED; } dataSize -= 16; offset += 16; if (dataType == 23 && dataSize >= 4) { // BE Float32 uint32_t val; if (!mDataSource->getUInt32(offset, &val)) { return ERROR_MALFORMED; } if (!strcasecmp(mMetaKeyMap[index].c_str(), "com.android.capture.fps")) { mFileMetaData->setFloat(kKeyCaptureFramerate, *(float *)&val); } } else { // add more keys if needed ALOGV("ignoring key: type %d, size %d", dataType, dataSize); } return OK; } status_t MPEG4Extractor::parseTrackHeader( off64_t data_offset, off64_t data_size) { Loading
media/libstagefright/StagefrightMetadataRetriever.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -519,6 +519,12 @@ void StagefrightMetadataRetriever::parseMetaData() { mMetaData.add(METADATA_KEY_NUM_TRACKS, String8(tmp)); float captureFps; if (meta->findFloat(kKeyCaptureFramerate, &captureFps)) { sprintf(tmp, "%f", captureFps); mMetaData.add(METADATA_KEY_CAPTURE_FRAMERATE, String8(tmp)); } bool hasAudio = false; bool hasVideo = false; int32_t videoWidth = -1; Loading
media/libstagefright/include/MPEG4Extractor.h +4 −0 Original line number Diff line number Diff line Loading @@ -104,11 +104,15 @@ private: String8 mLastCommentName; String8 mLastCommentData; KeyedVector<uint32_t, AString> mMetaKeyMap; status_t readMetaData(); status_t parseChunk(off64_t *offset, int depth); status_t parseITunesMetaData(off64_t offset, size_t size); status_t parse3GPPMetaData(off64_t offset, size_t size, int depth); void parseID3v2MetaData(off64_t offset); status_t parseQTMetaKey(off64_t data_offset, size_t data_size); status_t parseQTMetaVal(int32_t keyId, off64_t data_offset, size_t data_size); status_t updateAudioTrackInfoFromESDS_MPEG4Audio( const void *esds_data, size_t esds_size); Loading