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 #define LOG_TAG "MediaBuffer"
18 #include <utils/Log.h>
19
20 #include <errno.h>
21 #include <pthread.h>
22 #include <stdlib.h>
23
24 #include <media/stagefright/foundation/ABuffer.h>
25 #include <media/stagefright/foundation/ADebug.h>
26 #include <media/stagefright/MediaBuffer.h>
27 #include <media/stagefright/MetaData.h>
28
29 namespace android {
30
31 /* static */
32 std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0);
33
MediaBuffer(void * data,size_t size)34 MediaBuffer::MediaBuffer(void *data, size_t size)
35 : mObserver(NULL),
36 mRefCount(0),
37 mData(data),
38 mSize(size),
39 mRangeOffset(0),
40 mRangeLength(size),
41 mOwnsData(false),
42 mMetaData(new MetaDataBase) {
43 }
44
MediaBuffer(size_t size)45 MediaBuffer::MediaBuffer(size_t size)
46 : mObserver(NULL),
47 mRefCount(0),
48 mData(NULL),
49 mSize(size),
50 mRangeOffset(0),
51 mRangeLength(size),
52 mOwnsData(true),
53 mMetaData(new MetaDataBase) {
54 #ifndef NO_IMEMORY
55 if (size < kSharedMemThreshold
56 || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
57 #endif
58 mData = malloc(size);
59 #ifndef NO_IMEMORY
60 } else {
61 ALOGV("creating memoryDealer");
62 size_t newSize = 0;
63 if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) {
64 sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer");
65 mMemory = memoryDealer->allocate(newSize);
66 }
67 if (mMemory == NULL) {
68 ALOGW("Failed to allocate shared memory, trying regular allocation!");
69 mData = malloc(size);
70 if (mData == NULL) {
71 ALOGE("Out of memory");
72 }
73 } else {
74 getSharedControl()->clear();
75 mData = (uint8_t *)mMemory->unsecurePointer() + sizeof(SharedControl);
76 ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
77 }
78 }
79 #endif
80 }
81
MediaBuffer(const sp<ABuffer> & buffer)82 MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
83 : mObserver(NULL),
84 mRefCount(0),
85 mData(buffer->data()),
86 mSize(buffer->size()),
87 mRangeOffset(0),
88 mRangeLength(mSize),
89 mBuffer(buffer),
90 mOwnsData(false),
91 mMetaData(new MetaDataBase) {
92 }
93
release()94 void MediaBuffer::release() {
95 if (mObserver == NULL) {
96 // Legacy contract for MediaBuffer without a MediaBufferGroup.
97 CHECK_EQ(mRefCount, 0);
98 delete this;
99 return;
100 }
101
102 int prevCount = mRefCount.fetch_sub(1);
103 if (prevCount == 1) {
104 if (mObserver == NULL) {
105 delete this;
106 return;
107 }
108
109 mObserver->signalBufferReturned(this);
110 }
111 CHECK(prevCount > 0);
112 }
113
claim()114 void MediaBuffer::claim() {
115 CHECK(mObserver != NULL);
116 CHECK_EQ(mRefCount.load(std::memory_order_relaxed), 1);
117
118 mRefCount.store(0, std::memory_order_relaxed);
119 }
120
add_ref()121 void MediaBuffer::add_ref() {
122 (void) mRefCount.fetch_add(1);
123 }
124
data() const125 void *MediaBuffer::data() const {
126 return mData;
127 }
128
size() const129 size_t MediaBuffer::size() const {
130 return mSize;
131 }
132
range_offset() const133 size_t MediaBuffer::range_offset() const {
134 return mRangeOffset;
135 }
136
range_length() const137 size_t MediaBuffer::range_length() const {
138 return mRangeLength;
139 }
140
set_range(size_t offset,size_t length)141 void MediaBuffer::set_range(size_t offset, size_t length) {
142 if (offset + length > mSize) {
143 ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
144 }
145 CHECK(offset + length <= mSize);
146
147 mRangeOffset = offset;
148 mRangeLength = length;
149 }
150
meta_data()151 MetaDataBase& MediaBuffer::meta_data() {
152 return *mMetaData;
153 }
154
reset()155 void MediaBuffer::reset() {
156 mMetaData->clear();
157 set_range(0, mSize);
158 }
159
~MediaBuffer()160 MediaBuffer::~MediaBuffer() {
161 CHECK(mObserver == NULL);
162
163 if (mOwnsData && mData != NULL && mMemory == NULL) {
164 free(mData);
165 mData = NULL;
166 }
167
168 if (mMemory.get() != nullptr) {
169 getSharedControl()->setDeadObject();
170 }
171 delete mMetaData;
172 }
173
setObserver(MediaBufferObserver * observer)174 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
175 CHECK(observer == NULL || mObserver == NULL);
176 mObserver = observer;
177 }
178
179 } // namespace android
180