Loading media/extractors/mp4/MPEG4Extractor.cpp +76 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ #define UINT32_MAX (4294967295U) #endif #define ALAC_SPECIFIC_INFO_SIZE (36) namespace android { enum { Loading Loading @@ -331,6 +333,8 @@ static const char *FourCC2MIME(uint32_t fourcc) { case FOURCC('t', 'w', 'o', 's'): case FOURCC('s', 'o', 'w', 't'): return MEDIA_MIMETYPE_AUDIO_RAW; case FOURCC('a', 'l', 'a', 'c'): return MEDIA_MIMETYPE_AUDIO_ALAC; default: ALOGW("Unknown fourcc: %c%c%c%c", Loading Loading @@ -1122,6 +1126,43 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { mLastTrack->meta.setInt32(kKeyChannelCount, num_channels); mLastTrack->meta.setInt32(kKeySampleRate, sample_rate); } // If format type is 'alac', it is necessary to get the parameters // from a alac atom spreading behind the frma atom. // See 'external/alac/ALACMagicCookieDescription.txt'. if (original_fourcc == FOURCC('a', 'l', 'a', 'c')) { // Store ALAC magic cookie (decoder needs it). uint8_t alacInfo[12]; data_offset = *offset; if (mDataSource->readAt( data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) { return ERROR_IO; } uint32_t size = U32_AT(&alacInfo[0]); if ((size != ALAC_SPECIFIC_INFO_SIZE) || (U32_AT(&alacInfo[4]) != FOURCC('a', 'l', 'a', 'c')) || (U32_AT(&alacInfo[8]) != 0)) { return ERROR_MALFORMED; } data_offset += sizeof(alacInfo); uint8_t cookie[size - sizeof(alacInfo)]; if (mDataSource->readAt( data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) { return ERROR_IO; } uint8_t bitsPerSample = cookie[5]; mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample); mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]); mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20])); mLastTrack->meta.setData( kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie)); // Add the size of ALAC Specific Info (36 bytes) and terminator // atom (8 bytes). *offset += (size + 8); } break; } Loading Loading @@ -1490,6 +1531,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 'a', 'w', 'b'): case FOURCC('t', 'w', 'o', 's'): case FOURCC('s', 'o', 'w', 't'): case FOURCC('a', 'l', 'a', 'c'): { if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a') && depth >= 1 && mPath[depth - 1] == FOURCC('w', 'a', 'v', 'e')) { Loading Loading @@ -1572,6 +1614,40 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { mLastTrack->meta.setInt32(kKeyChannelCount, num_channels); mLastTrack->meta.setInt32(kKeySampleRate, sample_rate); if (chunk_type == FOURCC('a', 'l', 'a', 'c')) { // See 'external/alac/ALACMagicCookieDescription.txt for the detail'. // Store ALAC magic cookie (decoder needs it). uint8_t alacInfo[12]; data_offset += sizeof(buffer); if (mDataSource->readAt( data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) { return ERROR_IO; } uint32_t size = U32_AT(&alacInfo[0]); if ((size != ALAC_SPECIFIC_INFO_SIZE) || (U32_AT(&alacInfo[4]) != FOURCC('a', 'l', 'a', 'c')) || (U32_AT(&alacInfo[8]) != 0)) { return ERROR_MALFORMED; } data_offset += sizeof(alacInfo); uint8_t cookie[size - sizeof(alacInfo)]; if (mDataSource->readAt( data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) { return ERROR_IO; } uint8_t bitsPerSample = cookie[5]; mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample); mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]); mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20])); mLastTrack->meta.setData( kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie)); data_offset += sizeof(cookie); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading media/libmediaextractor/include/media/stagefright/MetaDataBase.h +3 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,9 @@ enum { kKeyIsExif = 'exif', // bool (int32_t) buffer contains exif data block kKeyPcmBigEndian = 'pcmb', // bool (int32_t) // Key for ALAC Magic Cookie kKeyAlacMagicCookie = 'almc', // raw data }; enum { Loading media/libstagefright/Utils.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -1135,6 +1135,17 @@ status_t convertMetaDataToMessage( msg->setBuffer("csd-0", buffer); parseVp9ProfileLevelFromCsd(buffer, msg); } else if (meta->findData(kKeyAlacMagicCookie, &type, &data, &size)) { ALOGV("convertMetaDataToMessage found kKeyAlacMagicCookie of size %zu\n", size); sp<ABuffer> buffer = new (std::nothrow) ABuffer(size); if (buffer.get() == NULL || buffer->base() == NULL) { return NO_MEMORY; } memcpy(buffer->data(), data, size); buffer->meta()->setInt32("csd", true); buffer->meta()->setInt64("timeUs", 0); msg->setBuffer("csd-0", buffer); } // TODO expose "crypto-key"/kKeyCryptoKey through public api Loading Loading @@ -1546,6 +1557,8 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { if (msg->findBuffer("csd-1", &csd1)) { meta->setData(kKeyVorbisBooks, 0, csd1->data(), csd1->size()); } } else if (mime == MEDIA_MIMETYPE_AUDIO_ALAC) { meta->setData(kKeyAlacMagicCookie, 0, csd0->data(), csd0->size()); } } Loading Loading @@ -1628,6 +1641,7 @@ static const struct mime_conv_t mimeLookup[] = { { MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS}, { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3}, { MEDIA_MIMETYPE_AUDIO_FLAC, AUDIO_FORMAT_FLAC}, { MEDIA_MIMETYPE_AUDIO_ALAC, AUDIO_FORMAT_ALAC }, { 0, AUDIO_FORMAT_INVALID } }; Loading media/libstagefright/foundation/MediaDefs.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm"; const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3"; const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3"; const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled"; const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4"; const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav"; Loading media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM; extern const char *MEDIA_MIMETYPE_AUDIO_AC3; extern const char *MEDIA_MIMETYPE_AUDIO_EAC3; extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED; extern const char *MEDIA_MIMETYPE_AUDIO_ALAC; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; Loading Loading
media/extractors/mp4/MPEG4Extractor.cpp +76 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,8 @@ #define UINT32_MAX (4294967295U) #endif #define ALAC_SPECIFIC_INFO_SIZE (36) namespace android { enum { Loading Loading @@ -331,6 +333,8 @@ static const char *FourCC2MIME(uint32_t fourcc) { case FOURCC('t', 'w', 'o', 's'): case FOURCC('s', 'o', 'w', 't'): return MEDIA_MIMETYPE_AUDIO_RAW; case FOURCC('a', 'l', 'a', 'c'): return MEDIA_MIMETYPE_AUDIO_ALAC; default: ALOGW("Unknown fourcc: %c%c%c%c", Loading Loading @@ -1122,6 +1126,43 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { mLastTrack->meta.setInt32(kKeyChannelCount, num_channels); mLastTrack->meta.setInt32(kKeySampleRate, sample_rate); } // If format type is 'alac', it is necessary to get the parameters // from a alac atom spreading behind the frma atom. // See 'external/alac/ALACMagicCookieDescription.txt'. if (original_fourcc == FOURCC('a', 'l', 'a', 'c')) { // Store ALAC magic cookie (decoder needs it). uint8_t alacInfo[12]; data_offset = *offset; if (mDataSource->readAt( data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) { return ERROR_IO; } uint32_t size = U32_AT(&alacInfo[0]); if ((size != ALAC_SPECIFIC_INFO_SIZE) || (U32_AT(&alacInfo[4]) != FOURCC('a', 'l', 'a', 'c')) || (U32_AT(&alacInfo[8]) != 0)) { return ERROR_MALFORMED; } data_offset += sizeof(alacInfo); uint8_t cookie[size - sizeof(alacInfo)]; if (mDataSource->readAt( data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) { return ERROR_IO; } uint8_t bitsPerSample = cookie[5]; mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample); mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]); mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20])); mLastTrack->meta.setData( kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie)); // Add the size of ALAC Specific Info (36 bytes) and terminator // atom (8 bytes). *offset += (size + 8); } break; } Loading Loading @@ -1490,6 +1531,7 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { case FOURCC('s', 'a', 'w', 'b'): case FOURCC('t', 'w', 'o', 's'): case FOURCC('s', 'o', 'w', 't'): case FOURCC('a', 'l', 'a', 'c'): { if (mIsQT && chunk_type == FOURCC('m', 'p', '4', 'a') && depth >= 1 && mPath[depth - 1] == FOURCC('w', 'a', 'v', 'e')) { Loading Loading @@ -1572,6 +1614,40 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) { mLastTrack->meta.setInt32(kKeyChannelCount, num_channels); mLastTrack->meta.setInt32(kKeySampleRate, sample_rate); if (chunk_type == FOURCC('a', 'l', 'a', 'c')) { // See 'external/alac/ALACMagicCookieDescription.txt for the detail'. // Store ALAC magic cookie (decoder needs it). uint8_t alacInfo[12]; data_offset += sizeof(buffer); if (mDataSource->readAt( data_offset, alacInfo, sizeof(alacInfo)) < (ssize_t)sizeof(alacInfo)) { return ERROR_IO; } uint32_t size = U32_AT(&alacInfo[0]); if ((size != ALAC_SPECIFIC_INFO_SIZE) || (U32_AT(&alacInfo[4]) != FOURCC('a', 'l', 'a', 'c')) || (U32_AT(&alacInfo[8]) != 0)) { return ERROR_MALFORMED; } data_offset += sizeof(alacInfo); uint8_t cookie[size - sizeof(alacInfo)]; if (mDataSource->readAt( data_offset, cookie, sizeof(cookie)) < (ssize_t)sizeof(cookie)) { return ERROR_IO; } uint8_t bitsPerSample = cookie[5]; mLastTrack->meta.setInt32(kKeyBitsPerSample, bitsPerSample); mLastTrack->meta.setInt32(kKeyChannelCount, cookie[9]); mLastTrack->meta.setInt32(kKeySampleRate, U32_AT(&cookie[20])); mLastTrack->meta.setData( kKeyAlacMagicCookie, MetaData::TYPE_NONE, cookie, sizeof(cookie)); data_offset += sizeof(cookie); *offset = data_offset; CHECK_EQ(*offset, stop_offset); } while (*offset < stop_offset) { status_t err = parseChunk(offset, depth + 1); if (err != OK) { Loading
media/libmediaextractor/include/media/stagefright/MetaDataBase.h +3 −0 Original line number Diff line number Diff line Loading @@ -228,6 +228,9 @@ enum { kKeyIsExif = 'exif', // bool (int32_t) buffer contains exif data block kKeyPcmBigEndian = 'pcmb', // bool (int32_t) // Key for ALAC Magic Cookie kKeyAlacMagicCookie = 'almc', // raw data }; enum { Loading
media/libstagefright/Utils.cpp +14 −0 Original line number Diff line number Diff line Loading @@ -1135,6 +1135,17 @@ status_t convertMetaDataToMessage( msg->setBuffer("csd-0", buffer); parseVp9ProfileLevelFromCsd(buffer, msg); } else if (meta->findData(kKeyAlacMagicCookie, &type, &data, &size)) { ALOGV("convertMetaDataToMessage found kKeyAlacMagicCookie of size %zu\n", size); sp<ABuffer> buffer = new (std::nothrow) ABuffer(size); if (buffer.get() == NULL || buffer->base() == NULL) { return NO_MEMORY; } memcpy(buffer->data(), data, size); buffer->meta()->setInt32("csd", true); buffer->meta()->setInt64("timeUs", 0); msg->setBuffer("csd-0", buffer); } // TODO expose "crypto-key"/kKeyCryptoKey through public api Loading Loading @@ -1546,6 +1557,8 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) { if (msg->findBuffer("csd-1", &csd1)) { meta->setData(kKeyVorbisBooks, 0, csd1->data(), csd1->size()); } } else if (mime == MEDIA_MIMETYPE_AUDIO_ALAC) { meta->setData(kKeyAlacMagicCookie, 0, csd0->data(), csd0->size()); } } Loading Loading @@ -1628,6 +1641,7 @@ static const struct mime_conv_t mimeLookup[] = { { MEDIA_MIMETYPE_AUDIO_OPUS, AUDIO_FORMAT_OPUS}, { MEDIA_MIMETYPE_AUDIO_AC3, AUDIO_FORMAT_AC3}, { MEDIA_MIMETYPE_AUDIO_FLAC, AUDIO_FORMAT_FLAC}, { MEDIA_MIMETYPE_AUDIO_ALAC, AUDIO_FORMAT_ALAC }, { 0, AUDIO_FORMAT_INVALID } }; Loading
media/libstagefright/foundation/MediaDefs.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,7 @@ const char *MEDIA_MIMETYPE_AUDIO_MSGSM = "audio/gsm"; const char *MEDIA_MIMETYPE_AUDIO_AC3 = "audio/ac3"; const char *MEDIA_MIMETYPE_AUDIO_EAC3 = "audio/eac3"; const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled"; const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac"; const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4"; const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav"; Loading
media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h +1 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,7 @@ extern const char *MEDIA_MIMETYPE_AUDIO_MSGSM; extern const char *MEDIA_MIMETYPE_AUDIO_AC3; extern const char *MEDIA_MIMETYPE_AUDIO_EAC3; extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED; extern const char *MEDIA_MIMETYPE_AUDIO_ALAC; extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4; extern const char *MEDIA_MIMETYPE_CONTAINER_WAV; Loading