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