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