MediaBuffer.cpp revision f59c0bafebcd795b20141bf928a5cab8ac46e882
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
33MediaBuffer::MediaBuffer(void *data, size_t size)
34    : mObserver(NULL),
35      mRefCount(0),
36      mData(data),
37      mSize(size),
38      mRangeOffset(0),
39      mRangeLength(size),
40      mOwnsData(false),
41      mMetaData(new MetaData),
42      mOriginal(NULL) {
43}
44
45MediaBuffer::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 MetaData),
54      mOriginal(NULL) {
55    if (size < kSharedMemThreshold) {
56        mData = malloc(size);
57    } else {
58        ALOGV("creating memoryDealer");
59        sp<MemoryDealer> memoryDealer =
60                new MemoryDealer(size + sizeof(SharedControl), "MediaBuffer");
61        mMemory = memoryDealer->allocate(size + sizeof(SharedControl));
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            getSharedControl()->clear();
70            mData = (uint8_t *)mMemory->pointer() + sizeof(SharedControl);
71            ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
72        }
73    }
74}
75
76MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
77    : mObserver(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
89MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
90    : mObserver(NULL),
91      mRefCount(0),
92      mData(buffer->data()),
93      mSize(buffer->size()),
94      mRangeOffset(0),
95      mRangeLength(mSize),
96      mBuffer(buffer),
97      mOwnsData(false),
98      mMetaData(new MetaData),
99      mOriginal(NULL) {
100}
101
102void MediaBuffer::release() {
103    if (mObserver == NULL) {
104        if (mMemory.get() != nullptr) {
105            // See if there is a pending release and there are no observers.
106            // Ideally this never happens.
107            while (addPendingRelease(-1) > 0) {
108                __sync_fetch_and_sub(&mRefCount, 1);
109            }
110            addPendingRelease(1);
111        }
112        CHECK_EQ(mRefCount, 0);
113        delete this;
114        return;
115    }
116
117    int prevCount = __sync_fetch_and_sub(&mRefCount, 1);
118    if (prevCount == 1) {
119        if (mObserver == NULL) {
120            delete this;
121            return;
122        }
123
124        mObserver->signalBufferReturned(this);
125    }
126    CHECK(prevCount > 0);
127}
128
129void MediaBuffer::claim() {
130    CHECK(mObserver != NULL);
131    CHECK_EQ(mRefCount, 1);
132
133    mRefCount = 0;
134}
135
136void MediaBuffer::add_ref() {
137    (void) __sync_fetch_and_add(&mRefCount, 1);
138}
139
140void *MediaBuffer::data() const {
141    CHECK(mGraphicBuffer == NULL);
142    return mData;
143}
144
145size_t MediaBuffer::size() const {
146    CHECK(mGraphicBuffer == NULL);
147    return mSize;
148}
149
150size_t MediaBuffer::range_offset() const {
151    return mRangeOffset;
152}
153
154size_t MediaBuffer::range_length() const {
155    return mRangeLength;
156}
157
158void MediaBuffer::set_range(size_t offset, size_t length) {
159    if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
160        ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
161    }
162    CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));
163
164    mRangeOffset = offset;
165    mRangeLength = length;
166}
167
168sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
169    return mGraphicBuffer;
170}
171
172sp<MetaData> MediaBuffer::meta_data() {
173    return mMetaData;
174}
175
176void MediaBuffer::reset() {
177    mMetaData->clear();
178    set_range(0, mSize);
179}
180
181MediaBuffer::~MediaBuffer() {
182    CHECK(mObserver == NULL);
183
184    if (mOwnsData && mData != NULL && mMemory == NULL) {
185        free(mData);
186        mData = NULL;
187    }
188
189    if (mOriginal != NULL) {
190        mOriginal->release();
191        mOriginal = NULL;
192    }
193
194   if (mMemory.get() != nullptr) {
195       getSharedControl()->setDeadObject();
196   }
197}
198
199void MediaBuffer::setObserver(MediaBufferObserver *observer) {
200    CHECK(observer == NULL || mObserver == NULL);
201    mObserver = observer;
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