• 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         return remoteRefcount >= 0 ? remoteRefcount : 0; // do not allow corrupted data.
109 #else
110         return 0;
111 #endif
112     }
113 
114     // returns old value
addRemoteRefcount(int32_t value)115     int addRemoteRefcount(int32_t value) {
116 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
117           // TODO: Using unsecurePointer() has some associated security pitfalls
118          //       (see declaration for details).
119          //       Either document why it is safe in this case or address the
120          //       issue (e.g. by copying).
121        if (mMemory.get() == nullptr || mMemory->unsecurePointer() == nullptr) return 0;
122         return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer())->addRemoteRefcount(value);
123 #else
124         (void) value;
125         return 0;
126 #endif
127     }
128 
isDeadObject()129     bool isDeadObject() const {
130         return isDeadObject(mMemory);
131     }
132 
isDeadObject(const sp<IMemory> & memory)133     static bool isDeadObject(const sp<IMemory> &memory) {
134 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
135          // TODO: Using unsecurePointer() has some associated security pitfalls
136          //       (see declaration for details).
137          //       Either document why it is safe in this case or address the
138          //       issue (e.g. by copying).
139         if (memory.get() == nullptr || memory->unsecurePointer() == nullptr) return false;
140         return reinterpret_cast<SharedControl *>(memory->unsecurePointer())->isDeadObject();
141 #else
142         (void) memory;
143         return false;
144 #endif
145     }
146 
147     // Sticky on enabling of shared memory MediaBuffers. By default we don't use
148     // shared memory for MediaBuffers, but we enable this for those processes
149     // that export MediaBuffers.
useSharedMemory()150     static void useSharedMemory() {
151         std::atomic_store_explicit(
152                 &mUseSharedMemory, (int_least32_t)1, std::memory_order_seq_cst);
153     }
154 
155 protected:
156     // true if MediaBuffer is observed (part of a MediaBufferGroup).
isObserved()157     inline bool isObserved() const {
158         return mObserver != nullptr;
159     }
160 
161     virtual ~MediaBuffer();
162 
163     sp<IMemory> mMemory;
164 
165 private:
166     friend class MediaBufferGroup;
167     friend class OMXDecoder;
168     friend class BnMediaSource;
169     friend class BpMediaSource;
170 
171     // For use by OMXDecoder, reference count must be 1, drop reference
172     // count to 0 without signalling the observer.
173     void claim();
174 
175     MediaBufferObserver *mObserver;
176     std::atomic<int> mRefCount;
177 
178     void *mData;
179     size_t mSize, mRangeOffset, mRangeLength;
180     sp<ABuffer> mBuffer;
181 
182     bool mOwnsData;
183 
184     MetaDataBase* mMetaData;
185 
186     static std::atomic_int_least32_t mUseSharedMemory;
187 
188     MediaBuffer(const MediaBuffer &);
189     MediaBuffer &operator=(const MediaBuffer &);
190 
191     // SharedControl block at the start of IMemory.
192     struct SharedControl {
193         enum {
194             FLAG_DEAD_OBJECT = (1 << 0),
195         };
196 
197         // returns old value
addRemoteRefcountSharedControl198         inline int32_t addRemoteRefcount(int32_t value) {
199             return std::atomic_fetch_add_explicit(
200                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
201         }
202 
getRemoteRefcountSharedControl203         inline int32_t getRemoteRefcount() const {
204             return std::atomic_load_explicit(&mRemoteRefcount, std::memory_order_seq_cst);
205         }
206 
setRemoteRefcountSharedControl207         inline void setRemoteRefcount(int32_t value) {
208             std::atomic_store_explicit(
209                     &mRemoteRefcount, (int_least32_t)value, std::memory_order_seq_cst);
210         }
211 
isDeadObjectSharedControl212         inline bool isDeadObject() const {
213             return (std::atomic_load_explicit(
214                     &mFlags, std::memory_order_seq_cst) & FLAG_DEAD_OBJECT) != 0;
215         }
216 
setDeadObjectSharedControl217         inline void setDeadObject() {
218             (void)std::atomic_fetch_or_explicit(
219                     &mFlags, (int_least32_t)FLAG_DEAD_OBJECT, std::memory_order_seq_cst);
220         }
221 
clearSharedControl222         inline void clear() {
223             std::atomic_store_explicit(
224                     &mFlags, (int_least32_t)0, std::memory_order_seq_cst);
225             std::atomic_store_explicit(
226                     &mRemoteRefcount, (int_least32_t)0, std::memory_order_seq_cst);
227         }
228 
229     private:
230         // Caution: atomic_int_fast32_t is 64 bits on LP64.
231         std::atomic_int_least32_t mFlags;
232         std::atomic_int_least32_t mRemoteRefcount;
233         int32_t unused[6] __attribute__((__unused__)); // additional buffer space
234     };
235 
getSharedControl()236     inline SharedControl *getSharedControl() const {
237 #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
238          // TODO: Using unsecurePointer() has some associated security pitfalls
239          //       (see declaration for details).
240          //       Either document why it is safe in this case or address the
241          //       issue (e.g. by copying).
242          return reinterpret_cast<SharedControl *>(mMemory->unsecurePointer());
243 #else
244          return nullptr;
245 #endif
246      }
247 };
248 
249 }  // namespace android
250 
251 #endif  // MEDIA_BUFFER_H_
252