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 #include <ui/GraphicBuffer.h>
30
31 namespace android {
32
33 /* static */
34 std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0);
35
MediaBuffer(void * data,size_t size)36 MediaBuffer::MediaBuffer(void *data, size_t size)
37 : mObserver(NULL),
38 mRefCount(0),
39 mData(data),
40 mSize(size),
41 mRangeOffset(0),
42 mRangeLength(size),
43 mOwnsData(false),
44 mMetaData(new MetaData),
45 mOriginal(NULL) {
46 }
47
MediaBuffer(size_t size)48 MediaBuffer::MediaBuffer(size_t size)
49 : mObserver(NULL),
50 mRefCount(0),
51 mData(NULL),
52 mSize(size),
53 mRangeOffset(0),
54 mRangeLength(size),
55 mOwnsData(true),
56 mMetaData(new MetaData),
57 mOriginal(NULL) {
58 if (size < kSharedMemThreshold
59 || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
60 mData = malloc(size);
61 } else {
62 ALOGV("creating memoryDealer");
63 sp<MemoryDealer> memoryDealer =
64 new MemoryDealer(size + sizeof(SharedControl), "MediaBuffer");
65 mMemory = memoryDealer->allocate(size + sizeof(SharedControl));
66 if (mMemory == NULL) {
67 ALOGW("Failed to allocate shared memory, trying regular allocation!");
68 mData = malloc(size);
69 if (mData == NULL) {
70 ALOGE("Out of memory");
71 }
72 } else {
73 getSharedControl()->clear();
74 mData = (uint8_t *)mMemory->pointer() + sizeof(SharedControl);
75 ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
76 }
77 }
78 }
79
MediaBuffer(const sp<GraphicBuffer> & graphicBuffer)80 MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
81 : mObserver(NULL),
82 mRefCount(0),
83 mData(NULL),
84 mSize(1),
85 mRangeOffset(0),
86 mRangeLength(mSize),
87 mGraphicBuffer(graphicBuffer),
88 mOwnsData(false),
89 mMetaData(new MetaData),
90 mOriginal(NULL) {
91 }
92
MediaBuffer(const sp<ABuffer> & buffer)93 MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
94 : mObserver(NULL),
95 mRefCount(0),
96 mData(buffer->data()),
97 mSize(buffer->size()),
98 mRangeOffset(0),
99 mRangeLength(mSize),
100 mBuffer(buffer),
101 mOwnsData(false),
102 mMetaData(new MetaData),
103 mOriginal(NULL) {
104 }
105
release()106 void MediaBuffer::release() {
107 if (mObserver == NULL) {
108 // Legacy contract for MediaBuffer without a MediaBufferGroup.
109 CHECK_EQ(mRefCount, 0);
110 delete this;
111 return;
112 }
113
114 int prevCount = __sync_fetch_and_sub(&mRefCount, 1);
115 if (prevCount == 1) {
116 if (mObserver == NULL) {
117 delete this;
118 return;
119 }
120
121 mObserver->signalBufferReturned(this);
122 }
123 CHECK(prevCount > 0);
124 }
125
claim()126 void MediaBuffer::claim() {
127 CHECK(mObserver != NULL);
128 CHECK_EQ(mRefCount, 1);
129
130 mRefCount = 0;
131 }
132
add_ref()133 void MediaBuffer::add_ref() {
134 (void) __sync_fetch_and_add(&mRefCount, 1);
135 }
136
data() const137 void *MediaBuffer::data() const {
138 CHECK(mGraphicBuffer == NULL);
139 return mData;
140 }
141
size() const142 size_t MediaBuffer::size() const {
143 CHECK(mGraphicBuffer == NULL);
144 return mSize;
145 }
146
range_offset() const147 size_t MediaBuffer::range_offset() const {
148 return mRangeOffset;
149 }
150
range_length() const151 size_t MediaBuffer::range_length() const {
152 return mRangeLength;
153 }
154
set_range(size_t offset,size_t length)155 void MediaBuffer::set_range(size_t offset, size_t length) {
156 if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
157 ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
158 }
159 CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));
160
161 mRangeOffset = offset;
162 mRangeLength = length;
163 }
164
graphicBuffer() const165 sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
166 return mGraphicBuffer;
167 }
168
meta_data()169 sp<MetaData> MediaBuffer::meta_data() {
170 return mMetaData;
171 }
172
reset()173 void MediaBuffer::reset() {
174 mMetaData->clear();
175 set_range(0, mSize);
176 }
177
~MediaBuffer()178 MediaBuffer::~MediaBuffer() {
179 CHECK(mObserver == NULL);
180
181 if (mOwnsData && mData != NULL && mMemory == NULL) {
182 free(mData);
183 mData = NULL;
184 }
185
186 if (mOriginal != NULL) {
187 mOriginal->release();
188 mOriginal = NULL;
189 }
190
191 if (mMemory.get() != nullptr) {
192 getSharedControl()->setDeadObject();
193 }
194 }
195
setObserver(MediaBufferObserver * observer)196 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
197 CHECK(observer == NULL || mObserver == NULL);
198 mObserver = observer;
199 }
200
clone()201 MediaBuffer *MediaBuffer::clone() {
202 CHECK(mGraphicBuffer == NULL);
203
204 MediaBuffer *buffer = new MediaBuffer(mData, mSize);
205 buffer->set_range(mRangeOffset, mRangeLength);
206 buffer->mMetaData = new MetaData(*mMetaData.get());
207
208 add_ref();
209 buffer->mOriginal = this;
210
211 return buffer;
212 }
213
214 } // namespace android
215