• 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 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
MediaBuffer(const sp<IMemory> & mem)50     MediaBuffer(const sp<IMemory> &mem) :
51          // TODO: Using unsecurePointer() has some associated security pitfalls
52          //       (see declaration for details).
53          //       Either document why it is safe in this case or address the
54          //       issue (e.g. by copying).
55         MediaBuffer((uint8_t *)mem->unsecurePointer() + sizeof(SharedControl), mem->size()) {
56         // delegate and override mMemory
57         mMemory = mem;
58     }
59 #endif
60 
61     // If MediaBufferGroup is set, decrement the local reference count;
62     // if the local reference count drops to 0, return the buffer to the
63     // associated MediaBufferGroup.
64     //
65     // If no MediaBufferGroup is set, the local reference count must be zero
66     // when called, whereupon the MediaBuffer is deleted.
67     virtual void release();
68 
69     // Increments the local reference count.
70     // Use only when MediaBufferGroup is set.
71     virtual void add_ref();
72 
73     virtual void *data() const;
74     virtual size_t size() const;
75 
76     virtual size_t range_offset() const;
77     virtual size_t range_length() const;
78 
79     virtual void set_range(size_t offset, size_t length);
80 
81     MetaDataBase& meta_data();
82 
83     // Clears meta data and resets the range to the full extent.
84     virtual void reset();
85 
86     virtual void setObserver(MediaBufferObserver *group);
87 
88     // sum of localRefcount() and remoteRefcount()
89     // Result should be treated as approximate unless the result precludes concurrent accesses.
refcount()90     virtual int refcount() const {
91         return localRefcount() + remoteRefcount();
92     }
93 
94     // Result should be treated as approximate unless the result precludes concurrent accesses.
localRefcount()95     virtual int localRefcount() const {
96         return mRefCount.load(std::memory_order_relaxed);
97     }
98 
remoteRefcount()99     virtual int remoteRefcount() const {
100 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
101          // TODO: Using unsecurePointer() has some associated security pitfalls
102          //       (see declaration for details).
103          //       Either document why it is safe in this case or address the
104          //       issue (e.g. by copying).
105         if (mMemory.get() == nullptr || mMemory->unsecurePointer() == nullptr) return 0;
106         int32_t remoteRefcount =
107                 reinterpret_cast<SharedControl *>(mMemory->unsecurePointer())->getRemoteRefcount();
108         // Sanity check so that remoteRefCount() is non-negative.
109         return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
110 #else
111         return 0;
112 #endif
113     }
114 
115     // returns old value
addRemoteRefcount(int32_t value)116     int addRemoteRefcount(int32_t value) {
117 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
118           // TODO: Using unsecurePointer() has some associated security pitfalls
119          //       (see declaration for details).
120          //       Either document why it is safe in this case or address the
121          //       issue (e.g. by copying).
122        if (mMemory.get() == nullptr || mMemory->unsecurePointer() == nullptr) return 0;
123         return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer())->addRemoteRefcount(value);
124 #else
125         (void) value;
126         return 0;
127 #endif
128     }
129 
isDeadObject()130     bool isDeadObject() const {
131         return isDeadObject(mMemory);
132     }
133 
isDeadObject(const sp<IMemory> & memory)134     static bool isDeadObject(const sp<IMemory> &memory) {
135 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
136          // TODO: Using unsecurePointer() has some associated security pitfalls
137          //       (see declaration for details).
138          //       Either document why it is safe in this case or address the
139          //       issue (e.g. by copying).
140         if (memory.get() == nullptr || memory->unsecurePointer() == nullptr) return false;
141         return reinterpret_cast<SharedControl *>(memory->unsecurePointer())->isDeadObject();
142 #else
143         (void) memory;
144         return false;
145 #endif
146     }
147 
148     // Sticky on enabling of shared memory MediaBuffers. By default we don't use
149     // shared memory for MediaBuffers, but we enable this for those processes
150     // that export MediaBuffers.
useSharedMemory()151     static void useSharedMemory() {
152         std::atomic_store_explicit(
153                 &mUseSharedMemory, (int_least32_t)1, std::memory_order_seq_cst);
154     }
155 
156 protected:
157     // true if MediaBuffer is observed (part of a MediaBufferGroup).
isObserved()158     inline bool isObserved() const {
159         return mObserver != nullptr;
160     }
161 
162     virtual ~MediaBuffer();
163 
164     sp<IMemory> mMemory;
165 
166 private:
167     friend class MediaBufferGroup;
168     friend class OMXDecoder;
169     friend class BnMediaSource;
170     friend class BpMediaSource;
171 
172     // For use by OMXDecoder, reference count must be 1, drop reference
173     // count to 0 without signalling the observer.
174     void claim();
175 
176     MediaBufferObserver *mObserver;
177     std::atomic<int> mRefCount;
178 
179     void *mData;
180     size_t mSize, mRangeOffset, mRangeLength;
181     sp<ABuffer> mBuffer;
182 
183     bool mOwnsData;
184 
185     MetaDataBase* mMetaData;
186 
187     static std::atomic_int_least32_t mUseSharedMemory;
188 
189     MediaBuffer(const MediaBuffer &);
190     MediaBuffer &operator=(const MediaBuffer &);
191 
192     // SharedControl block at the start of IMemory.
193     struct SharedControl {
194         enum {
195             FLAG_DEAD_OBJECT = (1 << 0),
196         };
197 
198         // returns old value
addRemoteRefcountSharedControl199         inline int32_t addRemoteRefcount(int32_t value) {
200             return std::atomic_fetch_add_explicit(
201                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
202         }
203 
getRemoteRefcountSharedControl204         inline int32_t getRemoteRefcount() const {
205             return std::atomic_load_explicit(&mRemoteRefcount, std::memory_order_seq_cst);
206         }
207 
setRemoteRefcountSharedControl208         inline void setRemoteRefcount(int32_t value) {
209             std::atomic_store_explicit(
210                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
211         }
212 
isDeadObjectSharedControl213         inline bool isDeadObject() const {
214             return (std::atomic_load_explicit(
215                     &mFlags, std::memory_order_seq_cst) & FLAG_DEAD_OBJECT) != 0;
216         }
217 
setDeadObjectSharedControl218         inline void setDeadObject() {
219             (void)std::atomic_fetch_or_explicit(
220                     &mFlags, (int_least32_t)FLAG_DEAD_OBJECT, std::memory_order_seq_cst);
221         }
222 
clearSharedControl223         inline void clear() {
224             std::atomic_store_explicit(
225                     &mFlags, (int_least32_t)0, std::memory_order_seq_cst);
226             std::atomic_store_explicit(
227                     &mRemoteRefcount, (int_least32_t)0, std::memory_order_seq_cst);
228         }
229 
230     private:
231         // Caution: atomic_int_fast32_t is 64 bits on LP64.
232         std::atomic_int_least32_t mFlags;
233         std::atomic_int_least32_t mRemoteRefcount;
234         int32_t unused[6] __attribute__((__unused__)); // additional buffer space
235     };
236 
getSharedControl()237     inline SharedControl *getSharedControl() const {
238 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
239          // TODO: Using unsecurePointer() has some associated security pitfalls
240          //       (see declaration for details).
241          //       Either document why it is safe in this case or address the
242          //       issue (e.g. by copying).
243          return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer());
244 #else
245          return nullptr;
246 #endif
247      }
248 };
249 
250 }  // namespace android
251 
252 #endif  // MEDIA_BUFFER_H_
253