Merge "mkv support more audio codec" into qt-dev
diff --git a/media/extractors/mkv/MatroskaExtractor.cpp b/media/extractors/mkv/MatroskaExtractor.cpp
index e284cda..a1c81f3 100644
--- a/media/extractors/mkv/MatroskaExtractor.cpp
+++ b/media/extractors/mkv/MatroskaExtractor.cpp
@@ -150,6 +150,7 @@
AAC,
HEVC,
MP3,
+ PCM,
OTHER
};
@@ -270,6 +271,8 @@
mType = AAC;
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
mType = MP3;
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_RAW)) {
+ mType = PCM;
}
}
@@ -1054,6 +1057,27 @@
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;
return AMEDIA_OK;
@@ -1170,6 +1194,51 @@
////////////////////////////////////////////////////////////////////////////////
+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
static uint32_t FourCCtoLower(uint32_t fourcc) {
uint8_t ch_1 = tolower((fourcc >> 24) & 0xff);
@@ -2036,20 +2105,40 @@
} else if (!strcmp("A_FLAC", codecID)) {
AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_FLAC);
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))) {
- if ((NULL == codecPrivate) || (codecPrivateSize < 30)) {
+ if ((NULL == codecPrivate) || (codecPrivateSize < 18)) {
ALOGW("unsupported audio: A_MS/ACM has no valid private data: %s, size: %zu",
codecPrivate == NULL ? "null" : "non-null", codecPrivateSize);
continue;
} else {
uint16_t ID = *(uint16_t *)codecPrivate;
- if (ID == 0x0055) {
- AMediaFormat_setString(meta,
- AMEDIAFORMAT_KEY_MIME, MEDIA_MIMETYPE_AUDIO_MPEG);
+ const char* mime = MKVWave2MIME(ID);
+ ALOGV("A_MS/ACM type is %s", mime);
+ if (!strncasecmp("audio/", mime, 6) &&
+ isMkvAudioCsdSizeOK(mime, codecPrivateSize)) {
+ AMediaFormat_setString(meta, AMEDIAFORMAT_KEY_MIME, mime);
} else {
- ALOGW("A_MS/ACM unsupported type , continue");
+ ALOGE("A_MS/ACM continue, unsupported audio type=%s, csdSize:%zu",
+ mime, codecPrivateSize);
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 {
ALOGW("%s is not supported.", codecID);
@@ -2058,6 +2147,7 @@
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_SAMPLE_RATE, atrack->GetSamplingRate());
AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_CHANNEL_COUNT, atrack->GetChannels());
+ AMediaFormat_setInt32(meta, AMEDIAFORMAT_KEY_BITS_PER_SAMPLE, atrack->GetBitDepth());
break;
}
diff --git a/media/libstagefright/Utils.cpp b/media/libstagefright/Utils.cpp
index c7b2719..537e4c0 100644
--- a/media/libstagefright/Utils.cpp
+++ b/media/libstagefright/Utils.cpp
@@ -1756,7 +1756,11 @@
size_t outsize = reassembleAVCC(csd0, csd1, avcc.data());
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);
// The written ESDS is actually for an audio stream, but it's enough
// for transporting the CSD to muxers.
diff --git a/media/libstagefright/foundation/MediaDefs.cpp b/media/libstagefright/foundation/MediaDefs.cpp
index 52b2765..a08fed1 100644
--- a/media/libstagefright/foundation/MediaDefs.cpp
+++ b/media/libstagefright/foundation/MediaDefs.cpp
@@ -59,6 +59,10 @@
const char *MEDIA_MIMETYPE_AUDIO_AC4 = "audio/ac4";
const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED = "audio/scrambled";
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_WAV = "audio/x-wav";
diff --git a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
index 007a09b..1f9e636 100644
--- a/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
+++ b/media/libstagefright/foundation/include/media/stagefright/foundation/MediaDefs.h
@@ -61,6 +61,10 @@
extern const char *MEDIA_MIMETYPE_AUDIO_AC4;
extern const char *MEDIA_MIMETYPE_AUDIO_SCRAMBLED;
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_WAV;