/*
 * Copyright (C) 2014, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdint.h>
#include <sys/types.h>

#include <binder/Parcel.h>
#include <media/stagefright/MediaCodecList.h>
#include <media/IMediaCodecList.h>
#include <media/MediaCodecInfo.h>

#include <utils/Errors.h>  // for status_t

namespace android {

enum {
    CREATE = IBinder::FIRST_CALL_TRANSACTION,
    COUNT_CODECS,
    GET_CODEC_INFO,
    FIND_CODEC_BY_TYPE,
    FIND_CODEC_BY_NAME,
};

class BpMediaCodecList: public BpInterface<IMediaCodecList>
{
public:
    BpMediaCodecList(const sp<IBinder>& impl)
        : BpInterface<IMediaCodecList>(impl)
    {
    }

    virtual size_t countCodecs() const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
        remote()->transact(COUNT_CODECS, data, &reply);
        return static_cast<size_t>(reply.readInt32());
    }

    virtual sp<MediaCodecInfo> getCodecInfo(size_t index) const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
        data.writeInt32(index);
        remote()->transact(GET_CODEC_INFO, data, &reply);
        status_t err = reply.readInt32();
        if (err == OK) {
            return MediaCodecInfo::FromParcel(reply);
        } else {
            return NULL;
        }
    }

    virtual ssize_t findCodecByType(
            const char *type, bool encoder, size_t startIndex = 0) const
    {
        if (startIndex > INT32_MAX) {
            return NAME_NOT_FOUND;
        }

        Parcel data, reply;
        data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
        data.writeCString(type);
        data.writeInt32(encoder);
        data.writeInt32(startIndex);
        remote()->transact(FIND_CODEC_BY_TYPE, data, &reply);
        return static_cast<ssize_t>(reply.readInt32());
    }

    virtual ssize_t findCodecByName(const char *name) const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
        data.writeCString(name);
        remote()->transact(FIND_CODEC_BY_NAME, data, &reply);
        return static_cast<ssize_t>(reply.readInt32());
    }
};

IMPLEMENT_META_INTERFACE(MediaCodecList, "android.media.IMediaCodecList");

// ----------------------------------------------------------------------

status_t BnMediaCodecList::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
        case COUNT_CODECS:
        {
            CHECK_INTERFACE(IMediaCodecList, data, reply);
            size_t count = countCodecs();
            if (count > INT32_MAX) {
                count = INT32_MAX;
            }
            reply->writeInt32(count);
            return NO_ERROR;
        }
        break;

        case GET_CODEC_INFO:
        {
            CHECK_INTERFACE(IMediaCodecList, data, reply);
            size_t index = static_cast<size_t>(data.readInt32());
            const sp<MediaCodecInfo> info = getCodecInfo(index);
            if (info != NULL) {
                reply->writeInt32(OK);
                info->writeToParcel(reply);
            } else {
                reply->writeInt32(-ERANGE);
            }
            return NO_ERROR;
        }
        break;

        case FIND_CODEC_BY_TYPE:
        {
            CHECK_INTERFACE(IMediaCodecList, data, reply);
            const char *type = data.readCString();
            bool isEncoder = static_cast<bool>(data.readInt32());
            size_t startIndex = static_cast<size_t>(data.readInt32());
            ssize_t index = findCodecByType(type, isEncoder, startIndex);
            if (index > INT32_MAX || index < 0) {
                index = NAME_NOT_FOUND;
            }
            reply->writeInt32(index);
            return NO_ERROR;
        }
        break;

        case FIND_CODEC_BY_NAME:
        {
            CHECK_INTERFACE(IMediaCodecList, data, reply);
            const char *name = data.readCString();
            ssize_t index = findCodecByName(name);
            if (index > INT32_MAX || index < 0) {
                index = NAME_NOT_FOUND;
            }
            reply->writeInt32(index);
            return NO_ERROR;
        }
        break;

        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

// ----------------------------------------------------------------------------

}; // namespace android
