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 FIND_CODEC_BY_TYPE, 34 FIND_CODEC_BY_NAME, 35 }; 36 37 class BpMediaCodecList: public BpInterface<IMediaCodecList> 38 { 39 public: 40 BpMediaCodecList(const sp<IBinder>& impl) 41 : BpInterface<IMediaCodecList>(impl) 42 { 43 } 44 45 virtual size_t countCodecs() const 46 { 47 Parcel data, reply; 48 data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); 49 remote()->transact(COUNT_CODECS, data, &reply); 50 return static_cast<size_t>(reply.readInt32()); 51 } 52 53 virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const 54 { 55 Parcel data, reply; 56 data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); 57 data.writeInt32(index); 58 remote()->transact(GET_CODEC_INFO, data, &reply); 59 status_t err = reply.readInt32(); 60 if (err == OK) { 61 return MediaCodecInfo::FromParcel(reply); 62 } else { 63 return NULL; 64 } 65 } 66 67 virtual ssize_t findCodecByType( 68 const char *type, bool encoder, size_t startIndex = 0) const 69 { 70 if (startIndex > INT32_MAX) { 71 return NAME_NOT_FOUND; 72 } 73 74 Parcel data, reply; 75 data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); 76 data.writeCString(type); 77 data.writeInt32(encoder); 78 data.writeInt32(startIndex); 79 remote()->transact(FIND_CODEC_BY_TYPE, data, &reply); 80 return static_cast<ssize_t>(reply.readInt32()); 81 } 82 83 virtual ssize_t findCodecByName(const char *name) const 84 { 85 Parcel data, reply; 86 data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor()); 87 data.writeCString(name); 88 remote()->transact(FIND_CODEC_BY_NAME, data, &reply); 89 return static_cast<ssize_t>(reply.readInt32()); 90 } 91 }; 92 93 IMPLEMENT_META_INTERFACE(MediaCodecList, "android.media.IMediaCodecList"); 94 95 // ---------------------------------------------------------------------- 96 97 status_t BnMediaCodecList::onTransact( 98 uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) 99 { 100 switch (code) { 101 case COUNT_CODECS: 102 { 103 CHECK_INTERFACE(IMediaCodecList, data, reply); 104 size_t count = countCodecs(); 105 if (count > INT32_MAX) { 106 count = INT32_MAX; 107 } 108 reply->writeInt32(count); 109 return NO_ERROR; 110 } 111 break; 112 113 case GET_CODEC_INFO: 114 { 115 CHECK_INTERFACE(IMediaCodecList, data, reply); 116 size_t index = static_cast<size_t>(data.readInt32()); 117 const sp<MediaCodecInfo> info = getCodecInfo(index); 118 if (info != NULL) { 119 reply->writeInt32(OK); 120 info->writeToParcel(reply); 121 } else { 122 reply->writeInt32(-ERANGE); 123 } 124 return NO_ERROR; 125 } 126 break; 127 128 case FIND_CODEC_BY_TYPE: 129 { 130 CHECK_INTERFACE(IMediaCodecList, data, reply); 131 const char *type = data.readCString(); 132 bool isEncoder = static_cast<bool>(data.readInt32()); 133 size_t startIndex = static_cast<size_t>(data.readInt32()); 134 ssize_t index = findCodecByType(type, isEncoder, startIndex); 135 if (index > INT32_MAX || index < 0) { 136 index = NAME_NOT_FOUND; 137 } 138 reply->writeInt32(index); 139 return NO_ERROR; 140 } 141 break; 142 143 case FIND_CODEC_BY_NAME: 144 { 145 CHECK_INTERFACE(IMediaCodecList, data, reply); 146 const char *name = data.readCString(); 147 ssize_t index = findCodecByName(name); 148 if (index > INT32_MAX || index < 0) { 149 index = NAME_NOT_FOUND; 150 } 151 reply->writeInt32(index); 152 return NO_ERROR; 153 } 154 break; 155 156 default: 157 return BBinder::onTransact(code, data, reply, flags); 158 } 159 } 160 161 // ---------------------------------------------------------------------------- 162 163 }; // namespace android 164