void MyVorbisExtractor::parseFileMetaData() { mFileMeta = new MetaData; mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); struct { const char *const mTag; uint32_t mKey; } kMap[] = { { "TITLE", kKeyTitle }, { "ARTIST", kKeyArtist }, { "ALBUM", kKeyAlbum }, { "ALBUMARTIST", kKeyAlbumArtist }, { "ALBUM ARIST", kKeyAlbumArtist }, { "COMPOSER", kKeyComposer }, { "GENRE", kKeyGenre }, { "AUTHOR", kKeyAuthor }, { "TRACKNUMBER", kKeyCDTrackNumber }, { "DISCNUMBER", kKeyDiscNumber }, { "DATE", kKeyDate }, { "LYRICIST", kKeyWriter }, { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, { "ANDROID_LOOP", kKeyAutoLoop }, }; for (int i = 0; i < mVc.comments; ++i) { const char *comment = mVc.user_comments[i]; for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { size_t tagLen = strlen(kMap[j].mTag); if (!strncasecmp(kMap[j].mTag, comment, tagLen) && comment[tagLen] == '=') { if (kMap[j].mKey == kKeyAlbumArt) { extractAlbumArt( &comment[tagLen + 1], mVc.comment_lengths[i] - tagLen - 1); } else if (kMap[j].mKey == kKeyAutoLoop) { if (!strcasecmp(&comment[tagLen + 1], "true")) { mFileMeta->setInt32(kKeyAutoLoop, true); } } else { mFileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); } } } } #if 0 for (int i = 0; i < mVc.comments; ++i) { LOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); } #endif }
void parseVorbisComment( const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) { struct { const char *const mTag; uint32_t mKey; } kMap[] = { { "TITLE", kKeyTitle }, { "ARTIST", kKeyArtist }, { "ALBUMARTIST", kKeyAlbumArtist }, { "ALBUM ARTIST", kKeyAlbumArtist }, { "COMPILATION", kKeyCompilation }, { "ALBUM", kKeyAlbum }, { "COMPOSER", kKeyComposer }, { "GENRE", kKeyGenre }, { "AUTHOR", kKeyAuthor }, { "TRACKNUMBER", kKeyCDTrackNumber }, { "DISCNUMBER", kKeyDiscNumber }, { "DATE", kKeyDate }, { "LYRICIST", kKeyWriter }, { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, { "ANDROID_LOOP", kKeyAutoLoop }, }; for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { size_t tagLen = strlen(kMap[j].mTag); if (!strncasecmp(kMap[j].mTag, comment, tagLen) && comment[tagLen] == '=') { if (kMap[j].mKey == kKeyAlbumArt) { extractAlbumArt( fileMeta, &comment[tagLen + 1], commentLength - tagLen - 1); } else if (kMap[j].mKey == kKeyAutoLoop) { if (!strcasecmp(&comment[tagLen + 1], "true")) { fileMeta->setInt32(kKeyAutoLoop, true); } } else { fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); } } } }
status_t BnMediaMetadataRetriever::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch (code) { case DISCONNECT: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); disconnect(); return NO_ERROR; } break; case SET_DATA_SOURCE_URL: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); sp<IMediaHTTPService> httpService; if (data.readInt32()) { httpService = interface_cast<IMediaHTTPService>(data.readStrongBinder()); } const char* srcUrl = data.readCString(); KeyedVector<String8, String8> headers; size_t numHeaders = (size_t) data.readInt64(); for (size_t i = 0; i < numHeaders; ++i) { String8 key = data.readString8(); String8 value = data.readString8(); headers.add(key, value); } reply->writeInt32( setDataSource( httpService, srcUrl, numHeaders > 0 ? &headers : NULL)); return NO_ERROR; } break; case SET_DATA_SOURCE_FD: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int fd = data.readFileDescriptor(); int64_t offset = data.readInt64(); int64_t length = data.readInt64(); reply->writeInt32(setDataSource(fd, offset, length)); return NO_ERROR; } break; case SET_DATA_SOURCE_CALLBACK: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); sp<IDataSource> source = interface_cast<IDataSource>(data.readStrongBinder()); reply->writeInt32(setDataSource(source)); return NO_ERROR; } break; case GET_FRAME_AT_TIME: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int64_t timeUs = data.readInt64(); int option = data.readInt32(); ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif sp<IMemory> bitmap = getFrameAtTime(timeUs, option); if (bitmap != 0) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeStrongBinder(IInterface::asBinder(bitmap)); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; case EXTRACT_ALBUM_ART: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif sp<IMemory> albumArt = extractAlbumArt(); if (albumArt != 0) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeStrongBinder(IInterface::asBinder(albumArt)); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; case EXTRACT_METADATA: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); #ifndef DISABLE_GROUP_SCHEDULE_HACK setSchedPolicy(data); #endif int keyCode = data.readInt32(); const char* value = extractMetadata(keyCode); if (value != NULL) { // Don't send NULL across the binder interface reply->writeInt32(NO_ERROR); reply->writeCString(value); } else { reply->writeInt32(UNKNOWN_ERROR); } #ifndef DISABLE_GROUP_SCHEDULE_HACK restoreSchedPolicy(); #endif return NO_ERROR; } break; default: return BBinder::onTransact(code, data, reply, flags); } }