1 /*
2  * Copyright (C) 2014, The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdint.h>
18 #include <sys/types.h>
19 
20 #include <binder/Parcel.h>
21 #include <media/stagefright/MediaCodecList.h>
22 #include <media/IMediaCodecList.h>
23 #include <media/MediaCodecInfo.h>
24 
25 #include <utils/Errors.h>  // for status_t
26 
27 namespace android {
28 
29 enum {
30     CREATE = IBinder::FIRST_CALL_TRANSACTION,
31     COUNT_CODECS,
32     GET_CODEC_INFO,
33     GET_GLOBAL_SETTINGS,
34     FIND_CODEC_BY_TYPE,
35     FIND_CODEC_BY_NAME,
36 };
37 
38 class BpMediaCodecList: public BpInterface<IMediaCodecList>
39 {
40 public:
BpMediaCodecList(const sp<IBinder> & impl)41     explicit BpMediaCodecList(const sp<IBinder>& impl)
42         : BpInterface<IMediaCodecList>(impl)
43     {
44     }
45 
countCodecs() const46     virtual size_t countCodecs() const
47     {
48         Parcel data, reply;
49         data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
50         remote()->transact(COUNT_CODECS, data, &reply);
51         return static_cast<size_t>(reply.readInt32());
52     }
53 
getCodecInfo(size_t index) const54     virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const
55     {
56         Parcel data, reply;
57         data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
58         data.writeInt32(index);
59         remote()->transact(GET_CODEC_INFO, data, &reply);
60         status_t err = reply.readInt32();
61         if (err == OK) {
62             return MediaCodecInfo::FromParcel(reply);
63         } else {
64             return NULL;
65         }
66     }
67 
getGlobalSettings() const68     virtual const sp<AMessage> getGlobalSettings() const
69     {
70         Parcel data, reply;
71         data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
72         remote()->transact(GET_GLOBAL_SETTINGS, data, &reply);
73         status_t err = reply.readInt32();
74         if (err == OK) {
75             return AMessage::FromParcel(reply);
76         } else {
77             return NULL;
78         }
79     }
80 
findCodecByType(const char * type,bool encoder,size_t startIndex=0) const81     virtual ssize_t findCodecByType(
82             const char *type, bool encoder, size_t startIndex = 0) const
83     {
84         if (startIndex > INT32_MAX) {
85             return NAME_NOT_FOUND;
86         }
87 
88         Parcel data, reply;
89         data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
90         data.writeCString(type);
91         data.writeInt32(encoder);
92         data.writeInt32(startIndex);
93         remote()->transact(FIND_CODEC_BY_TYPE, data, &reply);
94         return static_cast<ssize_t>(reply.readInt32());
95     }
96 
findCodecByName(const char * name) const97     virtual ssize_t findCodecByName(const char *name) const
98     {
99         Parcel data, reply;
100         data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
101         data.writeCString(name);
102         remote()->transact(FIND_CODEC_BY_NAME, data, &reply);
103         return static_cast<ssize_t>(reply.readInt32());
104     }
105 };
106 
107 IMPLEMENT_META_INTERFACE(MediaCodecList, "android.media.IMediaCodecList");
108 
109 // ----------------------------------------------------------------------
110 
onTransact(uint32_t code,const Parcel & data,Parcel * reply,uint32_t flags)111 status_t BnMediaCodecList::onTransact(
112     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
113 {
114     switch (code) {
115         case COUNT_CODECS:
116         {
117             CHECK_INTERFACE(IMediaCodecList, data, reply);
118             size_t count = countCodecs();
119             if (count > INT32_MAX) {
120                 count = INT32_MAX;
121             }
122             reply->writeInt32(count);
123             return NO_ERROR;
124         }
125         break;
126 
127         case GET_CODEC_INFO:
128         {
129             CHECK_INTERFACE(IMediaCodecList, data, reply);
130             size_t index = static_cast<size_t>(data.readInt32());
131             const sp<MediaCodecInfo> info = getCodecInfo(index);
132             if (info != NULL) {
133                 reply->writeInt32(OK);
134                 info->writeToParcel(reply);
135             } else {
136                 reply->writeInt32(-ERANGE);
137             }
138             return NO_ERROR;
139         }
140         break;
141 
142         case GET_GLOBAL_SETTINGS:
143         {
144             CHECK_INTERFACE(IMediaCodecList, data, reply);
145             const sp<AMessage> info = getGlobalSettings();
146             if (info != NULL) {
147                 reply->writeInt32(OK);
148                 info->writeToParcel(reply);
149             } else {
150                 reply->writeInt32(-ERANGE);
151             }
152             return NO_ERROR;
153         }
154         break;
155 
156         case FIND_CODEC_BY_TYPE:
157         {
158             CHECK_INTERFACE(IMediaCodecList, data, reply);
159             const char *type = data.readCString();
160             if (type == NULL) {
161                 reply->writeInt32(NAME_NOT_FOUND);
162                 return NO_ERROR;
163             }
164             bool isEncoder = static_cast<bool>(data.readInt32());
165             size_t startIndex = static_cast<size_t>(data.readInt32());
166             ssize_t index = findCodecByType(type, isEncoder, startIndex);
167             if (index > INT32_MAX || index < 0) {
168                 index = NAME_NOT_FOUND;
169             }
170             reply->writeInt32(index);
171             return NO_ERROR;
172         }
173         break;
174 
175         case FIND_CODEC_BY_NAME:
176         {
177             CHECK_INTERFACE(IMediaCodecList, data, reply);
178             const char *name = data.readCString();
179             if (name == NULL) {
180                 reply->writeInt32(NAME_NOT_FOUND);
181                 return NO_ERROR;
182             }
183             ssize_t index = findCodecByName(name);
184             if (index > INT32_MAX || index < 0) {
185                 index = NAME_NOT_FOUND;
186             }
187             reply->writeInt32(index);
188             return NO_ERROR;
189         }
190         break;
191 
192         default:
193             return BBinder::onTransact(code, data, reply, flags);
194     }
195 }
196 
197 // ----------------------------------------------------------------------------
198 
199 } // namespace android
200