| /* |
| * Copyright (C) 2009 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #define LOG_TAG "MediaBuffer" |
| #include <utils/Log.h> |
| |
| #include <errno.h> |
| #include <pthread.h> |
| #include <stdlib.h> |
| |
| #include <media/stagefright/foundation/ABuffer.h> |
| #include <media/stagefright/foundation/ADebug.h> |
| #include <media/stagefright/MediaBuffer.h> |
| #include <media/stagefright/MetaData.h> |
| |
| namespace android { |
| |
| /* static */ |
| std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0); |
| |
| MediaBuffer::MediaBuffer(void *data, size_t size) |
| : mObserver(NULL), |
| mRefCount(0), |
| mData(data), |
| mSize(size), |
| mRangeOffset(0), |
| mRangeLength(size), |
| mOwnsData(false), |
| mMetaData(new MetaDataBase) { |
| } |
| |
| MediaBuffer::MediaBuffer(size_t size) |
| : mObserver(NULL), |
| mRefCount(0), |
| mData(NULL), |
| mSize(size), |
| mRangeOffset(0), |
| mRangeLength(size), |
| mOwnsData(true), |
| mMetaData(new MetaDataBase) { |
| #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__) |
| if (size < kSharedMemThreshold |
| || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) { |
| #endif |
| mData = malloc(size); |
| #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__) |
| } else { |
| ALOGV("creating memoryDealer"); |
| size_t newSize = 0; |
| if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) { |
| sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer"); |
| mMemory = memoryDealer->allocate(newSize); |
| } |
| if (mMemory == NULL) { |
| ALOGW("Failed to allocate shared memory, trying regular allocation!"); |
| mData = malloc(size); |
| if (mData == NULL) { |
| ALOGE("Out of memory"); |
| } |
| } else { |
| getSharedControl()->clear(); |
| mData = (uint8_t *)mMemory->unsecurePointer() + sizeof(SharedControl); |
| ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData); |
| } |
| } |
| #endif |
| } |
| |
| MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer) |
| : mObserver(NULL), |
| mRefCount(0), |
| mData(buffer->data()), |
| mSize(buffer->size()), |
| mRangeOffset(0), |
| mRangeLength(mSize), |
| mBuffer(buffer), |
| mOwnsData(false), |
| mMetaData(new MetaDataBase) { |
| } |
| |
| void MediaBuffer::release() { |
| if (mObserver == NULL) { |
| // Legacy contract for MediaBuffer without a MediaBufferGroup. |
| CHECK_EQ(mRefCount, 0); |
| delete this; |
| return; |
| } |
| |
| int prevCount = mRefCount.fetch_sub(1); |
| if (prevCount == 1) { |
| if (mObserver == NULL) { |
| delete this; |
| return; |
| } |
| |
| mObserver->signalBufferReturned(this); |
| } |
| CHECK(prevCount > 0); |
| } |
| |
| void MediaBuffer::claim() { |
| CHECK(mObserver != NULL); |
| CHECK_EQ(mRefCount.load(std::memory_order_relaxed), 1); |
| |
| mRefCount.store(0, std::memory_order_relaxed); |
| } |
| |
| void MediaBuffer::add_ref() { |
| (void) mRefCount.fetch_add(1); |
| } |
| |
| void *MediaBuffer::data() const { |
| return mData; |
| } |
| |
| size_t MediaBuffer::size() const { |
| return mSize; |
| } |
| |
| size_t MediaBuffer::range_offset() const { |
| return mRangeOffset; |
| } |
| |
| size_t MediaBuffer::range_length() const { |
| return mRangeLength; |
| } |
| |
| void MediaBuffer::set_range(size_t offset, size_t length) { |
| if (offset + length > mSize) { |
| ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize); |
| } |
| CHECK(offset + length <= mSize); |
| |
| mRangeOffset = offset; |
| mRangeLength = length; |
| } |
| |
| MetaDataBase& MediaBuffer::meta_data() { |
| return *mMetaData; |
| } |
| |
| void MediaBuffer::reset() { |
| mMetaData->clear(); |
| set_range(0, mSize); |
| } |
| |
| MediaBuffer::~MediaBuffer() { |
| CHECK(mObserver == NULL); |
| |
| if (mOwnsData && mData != NULL && mMemory == NULL) { |
| free(mData); |
| mData = NULL; |
| } |
| |
| if (mMemory.get() != nullptr) { |
| getSharedControl()->setDeadObject(); |
| } |
| delete mMetaData; |
| } |
| |
| void MediaBuffer::setObserver(MediaBufferObserver *observer) { |
| CHECK(observer == NULL || mObserver == NULL); |
| mObserver = observer; |
| } |
| |
| } // namespace android |