StagefrightMediaScanner.cpp revision fc9ba09e3bb368f823d473f5e2bb9aa32dba6289
167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber/* 267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * Copyright (C) 2009 The Android Open Source Project 367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * 467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * you may not use this file except in compliance with the License. 667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * You may obtain a copy of the License at 767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * 867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * 1067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * Unless required by applicable law or agreed to in writing, software 1167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * See the License for the specific language governing permissions and 1467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber * limitations under the License. 1567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber */ 1667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 17fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber//#define LOG_NDEBUG 0 18fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#define LOG_TAG "StagefrightMediaScanner" 19fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <utils/Log.h> 20fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 2167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include <media/stagefright/StagefrightMediaScanner.h> 2267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 2367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include "include/StagefrightMetadataRetriever.h" 2467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 25fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Sonivox includes 26fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <libsonivox/eas.h> 27fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 28fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Ogg Vorbis includes 29fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include "ivorbiscodec.h" 30fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include "ivorbisfile.h" 31fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 3267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Hubernamespace android { 3367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 3467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas HuberStagefrightMediaScanner::StagefrightMediaScanner() 3567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber : mRetriever(new StagefrightMetadataRetriever) { 3667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber} 3767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 3867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas HuberStagefrightMediaScanner::~StagefrightMediaScanner() {} 3967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 40fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic bool FileHasAcceptableExtension(const char *extension) { 41fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const char *kValidExtensions[] = { 42fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2", 43fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac", 44fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota" 45fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber }; 46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber static const size_t kNumValidExtensions = 47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sizeof(kValidExtensions) / sizeof(kValidExtensions[0]); 48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber for (size_t i = 0; i < kNumValidExtensions; ++i) { 50fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcasecmp(extension, kValidExtensions[i])) { 51fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return true; 52fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 53fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return false; 56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic status_t HandleMIDI( 59fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const char *filename, MediaScannerClient *client) { 60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // get the library configuration and do sanity check 61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config(); 62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) { 63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber LOGE("EAS library/header mismatch\n"); 64fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 65fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_I32 temp; 67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // spin up a new EAS engine 69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_DATA_HANDLE easData = NULL; 70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_HANDLE easHandle = NULL; 71fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_RESULT result = EAS_Init(&easData); 72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (result == EAS_SUCCESS) { 73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_FILE file; 74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber file.path = filename; 75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber file.fd = 0; 76fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber file.offset = 0; 77fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber file.length = 0; 78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber result = EAS_OpenFile(easData, &file, &easHandle); 79fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 80fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (result == EAS_SUCCESS) { 81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber result = EAS_Prepare(easData, easHandle); 82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (result == EAS_SUCCESS) { 84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber result = EAS_ParseMetaData(easData, easHandle, &temp); 85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (easHandle) { 87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_CloseFile(easData, easHandle); 88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (easData) { 90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber EAS_Shutdown(easData); 91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (result != EAS_SUCCESS) { 94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 95fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char buffer[20]; 98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sprintf(buffer, "%ld", temp); 99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!client->addStringTag("duration", buffer)) return UNKNOWN_ERROR; 100fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 101fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return OK; 102fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 103fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 104fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic status_t HandleOGG( 105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const char *filename, MediaScannerClient *client) { 106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int duration; 107fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 108fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber FILE *file = fopen(filename,"r"); 109fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!file) 110fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 111fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 112fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber OggVorbis_File vf; 113fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (ov_open(file, &vf, NULL, 0) < 0) { 114fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 115fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 116fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 117fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char **ptr=ov_comment(&vf,-1)->user_comments; 118fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber while(*ptr){ 119fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char *val = strstr(*ptr, "="); 120fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (val) { 121fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber int keylen = val++ - *ptr; 122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char key[keylen + 1]; 123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber strncpy(key, *ptr, keylen); 124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber key[keylen] = 0; 125fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!client->addStringTag(key, val)) goto failure; 126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ++ptr; 128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 129fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber // Duration 131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber duration = ov_time_total(&vf, -1); 132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (duration > 0) { 133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char buffer[20]; 134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber sprintf(buffer, "%d", duration); 135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!client->addStringTag("duration", buffer)) goto failure; 136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ov_clear(&vf); // this also closes the FILE 139fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return OK; 140fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 141fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberfailure: 142fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber ov_clear(&vf); // this also closes the FILE 143fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 144fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber} 145fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 14667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huberstatus_t StagefrightMediaScanner::processFile( 14767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber const char *path, const char *mimeType, 14867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber MediaScannerClient &client) { 14967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber client.setLocale(locale()); 15067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber client.beginFile(); 15167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 152fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber const char *extension = strrchr(path, '.'); 153fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 154fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!extension) { 155fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 156fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 157fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 158fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!FileHasAcceptableExtension(extension)) { 159fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber client.endFile(); 160fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 161fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return UNKNOWN_ERROR; 162fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 163fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 164fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcasecmp(extension, ".mid") 165fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".smf") 166fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".imy") 167fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".midi") 168fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".xmf") 169fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".rtttl") 170fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".rtx") 171fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber || !strcasecmp(extension, ".ota")) { 172fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return HandleMIDI(path, &client); 173fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 174fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 175fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (!strcasecmp(extension, ".ogg")) { 176fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return HandleOGG(path, &client); 177fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 178fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 17967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber if (mRetriever->setDataSource(path) == OK 18067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber && mRetriever->setMode( 18167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber METADATA_MODE_METADATA_RETRIEVAL_ONLY) == OK) { 18267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber struct KeyMap { 18367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber const char *tag; 18467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber int key; 18567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber }; 18667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber static const KeyMap kKeyMap[] = { 18767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER }, 18867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "album", METADATA_KEY_ALBUM }, 18967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "artist", METADATA_KEY_ARTIST }, 19067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "composer", METADATA_KEY_COMPOSER }, 19167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "genre", METADATA_KEY_GENRE }, 19267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "title", METADATA_KEY_TITLE }, 19367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "year", METADATA_KEY_YEAR }, 19467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "duration", METADATA_KEY_DURATION }, 19567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber { "writer", METADATA_KEY_WRITER }, 19667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber }; 19767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]); 19867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 19967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber for (size_t i = 0; i < kNumEntries; ++i) { 20067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber const char *value; 20167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) { 20267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber client.addStringTag(kKeyMap[i].tag, value); 20367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber } 20467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber } 20567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber } 20667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 20767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber client.endFile(); 20867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 20967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber return OK; 21067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber} 21167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 21267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huberchar *StagefrightMediaScanner::extractAlbumArt(int fd) { 213fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber off_t size = lseek(fd, 0, SEEK_END); 214fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (size < 0) { 215fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return NULL; 216fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 217fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber lseek(fd, 0, SEEK_SET); 218fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 219fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (mRetriever->setDataSource(fd, 0, size) == OK 22067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber && mRetriever->setMode( 22167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber METADATA_MODE_FRAME_CAPTURE_ONLY) == OK) { 22267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber MediaAlbumArt *art = mRetriever->extractAlbumArt(); 22367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber if (art != NULL) { 225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber char *data = (char *)malloc(art->mSize + 4); 226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber *(int32_t *)data = art->mSize; 227fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber memcpy(&data[4], art->mData, art->mSize); 228fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 229fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber delete art; 230fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber art = NULL; 231fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber 232fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber return data; 233fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber } 23467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber } 23567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 23667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber return NULL; 23767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber} 23867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber 23967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber} // namespace android 240