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: 41 explicit BpMediaCodecList(const sp<IBinder>& impl) 42 : BpInterface<IMediaCodecList>(impl) 43 { 44 } 45 46 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 54 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 68 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 81 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 97 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 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