blob: 86427ede163a24125cf05e196e3f875bac38fe24 [file] [log] [blame]
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -08001/*
2**
3** Copyright (C) 2008 The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
Mark Salyzyn34fb2962014-06-18 16:30:56 -070018#include <inttypes.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080019#include <stdint.h>
20#include <sys/types.h>
Mark Salyzyn34fb2962014-06-18 16:30:56 -070021
Marco Nelissendab79b32019-11-18 08:25:47 -080022#include <android/IDataSource.h>
Mathias Agopian75624082009-05-19 19:08:10 -070023#include <binder/Parcel.h>
Andreas Huber1b86fe02014-01-29 11:13:26 -080024#include <media/IMediaHTTPService.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080025#include <media/IMediaMetadataRetriever.h>
Suren Baghdasaryan7435e7d2018-12-19 17:09:28 -080026#include <processgroup/sched_policy.h>
Andreas Huberaf8791e2011-03-21 10:25:44 -070027#include <utils/String8.h>
Sangkyu Leed01c1482013-02-08 16:26:39 +090028#include <utils/KeyedVector.h>
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080029
30namespace android {
31
32enum {
33 DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
34 SET_DATA_SOURCE_URL,
35 SET_DATA_SOURCE_FD,
Chris Watkins99f31602015-03-20 13:06:33 -070036 SET_DATA_SOURCE_CALLBACK,
James Dong16afe2f2010-12-02 17:42:08 -080037 GET_FRAME_AT_TIME,
Chong Zhangd3e0d862017-10-03 13:17:13 -070038 GET_IMAGE_AT_INDEX,
Chong Zhang0c1407f2018-05-02 17:09:05 -070039 GET_IMAGE_RECT_AT_INDEX,
Chong Zhangd3e0d862017-10-03 13:17:13 -070040 GET_FRAME_AT_INDEX,
Dave Sparksec4dde72009-11-23 16:51:15 -080041 EXTRACT_ALBUM_ART,
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080042 EXTRACT_METADATA,
43};
44
45class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
46{
47public:
Chih-Hung Hsieh090ef602016-04-27 10:39:54 -070048 explicit BpMediaMetadataRetriever(const sp<IBinder>& impl)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080049 : BpInterface<IMediaMetadataRetriever>(impl)
50 {
51 }
52
53 // disconnect from media metadata retriever service
54 void disconnect()
55 {
56 Parcel data, reply;
57 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
58 remote()->transact(DISCONNECT, data, &reply);
59 }
60
Andreas Huberaf8791e2011-03-21 10:25:44 -070061 status_t setDataSource(
Andreas Huber1b86fe02014-01-29 11:13:26 -080062 const sp<IMediaHTTPService> &httpService,
63 const char *srcUrl,
64 const KeyedVector<String8, String8> *headers)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080065 {
66 Parcel data, reply;
67 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Andreas Huber1b86fe02014-01-29 11:13:26 -080068 data.writeInt32(httpService != NULL);
69 if (httpService != NULL) {
Marco Nelissen06b46062014-11-14 07:58:25 -080070 data.writeStrongBinder(IInterface::asBinder(httpService));
Andreas Huber1b86fe02014-01-29 11:13:26 -080071 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080072 data.writeCString(srcUrl);
Andreas Huberaf8791e2011-03-21 10:25:44 -070073
74 if (headers == NULL) {
75 data.writeInt32(0);
76 } else {
77 // serialize the headers
Ray Essick9c9fdf62019-05-14 12:04:42 -070078 data.writeInt32(headers->size());
Andreas Huberaf8791e2011-03-21 10:25:44 -070079 for (size_t i = 0; i < headers->size(); ++i) {
80 data.writeString8(headers->keyAt(i));
81 data.writeString8(headers->valueAt(i));
82 }
83 }
84
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -080085 remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
86 return reply.readInt32();
87 }
88
89 status_t setDataSource(int fd, int64_t offset, int64_t length)
90 {
91 Parcel data, reply;
92 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
93 data.writeFileDescriptor(fd);
94 data.writeInt64(offset);
95 data.writeInt64(length);
96 remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
97 return reply.readInt32();
98 }
99
Chong Zhang24c15772017-07-26 16:25:28 -0700100 status_t setDataSource(const sp<IDataSource>& source, const char *mime)
Chris Watkins99f31602015-03-20 13:06:33 -0700101 {
102 Parcel data, reply;
103 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
104 data.writeStrongBinder(IInterface::asBinder(source));
Chong Zhang24c15772017-07-26 16:25:28 -0700105
106 if (mime != NULL) {
107 data.writeInt32(1);
108 data.writeCString(mime);
109 } else {
110 data.writeInt32(0);
111 }
Chris Watkins99f31602015-03-20 13:06:33 -0700112 remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply);
113 return reply.readInt32();
114 }
115
Chong Zhang24c15772017-07-26 16:25:28 -0700116 sp<IMemory> getFrameAtTime(int64_t timeUs, int option, int colorFormat, bool metaOnly)
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800117 {
Chong Zhang24c15772017-07-26 16:25:28 -0700118 ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d) metaOnly(%d)",
119 timeUs, option, colorFormat, metaOnly);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800120 Parcel data, reply;
121 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
James Dong16afe2f2010-12-02 17:42:08 -0800122 data.writeInt64(timeUs);
123 data.writeInt32(option);
Chong Zhang24c15772017-07-26 16:25:28 -0700124 data.writeInt32(colorFormat);
125 data.writeInt32(metaOnly);
James Dong16afe2f2010-12-02 17:42:08 -0800126 remote()->transact(GET_FRAME_AT_TIME, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800127 status_t ret = reply.readInt32();
128 if (ret != NO_ERROR) {
129 return NULL;
130 }
131 return interface_cast<IMemory>(reply.readStrongBinder());
132 }
133
Chong Zhangd5fa3572018-04-09 19:03:10 -0700134 sp<IMemory> getImageAtIndex(int index, int colorFormat, bool metaOnly, bool thumbnail)
Chong Zhangd3e0d862017-10-03 13:17:13 -0700135 {
Chong Zhangd5fa3572018-04-09 19:03:10 -0700136 ALOGV("getImageAtIndex: index %d, colorFormat(%d) metaOnly(%d) thumbnail(%d)",
137 index, colorFormat, metaOnly, thumbnail);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700138 Parcel data, reply;
139 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
140 data.writeInt32(index);
141 data.writeInt32(colorFormat);
142 data.writeInt32(metaOnly);
Chong Zhangd5fa3572018-04-09 19:03:10 -0700143 data.writeInt32(thumbnail);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700144 remote()->transact(GET_IMAGE_AT_INDEX, data, &reply);
145 status_t ret = reply.readInt32();
146 if (ret != NO_ERROR) {
147 return NULL;
148 }
149 return interface_cast<IMemory>(reply.readStrongBinder());
150 }
151
Chong Zhang0c1407f2018-05-02 17:09:05 -0700152 sp<IMemory> getImageRectAtIndex(
153 int index, int colorFormat, int left, int top, int right, int bottom)
154 {
155 ALOGV("getImageRectAtIndex: index %d, colorFormat(%d) rect {%d, %d, %d, %d}",
156 index, colorFormat, left, top, right, bottom);
157 Parcel data, reply;
158 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
159 data.writeInt32(index);
160 data.writeInt32(colorFormat);
161 data.writeInt32(left);
162 data.writeInt32(top);
163 data.writeInt32(right);
164 data.writeInt32(bottom);
Chong Zhang0c1407f2018-05-02 17:09:05 -0700165 remote()->transact(GET_IMAGE_RECT_AT_INDEX, data, &reply);
166 status_t ret = reply.readInt32();
167 if (ret != NO_ERROR) {
168 return NULL;
169 }
170 return interface_cast<IMemory>(reply.readStrongBinder());
171 }
172
Chong Zhang76a49d62019-07-12 11:20:33 -0700173 sp<IMemory> getFrameAtIndex(
174 int index, int colorFormat, bool metaOnly)
Chong Zhangd3e0d862017-10-03 13:17:13 -0700175 {
Chong Zhang76a49d62019-07-12 11:20:33 -0700176 ALOGV("getFrameAtIndex: index(%d), colorFormat(%d) metaOnly(%d)",
177 index, colorFormat, metaOnly);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700178 Parcel data, reply;
179 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Chong Zhang76a49d62019-07-12 11:20:33 -0700180 data.writeInt32(index);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700181 data.writeInt32(colorFormat);
182 data.writeInt32(metaOnly);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700183 remote()->transact(GET_FRAME_AT_INDEX, data, &reply);
184 status_t ret = reply.readInt32();
185 if (ret != NO_ERROR) {
Chong Zhang76a49d62019-07-12 11:20:33 -0700186 return NULL;
Chong Zhangd3e0d862017-10-03 13:17:13 -0700187 }
Chong Zhang76a49d62019-07-12 11:20:33 -0700188 return interface_cast<IMemory>(reply.readStrongBinder());
Chong Zhangd3e0d862017-10-03 13:17:13 -0700189 }
190
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800191 sp<IMemory> extractAlbumArt()
192 {
193 Parcel data, reply;
194 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
Dave Sparksec4dde72009-11-23 16:51:15 -0800195 remote()->transact(EXTRACT_ALBUM_ART, data, &reply);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800196 status_t ret = reply.readInt32();
197 if (ret != NO_ERROR) {
198 return NULL;
199 }
200 return interface_cast<IMemory>(reply.readStrongBinder());
201 }
202
203 const char* extractMetadata(int keyCode)
204 {
205 Parcel data, reply;
206 data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
207 data.writeInt32(keyCode);
208 remote()->transact(EXTRACT_METADATA, data, &reply);
209 status_t ret = reply.readInt32();
210 if (ret != NO_ERROR) {
211 return NULL;
212 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900213 const char* str = reply.readCString();
214 if (str != NULL) {
215 String8 value(str);
216 if (mMetadata.indexOfKey(keyCode) < 0) {
217 mMetadata.add(keyCode, value);
218 } else {
219 mMetadata.replaceValueFor(keyCode, value);
220 }
221 return mMetadata.valueFor(keyCode).string();
222 } else {
223 return NULL;
224 }
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800225 }
Sangkyu Leed01c1482013-02-08 16:26:39 +0900226
227private:
228 KeyedVector<int, String8> mMetadata;
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800229};
230
niko56f0cc52009-06-22 08:49:52 -0700231IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.media.IMediaMetadataRetriever");
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800232
233// ----------------------------------------------------------------------
234
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800235status_t BnMediaMetadataRetriever::onTransact(
236 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
237{
238 switch (code) {
239 case DISCONNECT: {
240 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
241 disconnect();
242 return NO_ERROR;
243 } break;
244 case SET_DATA_SOURCE_URL: {
245 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Andreas Huber1b86fe02014-01-29 11:13:26 -0800246
247 sp<IMediaHTTPService> httpService;
248 if (data.readInt32()) {
249 httpService =
250 interface_cast<IMediaHTTPService>(data.readStrongBinder());
251 }
252
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800253 const char* srcUrl = data.readCString();
Andreas Huberaf8791e2011-03-21 10:25:44 -0700254
Wei Jia2afac0c2016-01-07 12:13:07 -0800255 if (httpService == NULL || srcUrl == NULL) {
256 reply->writeInt32(BAD_VALUE);
257 return NO_ERROR;
258 }
259
Andreas Huberaf8791e2011-03-21 10:25:44 -0700260 KeyedVector<String8, String8> headers;
Ray Essick9c9fdf62019-05-14 12:04:42 -0700261 size_t numHeaders = (size_t) data.readInt32();
Glenn Kastene03dd222014-01-28 11:04:39 -0800262 for (size_t i = 0; i < numHeaders; ++i) {
Ray Essick9c9fdf62019-05-14 12:04:42 -0700263 String8 key;
264 String8 value;
265 status_t status;
266 status = data.readString8(&key);
267 if (status != OK) {
268 return status;
269 }
270 status = data.readString8(&value);
271 if (status != OK) {
272 return status;
273 }
274 if (headers.add(key, value) < 0) {
275 return UNKNOWN_ERROR;
276 }
Andreas Huberaf8791e2011-03-21 10:25:44 -0700277 }
278
279 reply->writeInt32(
Andreas Huber1b86fe02014-01-29 11:13:26 -0800280 setDataSource(
281 httpService, srcUrl, numHeaders > 0 ? &headers : NULL));
Andreas Huberaf8791e2011-03-21 10:25:44 -0700282
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800283 return NO_ERROR;
284 } break;
285 case SET_DATA_SOURCE_FD: {
286 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Taiju Tsuiki55203e22015-04-21 17:36:22 +0900287 int fd = data.readFileDescriptor();
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800288 int64_t offset = data.readInt64();
289 int64_t length = data.readInt64();
290 reply->writeInt32(setDataSource(fd, offset, length));
291 return NO_ERROR;
292 } break;
Chris Watkins99f31602015-03-20 13:06:33 -0700293 case SET_DATA_SOURCE_CALLBACK: {
294 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
295 sp<IDataSource> source =
296 interface_cast<IDataSource>(data.readStrongBinder());
Wei Jia2afac0c2016-01-07 12:13:07 -0800297 if (source == NULL) {
298 reply->writeInt32(BAD_VALUE);
299 } else {
Chong Zhang24c15772017-07-26 16:25:28 -0700300 int32_t hasMime = data.readInt32();
301 const char *mime = NULL;
302 if (hasMime) {
303 mime = data.readCString();
304 }
305 reply->writeInt32(setDataSource(source, mime));
Wei Jia2afac0c2016-01-07 12:13:07 -0800306 }
Chris Watkins99f31602015-03-20 13:06:33 -0700307 return NO_ERROR;
308 } break;
James Dong16afe2f2010-12-02 17:42:08 -0800309 case GET_FRAME_AT_TIME: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800310 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
James Dong16afe2f2010-12-02 17:42:08 -0800311 int64_t timeUs = data.readInt64();
312 int option = data.readInt32();
Chong Zhang24c15772017-07-26 16:25:28 -0700313 int colorFormat = data.readInt32();
314 bool metaOnly = (data.readInt32() != 0);
315 ALOGV("getTimeAtTime: time(%" PRId64 " us), option(%d), colorFormat(%d), metaOnly(%d)",
316 timeUs, option, colorFormat, metaOnly);
Chong Zhang24c15772017-07-26 16:25:28 -0700317 sp<IMemory> bitmap = getFrameAtTime(timeUs, option, colorFormat, metaOnly);
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800318 if (bitmap != 0) { // Don't send NULL across the binder interface
319 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800320 reply->writeStrongBinder(IInterface::asBinder(bitmap));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800321 } else {
322 reply->writeInt32(UNKNOWN_ERROR);
323 }
324 return NO_ERROR;
325 } break;
Chong Zhangd3e0d862017-10-03 13:17:13 -0700326 case GET_IMAGE_AT_INDEX: {
327 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
328 int index = data.readInt32();
329 int colorFormat = data.readInt32();
330 bool metaOnly = (data.readInt32() != 0);
Chong Zhangd5fa3572018-04-09 19:03:10 -0700331 bool thumbnail = (data.readInt32() != 0);
332 ALOGV("getImageAtIndex: index(%d), colorFormat(%d), metaOnly(%d), thumbnail(%d)",
333 index, colorFormat, metaOnly, thumbnail);
Chong Zhangd5fa3572018-04-09 19:03:10 -0700334 sp<IMemory> bitmap = getImageAtIndex(index, colorFormat, metaOnly, thumbnail);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700335 if (bitmap != 0) { // Don't send NULL across the binder interface
336 reply->writeInt32(NO_ERROR);
337 reply->writeStrongBinder(IInterface::asBinder(bitmap));
338 } else {
339 reply->writeInt32(UNKNOWN_ERROR);
340 }
Chong Zhangd3e0d862017-10-03 13:17:13 -0700341 return NO_ERROR;
342 } break;
Chong Zhang0c1407f2018-05-02 17:09:05 -0700343
344 case GET_IMAGE_RECT_AT_INDEX: {
345 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
346 int index = data.readInt32();
347 int colorFormat = data.readInt32();
348 int left = data.readInt32();
349 int top = data.readInt32();
350 int right = data.readInt32();
351 int bottom = data.readInt32();
352 ALOGV("getImageRectAtIndex: index(%d), colorFormat(%d), rect {%d, %d, %d, %d}",
353 index, colorFormat, left, top, right, bottom);
Chong Zhang0c1407f2018-05-02 17:09:05 -0700354 sp<IMemory> bitmap = getImageRectAtIndex(
355 index, colorFormat, left, top, right, bottom);
356 if (bitmap != 0) { // Don't send NULL across the binder interface
357 reply->writeInt32(NO_ERROR);
358 reply->writeStrongBinder(IInterface::asBinder(bitmap));
359 } else {
360 reply->writeInt32(UNKNOWN_ERROR);
361 }
Chong Zhang0c1407f2018-05-02 17:09:05 -0700362 return NO_ERROR;
363 } break;
364
Chong Zhangd3e0d862017-10-03 13:17:13 -0700365 case GET_FRAME_AT_INDEX: {
366 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
Chong Zhang76a49d62019-07-12 11:20:33 -0700367 int index = data.readInt32();
Chong Zhangd3e0d862017-10-03 13:17:13 -0700368 int colorFormat = data.readInt32();
369 bool metaOnly = (data.readInt32() != 0);
Chong Zhang76a49d62019-07-12 11:20:33 -0700370 ALOGV("getFrameAtIndex: index(%d), colorFormat(%d), metaOnly(%d)",
371 index, colorFormat, metaOnly);
Chong Zhang76a49d62019-07-12 11:20:33 -0700372 sp<IMemory> frame = getFrameAtIndex(index, colorFormat, metaOnly);
373 if (frame != nullptr) { // Don't send NULL across the binder interface
374 reply->writeInt32(NO_ERROR);
375 reply->writeStrongBinder(IInterface::asBinder(frame));
376 } else {
377 reply->writeInt32(UNKNOWN_ERROR);
Chong Zhangd3e0d862017-10-03 13:17:13 -0700378 }
Chong Zhangd3e0d862017-10-03 13:17:13 -0700379 return NO_ERROR;
380 } break;
Dave Sparksec4dde72009-11-23 16:51:15 -0800381 case EXTRACT_ALBUM_ART: {
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800382 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
383 sp<IMemory> albumArt = extractAlbumArt();
384 if (albumArt != 0) { // Don't send NULL across the binder interface
385 reply->writeInt32(NO_ERROR);
Marco Nelissen06b46062014-11-14 07:58:25 -0800386 reply->writeStrongBinder(IInterface::asBinder(albumArt));
The Android Open Source Project89fa4ad2009-03-03 19:31:44 -0800387 } else {
388 reply->writeInt32(UNKNOWN_ERROR);
389 }
390 return NO_ERROR;
391 } break;
392 case EXTRACT_METADATA: {
393 CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
394 int keyCode = data.readInt32();
395 const char* value = extractMetadata(keyCode);
396 if (value != NULL) { // Don't send NULL across the binder interface
397 reply->writeInt32(NO_ERROR);
398 reply->writeCString(value);
399 } else {
400 reply->writeInt32(UNKNOWN_ERROR);
401 }
402 return NO_ERROR;
403 } break;
404 default:
405 return BBinder::onTransact(code, data, reply, flags);
406 }
407}
408
409// ----------------------------------------------------------------------------
410
Glenn Kasten40bc9062015-03-20 09:09:33 -0700411} // namespace android