Merge "parse alac in MPEG4Extractor" am: 5692c9a727

am: b86da7f196

Change-Id: I8fc411b66a20eea6af70613c0849bafabac9c4e4
gugelfrei
Marco Nelissen 6 years ago committed by android-build-merger
commit 1bc4a8634b

@ -55,6 +55,8 @@
#define UINT32_MAX (4294967295U)
#endif
#define ALAC_SPECIFIC_INFO_SIZE (36)
namespace android {
enum {
@ -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",
@ -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;
}
@ -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')) {
@ -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) {

@ -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 {

@ -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
@ -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());
}
}
@ -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 }
};

@ -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";

@ -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…
Cancel
Save