/*
 * 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,
    GET_GLOBAL_SETTINGS,
    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 const sp<AMessage> getGlobalSettings() const
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaCodecList::getInterfaceDescriptor());
        remote()->transact(GET_GLOBAL_SETTINGS, data, &reply);
        status_t err = reply.readInt32();
        if (err == OK) {
            return AMessage::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 GET_GLOBAL_SETTINGS:
        {
            CHECK_INTERFACE(IMediaCodecList, data, reply);
            const sp<AMessage> info = getGlobalSettings();
            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();
            if (type == NULL) {
                reply->writeInt32(NAME_NOT_FOUND);
                return NO_ERROR;
            }
            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();
            if (name == NULL) {
                reply->writeInt32(NAME_NOT_FOUND);
                return NO_ERROR;
            }
            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
