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