xref: /aosp_15_r20/frameworks/av/media/libmedia/IMediaMetadataRetriever.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 #include <inttypes.h>
19*ec779b8eSAndroid Build Coastguard Worker #include <stdint.h>
20*ec779b8eSAndroid Build Coastguard Worker #include <sys/types.h>
21*ec779b8eSAndroid Build Coastguard Worker 
22*ec779b8eSAndroid Build Coastguard Worker #include <android/IDataSource.h>
23*ec779b8eSAndroid Build Coastguard Worker #include <binder/Parcel.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaHTTPService.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/IMediaMetadataRetriever.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <utils/String8.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <utils/KeyedVector.h>
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker namespace android {
30*ec779b8eSAndroid Build Coastguard Worker 
31*ec779b8eSAndroid Build Coastguard Worker enum {
32*ec779b8eSAndroid Build Coastguard Worker     DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
33*ec779b8eSAndroid Build Coastguard Worker     SET_DATA_SOURCE_URL,
34*ec779b8eSAndroid Build Coastguard Worker     SET_DATA_SOURCE_FD,
35*ec779b8eSAndroid Build Coastguard Worker     SET_DATA_SOURCE_CALLBACK,
36*ec779b8eSAndroid Build Coastguard Worker     GET_FRAME_AT_TIME,
37*ec779b8eSAndroid Build Coastguard Worker     GET_IMAGE_AT_INDEX,
38*ec779b8eSAndroid Build Coastguard Worker     GET_IMAGE_RECT_AT_INDEX,
39*ec779b8eSAndroid Build Coastguard Worker     GET_FRAME_AT_INDEX,
40*ec779b8eSAndroid Build Coastguard Worker     EXTRACT_ALBUM_ART,
41*ec779b8eSAndroid Build Coastguard Worker     EXTRACT_METADATA,
42*ec779b8eSAndroid Build Coastguard Worker };
43*ec779b8eSAndroid Build Coastguard Worker 
44*ec779b8eSAndroid Build Coastguard Worker class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
45*ec779b8eSAndroid Build Coastguard Worker {
46*ec779b8eSAndroid Build Coastguard Worker public:
BpMediaMetadataRetriever(const sp<IBinder> & impl)47*ec779b8eSAndroid Build Coastguard Worker     explicit BpMediaMetadataRetriever(const sp<IBinder>& impl)
48*ec779b8eSAndroid Build Coastguard Worker         : BpInterface<IMediaMetadataRetriever>(impl)
49*ec779b8eSAndroid Build Coastguard Worker     {
50*ec779b8eSAndroid Build Coastguard Worker     }
51*ec779b8eSAndroid Build Coastguard Worker 
52*ec779b8eSAndroid Build Coastguard Worker     // disconnect from media metadata retriever service
disconnect()53*ec779b8eSAndroid Build Coastguard Worker     void disconnect()
54*ec779b8eSAndroid Build Coastguard Worker     {
55*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
56*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
57*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(DISCONNECT, data, &reply);
58*ec779b8eSAndroid Build Coastguard Worker     }
59*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IMediaHTTPService> & httpService,const char * srcUrl,const KeyedVector<String8,String8> * headers)60*ec779b8eSAndroid Build Coastguard Worker     status_t setDataSource(
61*ec779b8eSAndroid Build Coastguard Worker             const sp<IMediaHTTPService> &httpService,
62*ec779b8eSAndroid Build Coastguard Worker             const char *srcUrl,
63*ec779b8eSAndroid Build Coastguard Worker             const KeyedVector<String8, String8> *headers)
64*ec779b8eSAndroid Build Coastguard Worker     {
65*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
66*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
67*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(httpService != NULL);
68*ec779b8eSAndroid Build Coastguard Worker         if (httpService != NULL) {
69*ec779b8eSAndroid Build Coastguard Worker             data.writeStrongBinder(IInterface::asBinder(httpService));
70*ec779b8eSAndroid Build Coastguard Worker         }
71*ec779b8eSAndroid Build Coastguard Worker         data.writeCString(srcUrl);
72*ec779b8eSAndroid Build Coastguard Worker 
73*ec779b8eSAndroid Build Coastguard Worker         if (headers == NULL) {
74*ec779b8eSAndroid Build Coastguard Worker             data.writeInt32(0);
75*ec779b8eSAndroid Build Coastguard Worker         } else {
76*ec779b8eSAndroid Build Coastguard Worker             // serialize the headers
77*ec779b8eSAndroid Build Coastguard Worker             data.writeInt32(headers->size());
78*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < headers->size(); ++i) {
79*ec779b8eSAndroid Build Coastguard Worker                 data.writeString8(headers->keyAt(i));
80*ec779b8eSAndroid Build Coastguard Worker                 data.writeString8(headers->valueAt(i));
81*ec779b8eSAndroid Build Coastguard Worker             }
82*ec779b8eSAndroid Build Coastguard Worker         }
83*ec779b8eSAndroid Build Coastguard Worker 
84*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
85*ec779b8eSAndroid Build Coastguard Worker         return reply.readInt32();
86*ec779b8eSAndroid Build Coastguard Worker     }
87*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(int fd,int64_t offset,int64_t length)88*ec779b8eSAndroid Build Coastguard Worker     status_t setDataSource(int fd, int64_t offset, int64_t length)
89*ec779b8eSAndroid Build Coastguard Worker     {
90*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
91*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
92*ec779b8eSAndroid Build Coastguard Worker         data.writeFileDescriptor(fd);
93*ec779b8eSAndroid Build Coastguard Worker         data.writeInt64(offset);
94*ec779b8eSAndroid Build Coastguard Worker         data.writeInt64(length);
95*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
96*ec779b8eSAndroid Build Coastguard Worker         return reply.readInt32();
97*ec779b8eSAndroid Build Coastguard Worker     }
98*ec779b8eSAndroid Build Coastguard Worker 
setDataSource(const sp<IDataSource> & source,const char * mime)99*ec779b8eSAndroid Build Coastguard Worker     status_t setDataSource(const sp<IDataSource>& source, const char *mime)
100*ec779b8eSAndroid Build Coastguard Worker     {
101*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
102*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
103*ec779b8eSAndroid Build Coastguard Worker         data.writeStrongBinder(IInterface::asBinder(source));
104*ec779b8eSAndroid Build Coastguard Worker 
105*ec779b8eSAndroid Build Coastguard Worker         if (mime != NULL) {
106*ec779b8eSAndroid Build Coastguard Worker             data.writeInt32(1);
107*ec779b8eSAndroid Build Coastguard Worker             data.writeCString(mime);
108*ec779b8eSAndroid Build Coastguard Worker         } else {
109*ec779b8eSAndroid Build Coastguard Worker             data.writeInt32(0);
110*ec779b8eSAndroid Build Coastguard Worker         }
111*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
112*ec779b8eSAndroid Build Coastguard Worker         return reply.readInt32();
113*ec779b8eSAndroid Build Coastguard Worker     }
114*ec779b8eSAndroid Build Coastguard Worker 
getFrameAtTime(int64_t timeUs,int option,int colorFormat,bool metaOnly)115*ec779b8eSAndroid Build Coastguard Worker     sp<IMemory> getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly)
116*ec779b8eSAndroid Build Coastguard Worker     {
117*ec779b8eSAndroid Build Coastguard Worker         ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d) metaOnly(%d)",
118*ec779b8eSAndroid Build Coastguard Worker                 timeUs, option, colorFormat, metaOnly);
119*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
120*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
121*ec779b8eSAndroid Build Coastguard Worker         data.writeInt64(timeUs);
122*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(option);
123*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(colorFormat);
124*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(metaOnly);
125*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(GET_FRAME_AT_TIME, data, &reply);
126*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
127*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
128*ec779b8eSAndroid Build Coastguard Worker             return NULL;
129*ec779b8eSAndroid Build Coastguard Worker         }
130*ec779b8eSAndroid Build Coastguard Worker         return interface_cast<IMemory>(reply.readStrongBinder());
131*ec779b8eSAndroid Build Coastguard Worker     }
132*ec779b8eSAndroid Build Coastguard Worker 
getImageAtIndex(int index,int colorFormat,bool metaOnly,bool thumbnail)133*ec779b8eSAndroid Build Coastguard Worker     sp<IMemory> getImageAtIndex(int index, int colorFormat, bool metaOnly, bool thumbnail)
134*ec779b8eSAndroid Build Coastguard Worker     {
135*ec779b8eSAndroid Build Coastguard Worker         ALOGV("getImageAtIndex: index %d, colorFormat(%d) metaOnly(%d) thumbnail(%d)",
136*ec779b8eSAndroid Build Coastguard Worker                 index, colorFormat, metaOnly, thumbnail);
137*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
138*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
139*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(index);
140*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(colorFormat);
141*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(metaOnly);
142*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(thumbnail);
143*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(GET_IMAGE_AT_INDEX, data, &reply);
144*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
145*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
146*ec779b8eSAndroid Build Coastguard Worker             return NULL;
147*ec779b8eSAndroid Build Coastguard Worker         }
148*ec779b8eSAndroid Build Coastguard Worker         return interface_cast<IMemory>(reply.readStrongBinder());
149*ec779b8eSAndroid Build Coastguard Worker     }
150*ec779b8eSAndroid Build Coastguard Worker 
getImageRectAtIndex(int index,int colorFormat,int left,int top,int right,int bottom)151*ec779b8eSAndroid Build Coastguard Worker     sp<IMemory> getImageRectAtIndex(
152*ec779b8eSAndroid Build Coastguard Worker             int index, int colorFormat, int left, int top, int right, int bottom)
153*ec779b8eSAndroid Build Coastguard Worker     {
154*ec779b8eSAndroid Build Coastguard Worker         ALOGV("getImageRectAtIndex: index %d, colorFormat(%d) rect {%d, %d, %d, %d}",
155*ec779b8eSAndroid Build Coastguard Worker                 index, colorFormat, left, top, right, bottom);
156*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
157*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
158*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(index);
159*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(colorFormat);
160*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(left);
161*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(top);
162*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(right);
163*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(bottom);
164*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(GET_IMAGE_RECT_AT_INDEX, data, &reply);
165*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
166*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
167*ec779b8eSAndroid Build Coastguard Worker             return NULL;
168*ec779b8eSAndroid Build Coastguard Worker         }
169*ec779b8eSAndroid Build Coastguard Worker         return interface_cast<IMemory>(reply.readStrongBinder());
170*ec779b8eSAndroid Build Coastguard Worker     }
171*ec779b8eSAndroid Build Coastguard Worker 
getFrameAtIndex(int index,int colorFormat,bool metaOnly)172*ec779b8eSAndroid Build Coastguard Worker     sp<IMemory> getFrameAtIndex(
173*ec779b8eSAndroid Build Coastguard Worker             int index, int colorFormat, bool metaOnly)
174*ec779b8eSAndroid Build Coastguard Worker     {
175*ec779b8eSAndroid Build Coastguard Worker         ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
176*ec779b8eSAndroid Build Coastguard Worker                 index, colorFormat, metaOnly);
177*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
178*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
179*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(index);
180*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(colorFormat);
181*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(metaOnly);
182*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
183*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
184*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
185*ec779b8eSAndroid Build Coastguard Worker             return NULL;
186*ec779b8eSAndroid Build Coastguard Worker         }
187*ec779b8eSAndroid Build Coastguard Worker         return interface_cast<IMemory>(reply.readStrongBinder());
188*ec779b8eSAndroid Build Coastguard Worker     }
189*ec779b8eSAndroid Build Coastguard Worker 
extractAlbumArt()190*ec779b8eSAndroid Build Coastguard Worker     sp<IMemory> extractAlbumArt()
191*ec779b8eSAndroid Build Coastguard Worker     {
192*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
193*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
194*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
195*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
196*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
197*ec779b8eSAndroid Build Coastguard Worker             return NULL;
198*ec779b8eSAndroid Build Coastguard Worker         }
199*ec779b8eSAndroid Build Coastguard Worker         return interface_cast<IMemory>(reply.readStrongBinder());
200*ec779b8eSAndroid Build Coastguard Worker     }
201*ec779b8eSAndroid Build Coastguard Worker 
extractMetadata(int keyCode)202*ec779b8eSAndroid Build Coastguard Worker     const char* extractMetadata(int keyCode)
203*ec779b8eSAndroid Build Coastguard Worker     {
204*ec779b8eSAndroid Build Coastguard Worker         Parcel data, reply;
205*ec779b8eSAndroid Build Coastguard Worker         data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
206*ec779b8eSAndroid Build Coastguard Worker         data.writeInt32(keyCode);
207*ec779b8eSAndroid Build Coastguard Worker         remote()->transact(EXTRACT_METADATA, data, &reply);
208*ec779b8eSAndroid Build Coastguard Worker         status_t ret = reply.readInt32();
209*ec779b8eSAndroid Build Coastguard Worker         if (ret != NO_ERROR) {
210*ec779b8eSAndroid Build Coastguard Worker             return NULL;
211*ec779b8eSAndroid Build Coastguard Worker         }
212*ec779b8eSAndroid Build Coastguard Worker         const char* str = reply.readCString();
213*ec779b8eSAndroid Build Coastguard Worker         if (str != NULL) {
214*ec779b8eSAndroid Build Coastguard Worker             String8 value(str);
215*ec779b8eSAndroid Build Coastguard Worker             if (mMetadata.indexOfKey(keyCode) < 0) {
216*ec779b8eSAndroid Build Coastguard Worker                 mMetadata.add(keyCode, value);
217*ec779b8eSAndroid Build Coastguard Worker             } else {
218*ec779b8eSAndroid Build Coastguard Worker                 mMetadata.replaceValueFor(keyCode, value);
219*ec779b8eSAndroid Build Coastguard Worker             }
220*ec779b8eSAndroid Build Coastguard Worker             return mMetadata.valueFor(keyCode).c_str();
221*ec779b8eSAndroid Build Coastguard Worker         } else {
222*ec779b8eSAndroid Build Coastguard Worker             return NULL;
223*ec779b8eSAndroid Build Coastguard Worker         }
224*ec779b8eSAndroid Build Coastguard Worker     }
225*ec779b8eSAndroid Build Coastguard Worker 
226*ec779b8eSAndroid Build Coastguard Worker private:
227*ec779b8eSAndroid Build Coastguard Worker     KeyedVector<int, String8> mMetadata;
228*ec779b8eSAndroid Build Coastguard Worker };
229*ec779b8eSAndroid Build Coastguard Worker 
230*ec779b8eSAndroid Build Coastguard Worker IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
231*ec779b8eSAndroid Build Coastguard Worker 
232*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------
233*ec779b8eSAndroid Build Coastguard Worker 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)234*ec779b8eSAndroid Build Coastguard Worker status_t BnMediaMetadataRetriever::onTransact(
235*ec779b8eSAndroid Build Coastguard Worker     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
236*ec779b8eSAndroid Build Coastguard Worker {
237*ec779b8eSAndroid Build Coastguard Worker     switch (code) {
238*ec779b8eSAndroid Build Coastguard Worker         case DISCONNECT: {
239*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
240*ec779b8eSAndroid Build Coastguard Worker             disconnect();
241*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
242*ec779b8eSAndroid Build Coastguard Worker         } break;
243*ec779b8eSAndroid Build Coastguard Worker         case SET_DATA_SOURCE_URL: {
244*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
245*ec779b8eSAndroid Build Coastguard Worker 
246*ec779b8eSAndroid Build Coastguard Worker             sp<IMediaHTTPService> httpService;
247*ec779b8eSAndroid Build Coastguard Worker             if (data.readInt32()) {
248*ec779b8eSAndroid Build Coastguard Worker                 httpService =
249*ec779b8eSAndroid Build Coastguard Worker                     interface_cast<IMediaHTTPService>(data.readStrongBinder());
250*ec779b8eSAndroid Build Coastguard Worker             }
251*ec779b8eSAndroid Build Coastguard Worker 
252*ec779b8eSAndroid Build Coastguard Worker             const char* srcUrl = data.readCString();
253*ec779b8eSAndroid Build Coastguard Worker 
254*ec779b8eSAndroid Build Coastguard Worker             if (httpService == NULL || srcUrl == NULL) {
255*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(BAD_VALUE);
256*ec779b8eSAndroid Build Coastguard Worker                 return NO_ERROR;
257*ec779b8eSAndroid Build Coastguard Worker             }
258*ec779b8eSAndroid Build Coastguard Worker 
259*ec779b8eSAndroid Build Coastguard Worker             KeyedVector<String8, String8> headers;
260*ec779b8eSAndroid Build Coastguard Worker             size_t numHeaders = (size_t) data.readInt32();
261*ec779b8eSAndroid Build Coastguard Worker             for (size_t i = 0; i < numHeaders; ++i) {
262*ec779b8eSAndroid Build Coastguard Worker                 String8 key;
263*ec779b8eSAndroid Build Coastguard Worker                 String8 value;
264*ec779b8eSAndroid Build Coastguard Worker                 status_t status;
265*ec779b8eSAndroid Build Coastguard Worker                 status = data.readString8(&key);
266*ec779b8eSAndroid Build Coastguard Worker                 if (status != OK) {
267*ec779b8eSAndroid Build Coastguard Worker                     return status;
268*ec779b8eSAndroid Build Coastguard Worker                 }
269*ec779b8eSAndroid Build Coastguard Worker                 status = data.readString8(&value);
270*ec779b8eSAndroid Build Coastguard Worker                 if (status != OK) {
271*ec779b8eSAndroid Build Coastguard Worker                     return status;
272*ec779b8eSAndroid Build Coastguard Worker                 }
273*ec779b8eSAndroid Build Coastguard Worker                 if (headers.add(key, value) < 0) {
274*ec779b8eSAndroid Build Coastguard Worker                     return UNKNOWN_ERROR;
275*ec779b8eSAndroid Build Coastguard Worker                 }
276*ec779b8eSAndroid Build Coastguard Worker             }
277*ec779b8eSAndroid Build Coastguard Worker 
278*ec779b8eSAndroid Build Coastguard Worker             reply->writeInt32(
279*ec779b8eSAndroid Build Coastguard Worker                     setDataSource(
280*ec779b8eSAndroid Build Coastguard Worker                         httpService, srcUrl, numHeaders > 0 ? &headers : NULL));
281*ec779b8eSAndroid Build Coastguard Worker 
282*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
283*ec779b8eSAndroid Build Coastguard Worker         } break;
284*ec779b8eSAndroid Build Coastguard Worker         case SET_DATA_SOURCE_FD: {
285*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
286*ec779b8eSAndroid Build Coastguard Worker             int fd = data.readFileDescriptor();
287*ec779b8eSAndroid Build Coastguard Worker             int64_t offset = data.readInt64();
288*ec779b8eSAndroid Build Coastguard Worker             int64_t length = data.readInt64();
289*ec779b8eSAndroid Build Coastguard Worker             reply->writeInt32(setDataSource(fd, offset, length));
290*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
291*ec779b8eSAndroid Build Coastguard Worker         } break;
292*ec779b8eSAndroid Build Coastguard Worker         case SET_DATA_SOURCE_CALLBACK: {
293*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
294*ec779b8eSAndroid Build Coastguard Worker             sp<IDataSource> source =
295*ec779b8eSAndroid Build Coastguard Worker                 interface_cast<IDataSource>(data.readStrongBinder());
296*ec779b8eSAndroid Build Coastguard Worker             if (source == NULL) {
297*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(BAD_VALUE);
298*ec779b8eSAndroid Build Coastguard Worker             } else {
299*ec779b8eSAndroid Build Coastguard Worker                 int32_t hasMime = data.readInt32();
300*ec779b8eSAndroid Build Coastguard Worker                 const char *mime = NULL;
301*ec779b8eSAndroid Build Coastguard Worker                 if (hasMime) {
302*ec779b8eSAndroid Build Coastguard Worker                     mime = data.readCString();
303*ec779b8eSAndroid Build Coastguard Worker                 }
304*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(setDataSource(source, mime));
305*ec779b8eSAndroid Build Coastguard Worker             }
306*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
307*ec779b8eSAndroid Build Coastguard Worker         } break;
308*ec779b8eSAndroid Build Coastguard Worker         case GET_FRAME_AT_TIME: {
309*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
310*ec779b8eSAndroid Build Coastguard Worker             int64_t timeUs = data.readInt64();
311*ec779b8eSAndroid Build Coastguard Worker             int option = data.readInt32();
312*ec779b8eSAndroid Build Coastguard Worker             int colorFormat = data.readInt32();
313*ec779b8eSAndroid Build Coastguard Worker             bool metaOnly = (data.readInt32() != 0);
314*ec779b8eSAndroid Build Coastguard Worker             ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
315*ec779b8eSAndroid Build Coastguard Worker                     timeUs, option, colorFormat, metaOnly);
316*ec779b8eSAndroid Build Coastguard Worker             sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
317*ec779b8eSAndroid Build Coastguard Worker             if (bitmap != 0) {  // Don't send NULL across the binder interface
318*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
319*ec779b8eSAndroid Build Coastguard Worker                 reply->writeStrongBinder(IInterface::asBinder(bitmap));
320*ec779b8eSAndroid Build Coastguard Worker             } else {
321*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
322*ec779b8eSAndroid Build Coastguard Worker             }
323*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
324*ec779b8eSAndroid Build Coastguard Worker         } break;
325*ec779b8eSAndroid Build Coastguard Worker         case GET_IMAGE_AT_INDEX: {
326*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
327*ec779b8eSAndroid Build Coastguard Worker             int index = data.readInt32();
328*ec779b8eSAndroid Build Coastguard Worker             int colorFormat = data.readInt32();
329*ec779b8eSAndroid Build Coastguard Worker             bool metaOnly = (data.readInt32() != 0);
330*ec779b8eSAndroid Build Coastguard Worker             bool thumbnail = (data.readInt32() != 0);
331*ec779b8eSAndroid Build Coastguard Worker             ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
332*ec779b8eSAndroid Build Coastguard Worker                     index, colorFormat, metaOnly, thumbnail);
333*ec779b8eSAndroid Build Coastguard Worker             sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
334*ec779b8eSAndroid Build Coastguard Worker             if (bitmap != 0) {  // Don't send NULL across the binder interface
335*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
336*ec779b8eSAndroid Build Coastguard Worker                 reply->writeStrongBinder(IInterface::asBinder(bitmap));
337*ec779b8eSAndroid Build Coastguard Worker             } else {
338*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
339*ec779b8eSAndroid Build Coastguard Worker             }
340*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
341*ec779b8eSAndroid Build Coastguard Worker         } break;
342*ec779b8eSAndroid Build Coastguard Worker 
343*ec779b8eSAndroid Build Coastguard Worker         case GET_IMAGE_RECT_AT_INDEX: {
344*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
345*ec779b8eSAndroid Build Coastguard Worker             int index = data.readInt32();
346*ec779b8eSAndroid Build Coastguard Worker             int colorFormat = data.readInt32();
347*ec779b8eSAndroid Build Coastguard Worker             int left = data.readInt32();
348*ec779b8eSAndroid Build Coastguard Worker             int top = data.readInt32();
349*ec779b8eSAndroid Build Coastguard Worker             int right = data.readInt32();
350*ec779b8eSAndroid Build Coastguard Worker             int bottom = data.readInt32();
351*ec779b8eSAndroid Build Coastguard Worker             ALOGV("getImageRectAtIndex: index(%d), colorFormat(%d), rect {%d, %d, %d, %d}",
352*ec779b8eSAndroid Build Coastguard Worker                     index, colorFormat, left, top, right, bottom);
353*ec779b8eSAndroid Build Coastguard Worker             sp<IMemory> bitmap = getImageRectAtIndex(
354*ec779b8eSAndroid Build Coastguard Worker                     index, colorFormat, left, top, right, bottom);
355*ec779b8eSAndroid Build Coastguard Worker             if (bitmap != 0) {  // Don't send NULL across the binder interface
356*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
357*ec779b8eSAndroid Build Coastguard Worker                 reply->writeStrongBinder(IInterface::asBinder(bitmap));
358*ec779b8eSAndroid Build Coastguard Worker             } else {
359*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
360*ec779b8eSAndroid Build Coastguard Worker             }
361*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
362*ec779b8eSAndroid Build Coastguard Worker         } break;
363*ec779b8eSAndroid Build Coastguard Worker 
364*ec779b8eSAndroid Build Coastguard Worker         case GET_FRAME_AT_INDEX: {
365*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
366*ec779b8eSAndroid Build Coastguard Worker             int index = data.readInt32();
367*ec779b8eSAndroid Build Coastguard Worker             int colorFormat = data.readInt32();
368*ec779b8eSAndroid Build Coastguard Worker             bool metaOnly = (data.readInt32() != 0);
369*ec779b8eSAndroid Build Coastguard Worker             ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
370*ec779b8eSAndroid Build Coastguard Worker                     index, colorFormat, metaOnly);
371*ec779b8eSAndroid Build Coastguard Worker             sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
372*ec779b8eSAndroid Build Coastguard Worker             if (frame != nullptr) {  // Don't send NULL across the binder interface
373*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
374*ec779b8eSAndroid Build Coastguard Worker                 reply->writeStrongBinder(IInterface::asBinder(frame));
375*ec779b8eSAndroid Build Coastguard Worker             } else {
376*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
377*ec779b8eSAndroid Build Coastguard Worker             }
378*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
379*ec779b8eSAndroid Build Coastguard Worker         } break;
380*ec779b8eSAndroid Build Coastguard Worker         case EXTRACT_ALBUM_ART: {
381*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
382*ec779b8eSAndroid Build Coastguard Worker             sp<IMemory> albumArt = extractAlbumArt();
383*ec779b8eSAndroid Build Coastguard Worker             if (albumArt != 0) {  // Don't send NULL across the binder interface
384*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
385*ec779b8eSAndroid Build Coastguard Worker                 reply->writeStrongBinder(IInterface::asBinder(albumArt));
386*ec779b8eSAndroid Build Coastguard Worker             } else {
387*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
388*ec779b8eSAndroid Build Coastguard Worker             }
389*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
390*ec779b8eSAndroid Build Coastguard Worker         } break;
391*ec779b8eSAndroid Build Coastguard Worker         case EXTRACT_METADATA: {
392*ec779b8eSAndroid Build Coastguard Worker             CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
393*ec779b8eSAndroid Build Coastguard Worker             int keyCode = data.readInt32();
394*ec779b8eSAndroid Build Coastguard Worker             const char* value = extractMetadata(keyCode);
395*ec779b8eSAndroid Build Coastguard Worker             if (value != NULL) {  // Don't send NULL across the binder interface
396*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(NO_ERROR);
397*ec779b8eSAndroid Build Coastguard Worker                 reply->writeCString(value);
398*ec779b8eSAndroid Build Coastguard Worker             } else {
399*ec779b8eSAndroid Build Coastguard Worker                 reply->writeInt32(UNKNOWN_ERROR);
400*ec779b8eSAndroid Build Coastguard Worker             }
401*ec779b8eSAndroid Build Coastguard Worker             return NO_ERROR;
402*ec779b8eSAndroid Build Coastguard Worker         } break;
403*ec779b8eSAndroid Build Coastguard Worker         default:
404*ec779b8eSAndroid Build Coastguard Worker             return BBinder::onTransact(code, data, reply, flags);
405*ec779b8eSAndroid Build Coastguard Worker     }
406*ec779b8eSAndroid Build Coastguard Worker }
407*ec779b8eSAndroid Build Coastguard Worker 
408*ec779b8eSAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
409*ec779b8eSAndroid Build Coastguard Worker 
410*ec779b8eSAndroid Build Coastguard Worker } // namespace android
411