Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5692c9a7 authored by Marco Nelissen's avatar Marco Nelissen Committed by Gerrit Code Review
Browse files

Merge "parse alac in MPEG4Extractor"

parents 0597a457 2c37f36e
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -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) {
+3 −0
Original line number Diff line number Diff line
@@ -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 {
+14 −0
Original line number Diff line number Diff line
@@ -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 }
};

+1 −0
Original line number Diff line number Diff line
@@ -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";
+1 −0
Original line number Diff line number Diff line
@@ -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;