summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/StagefrightMediaScanner.cpp
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-01-11 15:35:19 -0800
committerAndreas Huber <andih@google.com>2010-01-12 09:14:15 -0800
commitfc9ba09e3bb368f823d473f5e2bb9aa32dba6289 (patch)
treee7a6e0357e39c58d050b23a94b61f734e5578af7 /media/libstagefright/StagefrightMediaScanner.cpp
parent58e1f78683d9230932c4d5bee53b79fc685b5995 (diff)
downloadframeworks_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.cpp163
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;