xref: /aosp_15_r20/frameworks/av/media/module/foundation/MediaBuffer.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2009 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "MediaBuffer"
18*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
19*ec779b8eSAndroid Build Coastguard Worker 
20*ec779b8eSAndroid Build Coastguard Worker #include <errno.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <pthread.h>
22*ec779b8eSAndroid Build Coastguard Worker #include <stdlib.h>
23*ec779b8eSAndroid Build Coastguard Worker 
24*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABuffer.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
26*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MediaBuffer.h>
27*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/MetaData.h>
28*ec779b8eSAndroid Build Coastguard Worker 
29*ec779b8eSAndroid Build Coastguard Worker namespace android {
30*ec779b8eSAndroid Build Coastguard Worker 
31*ec779b8eSAndroid Build Coastguard Worker /* static */
32*ec779b8eSAndroid Build Coastguard Worker std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0);
33*ec779b8eSAndroid Build Coastguard Worker 
MediaBuffer(void * data,size_t size)34*ec779b8eSAndroid Build Coastguard Worker MediaBuffer::MediaBuffer(void *data, size_t size)
35*ec779b8eSAndroid Build Coastguard Worker     : mObserver(NULL),
36*ec779b8eSAndroid Build Coastguard Worker       mRefCount(0),
37*ec779b8eSAndroid Build Coastguard Worker       mData(data),
38*ec779b8eSAndroid Build Coastguard Worker       mSize(size),
39*ec779b8eSAndroid Build Coastguard Worker       mRangeOffset(0),
40*ec779b8eSAndroid Build Coastguard Worker       mRangeLength(size),
41*ec779b8eSAndroid Build Coastguard Worker       mOwnsData(false),
42*ec779b8eSAndroid Build Coastguard Worker       mMetaData(new MetaDataBase) {
43*ec779b8eSAndroid Build Coastguard Worker }
44*ec779b8eSAndroid Build Coastguard Worker 
MediaBuffer(size_t size)45*ec779b8eSAndroid Build Coastguard Worker MediaBuffer::MediaBuffer(size_t size)
46*ec779b8eSAndroid Build Coastguard Worker     : mObserver(NULL),
47*ec779b8eSAndroid Build Coastguard Worker       mRefCount(0),
48*ec779b8eSAndroid Build Coastguard Worker       mData(NULL),
49*ec779b8eSAndroid Build Coastguard Worker       mSize(size),
50*ec779b8eSAndroid Build Coastguard Worker       mRangeOffset(0),
51*ec779b8eSAndroid Build Coastguard Worker       mRangeLength(size),
52*ec779b8eSAndroid Build Coastguard Worker       mOwnsData(true),
53*ec779b8eSAndroid Build Coastguard Worker       mMetaData(new MetaDataBase) {
54*ec779b8eSAndroid Build Coastguard Worker #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
55*ec779b8eSAndroid Build Coastguard Worker     if (size < kSharedMemThreshold
56*ec779b8eSAndroid Build Coastguard Worker             || std::atomic_load_explicit(&mUseSharedMemory, std::memory_order_seq_cst) == 0) {
57*ec779b8eSAndroid Build Coastguard Worker #endif
58*ec779b8eSAndroid Build Coastguard Worker         mData = malloc(size);
59*ec779b8eSAndroid Build Coastguard Worker #if !defined(NO_IMEMORY) && !defined(__ANDROID_APEX__)
60*ec779b8eSAndroid Build Coastguard Worker     } else {
61*ec779b8eSAndroid Build Coastguard Worker         ALOGV("creating memoryDealer");
62*ec779b8eSAndroid Build Coastguard Worker         size_t newSize = 0;
63*ec779b8eSAndroid Build Coastguard Worker         if (!__builtin_add_overflow(size, sizeof(SharedControl), &newSize)) {
64*ec779b8eSAndroid Build Coastguard Worker             sp<MemoryDealer> memoryDealer = new MemoryDealer(newSize, "MediaBuffer");
65*ec779b8eSAndroid Build Coastguard Worker             mMemory = memoryDealer->allocate(newSize);
66*ec779b8eSAndroid Build Coastguard Worker         }
67*ec779b8eSAndroid Build Coastguard Worker         if (mMemory == NULL) {
68*ec779b8eSAndroid Build Coastguard Worker             ALOGW("Failed to allocate shared memory, trying regular allocation!");
69*ec779b8eSAndroid Build Coastguard Worker             mData = malloc(size);
70*ec779b8eSAndroid Build Coastguard Worker             if (mData == NULL) {
71*ec779b8eSAndroid Build Coastguard Worker                 ALOGE("Out of memory");
72*ec779b8eSAndroid Build Coastguard Worker             }
73*ec779b8eSAndroid Build Coastguard Worker         } else {
74*ec779b8eSAndroid Build Coastguard Worker             getSharedControl()->clear();
75*ec779b8eSAndroid Build Coastguard Worker             mData = (uint8_t *)mMemory->unsecurePointer() + sizeof(SharedControl);
76*ec779b8eSAndroid Build Coastguard Worker             ALOGV("Allocated shared mem buffer of size %zu @ %p", size, mData);
77*ec779b8eSAndroid Build Coastguard Worker         }
78*ec779b8eSAndroid Build Coastguard Worker     }
79*ec779b8eSAndroid Build Coastguard Worker #endif
80*ec779b8eSAndroid Build Coastguard Worker }
81*ec779b8eSAndroid Build Coastguard Worker 
MediaBuffer(const sp<ABuffer> & buffer)82*ec779b8eSAndroid Build Coastguard Worker MediaBuffer::MediaBuffer(const sp<ABuffer> &buffer)
83*ec779b8eSAndroid Build Coastguard Worker     : mObserver(NULL),
84*ec779b8eSAndroid Build Coastguard Worker       mRefCount(0),
85*ec779b8eSAndroid Build Coastguard Worker       mData(buffer->data()),
86*ec779b8eSAndroid Build Coastguard Worker       mSize(buffer->size()),
87*ec779b8eSAndroid Build Coastguard Worker       mRangeOffset(0),
88*ec779b8eSAndroid Build Coastguard Worker       mRangeLength(mSize),
89*ec779b8eSAndroid Build Coastguard Worker       mBuffer(buffer),
90*ec779b8eSAndroid Build Coastguard Worker       mOwnsData(false),
91*ec779b8eSAndroid Build Coastguard Worker       mMetaData(new MetaDataBase) {
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker 
release()94*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::release() {
95*ec779b8eSAndroid Build Coastguard Worker     if (mObserver == NULL) {
96*ec779b8eSAndroid Build Coastguard Worker         // Legacy contract for MediaBuffer without a MediaBufferGroup.
97*ec779b8eSAndroid Build Coastguard Worker         CHECK_EQ(mRefCount, 0);
98*ec779b8eSAndroid Build Coastguard Worker         delete this;
99*ec779b8eSAndroid Build Coastguard Worker         return;
100*ec779b8eSAndroid Build Coastguard Worker     }
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker     int prevCount = mRefCount.fetch_sub(1);
103*ec779b8eSAndroid Build Coastguard Worker     if (prevCount == 1) {
104*ec779b8eSAndroid Build Coastguard Worker         if (mObserver == NULL) {
105*ec779b8eSAndroid Build Coastguard Worker             delete this;
106*ec779b8eSAndroid Build Coastguard Worker             return;
107*ec779b8eSAndroid Build Coastguard Worker         }
108*ec779b8eSAndroid Build Coastguard Worker 
109*ec779b8eSAndroid Build Coastguard Worker         mObserver->signalBufferReturned(this);
110*ec779b8eSAndroid Build Coastguard Worker     }
111*ec779b8eSAndroid Build Coastguard Worker     CHECK(prevCount > 0);
112*ec779b8eSAndroid Build Coastguard Worker }
113*ec779b8eSAndroid Build Coastguard Worker 
claim()114*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::claim() {
115*ec779b8eSAndroid Build Coastguard Worker     CHECK(mObserver != NULL);
116*ec779b8eSAndroid Build Coastguard Worker     CHECK_EQ(mRefCount.load(std::memory_order_relaxed), 1);
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker     mRefCount.store(0, std::memory_order_relaxed);
119*ec779b8eSAndroid Build Coastguard Worker }
120*ec779b8eSAndroid Build Coastguard Worker 
add_ref()121*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::add_ref() {
122*ec779b8eSAndroid Build Coastguard Worker     (void) mRefCount.fetch_add(1);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker 
data() const125*ec779b8eSAndroid Build Coastguard Worker void *MediaBuffer::data() const {
126*ec779b8eSAndroid Build Coastguard Worker     return mData;
127*ec779b8eSAndroid Build Coastguard Worker }
128*ec779b8eSAndroid Build Coastguard Worker 
size() const129*ec779b8eSAndroid Build Coastguard Worker size_t MediaBuffer::size() const {
130*ec779b8eSAndroid Build Coastguard Worker     return mSize;
131*ec779b8eSAndroid Build Coastguard Worker }
132*ec779b8eSAndroid Build Coastguard Worker 
range_offset() const133*ec779b8eSAndroid Build Coastguard Worker size_t MediaBuffer::range_offset() const {
134*ec779b8eSAndroid Build Coastguard Worker     return mRangeOffset;
135*ec779b8eSAndroid Build Coastguard Worker }
136*ec779b8eSAndroid Build Coastguard Worker 
range_length() const137*ec779b8eSAndroid Build Coastguard Worker size_t MediaBuffer::range_length() const {
138*ec779b8eSAndroid Build Coastguard Worker     return mRangeLength;
139*ec779b8eSAndroid Build Coastguard Worker }
140*ec779b8eSAndroid Build Coastguard Worker 
set_range(size_t offset,size_t length)141*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::set_range(size_t offset, size_t length) {
142*ec779b8eSAndroid Build Coastguard Worker     if (offset + length > mSize) {
143*ec779b8eSAndroid Build Coastguard Worker         ALOGE("offset = %zu, length = %zu, mSize = %zu", offset, length, mSize);
144*ec779b8eSAndroid Build Coastguard Worker     }
145*ec779b8eSAndroid Build Coastguard Worker     CHECK(offset + length <= mSize);
146*ec779b8eSAndroid Build Coastguard Worker 
147*ec779b8eSAndroid Build Coastguard Worker     mRangeOffset = offset;
148*ec779b8eSAndroid Build Coastguard Worker     mRangeLength = length;
149*ec779b8eSAndroid Build Coastguard Worker }
150*ec779b8eSAndroid Build Coastguard Worker 
meta_data()151*ec779b8eSAndroid Build Coastguard Worker MetaDataBase& MediaBuffer::meta_data() {
152*ec779b8eSAndroid Build Coastguard Worker     return *mMetaData;
153*ec779b8eSAndroid Build Coastguard Worker }
154*ec779b8eSAndroid Build Coastguard Worker 
reset()155*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::reset() {
156*ec779b8eSAndroid Build Coastguard Worker     mMetaData->clear();
157*ec779b8eSAndroid Build Coastguard Worker     set_range(0, mSize);
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker 
~MediaBuffer()160*ec779b8eSAndroid Build Coastguard Worker MediaBuffer::~MediaBuffer() {
161*ec779b8eSAndroid Build Coastguard Worker     CHECK(mObserver == NULL);
162*ec779b8eSAndroid Build Coastguard Worker 
163*ec779b8eSAndroid Build Coastguard Worker     if (mOwnsData && mData != NULL && mMemory == NULL) {
164*ec779b8eSAndroid Build Coastguard Worker         free(mData);
165*ec779b8eSAndroid Build Coastguard Worker         mData = NULL;
166*ec779b8eSAndroid Build Coastguard Worker     }
167*ec779b8eSAndroid Build Coastguard Worker 
168*ec779b8eSAndroid Build Coastguard Worker    if (mMemory.get() != nullptr) {
169*ec779b8eSAndroid Build Coastguard Worker        getSharedControl()->setDeadObject();
170*ec779b8eSAndroid Build Coastguard Worker    }
171*ec779b8eSAndroid Build Coastguard Worker    delete mMetaData;
172*ec779b8eSAndroid Build Coastguard Worker }
173*ec779b8eSAndroid Build Coastguard Worker 
setObserver(MediaBufferObserver * observer)174*ec779b8eSAndroid Build Coastguard Worker void MediaBuffer::setObserver(MediaBufferObserver *observer) {
175*ec779b8eSAndroid Build Coastguard Worker     CHECK(observer == NULL || mObserver == NULL);
176*ec779b8eSAndroid Build Coastguard Worker     mObserver = observer;
177*ec779b8eSAndroid Build Coastguard Worker }
178*ec779b8eSAndroid Build Coastguard Worker 
179*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
180