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/MediaBuffer.h> 25 #include <media/stagefright/MediaDebug.h> 26 #include <media/stagefright/MetaData.h> 27 28 namespace android { 29 30 // XXX make this truly atomic. 31 static int atomic_add(int *value, int delta) { 32 int prev_value = *value; 33 *value += delta; 34 35 return prev_value; 36 } 37 38 MediaBuffer::MediaBuffer(void *data, size_t size) 39 : mObserver(NULL), 40 mNextBuffer(NULL), 41 mRefCount(0), 42 mData(data), 43 mSize(size), 44 mRangeOffset(0), 45 mRangeLength(size), 46 mOwnsData(false), 47 mMetaData(new MetaData), 48 mOriginal(NULL) { 49 } 50 51 MediaBuffer::MediaBuffer(size_t size) 52 : mObserver(NULL), 53 mNextBuffer(NULL), 54 mRefCount(0), 55 mData(malloc(size)), 56 mSize(size), 57 mRangeOffset(0), 58 mRangeLength(size), 59 mOwnsData(true), 60 mMetaData(new MetaData), 61 mOriginal(NULL) { 62 } 63 64 void MediaBuffer::release() { 65 if (mObserver == NULL) { 66 CHECK_EQ(mRefCount, 0); 67 delete this; 68 return; 69 } 70 71 int prevCount = atomic_add(&mRefCount, -1); 72 if (prevCount == 1) { 73 if (mObserver == NULL) { 74 delete this; 75 return; 76 } 77 78 mObserver->signalBufferReturned(this); 79 } 80 CHECK(prevCount > 0); 81 } 82 83 void MediaBuffer::claim() { 84 CHECK(mObserver != NULL); 85 CHECK_EQ(mRefCount, 1); 86 87 mRefCount = 0; 88 } 89 90 void MediaBuffer::add_ref() { 91 atomic_add(&mRefCount, 1); 92 } 93 94 void *MediaBuffer::data() const { 95 return mData; 96 } 97 98 size_t MediaBuffer::size() const { 99 return mSize; 100 } 101 102 size_t MediaBuffer::range_offset() const { 103 return mRangeOffset; 104 } 105 106 size_t MediaBuffer::range_length() const { 107 return mRangeLength; 108 } 109 110 void MediaBuffer::set_range(size_t offset, size_t length) { 111 if (offset + length > mSize) { 112 LOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize); 113 } 114 CHECK(offset + length <= mSize); 115 116 mRangeOffset = offset; 117 mRangeLength = length; 118 } 119 120 sp<MetaData> MediaBuffer::meta_data() { 121 return mMetaData; 122 } 123 124 void MediaBuffer::reset() { 125 mMetaData->clear(); 126 set_range(0, mSize); 127 } 128 129 MediaBuffer::~MediaBuffer() { 130 CHECK_EQ(mObserver, NULL); 131 132 if (mOwnsData && mData != NULL) { 133 free(mData); 134 mData = NULL; 135 } 136 137 if (mOriginal != NULL) { 138 mOriginal->release(); 139 mOriginal = NULL; 140 } 141 } 142 143 void MediaBuffer::setObserver(MediaBufferObserver *observer) { 144 CHECK(observer == NULL || mObserver == NULL); 145 mObserver = observer; 146 } 147 148 void MediaBuffer::setNextBuffer(MediaBuffer *buffer) { 149 mNextBuffer = buffer; 150 } 151 152 MediaBuffer *MediaBuffer::nextBuffer() { 153 return mNextBuffer; 154 } 155 156 int MediaBuffer::refcount() const { 157 return mRefCount; 158 } 159 160 MediaBuffer *MediaBuffer::clone() { 161 MediaBuffer *buffer = new MediaBuffer(mData, mSize); 162 buffer->set_range(mRangeOffset, mRangeLength); 163 buffer->mMetaData = new MetaData(*mMetaData.get()); 164 165 add_ref(); 166 buffer->mOriginal = this; 167 168 return buffer; 169 } 170 171 } // namespace android 172 173