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