1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker **
3*ec779b8eSAndroid Build Coastguard Worker ** Copyright (C) 2008 The Android Open Source Project
4*ec779b8eSAndroid Build Coastguard Worker **
5*ec779b8eSAndroid Build Coastguard Worker ** Licensed under the Apache License, Version 2.0 (the "License");
6*ec779b8eSAndroid Build Coastguard Worker ** you may not use this file except in compliance with the License.
7*ec779b8eSAndroid Build Coastguard Worker ** You may obtain a copy of the License at
8*ec779b8eSAndroid Build Coastguard Worker **
9*ec779b8eSAndroid Build Coastguard Worker ** http://www.apache.org/licenses/LICENSE-2.0
10*ec779b8eSAndroid Build Coastguard Worker **
11*ec779b8eSAndroid Build Coastguard Worker ** Unless required by applicable law or agreed to in writing, software
12*ec779b8eSAndroid Build Coastguard Worker ** distributed under the License is distributed on an "AS IS" BASIS,
13*ec779b8eSAndroid Build Coastguard Worker ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*ec779b8eSAndroid Build Coastguard Worker ** See the License for the specific language governing permissions and
15*ec779b8eSAndroid Build Coastguard Worker ** limitations under the License.
16*ec779b8eSAndroid Build Coastguard Worker */
17*ec779b8eSAndroid Build Coastguard Worker
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MetadataRetrieverClient"
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker
22*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <sys/stat.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <dirent.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <unistd.h>
26*ec779b8eSAndroid Build Coastguard Worker
27*ec779b8eSAndroid Build Coastguard Worker #include <string.h>
28*ec779b8eSAndroid Build Coastguard Worker #include <cutils/atomic.h>
29*ec779b8eSAndroid Build Coastguard Worker #include <cutils/properties.h>
30*ec779b8eSAndroid Build Coastguard Worker #include <binder/MemoryBase.h>
31*ec779b8eSAndroid Build Coastguard Worker #include <binder/MemoryHeapBase.h>
32*ec779b8eSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
33*ec779b8eSAndroid Build Coastguard Worker #include <binder/IServiceManager.h>
34*ec779b8eSAndroid Build Coastguard Worker #include <media/DataSource.h>
35*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
36*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaMetadataRetrieverInterface.h>
37*ec779b8eSAndroid Build Coastguard Worker #include <media/MediaPlayerInterface.h>
38*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/InterfaceUtils.h>
39*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/Utils.h>
40*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/FoundationUtils.h>
41*ec779b8eSAndroid Build Coastguard Worker #include <private/media/VideoFrame.h>
42*ec779b8eSAndroid Build Coastguard Worker #include "MetadataRetrieverClient.h"
43*ec779b8eSAndroid Build Coastguard Worker #include "StagefrightMetadataRetriever.h"
44*ec779b8eSAndroid Build Coastguard Worker #include "MediaPlayerFactory.h"
45*ec779b8eSAndroid Build Coastguard Worker
46*ec779b8eSAndroid Build Coastguard Worker namespace android {
47*ec779b8eSAndroid Build Coastguard Worker
MetadataRetrieverClient(pid_t pid)48*ec779b8eSAndroid Build Coastguard Worker MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
49*ec779b8eSAndroid Build Coastguard Worker {
50*ec779b8eSAndroid Build Coastguard Worker ALOGV("MetadataRetrieverClient constructor pid(%d)", pid);
51*ec779b8eSAndroid Build Coastguard Worker mPid = pid;
52*ec779b8eSAndroid Build Coastguard Worker mAlbumArt = NULL;
53*ec779b8eSAndroid Build Coastguard Worker mRetriever = NULL;
54*ec779b8eSAndroid Build Coastguard Worker }
55*ec779b8eSAndroid Build Coastguard Worker
~MetadataRetrieverClient()56*ec779b8eSAndroid Build Coastguard Worker MetadataRetrieverClient::~MetadataRetrieverClient()
57*ec779b8eSAndroid Build Coastguard Worker {
58*ec779b8eSAndroid Build Coastguard Worker ALOGV("MetadataRetrieverClient destructor");
59*ec779b8eSAndroid Build Coastguard Worker disconnect();
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker
dump(int fd,const Vector<String16> &)62*ec779b8eSAndroid Build Coastguard Worker status_t MetadataRetrieverClient::dump(int fd, const Vector<String16>& /*args*/)
63*ec779b8eSAndroid Build Coastguard Worker {
64*ec779b8eSAndroid Build Coastguard Worker const size_t SIZE = 256;
65*ec779b8eSAndroid Build Coastguard Worker char buffer[SIZE];
66*ec779b8eSAndroid Build Coastguard Worker String8 result;
67*ec779b8eSAndroid Build Coastguard Worker result.append(" MetadataRetrieverClient\n");
68*ec779b8eSAndroid Build Coastguard Worker snprintf(buffer, 255, " pid(%d)\n", mPid);
69*ec779b8eSAndroid Build Coastguard Worker result.append(buffer);
70*ec779b8eSAndroid Build Coastguard Worker write(fd, result.c_str(), result.size());
71*ec779b8eSAndroid Build Coastguard Worker write(fd, "\n", 1);
72*ec779b8eSAndroid Build Coastguard Worker return NO_ERROR;
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker
disconnect()75*ec779b8eSAndroid Build Coastguard Worker void MetadataRetrieverClient::disconnect()
76*ec779b8eSAndroid Build Coastguard Worker {
77*ec779b8eSAndroid Build Coastguard Worker ALOGV("disconnect from pid %d", mPid);
78*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
79*ec779b8eSAndroid Build Coastguard Worker mRetriever.clear();
80*ec779b8eSAndroid Build Coastguard Worker mAlbumArt.clear();
81*ec779b8eSAndroid Build Coastguard Worker IPCThreadState::self()->flushCommands();
82*ec779b8eSAndroid Build Coastguard Worker }
83*ec779b8eSAndroid Build Coastguard Worker
createRetriever(player_type playerType)84*ec779b8eSAndroid Build Coastguard Worker static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
85*ec779b8eSAndroid Build Coastguard Worker {
86*ec779b8eSAndroid Build Coastguard Worker sp<MediaMetadataRetrieverBase> p;
87*ec779b8eSAndroid Build Coastguard Worker switch (playerType) {
88*ec779b8eSAndroid Build Coastguard Worker case STAGEFRIGHT_PLAYER:
89*ec779b8eSAndroid Build Coastguard Worker case NU_PLAYER:
90*ec779b8eSAndroid Build Coastguard Worker {
91*ec779b8eSAndroid Build Coastguard Worker p = new StagefrightMetadataRetriever;
92*ec779b8eSAndroid Build Coastguard Worker break;
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker default:
95*ec779b8eSAndroid Build Coastguard Worker // TODO:
96*ec779b8eSAndroid Build Coastguard Worker // support for TEST_PLAYER
97*ec779b8eSAndroid Build Coastguard Worker ALOGE("player type %d is not supported", playerType);
98*ec779b8eSAndroid Build Coastguard Worker break;
99*ec779b8eSAndroid Build Coastguard Worker }
100*ec779b8eSAndroid Build Coastguard Worker if (p == NULL) {
101*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to create a retriever object");
102*ec779b8eSAndroid Build Coastguard Worker }
103*ec779b8eSAndroid Build Coastguard Worker return p;
104*ec779b8eSAndroid Build Coastguard Worker }
105*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<IMediaHTTPService> & httpService,const char * url,const KeyedVector<String8,String8> * headers)106*ec779b8eSAndroid Build Coastguard Worker status_t MetadataRetrieverClient::setDataSource(
107*ec779b8eSAndroid Build Coastguard Worker const sp<IMediaHTTPService> &httpService,
108*ec779b8eSAndroid Build Coastguard Worker const char *url,
109*ec779b8eSAndroid Build Coastguard Worker const KeyedVector<String8, String8> *headers)
110*ec779b8eSAndroid Build Coastguard Worker {
111*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(%s)", url);
112*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
113*ec779b8eSAndroid Build Coastguard Worker if (url == NULL) {
114*ec779b8eSAndroid Build Coastguard Worker return UNKNOWN_ERROR;
115*ec779b8eSAndroid Build Coastguard Worker }
116*ec779b8eSAndroid Build Coastguard Worker
117*ec779b8eSAndroid Build Coastguard Worker // When asking the MediaPlayerFactory subsystem to choose a media player for
118*ec779b8eSAndroid Build Coastguard Worker // a given URL, a pointer to an outer IMediaPlayer can be passed to the
119*ec779b8eSAndroid Build Coastguard Worker // factory system to be taken into consideration along with the URL. In the
120*ec779b8eSAndroid Build Coastguard Worker // case of choosing an instance of a MediaPlayerBase for a
121*ec779b8eSAndroid Build Coastguard Worker // MetadataRetrieverClient, there is no outer IMediaPlayer which will
122*ec779b8eSAndroid Build Coastguard Worker // eventually encapsulate the result of this selection. In this case, just
123*ec779b8eSAndroid Build Coastguard Worker // pass NULL to getPlayerType to indicate that there is no outer
124*ec779b8eSAndroid Build Coastguard Worker // IMediaPlayer to consider during selection.
125*ec779b8eSAndroid Build Coastguard Worker player_type playerType =
126*ec779b8eSAndroid Build Coastguard Worker MediaPlayerFactory::getPlayerType(NULL /* client */, url);
127*ec779b8eSAndroid Build Coastguard Worker ALOGV("player type = %d", playerType);
128*ec779b8eSAndroid Build Coastguard Worker sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
129*ec779b8eSAndroid Build Coastguard Worker if (p == NULL) return NO_INIT;
130*ec779b8eSAndroid Build Coastguard Worker status_t ret = p->setDataSource(httpService, url, headers);
131*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR) mRetriever = p;
132*ec779b8eSAndroid Build Coastguard Worker return ret;
133*ec779b8eSAndroid Build Coastguard Worker }
134*ec779b8eSAndroid Build Coastguard Worker
setDataSource(int fd,int64_t offset,int64_t length)135*ec779b8eSAndroid Build Coastguard Worker status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
136*ec779b8eSAndroid Build Coastguard Worker {
137*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource fd=%d (%s), offset=%lld, length=%lld",
138*ec779b8eSAndroid Build Coastguard Worker fd, nameForFd(fd).c_str(), (long long) offset, (long long) length);
139*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
140*ec779b8eSAndroid Build Coastguard Worker struct stat sb;
141*ec779b8eSAndroid Build Coastguard Worker int ret = fstat(fd, &sb);
142*ec779b8eSAndroid Build Coastguard Worker if (ret != 0) {
143*ec779b8eSAndroid Build Coastguard Worker ALOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
144*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
145*ec779b8eSAndroid Build Coastguard Worker }
146*ec779b8eSAndroid Build Coastguard Worker ALOGV("st_dev = %llu", static_cast<unsigned long long>(sb.st_dev));
147*ec779b8eSAndroid Build Coastguard Worker ALOGV("st_mode = %u", sb.st_mode);
148*ec779b8eSAndroid Build Coastguard Worker ALOGV("st_uid = %lu", static_cast<unsigned long>(sb.st_uid));
149*ec779b8eSAndroid Build Coastguard Worker ALOGV("st_gid = %lu", static_cast<unsigned long>(sb.st_gid));
150*ec779b8eSAndroid Build Coastguard Worker ALOGV("st_size = %llu", static_cast<unsigned long long>(sb.st_size));
151*ec779b8eSAndroid Build Coastguard Worker
152*ec779b8eSAndroid Build Coastguard Worker if (offset >= sb.st_size) {
153*ec779b8eSAndroid Build Coastguard Worker ALOGE("offset (%lld) bigger than file size (%llu)",
154*ec779b8eSAndroid Build Coastguard Worker (long long)offset, (unsigned long long)sb.st_size);
155*ec779b8eSAndroid Build Coastguard Worker return BAD_VALUE;
156*ec779b8eSAndroid Build Coastguard Worker }
157*ec779b8eSAndroid Build Coastguard Worker if (offset + length > sb.st_size) {
158*ec779b8eSAndroid Build Coastguard Worker length = sb.st_size - offset;
159*ec779b8eSAndroid Build Coastguard Worker ALOGV("calculated length = %lld", (long long)length);
160*ec779b8eSAndroid Build Coastguard Worker }
161*ec779b8eSAndroid Build Coastguard Worker
162*ec779b8eSAndroid Build Coastguard Worker player_type playerType =
163*ec779b8eSAndroid Build Coastguard Worker MediaPlayerFactory::getPlayerType(NULL /* client */,
164*ec779b8eSAndroid Build Coastguard Worker fd,
165*ec779b8eSAndroid Build Coastguard Worker offset,
166*ec779b8eSAndroid Build Coastguard Worker length);
167*ec779b8eSAndroid Build Coastguard Worker ALOGV("player type = %d", playerType);
168*ec779b8eSAndroid Build Coastguard Worker sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
169*ec779b8eSAndroid Build Coastguard Worker if (p == NULL) {
170*ec779b8eSAndroid Build Coastguard Worker return NO_INIT;
171*ec779b8eSAndroid Build Coastguard Worker }
172*ec779b8eSAndroid Build Coastguard Worker status_t status = p->setDataSource(fd, offset, length);
173*ec779b8eSAndroid Build Coastguard Worker if (status == NO_ERROR) mRetriever = p;
174*ec779b8eSAndroid Build Coastguard Worker return status;
175*ec779b8eSAndroid Build Coastguard Worker }
176*ec779b8eSAndroid Build Coastguard Worker
setDataSource(const sp<IDataSource> & source,const char * mime)177*ec779b8eSAndroid Build Coastguard Worker status_t MetadataRetrieverClient::setDataSource(
178*ec779b8eSAndroid Build Coastguard Worker const sp<IDataSource>& source, const char *mime)
179*ec779b8eSAndroid Build Coastguard Worker {
180*ec779b8eSAndroid Build Coastguard Worker ALOGV("setDataSource(IDataSource)");
181*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
182*ec779b8eSAndroid Build Coastguard Worker
183*ec779b8eSAndroid Build Coastguard Worker sp<DataSource> dataSource = CreateDataSourceFromIDataSource(source);
184*ec779b8eSAndroid Build Coastguard Worker player_type playerType =
185*ec779b8eSAndroid Build Coastguard Worker MediaPlayerFactory::getPlayerType(NULL /* client */, dataSource);
186*ec779b8eSAndroid Build Coastguard Worker ALOGV("player type = %d", playerType);
187*ec779b8eSAndroid Build Coastguard Worker sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
188*ec779b8eSAndroid Build Coastguard Worker if (p == NULL) return NO_INIT;
189*ec779b8eSAndroid Build Coastguard Worker status_t ret = p->setDataSource(dataSource, mime);
190*ec779b8eSAndroid Build Coastguard Worker if (ret == NO_ERROR) mRetriever = p;
191*ec779b8eSAndroid Build Coastguard Worker return ret;
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
194*ec779b8eSAndroid Build Coastguard Worker Mutex MetadataRetrieverClient::sLock;
195*ec779b8eSAndroid Build Coastguard Worker
getFrameAtTime(int64_t timeUs,int option,int colorFormat,bool metaOnly)196*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> MetadataRetrieverClient::getFrameAtTime(
197*ec779b8eSAndroid Build Coastguard Worker int64_t timeUs, int option, int colorFormat, bool metaOnly)
198*ec779b8eSAndroid Build Coastguard Worker {
199*ec779b8eSAndroid Build Coastguard Worker ALOGV("getFrameAtTime: time(%lld us) option(%d) colorFormat(%d), metaOnly(%d)",
200*ec779b8eSAndroid Build Coastguard Worker (long long)timeUs, option, colorFormat, metaOnly);
201*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
202*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock glock(sLock);
203*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
204*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
205*ec779b8eSAndroid Build Coastguard Worker return NULL;
206*ec779b8eSAndroid Build Coastguard Worker }
207*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> frame = mRetriever->getFrameAtTime(timeUs, option, colorFormat, metaOnly);
208*ec779b8eSAndroid Build Coastguard Worker if (frame == NULL) {
209*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to capture a video frame");
210*ec779b8eSAndroid Build Coastguard Worker return NULL;
211*ec779b8eSAndroid Build Coastguard Worker }
212*ec779b8eSAndroid Build Coastguard Worker return frame;
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker
getImageAtIndex(int index,int colorFormat,bool metaOnly,bool thumbnail)215*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> MetadataRetrieverClient::getImageAtIndex(
216*ec779b8eSAndroid Build Coastguard Worker int index, int colorFormat, bool metaOnly, bool thumbnail) {
217*ec779b8eSAndroid Build Coastguard Worker ALOGV("getImageAtIndex: index(%d) colorFormat(%d), metaOnly(%d) thumbnail(%d)",
218*ec779b8eSAndroid Build Coastguard Worker index, colorFormat, metaOnly, thumbnail);
219*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
220*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock glock(sLock);
221*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
222*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
223*ec779b8eSAndroid Build Coastguard Worker return NULL;
224*ec779b8eSAndroid Build Coastguard Worker }
225*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> frame = mRetriever->getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
226*ec779b8eSAndroid Build Coastguard Worker if (frame == NULL) {
227*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to extract image");
228*ec779b8eSAndroid Build Coastguard Worker return NULL;
229*ec779b8eSAndroid Build Coastguard Worker }
230*ec779b8eSAndroid Build Coastguard Worker return frame;
231*ec779b8eSAndroid Build Coastguard Worker }
232*ec779b8eSAndroid Build Coastguard Worker
getImageRectAtIndex(int index,int colorFormat,int left,int top,int right,int bottom)233*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> MetadataRetrieverClient::getImageRectAtIndex(
234*ec779b8eSAndroid Build Coastguard Worker int index, int colorFormat, int left, int top, int right, int bottom) {
235*ec779b8eSAndroid Build Coastguard Worker ALOGV("getImageRectAtIndex: index(%d) colorFormat(%d), rect {%d, %d, %d, %d}",
236*ec779b8eSAndroid Build Coastguard Worker index, colorFormat, left, top, right, bottom);
237*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
238*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock glock(sLock);
239*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
240*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
241*ec779b8eSAndroid Build Coastguard Worker return NULL;
242*ec779b8eSAndroid Build Coastguard Worker }
243*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> frame = mRetriever->getImageRectAtIndex(
244*ec779b8eSAndroid Build Coastguard Worker index, colorFormat, left, top, right, bottom);
245*ec779b8eSAndroid Build Coastguard Worker if (frame == NULL) {
246*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to extract image at index %d", index);
247*ec779b8eSAndroid Build Coastguard Worker }
248*ec779b8eSAndroid Build Coastguard Worker return frame;
249*ec779b8eSAndroid Build Coastguard Worker }
250*ec779b8eSAndroid Build Coastguard Worker
getFrameAtIndex(int index,int colorFormat,bool metaOnly)251*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> MetadataRetrieverClient::getFrameAtIndex(
252*ec779b8eSAndroid Build Coastguard Worker int index, int colorFormat, bool metaOnly) {
253*ec779b8eSAndroid Build Coastguard Worker ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
254*ec779b8eSAndroid Build Coastguard Worker index, colorFormat, metaOnly);
255*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
256*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock glock(sLock);
257*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
258*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
259*ec779b8eSAndroid Build Coastguard Worker return NULL;
260*ec779b8eSAndroid Build Coastguard Worker }
261*ec779b8eSAndroid Build Coastguard Worker
262*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> frame = mRetriever->getFrameAtIndex(index, colorFormat, metaOnly);
263*ec779b8eSAndroid Build Coastguard Worker if (frame == NULL) {
264*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to extract frame at index %d", index);
265*ec779b8eSAndroid Build Coastguard Worker }
266*ec779b8eSAndroid Build Coastguard Worker return frame;
267*ec779b8eSAndroid Build Coastguard Worker }
268*ec779b8eSAndroid Build Coastguard Worker
extractAlbumArt()269*ec779b8eSAndroid Build Coastguard Worker sp<IMemory> MetadataRetrieverClient::extractAlbumArt()
270*ec779b8eSAndroid Build Coastguard Worker {
271*ec779b8eSAndroid Build Coastguard Worker ALOGV("extractAlbumArt");
272*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
273*ec779b8eSAndroid Build Coastguard Worker mAlbumArt.clear();
274*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
275*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
276*ec779b8eSAndroid Build Coastguard Worker return NULL;
277*ec779b8eSAndroid Build Coastguard Worker }
278*ec779b8eSAndroid Build Coastguard Worker MediaAlbumArt *albumArt = mRetriever->extractAlbumArt();
279*ec779b8eSAndroid Build Coastguard Worker if (albumArt == NULL) {
280*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to extract an album art");
281*ec779b8eSAndroid Build Coastguard Worker return NULL;
282*ec779b8eSAndroid Build Coastguard Worker }
283*ec779b8eSAndroid Build Coastguard Worker size_t size = sizeof(MediaAlbumArt) + albumArt->size();
284*ec779b8eSAndroid Build Coastguard Worker sp<MemoryHeapBase> heap = new MemoryHeapBase(size, 0, "MetadataRetrieverClient");
285*ec779b8eSAndroid Build Coastguard Worker if (heap == NULL) {
286*ec779b8eSAndroid Build Coastguard Worker ALOGE("failed to create MemoryDealer object");
287*ec779b8eSAndroid Build Coastguard Worker delete albumArt;
288*ec779b8eSAndroid Build Coastguard Worker return NULL;
289*ec779b8eSAndroid Build Coastguard Worker }
290*ec779b8eSAndroid Build Coastguard Worker mAlbumArt = new MemoryBase(heap, 0, size);
291*ec779b8eSAndroid Build Coastguard Worker if (mAlbumArt == NULL) {
292*ec779b8eSAndroid Build Coastguard Worker ALOGE("not enough memory for MediaAlbumArt size=%zu", size);
293*ec779b8eSAndroid Build Coastguard Worker delete albumArt;
294*ec779b8eSAndroid Build Coastguard Worker return NULL;
295*ec779b8eSAndroid Build Coastguard Worker }
296*ec779b8eSAndroid Build Coastguard Worker MediaAlbumArt::init((MediaAlbumArt *) mAlbumArt->unsecurePointer(),
297*ec779b8eSAndroid Build Coastguard Worker albumArt->size(), albumArt->data());
298*ec779b8eSAndroid Build Coastguard Worker delete albumArt; // We've taken our copy.
299*ec779b8eSAndroid Build Coastguard Worker return mAlbumArt;
300*ec779b8eSAndroid Build Coastguard Worker }
301*ec779b8eSAndroid Build Coastguard Worker
extractMetadata(int keyCode)302*ec779b8eSAndroid Build Coastguard Worker const char* MetadataRetrieverClient::extractMetadata(int keyCode)
303*ec779b8eSAndroid Build Coastguard Worker {
304*ec779b8eSAndroid Build Coastguard Worker ALOGV("extractMetadata");
305*ec779b8eSAndroid Build Coastguard Worker Mutex::Autolock lock(mLock);
306*ec779b8eSAndroid Build Coastguard Worker if (mRetriever == NULL) {
307*ec779b8eSAndroid Build Coastguard Worker ALOGE("retriever is not initialized");
308*ec779b8eSAndroid Build Coastguard Worker return NULL;
309*ec779b8eSAndroid Build Coastguard Worker }
310*ec779b8eSAndroid Build Coastguard Worker return mRetriever->extractMetadata(keyCode);
311*ec779b8eSAndroid Build Coastguard Worker }
312*ec779b8eSAndroid Build Coastguard Worker
313*ec779b8eSAndroid Build Coastguard Worker }; // namespace android
314