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 namespace android {
30 
31 /* static */
32 std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0);
33 
MediaBuffer(void * data,size_t size)34 MediaBuffer::MediaBuffer(void *data, size_t size)
35     : mObserver(NULL),
36       mRefCount(0),
37       mData(data),
38       mSize(size),
39       mRangeOffset(0),
40       mRangeLength(size),
41       mOwnsData(false),
42       mMetaData(new MetaDataBase) {
43 }
44 
MediaBuffer(size_t size)45 MediaBuffer::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 MetaDataBase) {
54 #ifndef NO_IMEMORY
55     if (size < kSharedMemThreshold
56             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
57 #endif
58         mData = malloc(size);
59 #ifndef NO_IMEMORY
60     } else {
61         ALOGV("creating memoryDealer");
62         size_t newSize = 0;
63         if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) {
64             sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer");
65             mMemory = memoryDealer->allocate(newSize);
66         }
67         if (mMemory == NULL) {
68             ALOGW("Failed to allocate shared memory, trying regular allocation!");
69             mData = malloc(size);
70             if (mData == NULL) {
71                 ALOGE("Out of memory");
72             }
73         } else {
74             getSharedControl()->clear();
75             mData = (uint8_t *)mMemory->pointer() + sizeof(SharedControl);
76             ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
77         }
78     }
79 #endif
80 }
81 
MediaBuffer(const sp<ABuffer> & buffer)82 MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
83     : mObserver(NULL),
84       mRefCount(0),
85       mData(buffer->data()),
86       mSize(buffer->size()),
87       mRangeOffset(0),
88       mRangeLength(mSize),
89       mBuffer(buffer),
90       mOwnsData(false),
91       mMetaData(new MetaDataBase) {
92 }
93 
release()94 void MediaBuffer::release() {
95     if (mObserver == NULL) {
96         // Legacy contract for MediaBuffer without a MediaBufferGroup.
97         CHECK_EQ(mRefCount, 0);
98         delete this;
99         return;
100     }
101 
102     int prevCount = mRefCount.fetch_sub(1);
103     if (prevCount == 1) {
104         if (mObserver == NULL) {
105             delete this;
106             return;
107         }
108 
109         mObserver->signalBufferReturned(this);
110     }
111     CHECK(prevCount > 0);
112 }
113 
claim()114 void MediaBuffer::claim() {
115     CHECK(mObserver != NULL);
116     CHECK_EQ(mRefCount.load(std::memory_order_relaxed), 1);
117 
118     mRefCount.store(0, std::memory_order_relaxed);
119 }
120 
add_ref()121 void MediaBuffer::add_ref() {
122     (void) mRefCount.fetch_add(1);
123 }
124 
data() const125 void *MediaBuffer::data() const {
126     return mData;
127 }
128 
size() const129 size_t MediaBuffer::size() const {
130     return mSize;
131 }
132 
range_offset() const133 size_t MediaBuffer::range_offset() const {
134     return mRangeOffset;
135 }
136 
range_length() const137 size_t MediaBuffer::range_length() const {
138     return mRangeLength;
139 }
140 
set_range(size_t offset,size_t length)141 void MediaBuffer::set_range(size_t offset, size_t length) {
142     if (offset + length > mSize) {
143         ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
144     }
145     CHECK(offset + length <= mSize);
146 
147     mRangeOffset = offset;
148     mRangeLength = length;
149 }
150 
meta_data()151 MetaDataBase& MediaBuffer::meta_data() {
152     return *mMetaData;
153 }
154 
reset()155 void MediaBuffer::reset() {
156     mMetaData->clear();
157     set_range(0, mSize);
158 }
159 
~MediaBuffer()160 MediaBuffer::~MediaBuffer() {
161     CHECK(mObserver == NULL);
162 
163     if (mOwnsData && mData != NULL && mMemory == NULL) {
164         free(mData);
165         mData = NULL;
166     }
167 
168    if (mMemory.get() != nullptr) {
169        getSharedControl()->setDeadObject();
170    }
171    delete mMetaData;
172 }
173 
setObserver(MediaBufferObserver * observer)174 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
175     CHECK(observer == NULL || mObserver == NULL);
176     mObserver = observer;
177 }
178 
179 }  // namespace android
180