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/MediaBuffer.h>
25 #include <media/stagefright/MediaDebug.h>
26 #include <media/stagefright/MetaData.h>
27
28 namespace android {
29
30 // XXX make this truly atomic.
atomic_add(int * value,int delta)31 static int atomic_add(int *value, int delta) {
32 int prev_value = *value;
33 *value += delta;
34
35 return prev_value;
36 }
37
MediaBuffer(void * data,size_t size)38 MediaBuffer::MediaBuffer(void *data, size_t size)
39 : mObserver(NULL),
40 mNextBuffer(NULL),
41 mRefCount(0),
42 mData(data),
43 mSize(size),
44 mRangeOffset(0),
45 mRangeLength(size),
46 mOwnsData(false),
47 mMetaData(new MetaData),
48 mOriginal(NULL) {
49 }
50
MediaBuffer(size_t size)51 MediaBuffer::MediaBuffer(size_t size)
52 : mObserver(NULL),
53 mNextBuffer(NULL),
54 mRefCount(0),
55 mData(malloc(size)),
56 mSize(size),
57 mRangeOffset(0),
58 mRangeLength(size),
59 mOwnsData(true),
60 mMetaData(new MetaData),
61 mOriginal(NULL) {
62 }
63
release()64 void MediaBuffer::release() {
65 if (mObserver == NULL) {
66 CHECK_EQ(mRefCount, 0);
67 delete this;
68 return;
69 }
70
71 int prevCount = atomic_add(&mRefCount, -1);
72 if (prevCount == 1) {
73 if (mObserver == NULL) {
74 delete this;
75 return;
76 }
77
78 mObserver->signalBufferReturned(this);
79 }
80 CHECK(prevCount > 0);
81 }
82
claim()83 void MediaBuffer::claim() {
84 CHECK(mObserver != NULL);
85 CHECK_EQ(mRefCount, 1);
86
87 mRefCount = 0;
88 }
89
add_ref()90 void MediaBuffer::add_ref() {
91 atomic_add(&mRefCount, 1);
92 }
93
data() const94 void *MediaBuffer::data() const {
95 return mData;
96 }
97
size() const98 size_t MediaBuffer::size() const {
99 return mSize;
100 }
101
range_offset() const102 size_t MediaBuffer::range_offset() const {
103 return mRangeOffset;
104 }
105
range_length() const106 size_t MediaBuffer::range_length() const {
107 return mRangeLength;
108 }
109
set_range(size_t offset,size_t length)110 void MediaBuffer::set_range(size_t offset, size_t length) {
111 if (offset < 0 || offset + length > mSize) {
112 LOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
113 }
114 CHECK(offset >= 0 && offset + length <= mSize);
115
116 mRangeOffset = offset;
117 mRangeLength = length;
118 }
119
meta_data()120 sp<MetaData> MediaBuffer::meta_data() {
121 return mMetaData;
122 }
123
reset()124 void MediaBuffer::reset() {
125 mMetaData->clear();
126 set_range(0, mSize);
127 }
128
~MediaBuffer()129 MediaBuffer::~MediaBuffer() {
130 CHECK_EQ(mObserver, NULL);
131
132 if (mOwnsData && mData != NULL) {
133 free(mData);
134 mData = NULL;
135 }
136
137 if (mOriginal != NULL) {
138 mOriginal->release();
139 mOriginal = NULL;
140 }
141 }
142
setObserver(MediaBufferObserver * observer)143 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
144 CHECK(observer == NULL || mObserver == NULL);
145 mObserver = observer;
146 }
147
setNextBuffer(MediaBuffer * buffer)148 void MediaBuffer::setNextBuffer(MediaBuffer *buffer) {
149 mNextBuffer = buffer;
150 }
151
nextBuffer()152 MediaBuffer *MediaBuffer::nextBuffer() {
153 return mNextBuffer;
154 }
155
refcount() const156 int MediaBuffer::refcount() const {
157 return mRefCount;
158 }
159
clone()160 MediaBuffer *MediaBuffer::clone() {
161 MediaBuffer *buffer = new MediaBuffer(mData, mSize);
162 buffer->set_range(mRangeOffset, mRangeLength);
163 buffer->mMetaData = new MetaData(*mMetaData.get());
164
165 add_ref();
166 buffer->mOriginal = this;
167
168 return buffer;
169 }
170
171 } // namespace android
172
173