• 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 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 MetaData),
43       mOriginal(NULL) {
44 }
45 
MediaBuffer(size_t size)46 MediaBuffer::MediaBuffer(size_t size)
47     : mObserver(NULL),
48       mRefCount(0),
49       mData(NULL),
50       mSize(size),
51       mRangeOffset(0),
52       mRangeLength(size),
53       mOwnsData(true),
54       mMetaData(new MetaData),
55       mOriginal(NULL) {
56     if (size < kSharedMemThreshold
57             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
58         mData = malloc(size);
59     } else {
60         ALOGV("creating memoryDealer");
61         sp<MemoryDealer> memoryDealer =
62                 new MemoryDealer(size + sizeof(SharedControl), "MediaBuffer");
63         mMemory = memoryDealer->allocate(size + sizeof(SharedControl));
64         if (mMemory == NULL) {
65             ALOGW("Failed to allocate shared memory, trying regular allocation!");
66             mData = malloc(size);
67             if (mData == NULL) {
68                 ALOGE("Out of memory");
69             }
70         } else {
71             getSharedControl()->clear();
72             mData = (uint8_t *)mMemory->pointer() + sizeof(SharedControl);
73             ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
74         }
75     }
76 }
77 
MediaBuffer(const sp<ABuffer> & buffer)78 MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
79     : mObserver(NULL),
80       mRefCount(0),
81       mData(buffer->data()),
82       mSize(buffer->size()),
83       mRangeOffset(0),
84       mRangeLength(mSize),
85       mBuffer(buffer),
86       mOwnsData(false),
87       mMetaData(new MetaData),
88       mOriginal(NULL) {
89 }
90 
release()91 void MediaBuffer::release() {
92     if (mObserver == NULL) {
93         // Legacy contract for MediaBuffer without a MediaBufferGroup.
94         CHECK_EQ(mRefCount, 0);
95         delete this;
96         return;
97     }
98 
99     int prevCount = __sync_fetch_and_sub(&mRefCount, 1);
100     if (prevCount == 1) {
101         if (mObserver == NULL) {
102             delete this;
103             return;
104         }
105 
106         mObserver->signalBufferReturned(this);
107     }
108     CHECK(prevCount > 0);
109 }
110 
claim()111 void MediaBuffer::claim() {
112     CHECK(mObserver != NULL);
113     CHECK_EQ(mRefCount, 1);
114 
115     mRefCount = 0;
116 }
117 
add_ref()118 void MediaBuffer::add_ref() {
119     (void) __sync_fetch_and_add(&mRefCount, 1);
120 }
121 
data() const122 void *MediaBuffer::data() const {
123     return mData;
124 }
125 
size() const126 size_t MediaBuffer::size() const {
127     return mSize;
128 }
129 
range_offset() const130 size_t MediaBuffer::range_offset() const {
131     return mRangeOffset;
132 }
133 
range_length() const134 size_t MediaBuffer::range_length() const {
135     return mRangeLength;
136 }
137 
set_range(size_t offset,size_t length)138 void MediaBuffer::set_range(size_t offset, size_t length) {
139     if (offset + length > mSize) {
140         ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
141     }
142     CHECK(offset + length <= mSize);
143 
144     mRangeOffset = offset;
145     mRangeLength = length;
146 }
147 
meta_data()148 MetaDataBase& MediaBuffer::meta_data() {
149     return *mMetaData;
150 }
151 
reset()152 void MediaBuffer::reset() {
153     mMetaData->clear();
154     set_range(0, mSize);
155 }
156 
~MediaBuffer()157 MediaBuffer::~MediaBuffer() {
158     CHECK(mObserver == NULL);
159 
160     if (mOwnsData && mData != NULL && mMemory == NULL) {
161         free(mData);
162         mData = NULL;
163     }
164 
165     if (mOriginal != NULL) {
166         mOriginal->release();
167         mOriginal = NULL;
168     }
169 
170    if (mMemory.get() != nullptr) {
171        getSharedControl()->setDeadObject();
172    }
173    delete mMetaData;
174 }
175 
setObserver(MediaBufferObserver * observer)176 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
177     CHECK(observer == NULL || mObserver == NULL);
178     mObserver = observer;
179 }
180 
clone()181 MediaBufferBase *MediaBuffer::clone() {
182     MediaBuffer *buffer = new MediaBuffer(mData, mSize);
183     buffer->set_range(mRangeOffset, mRangeLength);
184     buffer->mMetaData = new MetaDataBase(*mMetaData);
185 
186     add_ref();
187     buffer->mOriginal = this;
188 
189     return buffer;
190 }
191 
192 }  // namespace android
193