* -------------------------------------------------------------------
*/
+
#include <media/mediascanner.h>
+#include <private/media/VideoFrame.h>
#include <stdio.h>
#include "media/mediametadataretriever.h"
#include <media/thread_init.h>
-#include <utils/string_array.h>
+#include <utils/StringArray.h>
#define MAX_BUFF_SIZE 1024
free(mLocale);
}
-static PVMFStatus parseMP3(const char *filename, MediaScannerClient& client)
+static PVMFStatus parseID3Tag(const char *filename, MediaScannerClient& client)
{
+ // This method parses the ID3 tags in a source file.
PVID3ParCom pvId3Param;
PVFile fileHandle;
Oscl_FileServer iFs;
bool isIso88591 = false;
// type should follow first semicolon
- const char* type = strchr(key, ';') + 1;
- if (type == 0) continue;
-
+ const char* type = strchr(key, ';');
+ if (type == NULL) continue;
+ type++;
+
+ char tracknumkeybuf[MAX_BUFF_SIZE];
+ if (oscl_strncmp(key, "track-info/track-number;", 24) == 0) {
+ // Java expects the track number key to be called "tracknumber", so
+ // construct a temporary one here.
+ snprintf(tracknumkeybuf, sizeof(tracknumkeybuf),"tracknumber;%s", type);
+ key = tracknumkeybuf;
+ }
const char* value = framevector[i]->value.pChar_value;
MP3ErrorType err;
IMpeg3File mp3File(mp3filename, err);
if (err != MP3_SUCCESS) {
- LOGE("IMpeg3File constructor returned %d for %s\n", err, filename);
+ LOGE("IMpeg3File constructor returned %d.\n", err);
return err;
}
err = mp3File.ParseMp3File();
if (err != MP3_SUCCESS) {
- LOGE("IMpeg3File::ParseMp3File returned %d for %s\n", err, filename);
+ LOGE("IMpeg3File::ParseMp3File returned %d.\n", err);
return err;
}
trackNum = mp4Input->getITunesThisTrackNo();
totalTracks = mp4Input->getITunesTotalTracks();
sprintf(buffer, "%d/%d", trackNum, totalTracks);
- if (!client.addStringTag("tracknumber", buffer)) goto failure;
+ if (!client.addStringTag("track-info/track-number", buffer)) goto failure;
// Duration
duration = mp4Input->getMovieDuration();
uint32 trackType = mp4Input->getTrackMediaType(tracks[i]);
OSCL_HeapString<OsclMemAllocator> streamtype;
mp4Input->getTrackMIMEType(tracks[i], streamtype);
- char streamtypeutf8[128];
- strncpy (streamtypeutf8, streamtype.get_str(), streamtype.get_size());
- if (streamtypeutf8[0])
- {
- if (strcmp(streamtypeutf8,"FORMATUNKNOWN") != 0) {
- if (trackType == MEDIA_TYPE_AUDIO) {
- hasAudio = true;
- } else if (trackType == MEDIA_TYPE_VISUAL) {
- hasVideo = true;
- }
- } else {
- //LOGI("@@@@@@@@ %100s: %s\n", filename, streamtypeutf8);
+
+ if (!(streamtype == "FORMATUNKNOWN")) {
+ if (trackType == MEDIA_TYPE_AUDIO) {
+ hasAudio = true;
+ } else if (trackType == MEDIA_TYPE_VISUAL) {
+ hasVideo = true;
}
+ } else {
+ //LOGI("@@@@@@@@ %100s: %s\n", filename, streamtypeutf8);
}
}
return PVMFSuccess;
}
-static PVMFStatus parseWMA(const char *filename, MediaScannerClient& client)
+static PVMFStatus parseASF(const char *filename, MediaScannerClient& client)
{
sp<MediaMetadataRetriever> retriever = new MediaMetadataRetriever();
+ if(retriever == NULL) {
+ return PVMFErrNoMemory;
+ }
retriever->setMode( 1 /*MediaMetadataRetriever.MODE_GET_METADATA_ONLY*/);
status_t status = retriever->setDataSource(filename);
if (status != NO_ERROR) {
- LOGE("parseWMA setDataSource failed (%d)", status);
+ LOGE("parseASF setDataSource failed (%d)", status);
retriever->disconnect();
return PVMFFailure;
}
// setting this invalid mimetype will make the java side ignore this file
client.setMimeType("audio/x-wma-drm");
}
+
value = retriever->extractMetadata(METADATA_KEY_CODEC);
if (value && strcmp(value, "Windows Media Audio 10 Professional") == 0) {
// we don't support WM 10 Professional currently
client.addStringTag("year", value);
value = retriever->extractMetadata(METADATA_KEY_CD_TRACK_NUMBER);
if (value)
- client.addStringTag("tracknumber", value);
-
+ client.addStringTag("track-info/track-number", value);
+ value = retriever->extractMetadata(METADATA_KEY_DURATION);
+ if (value) {
+ client.addStringTag("duration",value);
+ LOGE("Duration Value %s for \n",value);
+ }
retriever->disconnect();
return PVMFSuccess;
}
status_t MediaScanner::processFile(const char *path, const char* mimeType, MediaScannerClient& client)
{
- status_t result;
+ status_t result = PVMFSuccess;
+ int error = 0;
InitializeForThread();
- client.setLocale(mLocale);
- client.beginFile();
-
- //LOGD("processFile %s mimeType: %s\n", path, mimeType);
- const char* extension = strrchr(path, '.');
-
- if (extension && strcasecmp(extension, ".mp3") == 0) {
- result = parseMP3(path, client);
- } else if (extension &&
- (strcasecmp(extension, ".mp4") == 0 || strcasecmp(extension, ".m4a") == 0 ||
- strcasecmp(extension, ".3gp") == 0 || strcasecmp(extension, ".3gpp") == 0 ||
- strcasecmp(extension, ".3g2") == 0 || strcasecmp(extension, ".3gpp2") == 0)) {
- result = parseMP4(path, client);
- } else if (extension && strcasecmp(extension, ".ogg") == 0) {
- result = parseOgg(path, client);
- } else if (extension &&
- ( strcasecmp(extension, ".mid") == 0 || strcasecmp(extension, ".smf") == 0
- || strcasecmp(extension, ".imy") == 0)) {
- result = parseMidi(path, client);
- } else if (extension && strcasecmp(extension, ".wma") == 0) {
- result = parseWMA(path, client);
- } else {
- result = PVMFFailure;
- }
-
- client.endFile();
+ OSCL_TRY(error,
+ client.setLocale(mLocale);
+ client.beginFile();
+
+ //LOGD("processFile %s mimeType: %s\n", path, mimeType);
+ const char* extension = strrchr(path, '.');
+
+ if (extension &&
+ (strcasecmp(extension, ".mp3") == 0 || strcasecmp(extension, ".aac") == 0)) {
+ // Both mp3 and aac files use ID3 tags to hold metadata
+ result = parseID3Tag(path, client);
+ } else if (extension &&
+ (strcasecmp(extension, ".mp4") == 0 || strcasecmp(extension, ".m4a") == 0 ||
+ strcasecmp(extension, ".3gp") == 0 || strcasecmp(extension, ".3gpp") == 0 ||
+ strcasecmp(extension, ".3g2") == 0 || strcasecmp(extension, ".m4b") == 0 ||
+ strcasecmp(extension, ".3gpp2") == 0)) {
+ result = parseMP4(path, client);
+ } else if (extension && strcasecmp(extension, ".ogg") == 0) {
+ result = parseOgg(path, client);
+ } else if (extension &&
+ (strcasecmp(extension, ".mid") == 0 || strcasecmp(extension, ".smf") == 0 ||
+ strcasecmp(extension, ".imy") == 0)) {
+ result = parseMidi(path, client);
+ } else if (extension &&
+ (strcasecmp(extension, ".wma") == 0 || strcasecmp(extension, ".wmv") == 0 ||
+ strcasecmp(extension, ".asf") == 0 || strcasecmp(extension, ".amr") == 0 ||
+ strcasecmp(extension, ".wav") == 0 || strcasecmp(extension, ".awb") == 0)) {
+ result = parseASF(path, client);
+ } else {
+ result = PVMFFailure;
+ }
+ client.endFile();
+ );
+ OSCL_FIRST_CATCH_ANY( error,LOGV("OSCL_LEAVE happened in processFile Exit with failure");return PVMFFailure);
return result;
}
strcpy(fileSpot, ".nomedia");
if (access(path, F_OK) == 0) {
LOGD("found .nomedia, skipping directory\n");
+ // restore path
+ fileSpot[0] = 0;
+ // notify client
+ client.addNoMediaFolder(path);
return OK;
}
strcat(fileSpot, "/");
int err = doProcessDirectory(path, pathRemaining - nameLength - 1, extensions, client, exceptionCheck, exceptionEnv);
if (err) {
- // pass exceptions up - ignore other errors
- if (exceptionCheck && exceptionCheck(exceptionEnv)) goto failure;
LOGE("Error processing '%s' - skipping\n", path);
continue;
}
MediaScannerClient& client, ExceptionCheck exceptionCheck, void* exceptionEnv)
{
InitializeForThread();
+ int error = 0;
+ status_t result = PVMFSuccess;
- int pathLength = strlen(path);
- if (pathLength >= PATH_MAX) {
- return PVMFFailure;
- }
- char* pathBuffer = (char *)malloc(PATH_MAX + 1);
- if (!pathBuffer) {
- return PVMFFailure;
- }
+ OSCL_TRY(error,
+ int pathLength = strlen(path);
+ if (pathLength >= PATH_MAX) {
+ return PVMFFailure;
+ }
+ char* pathBuffer = (char *)malloc(PATH_MAX + 1);
+ if (!pathBuffer) {
+ return PVMFFailure;
+ }
- int pathRemaining = PATH_MAX - pathLength;
- strcpy(pathBuffer, path);
- if (pathBuffer[pathLength - 1] != '/') {
- pathBuffer[pathLength] = '/';
- pathBuffer[pathLength + 1] = 0;
- --pathRemaining;
- }
+ int pathRemaining = PATH_MAX - pathLength;
+ strcpy(pathBuffer, path);
+ if (pathBuffer[pathLength - 1] != '/') {
+ pathBuffer[pathLength] = '/';
+ pathBuffer[pathLength + 1] = 0;
+ --pathRemaining;
+ }
+
+ client.setLocale(mLocale);
+ result = doProcessDirectory(pathBuffer, pathRemaining, extensions, client, exceptionCheck, exceptionEnv);
- client.setLocale(mLocale);
- status_t result = doProcessDirectory(pathBuffer, pathRemaining, extensions, client, exceptionCheck, exceptionEnv);
+ free(pathBuffer);
+ );
- free(pathBuffer);
+ OSCL_FIRST_CATCH_ANY(error,LOGV("OSCL_LEAVE happened in processDirectory Exit with failure"); return PVMFFailure);
return result;
}
FILE *f = fdopen(fd, "r");
filehandle = new OsclFileHandle(f);
+ if(filehandle == NULL) {
+ return NULL;
+ }
file.SetFileHandle(filehandle);
if( 0 != file.Open(NULL, Oscl_File::MODE_READ | Oscl_File::MODE_BINARY, iFs) )
return result;
}
+static char* extractASFAlbumArt(int fd)
+{
+ struct stat asfbuf;
+ char *data = NULL;
+ sp<MediaMetadataRetriever> retriever = new MediaMetadataRetriever();
+ if ((retriever == NULL) && (0 != (fstat(fd,&asfbuf)))) {
+ return data;
+ }
+ retriever->setMode( 1 /*MediaMetadataRetriever.MODE_GET_METADATA_ONLY*/);
+ status_t status = retriever->setDataSource(fd,0,asfbuf.st_size);
+ if (status == NO_ERROR) {
+ sp<IMemory> bitmap = retriever->extractAlbumArt();
+ if (bitmap != NULL) {
+ MediaAlbumArt *albumArtCopy = static_cast<MediaAlbumArt *>(bitmap->pointer());
+ data = (char*)malloc(albumArtCopy->mSize + 4);
+ if (data && albumArtCopy->mData) {
+ long *len = (long*)data;
+ *len = albumArtCopy->mSize;
+ albumArtCopy->mData = (uint8_t *)albumArtCopy + sizeof(MediaAlbumArt);
+ memcpy(data + 4, (const char*)albumArtCopy->mData, *len);
+ }
+ }
+ }
+ retriever->disconnect();
+ return data;
+}
char* MediaScanner::extractAlbumArt(int fd)
{
InitializeForThread();
-
+
+ char * albumArtData = NULL;
+ int error = 0;
int32 ident;
lseek(fd, 4, SEEK_SET);
read(fd, &ident, sizeof(ident));
+
+ OSCL_TRY(error,
+ if (ident == 0x70797466) {
+ // some kind of mpeg 4 stream
+ lseek(fd, 0, SEEK_SET);
+ albumArtData = extractM4AAlbumArt(fd);
+ }else if (ident == 0x11CF668E) {
+ lseek(fd, 0, SEEK_SET);
+ albumArtData = extractASFAlbumArt(fd);
+ }else {
+ // might be mp3
+ albumArtData = extractMP3AlbumArt(fd);
+ }
+ );
- if (ident == 0x70797466) {
- // some kind of mpeg 4 stream
- lseek(fd, 0, SEEK_SET);
- return extractM4AAlbumArt(fd);
- } else {
- // might be mp3
- return extractMP3AlbumArt(fd);
- }
+ OSCL_FIRST_CATCH_ANY(error,LOGV("OSCL_LEAVE happened in extractAlbumArt retrun null");return NULL);
+ return albumArtData;
+
}
MediaScannerClient::MediaScannerClient()