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
21a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen#include <sys/types.h>
22a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen#include <sys/stat.h>
23a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen#include <fcntl.h>
24a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen
2567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber#include <media/stagefright/StagefrightMediaScanner.h>
2667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
272e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber#include <media/mediametadataretriever.h>
282e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber#include <private/media/VideoFrame.h>
2967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
30fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber// Sonivox includes
31fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber#include <libsonivox/eas.h>
32fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
3367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Hubernamespace android {
3467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
350a095d09464ba18e288a3f529410af0f1257ac2aMike LockwoodStagefrightMediaScanner::StagefrightMediaScanner() {}
3667e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
3767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas HuberStagefrightMediaScanner::~StagefrightMediaScanner() {}
3867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
39fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huberstatic bool FileHasAcceptableExtension(const char *extension) {
40fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const char *kValidExtensions[] = {
41fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        ".mp3", ".mp4", ".m4a", ".3gp", ".3gpp", ".3g2", ".3gpp2",
42fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        ".mpeg", ".ogg", ".mid", ".smf", ".imy", ".wma", ".aac",
43093437c388e5dff6903a3d43f2ca9f8a1ba4744aAndreas Huber        ".wav", ".amr", ".midi", ".xmf", ".rtttl", ".rtx", ".ota",
448d30cc86d36c5e2d7d8defab8f58faed4139ed7fAndreas Huber        ".mkv", ".mka", ".webm", ".ts", ".fl", ".flac", ".mxmf",
452944eca607304a095ea43ba2b8f0b9de61249f9fAndreas Huber        ".avi", ".mpeg", ".mpg"
46fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    };
47fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    static const size_t kNumValidExtensions =
48fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        sizeof(kValidExtensions) / sizeof(kValidExtensions[0]);
49fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
50fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    for (size_t i = 0; i < kNumValidExtensions; ++i) {
51fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        if (!strcasecmp(extension, kValidExtensions[i])) {
52fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return true;
53fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
54fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
55fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
56fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    return false;
57fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
58fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
597188e55f54a43c55fd6b96454720c447f1dc454eJeff Brownstatic MediaScanResult HandleMIDI(
60fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        const char *filename, MediaScannerClient *client) {
61fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // get the library configuration and do sanity check
62fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    const S_EAS_LIB_CONFIG* pLibConfig = EAS_Config();
63fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if ((pLibConfig == NULL) || (LIB_VERSION != pLibConfig->libVersion)) {
6429357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block        ALOGE("EAS library/header mismatch\n");
657188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_ERROR;
66fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
67fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    EAS_I32 temp;
68fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
69fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    // spin up a new EAS engine
70fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    EAS_DATA_HANDLE easData = NULL;
71fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    EAS_HANDLE easHandle = NULL;
72fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    EAS_RESULT result = EAS_Init(&easData);
73fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (result == EAS_SUCCESS) {
74fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        EAS_FILE file;
75fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        file.path = filename;
76fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        file.fd = 0;
77fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        file.offset = 0;
78fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        file.length = 0;
79fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        result = EAS_OpenFile(easData, &file, &easHandle);
80fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
81fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (result == EAS_SUCCESS) {
82fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        result = EAS_Prepare(easData, easHandle);
83fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
84fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (result == EAS_SUCCESS) {
85fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        result = EAS_ParseMetaData(easData, easHandle, &temp);
86fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
87fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (easHandle) {
88fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        EAS_CloseFile(easData, easHandle);
89fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
90fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (easData) {
91fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        EAS_Shutdown(easData);
92fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
93fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
94fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (result != EAS_SUCCESS) {
957188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_SKIPPED;
96fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
97fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
98fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    char buffer[20];
99fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    sprintf(buffer, "%ld", temp);
1007188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    status_t status = client->addStringTag("duration", buffer);
101153cefdf4acab25355f590d7760ebf73ef6096a9Marco Nelissen    if (status != OK) {
1027188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_ERROR;
1037188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    }
1047188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    return MEDIA_SCAN_RESULT_OK;
105fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber}
106fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
1077188e55f54a43c55fd6b96454720c447f1dc454eJeff BrownMediaScanResult StagefrightMediaScanner::processFile(
10867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber        const char *path, const char *mimeType,
10967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber        MediaScannerClient &client) {
1103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("processFile '%s'.", path);
1112e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber
11267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber    client.setLocale(locale());
11367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber    client.beginFile();
1147188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    MediaScanResult result = processFileInternal(path, mimeType, client);
1157188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    client.endFile();
1167188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    return result;
1177188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown}
11867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
1197188e55f54a43c55fd6b96454720c447f1dc454eJeff BrownMediaScanResult StagefrightMediaScanner::processFileInternal(
1207188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        const char *path, const char *mimeType,
1217188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        MediaScannerClient &client) {
122fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    const char *extension = strrchr(path, '.');
123fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
124fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!extension) {
1257188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_SKIPPED;
126fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
127fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
128fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!FileHasAcceptableExtension(extension)) {
1297188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_SKIPPED;
130fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
131fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
132fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (!strcasecmp(extension, ".mid")
133fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".smf")
134fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".imy")
135fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".midi")
136fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".xmf")
137fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".rtttl")
138fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            || !strcasecmp(extension, ".rtx")
1398d30cc86d36c5e2d7d8defab8f58faed4139ed7fAndreas Huber            || !strcasecmp(extension, ".ota")
1408d30cc86d36c5e2d7d8defab8f58faed4139ed7fAndreas Huber            || !strcasecmp(extension, ".mxmf")) {
1417188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return HandleMIDI(path, &client);
1427188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    }
1437188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown
1447188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
1457188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown
146a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen    int fd = open(path, O_RDONLY | O_LARGEFILE);
147a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen    status_t status;
148a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen    if (fd < 0) {
149a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen        // couldn't open it locally, maybe the media server can?
150a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen        status = mRetriever->setDataSource(path);
151a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen    } else {
152a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen        status = mRetriever->setDataSource(fd, 0, 0x7ffffffffffffffL);
153a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen        close(fd);
154a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen    }
155a28976b04c70cef3c8e79137478b6a7bc05608acMarco Nelissen
1567188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    if (status) {
1577188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        return MEDIA_SCAN_RESULT_ERROR;
1587188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    }
1597188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown
1607188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    const char *value;
1617188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    if ((value = mRetriever->extractMetadata(
1627188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown                    METADATA_KEY_MIMETYPE)) != NULL) {
1637188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        status = client.setMimeType(value);
1647188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        if (status) {
1657188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown            return MEDIA_SCAN_RESULT_ERROR;
1666ed70d2d41f9929d1c3f5179d947766495f9efe5Hiroshi Takekawa        }
1677188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    }
1680a095d09464ba18e288a3f529410af0f1257ac2aMike Lockwood
1697188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    struct KeyMap {
1707188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        const char *tag;
1717188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        int key;
1727188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    };
1737188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    static const KeyMap kKeyMap[] = {
1747188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "tracknumber", METADATA_KEY_CD_TRACK_NUMBER },
1757188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "discnumber", METADATA_KEY_DISC_NUMBER },
1767188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "album", METADATA_KEY_ALBUM },
1777188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "artist", METADATA_KEY_ARTIST },
1787188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "albumartist", METADATA_KEY_ALBUMARTIST },
1797188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "composer", METADATA_KEY_COMPOSER },
1807188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "genre", METADATA_KEY_GENRE },
1817188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "title", METADATA_KEY_TITLE },
1827188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "year", METADATA_KEY_YEAR },
1837188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "duration", METADATA_KEY_DURATION },
1847188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "writer", METADATA_KEY_WRITER },
1857188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "compilation", METADATA_KEY_COMPILATION },
1867188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        { "isdrm", METADATA_KEY_IS_DRM },
1874762a5164a986bd6a7ca0e7aba43881b64f146ddMarco Nelissen        { "width", METADATA_KEY_VIDEO_WIDTH },
1884762a5164a986bd6a7ca0e7aba43881b64f146ddMarco Nelissen        { "height", METADATA_KEY_VIDEO_HEIGHT },
1897188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    };
1907188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    static const size_t kNumEntries = sizeof(kKeyMap) / sizeof(kKeyMap[0]);
1917188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown
1927188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    for (size_t i = 0; i < kNumEntries; ++i) {
1937188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        const char *value;
1947188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown        if ((value = mRetriever->extractMetadata(kKeyMap[i].key)) != NULL) {
1957188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown            status = client.addStringTag(kKeyMap[i].tag, value);
196153cefdf4acab25355f590d7760ebf73ef6096a9Marco Nelissen            if (status != OK) {
1977188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown                return MEDIA_SCAN_RESULT_ERROR;
19867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber            }
19967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber        }
20067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber    }
20167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
2027188e55f54a43c55fd6b96454720c447f1dc454eJeff Brown    return MEDIA_SCAN_RESULT_OK;
20367e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber}
20467e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
20567e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huberchar *StagefrightMediaScanner::extractAlbumArt(int fd) {
2063856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ALOGV("extractAlbumArt %d", fd);
2072e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber
208c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    off64_t size = lseek64(fd, 0, SEEK_END);
209fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    if (size < 0) {
210fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        return NULL;
211fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber    }
212c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong    lseek64(fd, 0, SEEK_SET);
213fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
2140a095d09464ba18e288a3f529410af0f1257ac2aMike Lockwood    sp<MediaMetadataRetriever> mRetriever(new MediaMetadataRetriever);
2157f7d52ac18dfc3c6d8f6267dad29306613e9bd0eJames Dong    if (mRetriever->setDataSource(fd, 0, size) == OK) {
2162e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber        sp<IMemory> mem = mRetriever->extractAlbumArt();
2172e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber
2182e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber        if (mem != NULL) {
2192e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber            MediaAlbumArt *art = static_cast<MediaAlbumArt *>(mem->pointer());
22067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
221fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            char *data = (char *)malloc(art->mSize + 4);
222fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            *(int32_t *)data = art->mSize;
2232e39c1ca101e01ff13b03129a87939e7982b25bfAndreas Huber            memcpy(&data[4], &art[1], art->mSize);
224fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber
225fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber            return data;
226fc9ba09e3bb368f823d473f5e2bb9aa32dba6289Andreas Huber        }
22767e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber    }
22867e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
22967e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber    return NULL;
23067e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber}
23167e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber
23267e5a4f6f6879d512a859e5dba92e9beec7a2f91Andreas Huber}  // namespace android
233