/*
 * Copyright (C) 2009 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.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "BpMediaSource"
#include <utils/Log.h>

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

#include <binder/Parcel.h>
#include <media/IMediaSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>

namespace android {

enum {
    START = IBinder::FIRST_CALL_TRANSACTION,
    STOP,
    PAUSE,
    GETFORMAT,
    READ,
    READMULTIPLE,
    RELEASE_BUFFER
};

enum {
    NULL_BUFFER,
    SHARED_BUFFER,
    INLINE_BUFFER
};

class RemoteMediaBufferReleaser : public BBinder {
public:
    RemoteMediaBufferReleaser(MediaBuffer *buf, sp<BnMediaSource> owner) {
        mBuf = buf;
        mOwner = owner;
    }
    ~RemoteMediaBufferReleaser() {
        if (mBuf) {
            ALOGW("RemoteMediaBufferReleaser dtor called while still holding buffer");
            mBuf->release();
        }
    }
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0) {
        if (code == RELEASE_BUFFER) {
            mBuf->release();
            mBuf = NULL;
            return OK;
        } else {
            return BBinder::onTransact(code, data, reply, flags);
        }
    }
private:
    MediaBuffer *mBuf;
    // Keep a ref to ensure MediaBuffer is released before the owner, i.e., BnMediaSource,
    // because BnMediaSource needs to delete MediaBufferGroup in its dtor and
    // MediaBufferGroup dtor requires all MediaBuffer's have 0 ref count.
    sp<BnMediaSource> mOwner;
};


class RemoteMediaBufferWrapper : public MediaBuffer {
public:
    RemoteMediaBufferWrapper(sp<IMemory> mem, sp<IBinder> source);
protected:
    virtual ~RemoteMediaBufferWrapper();
private:
    sp<IMemory> mMemory;
    sp<IBinder> mRemoteSource;
};

RemoteMediaBufferWrapper::RemoteMediaBufferWrapper(sp<IMemory> mem, sp<IBinder> source)
: MediaBuffer(mem->pointer(), mem->size()) {
    mMemory = mem;
    mRemoteSource = source;
}

RemoteMediaBufferWrapper::~RemoteMediaBufferWrapper() {
    mMemory.clear();
    // Explicitly ask the remote side to release the buffer. We could also just clear
    // mRemoteSource, but that doesn't immediately release the reference on the remote side.
    Parcel data, reply;
    mRemoteSource->transact(RELEASE_BUFFER, data, &reply);
    mRemoteSource.clear();
}

class BpMediaSource : public BpInterface<IMediaSource> {
public:
    BpMediaSource(const sp<IBinder>& impl)
        : BpInterface<IMediaSource>(impl)
    {
    }

    virtual status_t start(MetaData *params) {
        ALOGV("start");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        if (params) {
            params->writeToParcel(data);
        }
        status_t ret = remote()->transact(START, data, &reply);
        if (ret == NO_ERROR && params) {
            ALOGW("ignoring potentially modified MetaData from start");
            ALOGW("input:");
            params->dumpToLog();
            sp<MetaData> meta = MetaData::createFromParcel(reply);
            ALOGW("output:");
            meta->dumpToLog();
        }
        return ret;
    }

    virtual status_t stop() {
        ALOGV("stop");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        return remote()->transact(STOP, data, &reply);
    }

    virtual sp<MetaData> getFormat() {
        ALOGV("getFormat");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        status_t ret = remote()->transact(GETFORMAT, data, &reply);
        if (ret == NO_ERROR) {
            mMetaData = MetaData::createFromParcel(reply);
            return mMetaData;
        }
        return NULL;
    }

    virtual status_t read(MediaBuffer **buffer, const ReadOptions *options) {
        ALOGV("read");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        if (options) {
            data.writeByteArray(sizeof(*options), (uint8_t*) options);
        }
        status_t ret = remote()->transact(READ, data, &reply);
        if (ret != NO_ERROR) {
            return ret;
        }
        // wrap the returned data in a MediaBuffer
        ret = reply.readInt32();
        int32_t buftype = reply.readInt32();
        if (buftype == SHARED_BUFFER) {
            sp<IBinder> remote = reply.readStrongBinder();
            sp<IBinder> binder = reply.readStrongBinder();
            sp<IMemory> mem = interface_cast<IMemory>(binder);
            if (mem == NULL) {
                ALOGE("received NULL IMemory for shared buffer");
            }
            size_t offset = reply.readInt32();
            size_t length = reply.readInt32();
            MediaBuffer *buf = new RemoteMediaBufferWrapper(mem, remote);
            buf->set_range(offset, length);
            buf->meta_data()->updateFromParcel(reply);
            *buffer = buf;
        } else if (buftype == NULL_BUFFER) {
            ALOGV("got status %d and NULL buffer", ret);
            *buffer = NULL;
        } else {
            int32_t len = reply.readInt32();
            ALOGV("got status %d and len %d", ret, len);
            *buffer = new MediaBuffer(len);
            reply.read((*buffer)->data(), len);
            (*buffer)->meta_data()->updateFromParcel(reply);
        }
        return ret;
    }

    virtual status_t readMultiple(Vector<MediaBuffer *> *buffers, uint32_t maxNumBuffers) {
        ALOGV("readMultiple");
        if (buffers == NULL || !buffers->isEmpty()) {
            return BAD_VALUE;
        }
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        data.writeUint32(maxNumBuffers);
        status_t ret = remote()->transact(READMULTIPLE, data, &reply);
        if (ret != NO_ERROR) {
            return ret;
        }
        // wrap the returned data in a vector of MediaBuffers
        int32_t bufCount = 0;
        while (1) {
            if (reply.readInt32() == 0) {
                break;
            }
            int32_t len = reply.readInt32();
            ALOGV("got len %d", len);
            MediaBuffer *buf = new MediaBuffer(len);
            reply.read(buf->data(), len);
            buf->meta_data()->updateFromParcel(reply);
            buffers->push_back(buf);
            ++bufCount;
        }
        ret = reply.readInt32();
        ALOGV("got status %d, bufCount %d", ret, bufCount);
        return ret;
    }

    bool supportReadMultiple() {
        return true;
    }

    virtual status_t pause() {
        ALOGV("pause");
        Parcel data, reply;
        data.writeInterfaceToken(BpMediaSource::getInterfaceDescriptor());
        return remote()->transact(PAUSE, data, &reply);
    }

    virtual status_t setBuffers(const Vector<MediaBuffer *> & buffers __unused) {
        ALOGV("setBuffers NOT IMPLEMENTED");
        return ERROR_UNSUPPORTED; // default
    }

private:
    // NuPlayer passes pointers-to-metadata around, so we use this to keep the metadata alive
    // XXX: could we use this for caching, or does metadata change on the fly?
    sp<MetaData> mMetaData;

};

IMPLEMENT_META_INTERFACE(MediaSource, "android.media.IMediaSource");

#undef LOG_TAG
#define LOG_TAG "BnMediaSource"

BnMediaSource::BnMediaSource()
    : mGroup(NULL) {
}

BnMediaSource::~BnMediaSource() {
    delete mGroup;
    mGroup = NULL;
}

status_t BnMediaSource::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch (code) {
        case START: {
            ALOGV("start");
            CHECK_INTERFACE(IMediaSource, data, reply);
            sp<MetaData> meta;
            if (data.dataAvail()) {
                meta = MetaData::createFromParcel(data);
            }
            status_t ret = start(meta.get());
            if (ret == NO_ERROR && meta != NULL) {
                meta->writeToParcel(*reply);
            }
            return ret;
        }
        case STOP: {
            ALOGV("stop");
            CHECK_INTERFACE(IMediaSource, data, reply);
            return stop();
        }
        case PAUSE: {
            ALOGV("pause");
            CHECK_INTERFACE(IMediaSource, data, reply);
            return pause();
        }
        case GETFORMAT: {
            ALOGV("getFormat");
            CHECK_INTERFACE(IMediaSource, data, reply);
            sp<MetaData> meta = getFormat();
            if (meta != NULL) {
                meta->writeToParcel(*reply);
                return NO_ERROR;
            }
            return UNKNOWN_ERROR;
        }
        case READ: {
            ALOGV("read");
            CHECK_INTERFACE(IMediaSource, data, reply);
            status_t ret;
            MediaBuffer *buf = NULL;
            ReadOptions opts;
            uint32_t len;
            if (data.readUint32(&len) == NO_ERROR &&
                    len == sizeof(opts) && data.read((void*)&opts, len) == NO_ERROR) {
                ret = read(&buf, &opts);
            } else {
                ret = read(&buf, NULL);
            }

            reply->writeInt32(ret);
            if (buf != NULL) {
                size_t usedSize = buf->range_length();
                // even if we're using shared memory, we might not want to use it, since for small
                // sizes it's faster to copy data through the Binder transaction
                // On the other hand, if the data size is large enough, it's better to use shared
                // memory. When data is too large, binder can't handle it.
                if (usedSize >= MediaBuffer::kSharedMemThreshold) {
                    ALOGV("use shared memory: %zu", usedSize);

                    MediaBuffer *transferBuf = buf;
                    size_t offset = buf->range_offset();
                    if (transferBuf->mMemory == NULL) {
                        if (mGroup == NULL) {
                            mGroup = new MediaBufferGroup;
                            size_t allocateSize = usedSize;
                            if (usedSize < SIZE_MAX / 3) {
                                allocateSize = usedSize * 3 / 2;
                            }
                            mGroup->add_buffer(new MediaBuffer(allocateSize));
                        }

                        MediaBuffer *newBuf = NULL;
                        ret = mGroup->acquire_buffer(
                                &newBuf, false /* nonBlocking */, usedSize);
                        if (ret != OK || newBuf == NULL || newBuf->mMemory == NULL) {
                            ALOGW("failed to acquire shared memory, ret %d", ret);
                            buf->release();
                            if (newBuf != NULL) {
                                newBuf->release();
                            }
                            reply->writeInt32(NULL_BUFFER);
                            return NO_ERROR;
                        }
                        transferBuf = newBuf;
                        memcpy(transferBuf->data(), (uint8_t*)buf->data() + buf->range_offset(),
                                buf->range_length());
                        offset = 0;
                    }

                    reply->writeInt32(SHARED_BUFFER);
                    RemoteMediaBufferReleaser *wrapper =
                        new RemoteMediaBufferReleaser(transferBuf, this);
                    reply->writeStrongBinder(wrapper);
                    reply->writeStrongBinder(IInterface::asBinder(transferBuf->mMemory));
                    reply->writeInt32(offset);
                    reply->writeInt32(usedSize);
                    buf->meta_data()->writeToParcel(*reply);
                    if (buf->mMemory == NULL) {
                        buf->release();
                    }
                } else {
                    // buffer is small: copy it
                    if (buf->mMemory != NULL) {
                        ALOGV("%zu shared mem available, but only %zu used", buf->mMemory->size(), buf->range_length());
                    }
                    reply->writeInt32(INLINE_BUFFER);
                    reply->writeByteArray(buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
                    buf->meta_data()->writeToParcel(*reply);
                    buf->release();
                }
            } else {
                ALOGV("ret %d, buf %p", ret, buf);
                reply->writeInt32(NULL_BUFFER);
            }
            return NO_ERROR;
        }
        case READMULTIPLE: {
            ALOGV("readmultiple");
            CHECK_INTERFACE(IMediaSource, data, reply);
            uint32_t maxNumBuffers;
            data.readUint32(&maxNumBuffers);
            status_t ret = NO_ERROR;
            uint32_t bufferCount = 0;
            if (maxNumBuffers > kMaxNumReadMultiple) {
                maxNumBuffers = kMaxNumReadMultiple;
            }
            while (bufferCount < maxNumBuffers) {
                if (reply->dataSize() >= MediaBuffer::kSharedMemThreshold) {
                    break;
                }

                MediaBuffer *buf = NULL;
                ret = read(&buf, NULL);
                if (ret != NO_ERROR || buf == NULL) {
                    break;
                }
                ++bufferCount;
                reply->writeInt32(1);  // indicate one more MediaBuffer.
                reply->writeByteArray(
                        buf->range_length(), (uint8_t*)buf->data() + buf->range_offset());
                buf->meta_data()->writeToParcel(*reply);
                buf->release();
            }
            reply->writeInt32(0);  // indicate no more MediaBuffer.
            reply->writeInt32(ret);
            return NO_ERROR;
        }
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

