Home | History | Annotate | Download | only in libmedia
      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