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