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