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 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 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 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 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 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 126 void MediaBuffer::claim() { 127 CHECK(mObserver != NULL); 128 CHECK_EQ(mRefCount, 1); 129 130 mRefCount = 0; 131 } 132 133 void MediaBuffer::add_ref() { 134 (void) __sync_fetch_and_add(&mRefCount, 1); 135 } 136 137 void *MediaBuffer::data() const { 138 CHECK(mGraphicBuffer == NULL); 139 return mData; 140 } 141 142 size_t MediaBuffer::size() const { 143 CHECK(mGraphicBuffer == NULL); 144 return mSize; 145 } 146 147 size_t MediaBuffer::range_offset() const { 148 return mRangeOffset; 149 } 150 151 size_t MediaBuffer::range_length() const { 152 return mRangeLength; 153 } 154 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 165 sp<GraphicBuffer> MediaBuffer::graphicBuffer() const { 166 return mGraphicBuffer; 167 } 168 169 sp<MetaData> MediaBuffer::meta_data() { 170 return mMetaData; 171 } 172 173 void MediaBuffer::reset() { 174 mMetaData->clear(); 175 set_range(0, mSize); 176 } 177 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 196 void MediaBuffer::setObserver(MediaBufferObserver *observer) { 197 CHECK(observer == NULL || mObserver == NULL); 198 mObserver = observer; 199 } 200 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