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