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#include <sys/atomics.h>
31
32namespace android {
33
34MediaBuffer::MediaBuffer(void *data, size_t size)
35    : mObserver(NULL),
36      mNextBuffer(NULL),
37      mRefCount(0),
38      mData(data),
39      mSize(size),
40      mRangeOffset(0),
41      mRangeLength(size),
42      mOwnsData(false),
43      mMetaData(new MetaData),
44      mOriginal(NULL) {
45}
46
47MediaBuffer::MediaBuffer(size_t size)
48    : mObserver(NULL),
49      mNextBuffer(NULL),
50      mRefCount(0),
51      mData(malloc(size)),
52      mSize(size),
53      mRangeOffset(0),
54      mRangeLength(size),
55      mOwnsData(true),
56      mMetaData(new MetaData),
57      mOriginal(NULL) {
58}
59
60MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer)
61    : mObserver(NULL),
62      mNextBuffer(NULL),
63      mRefCount(0),
64      mData(NULL),
65      mSize(1),
66      mRangeOffset(0),
67      mRangeLength(mSize),
68      mGraphicBuffer(graphicBuffer),
69      mOwnsData(false),
70      mMetaData(new MetaData),
71      mOriginal(NULL) {
72}
73
74MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
75    : mObserver(NULL),
76      mNextBuffer(NULL),
77      mRefCount(0),
78      mData(buffer->data()),
79      mSize(buffer->size()),
80      mRangeOffset(0),
81      mRangeLength(mSize),
82      mBuffer(buffer),
83      mOwnsData(false),
84      mMetaData(new MetaData),
85      mOriginal(NULL) {
86}
87
88void MediaBuffer::release() {
89    if (mObserver == NULL) {
90        CHECK_EQ(mRefCount, 0);
91        delete this;
92        return;
93    }
94
95    int prevCount = __atomic_dec(&mRefCount);
96    if (prevCount == 1) {
97        if (mObserver == NULL) {
98            delete this;
99            return;
100        }
101
102        mObserver->signalBufferReturned(this);
103    }
104    CHECK(prevCount > 0);
105}
106
107void MediaBuffer::claim() {
108    CHECK(mObserver != NULL);
109    CHECK_EQ(mRefCount, 1);
110
111    mRefCount = 0;
112}
113
114void MediaBuffer::add_ref() {
115    (void) __atomic_inc(&mRefCount);
116}
117
118void *MediaBuffer::data() const {
119    CHECK(mGraphicBuffer == NULL);
120    return mData;
121}
122
123size_t MediaBuffer::size() const {
124    CHECK(mGraphicBuffer == NULL);
125    return mSize;
126}
127
128size_t MediaBuffer::range_offset() const {
129    return mRangeOffset;
130}
131
132size_t MediaBuffer::range_length() const {
133    return mRangeLength;
134}
135
136void MediaBuffer::set_range(size_t offset, size_t length) {
137    if ((mGraphicBuffer == NULL) && (offset + length > mSize)) {
138        ALOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
139    }
140    CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize));
141
142    mRangeOffset = offset;
143    mRangeLength = length;
144}
145
146sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
147    return mGraphicBuffer;
148}
149
150sp<MetaData> MediaBuffer::meta_data() {
151    return mMetaData;
152}
153
154void MediaBuffer::reset() {
155    mMetaData->clear();
156    set_range(0, mSize);
157}
158
159MediaBuffer::~MediaBuffer() {
160    CHECK(mObserver == NULL);
161
162    if (mOwnsData && mData != NULL) {
163        free(mData);
164        mData = NULL;
165    }
166
167    if (mOriginal != NULL) {
168        mOriginal->release();
169        mOriginal = NULL;
170    }
171}
172
173void MediaBuffer::setObserver(MediaBufferObserver *observer) {
174    CHECK(observer == NULL || mObserver == NULL);
175    mObserver = observer;
176}
177
178void MediaBuffer::setNextBuffer(MediaBuffer *buffer) {
179    mNextBuffer = buffer;
180}
181
182MediaBuffer *MediaBuffer::nextBuffer() {
183    return mNextBuffer;
184}
185
186int MediaBuffer::refcount() const {
187    return mRefCount;
188}
189
190MediaBuffer *MediaBuffer::clone() {
191    CHECK(mGraphicBuffer == NULL);
192
193    MediaBuffer *buffer = new MediaBuffer(mData, mSize);
194    buffer->set_range(mRangeOffset, mRangeLength);
195    buffer->mMetaData = new MetaData(*mMetaData.get());
196
197    add_ref();
198    buffer->mOriginal = this;
199
200    return buffer;
201}
202
203}  // namespace android
204