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 33MediaBuffer::MediaBuffer(void *data, size_t size) 34 : mObserver(NULL), 35 mNextBuffer(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 46MediaBuffer::MediaBuffer(size_t size) 47 : mObserver(NULL), 48 mNextBuffer(NULL), 49 mRefCount(0), 50 mData(NULL), 51 mSize(size), 52 mRangeOffset(0), 53 mRangeLength(size), 54 mOwnsData(true), 55 mMetaData(new MetaData), 56 mOriginal(NULL) { 57 if (size < kSharedMemThreshold) { 58 mData = malloc(size); 59 } else { 60 sp<MemoryDealer> memoryDealer = new MemoryDealer(size, "MediaBuffer"); 61 mMemory = memoryDealer->allocate(size); 62 if (mMemory == NULL) { 63 ALOGW("Failed to allocate shared memory, trying regular allocation!"); 64 mData = malloc(size); 65 if (mData == NULL) { 66 ALOGE("Out of memory"); 67 } 68 } else { 69 mData = mMemory->pointer(); 70 ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData); 71 } 72 } 73} 74 75MediaBuffer::MediaBuffer(const sp<GraphicBuffer>& graphicBuffer) 76 : mObserver(NULL), 77 mNextBuffer(NULL), 78 mRefCount(0), 79 mData(NULL), 80 mSize(1), 81 mRangeOffset(0), 82 mRangeLength(mSize), 83 mGraphicBuffer(graphicBuffer), 84 mOwnsData(false), 85 mMetaData(new MetaData), 86 mOriginal(NULL) { 87} 88 89MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer) 90 : mObserver(NULL), 91 mNextBuffer(NULL), 92 mRefCount(0), 93 mData(buffer->data()), 94 mSize(buffer->size()), 95 mRangeOffset(0), 96 mRangeLength(mSize), 97 mBuffer(buffer), 98 mOwnsData(false), 99 mMetaData(new MetaData), 100 mOriginal(NULL) { 101} 102 103void MediaBuffer::release() { 104 if (mObserver == NULL) { 105 CHECK_EQ(mRefCount, 0); 106 delete this; 107 return; 108 } 109 110 int prevCount = __sync_fetch_and_sub(&mRefCount, 1); 111 if (prevCount == 1) { 112 if (mObserver == NULL) { 113 delete this; 114 return; 115 } 116 117 mObserver->signalBufferReturned(this); 118 } 119 CHECK(prevCount > 0); 120} 121 122void MediaBuffer::claim() { 123 CHECK(mObserver != NULL); 124 CHECK_EQ(mRefCount, 1); 125 126 mRefCount = 0; 127} 128 129void MediaBuffer::add_ref() { 130 (void) __sync_fetch_and_add(&mRefCount, 1); 131} 132 133void *MediaBuffer::data() const { 134 CHECK(mGraphicBuffer == NULL); 135 return mData; 136} 137 138size_t MediaBuffer::size() const { 139 CHECK(mGraphicBuffer == NULL); 140 return mSize; 141} 142 143size_t MediaBuffer::range_offset() const { 144 return mRangeOffset; 145} 146 147size_t MediaBuffer::range_length() const { 148 return mRangeLength; 149} 150 151void MediaBuffer::set_range(size_t offset, size_t length) { 152 if ((mGraphicBuffer == NULL) && (offset + length > mSize)) { 153 ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize); 154 } 155 CHECK((mGraphicBuffer != NULL) || (offset + length <= mSize)); 156 157 mRangeOffset = offset; 158 mRangeLength = length; 159} 160 161sp<GraphicBuffer> MediaBuffer::graphicBuffer() const { 162 return mGraphicBuffer; 163} 164 165sp<MetaData> MediaBuffer::meta_data() { 166 return mMetaData; 167} 168 169void MediaBuffer::reset() { 170 mMetaData->clear(); 171 set_range(0, mSize); 172} 173 174MediaBuffer::~MediaBuffer() { 175 CHECK(mObserver == NULL); 176 177 if (mOwnsData && mData != NULL && mMemory == NULL) { 178 free(mData); 179 mData = NULL; 180 } 181 182 if (mOriginal != NULL) { 183 mOriginal->release(); 184 mOriginal = NULL; 185 } 186} 187 188void MediaBuffer::setObserver(MediaBufferObserver *observer) { 189 CHECK(observer == NULL || mObserver == NULL); 190 mObserver = observer; 191} 192 193void MediaBuffer::setNextBuffer(MediaBuffer *buffer) { 194 mNextBuffer = buffer; 195} 196 197MediaBuffer *MediaBuffer::nextBuffer() { 198 return mNextBuffer; 199} 200 201int MediaBuffer::refcount() const { 202 return mRefCount; 203} 204 205MediaBuffer *MediaBuffer::clone() { 206 CHECK(mGraphicBuffer == NULL); 207 208 MediaBuffer *buffer = new MediaBuffer(mData, mSize); 209 buffer->set_range(mRangeOffset, mRangeLength); 210 buffer->mMetaData = new MetaData(*mMetaData.get()); 211 212 add_ref(); 213 buffer->mOriginal = this; 214 215 return buffer; 216} 217 218} // namespace android 219