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

Commit 06001610 authored by Marco Nelissen's avatar Marco Nelissen Committed by Android (Google) Code Review
Browse files

Merge "mkv support more audio codec" into qt-dev

parents 29ccc29d 4c7b61e7
Loading
Loading
Loading
Loading
+95 −5
Original line number Original line Diff line number Diff line
@@ -150,6 +150,7 @@ private:
        AAC,
        AAC,
        HEVC,
        HEVC,
        MP3,
        MP3,
        PCM,
        OTHER
        OTHER
    };
    };


@@ -270,6 +271,8 @@ MatroskaSource::MatroskaSource(
        mType = AAC;
        mType = AAC;
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
        mType = MP3;
        mType = MP3;
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
        mType = PCM;
    }
    }
}
}


@@ -1054,6 +1057,27 @@ media_status_t MatroskaSource::read(
                    AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
                    AMEDIAFORMAT_KEY_TARGET_TIME, targetSampleTimeUs);
        }
        }


        if (mType == PCM) {
            int32_t bitPerFrame = 16;
            int32_t bigEndian = 0;
            AMediaFormat *meta = AMediaFormat_new();
            if (getFormat(meta) == AMEDIA_OK && meta != NULL) {
                AMediaFormat_getInt32(meta,
                                AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, &bitPerFrame);
                AMediaFormat_getInt32(meta,
                                AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, &bigEndian);
            }
            AMediaFormat_delete(meta);
            if (bigEndian == 1 && bitPerFrame == 16) {
                // Big-endian -> little-endian
                uint16_t *dstData = (uint16_t *)frame->data() + frame->range_offset();
                uint16_t *srcData = (uint16_t *)frame->data() + frame->range_offset();
                for (size_t i = 0; i < frame->range_length() / 2; i++) {
                    dstData[i] = ntohs(srcData[i]);
                }
            }
        }

        *out = frame;
        *out = frame;


        return AMEDIA_OK;
        return AMEDIA_OK;
@@ -1170,6 +1194,51 @@ media_status_t MatroskaSource::read(


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////


enum WaveID {
    MKV_RIFF_WAVE_FORMAT_PCM = 0x0001,
    MKV_RIFF_WAVE_FORMAT_ADPCM_ms = 0x0002,
    MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav = 0x0011,
    MKV_RIFF_WAVE_FORMAT_MPEGL12 = 0x0050,
    MKV_RIFF_WAVE_FORMAT_MPEGL3 = 0x0055,
    MKV_RIFF_WAVE_FORMAT_WMAV1 = 0x0160,
    MKV_RIFF_WAVE_FORMAT_WMAV2 = 0x0161,
};

static const char *MKVWave2MIME(uint16_t id) {
    switch (id) {
        case  MKV_RIFF_WAVE_FORMAT_MPEGL12:
            return MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II;

        case  MKV_RIFF_WAVE_FORMAT_MPEGL3:
            return MEDIA_MIMETYPE_AUDIO_MPEG;

        case MKV_RIFF_WAVE_FORMAT_PCM:
            return MEDIA_MIMETYPE_AUDIO_RAW;

        case MKV_RIFF_WAVE_FORMAT_ADPCM_ms:
            return MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
        case MKV_RIFF_WAVE_FORMAT_ADPCM_ima_wav:
            return MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;

        case MKV_RIFF_WAVE_FORMAT_WMAV1:
        case MKV_RIFF_WAVE_FORMAT_WMAV2:
            return MEDIA_MIMETYPE_AUDIO_WMA;
        default:
            ALOGW("unknown wave %x", id);
            return "";
    };
}

static bool isMkvAudioCsdSizeOK(const char* mime, size_t csdSize) {
    if ((!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) && csdSize < 50) ||
        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) && csdSize < 20) ||
        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA) && csdSize < 28) ||
        (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG) && csdSize < 30)) {
        return false;
    }
    return true;
}