////////////////////////////////////////////////////////////////////////////////

IMediaSource::ReadOptions::ReadOptions() {
    reset();
}

void IMediaSource::ReadOptions::reset() {
    mOptions = 0;
    mSeekTimeUs = 0;
    mLatenessUs = 0;
    mNonBlocking = false;
}

void IMediaSource::ReadOptions::setNonBlocking() {
    mNonBlocking = true;
}

void IMediaSource::ReadOptions::clearNonBlocking() {
    mNonBlocking = false;
}

bool IMediaSource::ReadOptions::getNonBlocking() const {
    return mNonBlocking;
}

void IMediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
    mOptions |= kSeekTo_Option;
    mSeekTimeUs = time_us;
    mSeekMode = mode;
}

void IMediaSource::ReadOptions::clearSeekTo() {
    mOptions &= ~kSeekTo_Option;
    mSeekTimeUs = 0;
    mSeekMode = SEEK_CLOSEST_SYNC;
}

bool IMediaSource::ReadOptions::getSeekTo(
        int64_t *time_us, SeekMode *mode) const {
    *time_us = mSeekTimeUs;
    *mode = mSeekMode;
    return (mOptions & kSeekTo_Option) != 0;
}

void IMediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
    mLatenessUs = lateness_us;
}

int64_t IMediaSource::ReadOptions::getLateBy() const {
    return mLatenessUs;
}


}  // namespace android

