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 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