/*
 * 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.
 */

#ifndef MEDIA_BUFFER_H_

#define MEDIA_BUFFER_H_

#include <atomic>
#include <list>
#include <media/stagefright/foundation/MediaBufferBase.h>

#include <pthread.h>

#include <binder/MemoryDealer.h>
#include <utils/Errors.h>
#include <utils/RefBase.h>

namespace android {

struct ABuffer;
class GraphicBuffer;
class MediaBuffer;
class MediaBufferObserver;
class MetaData;

class MediaBufferObserver {
public:
    MediaBufferObserver() {}
    virtual ~MediaBufferObserver() {}

    virtual void signalBufferReturned(MediaBuffer *buffer) = 0;

private:
    MediaBufferObserver(const MediaBufferObserver &);
    MediaBufferObserver &operator=(const MediaBufferObserver &);
};

class MediaBuffer : public MediaBufferBase {
public:
    // allocations larger than or equal to this will use shared memory.
    static const size_t kSharedMemThreshold = 64 * 1024;

    // The underlying data remains the responsibility of the caller!
    MediaBuffer(void *data, size_t size);

    explicit MediaBuffer(size_t size);

    explicit MediaBuffer(const sp<GraphicBuffer>& graphicBuffer);

    explicit MediaBuffer(const sp<ABuffer> &buffer);

    MediaBuffer(const sp<IMemory> &mem) :
        MediaBuffer((uint8_t *)mem->pointer() + sizeof(SharedControl), mem->size()) {
        // delegate and override mMemory
        mMemory = mem;
    }

    // If MediaBufferGroup is set, decrement the local reference count;
    // if the local reference count drops to 0, return the buffer to the
    // associated MediaBufferGroup.
    //
    // If no MediaBufferGroup is set, the local reference count must be zero
    // when called, whereupon the MediaBuffer is deleted.
    virtual void release();

    // Increments the local reference count.
    // Use only when MediaBufferGroup is set.
    virtual void add_ref();

    void *data() const;
    size_t size() const;

    size_t range_offset() const;
    size_t range_length() const;

    void set_range(size_t offset, size_t length);

    sp<GraphicBuffer> graphicBuffer() const;

    sp<MetaData> meta_data();

    // Clears meta data and resets the range to the full extent.
    void reset();

    void setObserver(MediaBufferObserver *group);

    // Returns a clone of this MediaBuffer increasing its reference count.
    // The clone references the same data but has its own range and
    // MetaData.
    MediaBuffer *clone();

    // sum of localRefcount() and remoteRefcount()
    int refcount() const {
        return localRefcount() + remoteRefcount();
    }

    int localRefcount() const {
        return mRefCount;
    }

    int remoteRefcount() const {
        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
        int32_t remoteRefcount =
                reinterpret_cast<SharedControl *>(mMemory->pointer())->getRemoteRefcount();
        // Sanity check so that remoteRefCount() is non-negative.
        return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
    }

    // returns old value
    int addRemoteRefcount(int32_t value) {
        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
        return reinterpret_cast<SharedControl *>(mMemory->pointer())->addRemoteRefcount(value);
    }

    bool isDeadObject() const {
        return isDeadObject(mMemory);
    }

    static bool isDeadObject(const sp<IMemory> &memory) {
        if (memory.get() == nullptr || memory->pointer() == nullptr) return false;
        return reinterpret_cast<SharedControl *>(memory->pointer())->isDeadObject();
    }

    // Sticky on enabling of shared memory MediaBuffers. By default we don't use
    // shared memory for MediaBuffers, but we enable this for those processes
    // that export MediaBuffers.
    static void useSharedMemory() {
        std::atomic_store_explicit(
                &mUseSharedMemory, (int_least32_t)1, std::memory_order_seq_cst);
    }

protected:
    // true if MediaBuffer is observed (part of a MediaBufferGroup).
    inline bool isObserved() const {
        return mObserver != nullptr;
    }

    virtual ~MediaBuffer();

    sp<IMemory> mMemory;

private:
    friend class MediaBufferGroup;
    friend class OMXDecoder;
    friend class BnMediaSource;
    friend class BpMediaSource;

    // For use by OMXDecoder, reference count must be 1, drop reference
    // count to 0 without signalling the observer.
    void claim();

    MediaBufferObserver *mObserver;
    int mRefCount;

    void *mData;
    size_t mSize, mRangeOffset, mRangeLength;
    sp<GraphicBuffer> mGraphicBuffer;
    sp<ABuffer> mBuffer;

    bool mOwnsData;

    sp<MetaData> mMetaData;

    MediaBuffer *mOriginal;

    static std::atomic_int_least32_t mUseSharedMemory;

    MediaBuffer(const MediaBuffer &);
    MediaBuffer &operator=(const MediaBuffer &);

    // SharedControl block at the start of IMemory.
    struct SharedControl {
        enum {
            FLAG_DEAD_OBJECT = (1 << 0),
        };

        // returns old value
        inline int32_t addRemoteRefcount(int32_t value) {
            return std::atomic_fetch_add_explicit(
                    &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
        }

        inline int32_t getRemoteRefcount() const {
            return std::atomic_load_explicit(&mRemoteRefcount, std::memory_order_seq_cst);
        }

        inline void setRemoteRefcount(int32_t value) {
            std::atomic_store_explicit(
                    &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
        }

        inline bool isDeadObject() const {
            return (std::atomic_load_explicit(
                    &mFlags, std::memory_order_seq_cst) & FLAG_DEAD_OBJECT) != 0;
        }

        inline void setDeadObject() {
            (void)std::atomic_fetch_or_explicit(
                    &mFlags, (int_least32_t)FLAG_DEAD_OBJECT, std::memory_order_seq_cst);
        }

        inline void clear() {
            std::atomic_store_explicit(
                    &mFlags, (int_least32_t)0, std::memory_order_seq_cst);
            std::atomic_store_explicit(
                    &mRemoteRefcount, (int_least32_t)0, std::memory_order_seq_cst);
        }

    private:
        // Caution: atomic_int_fast32_t is 64 bits on LP64.
        std::atomic_int_least32_t mFlags;
        std::atomic_int_least32_t mRemoteRefcount;
        int32_t unused[6] __attribute__((__unused__)); // additional buffer space
    };

    inline SharedControl *getSharedControl() const {
         return reinterpret_cast<SharedControl *>(mMemory->pointer());
     }
};

}  // namespace android

#endif  // MEDIA_BUFFER_H_
