1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef MEDIA_BUFFER_H_
18
19#define MEDIA_BUFFER_H_
20
21#include <atomic>
22#include <list>
23
24#include <pthread.h>
25
26#include <binder/MemoryDealer.h>
27#include <utils/Errors.h>
28#include <utils/RefBase.h>
29#include <media/stagefright/MediaBufferBase.h>
30
31namespace android {
32
33struct ABuffer;
34class MediaBuffer;
35class MediaBufferObserver;
36class MetaDataBase;
37
38class MediaBuffer : public MediaBufferBase {
39public:
40    // allocations larger than or equal to this will use shared memory.
41    static const size_t kSharedMemThreshold = 64 * 1024;
42
43    // The underlying data remains the responsibility of the caller!
44    MediaBuffer(void *data, size_t size);
45
46    explicit MediaBuffer(size_t size);
47
48    explicit MediaBuffer(const sp<ABuffer> &buffer);
49
50    MediaBuffer(const sp<IMemory> &mem) :
51        MediaBuffer((uint8_t *)mem->pointer() + sizeof(SharedControl), mem->size()) {
52        // delegate and override mMemory
53        mMemory = mem;
54    }
55
56    // If MediaBufferGroup is set, decrement the local reference count;
57    // if the local reference count drops to 0, return the buffer to the
58    // associated MediaBufferGroup.
59    //
60    // If no MediaBufferGroup is set, the local reference count must be zero
61    // when called, whereupon the MediaBuffer is deleted.
62    virtual void release();
63
64    // Increments the local reference count.
65    // Use only when MediaBufferGroup is set.
66    virtual void add_ref();
67
68    virtual void *data() const;
69    virtual size_t size() const;
70
71    virtual size_t range_offset() const;
72    virtual size_t range_length() const;
73
74    virtual void set_range(size_t offset, size_t length);
75
76    MetaDataBase& meta_data();
77
78    // Clears meta data and resets the range to the full extent.
79    virtual void reset();
80
81    virtual void setObserver(MediaBufferObserver *group);
82
83    // Returns a clone of this MediaBuffer increasing its reference count.
84    // The clone references the same data but has its own range and
85    // MetaData.
86    virtual MediaBufferBase *clone();
87
88    // sum of localRefcount() and remoteRefcount()
89    virtual int refcount() const {
90        return localRefcount() + remoteRefcount();
91    }
92
93    virtual int localRefcount() const {
94        return mRefCount;
95    }
96
97    virtual int remoteRefcount() const {
98        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
99        int32_t remoteRefcount =
100                reinterpret_cast<SharedControl *>(mMemory->pointer())->getRemoteRefcount();
101        // Sanity check so that remoteRefCount() is non-negative.
102        return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
103    }
104
105    // returns old value
106    int addRemoteRefcount(int32_t value) {
107        if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
108        return reinterpret_cast<SharedControl *>(mMemory->pointer())->addRemoteRefcount(value);
109    }
110
111    bool isDeadObject() const {
112        return isDeadObject(mMemory);
113    }
114
115    static bool isDeadObject(const sp<IMemory> &memory) {
116        if (memory.get() == nullptr || memory->pointer() == nullptr) return false;
117        return reinterpret_cast<SharedControl *>(memory->pointer())->isDeadObject();
118    }
119
120    // Sticky on enabling of shared memory MediaBuffers. By default we don't use
121    // shared memory for MediaBuffers, but we enable this for those processes
122    // that export MediaBuffers.
123    static void useSharedMemory() {
124        std::atomic_store_explicit(
125                &mUseSharedMemory, (int_least32_t)1, std::memory_order_seq_cst);
126    }
127
128protected:
129    // true if MediaBuffer is observed (part of a MediaBufferGroup).
130    inline bool isObserved() const {
131        return mObserver != nullptr;
132    }
133
134    virtual ~MediaBuffer();
135
136    sp<IMemory> mMemory;
137
138private:
139    friend class MediaBufferGroup;
140    friend class OMXDecoder;
141    friend class BnMediaSource;
142    friend class BpMediaSource;
143
144    // For use by OMXDecoder, reference count must be 1, drop reference
145    // count to 0 without signalling the observer.
146    void claim();
147
148    MediaBufferObserver *mObserver;
149    int mRefCount;
150
151    void *mData;
152    size_t mSize, mRangeOffset, mRangeLength;
153    sp<ABuffer> mBuffer;
154
155    bool mOwnsData;
156
157    MetaDataBase* mMetaData;
158
159    MediaBuffer *mOriginal;
160
161    static std::atomic_int_least32_t mUseSharedMemory;
162
163    MediaBuffer(const MediaBuffer &);
164    MediaBuffer &operator=(const MediaBuffer &);
165
166    // SharedControl block at the start of IMemory.
167    struct SharedControl {
168        enum {
169            FLAG_DEAD_OBJECT = (1 << 0),
170        };
171
172        // returns old value
173        inline int32_t addRemoteRefcount(int32_t value) {
174            return std::atomic_fetch_add_explicit(
175                    &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
176        }
177
178        inline int32_t getRemoteRefcount() const {
179            return std::atomic_load_explicit(&mRemoteRefcount, std::memory_order_seq_cst);
180        }
181
182        inline void setRemoteRefcount(int32_t value) {
183            std::atomic_store_explicit(
184                    &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
185        }
186
187        inline bool isDeadObject() const {
188            return (std::atomic_load_explicit(
189                    &mFlags, std::memory_order_seq_cst) & FLAG_DEAD_OBJECT) != 0;
190        }
191
192        inline void setDeadObject() {
193            (void)std::atomic_fetch_or_explicit(
194                    &mFlags, (int_least32_t)FLAG_DEAD_OBJECT, std::memory_order_seq_cst);
195        }
196
197        inline void clear() {
198            std::atomic_store_explicit(
199                    &mFlags, (int_least32_t)0, std::memory_order_seq_cst);
200            std::atomic_store_explicit(
201                    &mRemoteRefcount, (int_least32_t)0, std::memory_order_seq_cst);
202        }
203
204    private:
205        // Caution: atomic_int_fast32_t is 64 bits on LP64.
206        std::atomic_int_least32_t mFlags;
207        std::atomic_int_least32_t mRemoteRefcount;
208        int32_t unused[6] __attribute__((__unused__)); // additional buffer space
209    };
210
211    inline SharedControl *getSharedControl() const {
212         return reinterpret_cast<SharedControl *>(mMemory->pointer());
213     }
214};
215
216}  // namespace android
217
218#endif  // MEDIA_BUFFER_H_
219