void MatroskaExtractor::addTracks() { const mkvparser::Tracks *tracks = mSegment->GetTracks(); for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { const mkvparser::Track *track = tracks->GetTrackByIndex(index); if (track == NULL) { // Apparently this is currently valid (if unexpected) behaviour // of the mkv parser lib. continue; } const char *const codecID = track->GetCodecId(); ALOGV("codec id = %s", codecID); ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); if (codecID == NULL) { ALOGW("unknown codecID is not supported."); continue; } size_t codecPrivateSize; const unsigned char *codecPrivate = track->GetCodecPrivate(codecPrivateSize); enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; sp<MetaData> meta = new MetaData; status_t err = OK; switch (track->GetType()) { case VIDEO_TRACK: { const mkvparser::VideoTrack *vtrack = static_cast<const mkvparser::VideoTrack *>(track); if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { if (codecPrivateSize > 0) { meta->setCString( kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); addESDSFromCodecPrivate( meta, false, codecPrivate, codecPrivateSize); } else { ALOGW("%s is detected, but does not have configuration.", codecID); continue; } } else if (!strcmp("V_VP8", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); } else if (!strcmp("V_VP9", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); if (codecPrivateSize > 0) { // 'csd-0' for VP9 is the Blob of Codec Private data as // specified in http://www.webmproject.org/vp9/profiles/. meta->setData( kKeyVp9CodecPrivate, 0, codecPrivate, codecPrivateSize); } } else { ALOGW("%s is not supported.", codecID); continue; } meta->setInt32(kKeyWidth, vtrack->GetWidth()); meta->setInt32(kKeyHeight, vtrack->GetHeight()); getColorInformation(vtrack, meta); break; } case AUDIO_TRACK: { const mkvparser::AudioTrack *atrack = static_cast<const mkvparser::AudioTrack *>(track); if (!strcmp("A_AAC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); CHECK(codecPrivateSize >= 2); addESDSFromCodecPrivate( meta, true, codecPrivate, codecPrivateSize); } else if (!strcmp("A_VORBIS", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); err = addVorbisCodecInfo( meta, codecPrivate, codecPrivateSize); } else if (!strcmp("A_OPUS", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); mSeekPreRollNs = track->GetSeekPreRoll(); } else if (!strcmp("A_MPEG/L3", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); } else { ALOGW("%s is not supported.", codecID); continue; } meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); meta->setInt32(kKeyChannelCount, atrack->GetChannels()); break; } default: continue; } if (err != OK) { ALOGE("skipping track, codec specific data was malformed."); continue; } long long durationNs = mSegment->GetDuration(); meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); mTracks.push(); size_t n = mTracks.size() - 1; TrackInfo *trackInfo = &mTracks.editItemAt(n); trackInfo->mTrackNum = track->GetNumber(); trackInfo->mMeta = meta; trackInfo->mExtractor = this; trackInfo->mEncrypted = false; for(size_t i = 0; i < track->GetContentEncodingCount() && !trackInfo->mEncrypted; i++) { const mkvparser::ContentEncoding *encoding = track->GetContentEncodingByIndex(i); for(size_t j = 0; j < encoding->GetEncryptionCount(); j++) { const mkvparser::ContentEncoding::ContentEncryption *encryption; encryption = encoding->GetEncryptionByIndex(j); meta->setData(kKeyCryptoKey, 0, encryption->key_id, encryption->key_id_len); trackInfo->mEncrypted = true; break; } } if (!strcmp("V_MPEG4/ISO/AVC", codecID) && codecPrivateSize == 0) { // Attempt to recover from AVC track without codec private data err = synthesizeAVCC(trackInfo, n); if (err != OK) { mTracks.pop(); } } } }
void MatroskaExtractor::addTracks() { const mkvparser::Tracks *tracks = mSegment->GetTracks(); for (size_t index = 0; index < tracks->GetTracksCount(); ++index) { const mkvparser::Track *track = tracks->GetTrackByIndex(index); if (track == NULL) { // Apparently this is currently valid (if unexpected) behaviour // of the mkv parser lib. continue; } const char *const codecID = track->GetCodecId(); ALOGV("codec id = %s", codecID); ALOGV("codec name = %s", track->GetCodecNameAsUTF8()); if (codecID == NULL) { ALOGW("unknown codecID is not supported."); continue; } size_t codecPrivateSize; const unsigned char *codecPrivate = track->GetCodecPrivate(codecPrivateSize); enum { VIDEO_TRACK = 1, AUDIO_TRACK = 2 }; sp<MetaData> meta = new MetaData; status_t err = OK; switch (track->GetType()) { case VIDEO_TRACK: { const mkvparser::VideoTrack *vtrack = static_cast<const mkvparser::VideoTrack *>(track); if (!strcmp("V_MPEG4/ISO/AVC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); meta->setData(kKeyAVCC, 0, codecPrivate, codecPrivateSize); } else if (!strcmp("V_MPEG4/ISO/ASP", codecID)) { if (codecPrivateSize > 0) { meta->setCString( kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); addESDSFromCodecPrivate( meta, false, codecPrivate, codecPrivateSize); } else { ALOGW("%s is detected, but does not have configuration.", codecID); continue; } } else if (!strcmp("V_VP8", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP8); } else if (!strcmp("V_VP9", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_VP9); } else { ALOGW("%s is not supported.", codecID); continue; } meta->setInt32(kKeyWidth, vtrack->GetWidth()); meta->setInt32(kKeyHeight, vtrack->GetHeight()); break; } case AUDIO_TRACK: { const mkvparser::AudioTrack *atrack = static_cast<const mkvparser::AudioTrack *>(track); if (!strcmp("A_AAC", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC); CHECK(codecPrivateSize >= 2); addESDSFromCodecPrivate( meta, true, codecPrivate, codecPrivateSize); } else if (!strcmp("A_VORBIS", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); err = addVorbisCodecInfo( meta, codecPrivate, codecPrivateSize); } else if (!strcmp("A_OPUS", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_OPUS); meta->setData(kKeyOpusHeader, 0, codecPrivate, codecPrivateSize); meta->setInt64(kKeyOpusCodecDelay, track->GetCodecDelay()); meta->setInt64(kKeyOpusSeekPreRoll, track->GetSeekPreRoll()); mSeekPreRollNs = track->GetSeekPreRoll(); } else if (!strcmp("A_MPEG/L3", codecID)) { meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG); } else { ALOGW("%s is not supported.", codecID); continue; } meta->setInt32(kKeySampleRate, atrack->GetSamplingRate()); meta->setInt32(kKeyChannelCount, atrack->GetChannels()); break; } default: continue; } if (err != OK) { ALOGE("skipping track, codec specific data was malformed."); continue; } long long durationNs = mSegment->GetDuration(); meta->setInt64(kKeyDuration, (durationNs + 500) / 1000); mTracks.push(); TrackInfo *trackInfo = &mTracks.editItemAt(mTracks.size() - 1); trackInfo->mTrackNum = track->GetNumber(); trackInfo->mMeta = meta; trackInfo->mExtractor = this; } }