// trans all FOURCC  to lower char
// trans all FOURCC  to lower char
static uint32_t FourCCtoLower(uint32_t fourcc) {
static uint32_t FourCCtoLower(uint32_t fourcc) {
    uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
    uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
@@ -2036,20 +2105,40 @@ void MatroskaExtractor::addTracks() {
                } else if (!strcmp("A_FLAC", codecID)) {
                } else if (!strcmp("A_FLAC", codecID)) {
                    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
                    AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
                    err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
                    err = addFlacMetadata(meta, codecPrivate, codecPrivateSize);
                } else if (!strcmp("A_MPEG/L2", codecID)) {
                    AMediaFormat_setString(meta,
                            AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
                } else if (!strcmp("A_PCM/INT/LIT", codecID) ||
                         !strcmp("A_PCM/INT/BIG", codecID)) {
                    AMediaFormat_setString(meta,
                            AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_RAW);
                    int32_t bigEndian = !strcmp("A_PCM/INT/BIG", codecID) ? 1: 0;
                    AMediaFormat_setInt32(meta,
                            AMEDIAFORMAT_KEY_PCM_BIG_ENDIAN, bigEndian);
                } else if ((!strcmp("A_MS/ACM", codecID))) {
                } else if ((!strcmp("A_MS/ACM", codecID))) {
                    if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
                    if ((NULL == codecPrivate) || (codecPrivateSize < 18)) {
                        ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
                        ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
                               codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
                               codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
                        continue;
                        continue;
                    } else {
                    } else {
                        uint16_t ID = *(uint16_t *)codecPrivate;
                        uint16_t ID = *(uint16_t *)codecPrivate;
                        if (ID == 0x0055) {
                        const char* mime = MKVWave2MIME(ID);
                            AMediaFormat_setString(meta,
                        ALOGV("A_MS/ACM type is %s", mime);
                                    AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
                        if (!strncasecmp("audio/", mime, 6) &&
                                isMkvAudioCsdSizeOK(mime, codecPrivateSize)) {
                            AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
                        } else {
                        } else {
                            ALOGW("A_MS/ACM unsupported type , continue");
                            ALOGE("A_MS/ACM continue, unsupported audio type=%s, csdSize:%zu",
                                mime, codecPrivateSize);
                            continue;
                            continue;
                        }
                        }
                        if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_WMA)) {
                            addESDSFromCodecPrivate(meta, true, codecPrivate, codecPrivateSize);
                        } else if (!strcmp(mime, MEDIA_MIMETYPE_AUDIO_MS_ADPCM) ||
                                    !strcmp(mime, MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM)) {
                            uint32_t blockAlign = *(uint16_t*)(codecPrivate + 12);
                            addESDSFromCodecPrivate(meta, true, &blockAlign, sizeof(blockAlign));
                        }
                    }
                    }
                } else {
                } else {
                    ALOGW("%s is not supported.", codecID);
                    ALOGW("%s is not supported.", codecID);
@@ -2058,6 +2147,7 @@ void MatroskaExtractor::addTracks() {


                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
                AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, atrack->GetBitDepth());
                break;
                break;
            }
            }


+5 −1
Original line number Original line Diff line number Diff line
@@ -1756,7 +1756,11 @@ void convertMessageToMetaData(const sp<AMessage> &msg, sp<MetaData> &meta) {
                size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
                size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
                meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
                meta->setData(kKeyAVCC, kTypeAVCC, avcc.data(), outsize);
            }
            }
        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC || mime == MEDIA_MIMETYPE_VIDEO_MPEG4) {
        } else if (mime == MEDIA_MIMETYPE_AUDIO_AAC ||
                mime == MEDIA_MIMETYPE_VIDEO_MPEG4 ||
                mime == MEDIA_MIMETYPE_AUDIO_WMA ||
                mime == MEDIA_MIMETYPE_AUDIO_MS_ADPCM ||
                mime == MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM) {
            std::vector<char> esds(csd0size + 31);
            std::vector<char> esds(csd0size + 31);
            // The written ESDS is actually for an audio stream, but it's enough
            // The written ESDS is actually for an audio stream, but it's enough
            // for transporting the CSD to muxers.
            // for transporting the CSD to muxers.
+4 −0
Original line number Original line Diff line number Diff line
@@ -59,6 +59,10 @@ const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC = "audio/eac3-joc";
const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
const char *MEDIA_MIMETYPE_AUDIO_ALAC = "audio/alac";
const char *MEDIA_MIMETYPE_AUDIO_WMA = "audio/x-ms-wma";
const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM = "audio/x-adpcm-ms";
const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM = "audio/x-adpcm-dvi-ima";



const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
const char *MEDIA_MIMETYPE_CONTAINER_MPEG4 = "video/mp4";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
const char *MEDIA_MIMETYPE_CONTAINER_WAV = "audio/x-wav";
+4 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,10 @@ extern const char *MEDIA_MIMETYPE_AUDIO_EAC3_JOC;
extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
extern const char *MEDIA_MIMETYPE_AUDIO_ALAC;
extern const char *MEDIA_MIMETYPE_AUDIO_WMA;
extern const char *MEDIA_MIMETYPE_AUDIO_MS_ADPCM;
extern const char *MEDIA_MIMETYPE_AUDIO_DVI_IMA_ADPCM;



extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
extern const char *MEDIA_MIMETYPE_CONTAINER_MPEG4;
extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;
extern const char *MEDIA_MIMETYPE_CONTAINER_WAV;