diff options
author | Andreas Huber <andih@google.com> | 2010-01-11 15:35:19 -0800 |
---|---|---|
committer | Andreas Huber <andih@google.com> | 2010-01-12 09:14:15 -0800 |
commit | fc9ba09e3bb368f823d473f5e2bb9aa32dba6289 (patch) | |
tree | e7a6e0357e39c58d050b23a94b61f734e5578af7 /media/libstagefright/StagefrightMediaScanner.cpp | |
parent | 58e1f78683d9230932c4d5bee53b79fc685b5995 (diff) | |
download | frameworks_av-fc9ba09e3bb368f823d473f5e2bb9aa32dba6289.zip frameworks_av-fc9ba09e3bb368f823d473f5e2bb9aa32dba6289.tar.gz frameworks_av-fc9ba09e3bb368f823d473f5e2bb9aa32dba6289.tar.bz2 |
Squashed commit of the following:
commit f81bb1dac5ef107bb0d7d5d756fb1ffa532ba2cc
Author: Andreas Huber <andih@google.com>
Date: Mon Jan 11 14:55:56 2010 -0800
Support for duration metadata, midi and ogg-vorbis files (in mediascanner)
commit 0b1385a0dc156ce27985a1ff757c4c142fd7ec39
Author: Andreas Huber <andih@google.com>
Date: Mon Jan 11 14:20:45 2010 -0800
Refactor meta data logic. Container specific metadata is now also returned by the MediaExtractor.
commit f9818dfac39c96e5fefe8c8295e60580692d5990
Author: Andreas Huber <andih@google.com>
Date: Fri Jan 8 14:26:09 2010 -0800
A first pass at supporting metadata through ID3 tags.
commit 476e9e253633336ab790f943e2d6c0cd8991d76a
Author: Andreas Huber <andih@google.com>
Date: Thu Jan 7 15:48:44 2010 -0800
Initial checkin of ID3 (V2.2 and V2.3) parser for use in stagefright.
related-to-bug: 2295456
Diffstat (limited to 'media/libstagefright/StagefrightMediaScanner.cpp')
-rw-r--r-- | media/libstagefright/StagefrightMediaScanner.cpp | 163 |
1 files changed, 161 insertions, 2 deletions
diff --git a/media/libstagefright/StagefrightMediaScanner.cpp b/media/libstagefright/StagefrightMediaScanner.cpp index 9b41929..4815db2 100644 --- a/media/libstagefright/StagefrightMediaScanner.cpp +++ b/media/libstagefright/StagefrightMediaScanner.cpp @@ -14,10 +14,21 @@ * limitations under the License. */ +//#define LOG_NDEBUG 0 +#define LOG_TAG "StagefrightMediaScanner" +#include <utils/Log.h> + #include <media/stagefright/StagefrightMediaScanner.h> #include "include/StagefrightMetadataRetriever.h" +// Sonivox includes +#include <libsonivox/eas.h> + +// Ogg Vorbis includes +#include "ivorbiscodec.h" +#include "ivorbisfile.h" + namespace android { StagefrightMediaScanner::StagefrightMediaScanner() @@ -26,12 +37,145 @@ StagefrightMediaScanner::StagefrightMediaScanner() StagefrightMediaScanner::~StagefrightMediaScanner() {} +static bool FileHasAcceptableExtension(const char *extension) { + static const char *kValidExtensions[] = { + ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2", + ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac", + ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota" + }; + static const size_t kNumValidExtensions = + sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); + + for (size_t i = 0; i < kNumValidExtensions; ++i) { + if (!strcasecmp(extension, kValidExtensions[i])) { + return true; + } + } + + return false; +} + +static status_t HandleMIDI( + const char *filename, MediaScannerClient *client) { + // get the library configuration and do sanity check + const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config(); + if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) { + LOGE("EAS library/header mismatch\n"); + return UNKNOWN_ERROR; + } + EAS_I32 temp; + + // spin up a new EAS engine + EAS_DATA_HANDLE easData = NULL; + EAS_HANDLE easHandle = NULL; + EAS_RESULT result = EAS_Init(&easData); + if (result == EAS_SUCCESS) { + EAS_FILE file; + file.path = filename; + file.fd = 0; + file.offset = 0; + file.length = 0; + result = EAS_OpenFile(easData, &file, &easHandle); + } + if (result == EAS_SUCCESS) { + result = EAS_Prepare(easData, easHandle); + } + if (result == EAS_SUCCESS) { + result = EAS_ParseMetaData(easData, easHandle, &temp); + } + if (easHandle) { + EAS_CloseFile(easData, easHandle); + } + if (easData) { + EAS_Shutdown(easData); + } + + if (result != EAS_SUCCESS) { + return UNKNOWN_ERROR; + } + + char buffer[20]; + sprintf(buffer, "%ld", temp); + if (!client->addStringTag("duration", buffer)) return UNKNOWN_ERROR; + + return OK; +} + +static status_t HandleOGG( + const char *filename, MediaScannerClient *client) { + int duration; + + FILE *file = fopen(filename,"r"); + if (!file) + return UNKNOWN_ERROR; + + OggVorbis_File vf; + if (ov_open(file, &vf, NULL, 0) < 0) { + return UNKNOWN_ERROR; + } + + char **ptr=ov_comment(&vf,-1)->user_comments; + while(*ptr){ + char *val = strstr(*ptr, "="); + if (val) { + int keylen = val++ - *ptr; + char key[keylen + 1]; + strncpy(key, *ptr, keylen); + key[keylen] = 0; + if (!client->addStringTag(key, val)) goto failure; + } + ++ptr; + } + + // Duration + duration = ov_time_total(&vf, -1); + if (duration > 0) { + char buffer[20]; + sprintf(buffer, "%d", duration); + if (!client->addStringTag("duration", buffer)) goto failure; + } + + ov_clear(&vf); // this also closes the FILE + return OK; + +failure: + ov_clear(&vf); // this also closes the FILE + return UNKNOWN_ERROR; +} + status_t StagefrightMediaScanner::processFile( const char *path, const char *mimeType, MediaScannerClient &client) { client.setLocale(locale()); client.beginFile(); + const char *extension = strrchr(path, '.'); + + if (!extension) { + return UNKNOWN_ERROR; + } + + if (!FileHasAcceptableExtension(extension)) { + client.endFile(); + + return UNKNOWN_ERROR; + } + + if (!strcasecmp(extension, ".mid") + || !strcasecmp(extension, ".smf") + || !strcasecmp(extension, ".imy") + || !strcasecmp(extension, ".midi") + || !strcasecmp(extension, ".xmf") + || !strcasecmp(extension, ".rtttl") + || !strcasecmp(extension, ".rtx") + || !strcasecmp(extension, ".ota")) { + return HandleMIDI(path, &client); + } + + if (!strcasecmp(extension, ".ogg")) { + return HandleOGG(path, &client); + } + if (mRetriever->setDataSource(path) == OK && mRetriever->setMode( METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) { @@ -66,12 +210,27 @@ status_t StagefrightMediaScanner::processFile( } char *StagefrightMediaScanner::extractAlbumArt(int fd) { - if (mRetriever->setDataSource(fd, 0, 0) == OK + off_t size = lseek(fd, 0, SEEK_END); + if (size < 0) { + return NULL; + } + lseek(fd, 0, SEEK_SET); + + if (mRetriever->setDataSource(fd, 0, size) == OK && mRetriever->setMode( METADATA_MODE_FRAME_CAPTURE_ONLY) == OK) { MediaAlbumArt *art = mRetriever->extractAlbumArt(); - // TODO: figure out what format the result should be in. + if (art != NULL) { + char *data = (char *)malloc(art->mSize + 4); + *(int32_t *)data = art->mSize; + memcpy(&data[4], art->mData, art->mSize); + + delete art; + art = NULL; + + return data; + } } return NULL; |