Home | History | Annotate | Download | only in foundation
      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 
     31 namespace android {
     32 
     33 /* static */
     34 std::atomic_int_least32_t MediaBuffer::mUseSharedMemory(0);
     35 
     36 MediaBuffer::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 
     48 MediaBuffer::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 
     80 MediaBuffer::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 
     93 MediaBuffer::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 
    106 void 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 
    126 void MediaBuffer::claim() {
    127     CHECK(mObserver != NULL);
    128     CHECK_EQ(mRefCount, 1);
    129 
    130     mRefCount = 0;
    131 }
    132 
    133 void MediaBuffer::add_ref() {
    134     (void) __sync_fetch_and_add(&mRefCount, 1);
    135 }
    136 
    137 void *MediaBuffer::data() const {
    138     CHECK(mGraphicBuffer == NULL);
    139     return mData;
    140 }
    141 
    142 size_t MediaBuffer::size() const {
    143     CHECK(mGraphicBuffer == NULL);
    144     return mSize;
    145 }
    146 
    147 size_t MediaBuffer::range_offset() const {
    148     return mRangeOffset;
    149 }
    150 
    151 size_t MediaBuffer::range_length() const {
    152     return mRangeLength;
    153 }
    154 
    155 void 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 
    165 sp<GraphicBuffer> MediaBuffer::graphicBuffer() const {
    166     return mGraphicBuffer;
    167 }
    168 
    169 sp<MetaData> MediaBuffer::meta_data() {
    170     return mMetaData;
    171 }
    172 
    173 void MediaBuffer::reset() {
    174     mMetaData->clear();
    175     set_range(0, mSize);
    176 }
    177 
    178 MediaBuffer::~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 
    196 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
    197     CHECK(observer == NULL || mObserver == NULL);
    198     mObserver = observer;
    199 }
    200 
    201 MediaBuffer *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