180 lines
4.5 KiB
C++
180 lines
4.5 KiB
C++
|
|
/*
|
||
|
|
* 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
|