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