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