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