xref: /aosp_15_r20/frameworks/av/media/libmediaplayerservice/MetadataRetrieverClient.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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