/*
 * Copyright (C) 2010 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 "NuPlayerStreamListener"
#include <utils/Log.h>

#include "NuPlayerStreamListener.h"

#include <binder/MemoryDealer.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/MediaErrors.h>

namespace android {

NuPlayer::NuPlayerStreamListener::NuPlayerStreamListener(
        const sp<IStreamSource> &source,
        const sp<AHandler> &targetHandler)
    : mSource(source),
      mTargetHandler(targetHandler),
      mEOS(false),
      mSendDataNotification(true) {
    mSource->setListener(this);

    mMemoryDealer = new MemoryDealer(kNumBuffers * kBufferSize);
    for (size_t i = 0; i < kNumBuffers; ++i) {
        sp<IMemory> mem = mMemoryDealer->allocate(kBufferSize);
        CHECK(mem != NULL);

        mBuffers.push(mem);
    }
    mSource->setBuffers(mBuffers);
}

void NuPlayer::NuPlayerStreamListener::start() {
    for (size_t i = 0; i < kNumBuffers; ++i) {
        mSource->onBufferAvailable(i);
    }
}

void NuPlayer::NuPlayerStreamListener::queueBuffer(size_t index, size_t size) {
    QueueEntry entry;
    entry.mIsCommand = false;
    entry.mIndex = index;
    entry.mSize = size;
    entry.mOffset = 0;

    Mutex::Autolock autoLock(mLock);
    mQueue.push_back(entry);

    if (mSendDataNotification) {
        mSendDataNotification = false;

        if (mTargetHandler != NULL) {
            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
        }
    }
}

void NuPlayer::NuPlayerStreamListener::issueCommand(
        Command cmd, bool synchronous, const sp<AMessage> &extra) {
    CHECK(!synchronous);

    QueueEntry entry;
    entry.mIsCommand = true;
    entry.mCommand = cmd;
    entry.mExtra = extra;

    Mutex::Autolock autoLock(mLock);
    mQueue.push_back(entry);

    if (mSendDataNotification) {
        mSendDataNotification = false;

        if (mTargetHandler != NULL) {
            (new AMessage(kWhatMoreDataQueued, mTargetHandler))->post();
        }
    }
}

ssize_t NuPlayer::NuPlayerStreamListener::read(
        void *data, size_t size, sp<AMessage> *extra) {
    CHECK_GT(size, 0u);

    extra->clear();

    Mutex::Autolock autoLock(mLock);

    if (mEOS) {
        return 0;
    }

    if (mQueue.empty()) {
        mSendDataNotification = true;

        return -EWOULDBLOCK;
    }

    QueueEntry *entry = &*mQueue.begin();

    if (entry->mIsCommand) {
        switch (entry->mCommand) {
            case EOS:
            {
                mQueue.erase(mQueue.begin());
                entry = NULL;

                mEOS = true;
                return 0;
            }

            case DISCONTINUITY:
            {
                *extra = entry->mExtra;

                mQueue.erase(mQueue.begin());
                entry = NULL;

                return INFO_DISCONTINUITY;
            }

            default:
                TRESPASS();
                break;
        }
    }

    size_t copy = entry->mSize;
    if (copy > size) {
        copy = size;
    }

    if (entry->mIndex >= mBuffers.size()) {
        return ERROR_MALFORMED;
    }

    sp<IMemory> mem = mBuffers.editItemAt(entry->mIndex);
    if (mem == NULL || mem->size() < copy || mem->size() - copy < entry->mOffset) {
        return ERROR_MALFORMED;
    }

    memcpy(data,
           (const uint8_t *)mem->pointer()
            + entry->mOffset,
           copy);

    entry->mOffset += copy;
    entry->mSize -= copy;

    if (entry->mSize == 0) {
        mSource->onBufferAvailable(entry->mIndex);
        mQueue.erase(mQueue.begin());
        entry = NULL;
    }

    return copy;
}

}  // namespace android
