IMediaMetadataRetriever.cpp revision b7056fc8525e0515c6f46676e3307088f8b64cdc
1/*
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
18#include <stdint.h>
19#include <sys/types.h>
20#include <binder/Parcel.h>
21#include <SkBitmap.h>
22#include <media/IMediaMetadataRetriever.h>
23
24namespace android {
25
26enum {
27    DISCONNECT = IBinder::FIRST_CALL_TRANSACTION,
28    SET_DATA_SOURCE_URL,
29    SET_DATA_SOURCE_FD,
30    SET_MODE,
31    GET_MODE,
32    CAPTURE_FRAME,
33    EXTARCT_ALBUM_ART,
34    EXTRACT_METADATA,
35};
36
37class BpMediaMetadataRetriever: public BpInterface<IMediaMetadataRetriever>
38{
39public:
40    BpMediaMetadataRetriever(const sp<IBinder>& impl)
41        : BpInterface<IMediaMetadataRetriever>(impl)
42    {
43    }
44
45    // disconnect from media metadata retriever service
46    void disconnect()
47    {
48        Parcel data, reply;
49        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
50        remote()->transact(DISCONNECT, data, &reply);
51    }
52
53    status_t setDataSource(const char* srcUrl)
54    {
55        Parcel data, reply;
56        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
57        data.writeCString(srcUrl);
58        remote()->transact(SET_DATA_SOURCE_URL, data, &reply);
59        return reply.readInt32();
60    }
61
62    status_t setDataSource(int fd, int64_t offset, int64_t length)
63    {
64        Parcel data, reply;
65        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
66        data.writeFileDescriptor(fd);
67        data.writeInt64(offset);
68        data.writeInt64(length);
69        remote()->transact(SET_DATA_SOURCE_FD, data, &reply);
70        return reply.readInt32();
71    }
72
73    status_t setMode(int mode)
74    {
75        Parcel data, reply;
76        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
77        data.writeInt32(mode);
78        remote()->transact(SET_MODE, data, &reply);
79        return reply.readInt32();
80    }
81
82    status_t getMode(int* mode) const
83    {
84        Parcel data, reply;
85        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
86        remote()->transact(GET_MODE, data, &reply);
87        *mode = reply.readInt32();
88        return reply.readInt32();
89    }
90
91    sp<IMemory> captureFrame()
92    {
93        Parcel data, reply;
94        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
95        remote()->transact(CAPTURE_FRAME, data, &reply);
96        status_t ret = reply.readInt32();
97        if (ret != NO_ERROR) {
98            return NULL;
99        }
100        return interface_cast<IMemory>(reply.readStrongBinder());
101    }
102
103    sp<IMemory> extractAlbumArt()
104    {
105        Parcel data, reply;
106        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
107        remote()->transact(EXTARCT_ALBUM_ART, data, &reply);
108        status_t ret = reply.readInt32();
109        if (ret != NO_ERROR) {
110            return NULL;
111        }
112        return interface_cast<IMemory>(reply.readStrongBinder());
113    }
114
115    const char* extractMetadata(int keyCode)
116    {
117        Parcel data, reply;
118        data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor());
119        data.writeInt32(keyCode);
120        remote()->transact(EXTRACT_METADATA, data, &reply);
121        status_t ret = reply.readInt32();
122        if (ret != NO_ERROR) {
123            return NULL;
124        }
125        return reply.readCString();
126    }
127};
128
129IMPLEMENT_META_INTERFACE(MediaMetadataRetriever, "android.hardware.IMediaMetadataRetriever");
130
131// ----------------------------------------------------------------------
132
133status_t BnMediaMetadataRetriever::onTransact(
134    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
135{
136    switch (code) {
137        case DISCONNECT: {
138            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
139            disconnect();
140            return NO_ERROR;
141        } break;
142        case SET_DATA_SOURCE_URL: {
143            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
144            const char* srcUrl = data.readCString();
145            reply->writeInt32(setDataSource(srcUrl));
146            return NO_ERROR;
147        } break;
148        case SET_DATA_SOURCE_FD: {
149            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
150            int fd = dup(data.readFileDescriptor());
151            int64_t offset = data.readInt64();
152            int64_t length = data.readInt64();
153            reply->writeInt32(setDataSource(fd, offset, length));
154            return NO_ERROR;
155        } break;
156        case SET_MODE: {
157            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
158            int mode = data.readInt32();
159            reply->writeInt32(setMode(mode));
160            return NO_ERROR;
161        } break;
162        case GET_MODE: {
163            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
164            int mode;
165            status_t status = getMode(&mode);
166            reply->writeInt32(mode);
167            reply->writeInt32(status);
168            return NO_ERROR;
169        } break;
170        case CAPTURE_FRAME: {
171            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
172            sp<IMemory> bitmap = captureFrame();
173            if (bitmap != 0) {  // Don't send NULL across the binder interface
174                reply->writeInt32(NO_ERROR);
175                reply->writeStrongBinder(bitmap->asBinder());
176            } else {
177                reply->writeInt32(UNKNOWN_ERROR);
178            }
179            return NO_ERROR;
180        } break;
181        case EXTARCT_ALBUM_ART: {
182            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
183            sp<IMemory> albumArt = extractAlbumArt();
184            if (albumArt != 0) {  // Don't send NULL across the binder interface
185                reply->writeInt32(NO_ERROR);
186                reply->writeStrongBinder(albumArt->asBinder());
187            } else {
188                reply->writeInt32(UNKNOWN_ERROR);
189            }
190            return NO_ERROR;
191        } break;
192        case EXTRACT_METADATA: {
193            CHECK_INTERFACE(IMediaMetadataRetriever, data, reply);
194            int keyCode = data.readInt32();
195            const char* value = extractMetadata(keyCode);
196            if (value != NULL) {  // Don't send NULL across the binder interface
197                reply->writeInt32(NO_ERROR);
198                reply->writeCString(value);
199            } else {
200                reply->writeInt32(UNKNOWN_ERROR);
201            }
202            return NO_ERROR;
203        } break;
204        default:
205            return BBinder::onTransact(code, data, reply, flags);
206    }
207}
208
209// ----------------------------------------------------------------------------
210
211}; // namespace android
212
213