• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
31 namespace android {
32 
33 struct ABuffer;
34 class MediaBuffer;
35 class MediaBufferObserver;
36 class MetaDataBase;
37 
38 class MediaBuffer : public MediaBufferBase {
39 public:
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 #ifndef NO_IMEMORY
MediaBuffer(const sp<IMemory> & mem)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 #endif
56 
57     // If MediaBufferGroup is set, decrement the local reference count;
58     // if the local reference count drops to 0, return the buffer to the
59     // associated MediaBufferGroup.
60     //
61     // If no MediaBufferGroup is set, the local reference count must be zero
62     // when called, whereupon the MediaBuffer is deleted.
63     virtual void release();
64 
65     // Increments the local reference count.
66     // Use only when MediaBufferGroup is set.
67     virtual void add_ref();
68 
69     virtual void *data() const;
70     virtual size_t size() const;
71 
72     virtual size_t range_offset() const;
73     virtual size_t range_length() const;
74 
75     virtual void set_range(size_t offset, size_t length);
76 
77     MetaDataBase& meta_data();
78 
79     // Clears meta data and resets the range to the full extent.
80     virtual void reset();
81 
82     virtual void setObserver(MediaBufferObserver *group);
83 
84     // sum of localRefcount() and remoteRefcount()
85     // Result should be treated as approximate unless the result precludes concurrent accesses.
refcount()86     virtual int refcount() const {
87         return localRefcount() + remoteRefcount();
88     }
89 
90     // Result should be treated as approximate unless the result precludes concurrent accesses.
localRefcount()91     virtual int localRefcount() const {
92         return mRefCount.load(std::memory_order_relaxed);
93     }
94 
remoteRefcount()95     virtual int remoteRefcount() const {
96 #ifndef NO_IMEMORY
97         if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
98         int32_t remoteRefcount =
99                 reinterpret_cast<SharedControl *>(mMemory->pointer())->getRemoteRefcount();
100         // Sanity check so that remoteRefCount() is non-negative.
101         return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
102 #else
103         return 0;
104 #endif
105     }
106 
107     // returns old value
addRemoteRefcount(int32_t value)108     int addRemoteRefcount(int32_t value) {
109 #ifndef NO_IMEMORY
110         if (mMemory.get() == nullptr || mMemory->pointer() == nullptr) return 0;
111         return reinterpret_cast<SharedControl *>(mMemory->pointer())->addRemoteRefcount(value);
112 #else
113         (void) value;
114         return 0;
115 #endif
116     }
117 
isDeadObject()118     bool isDeadObject() const {
119         return isDeadObject(mMemory);
120     }
121 
isDeadObject(const sp<IMemory> & memory)122     static bool isDeadObject(const sp<IMemory> &memory) {
123 #ifndef NO_IMEMORY
124         if (memory.get() == nullptr || memory->pointer() == nullptr) return false;
125         return reinterpret_cast<SharedControl *>(memory->pointer())->isDeadObject();
126 #else
127         (void) memory;
128         return false;
129 #endif
130     }
131 
132     // Sticky on enabling of shared memory MediaBuffers. By default we don't use
133     // shared memory for MediaBuffers, but we enable this for those processes
134     // that export MediaBuffers.
useSharedMemory()135     static void useSharedMemory() {
136         std::atomic_store_explicit(
137                 &mUseSharedMemory, (int_least32_t)1, std::memory_order_seq_cst);
138     }
139 
140 protected:
141     // true if MediaBuffer is observed (part of a MediaBufferGroup).
isObserved()142     inline bool isObserved() const {
143         return mObserver != nullptr;
144     }
145 
146     virtual ~MediaBuffer();
147 
148     sp<IMemory> mMemory;
149 
150 private:
151     friend class MediaBufferGroup;
152     friend class OMXDecoder;
153     friend class BnMediaSource;
154     friend class BpMediaSource;
155 
156     // For use by OMXDecoder, reference count must be 1, drop reference
157     // count to 0 without signalling the observer.
158     void claim();
159 
160     MediaBufferObserver *mObserver;
161     std::atomic<int> mRefCount;
162 
163     void *mData;
164     size_t mSize, mRangeOffset, mRangeLength;
165     sp<ABuffer> mBuffer;
166 
167     bool mOwnsData;
168 
169     MetaDataBase* mMetaData;
170 
171     static std::atomic_int_least32_t mUseSharedMemory;
172 
173     MediaBuffer(const MediaBuffer &);
174     MediaBuffer &operator=(const MediaBuffer &);
175 
176     // SharedControl block at the start of IMemory.
177     struct SharedControl {
178         enum {
179             FLAG_DEAD_OBJECT = (1 << 0),
180         };
181 
182         // returns old value
addRemoteRefcountSharedControl183         inline int32_t addRemoteRefcount(int32_t value) {
184             return std::atomic_fetch_add_explicit(
185                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
186         }
187 
getRemoteRefcountSharedControl188         inline int32_t getRemoteRefcount() const {
189             return std::atomic_load_explicit(&mRemoteRefcount, std::memory_order_seq_cst);
190         }
191 
setRemoteRefcountSharedControl192         inline void setRemoteRefcount(int32_t value) {
193             std::atomic_store_explicit(
194                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
195         }
196 
isDeadObjectSharedControl197         inline bool isDeadObject() const {
198             return (std::atomic_load_explicit(
199                     &mFlags, std::memory_order_seq_cst) & FLAG_DEAD_OBJECT) != 0;
200         }
201 
setDeadObjectSharedControl202         inline void setDeadObject() {
203             (void)std::atomic_fetch_or_explicit(
204                     &mFlags, (int_least32_t)FLAG_DEAD_OBJECT, std::memory_order_seq_cst);
205         }
206 
clearSharedControl207         inline void clear() {
208             std::atomic_store_explicit(
209                     &mFlags, (int_least32_t)0, std::memory_order_seq_cst);
210             std::atomic_store_explicit(
211                     &mRemoteRefcount, (int_least32_t)0, std::memory_order_seq_cst);
212         }
213 
214     private:
215         // Caution: atomic_int_fast32_t is 64 bits on LP64.
216         std::atomic_int_least32_t mFlags;
217         std::atomic_int_least32_t mRemoteRefcount;
218         int32_t unused[6] __attribute__((__unused__)); // additional buffer space
219     };
220 
getSharedControl()221     inline SharedControl *getSharedControl() const {
222 #ifndef NO_IMEMORY
223          return reinterpret_cast<SharedControl *>(mMemory->pointer());
224 #else
225          return nullptr;
226 #endif
227      }
228 };
229 
230 }  // namespace android
231 
232 #endif  // MEDIA_BUFFER_H_
233