Home | History | Annotate | Download | only in libstagefright
      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/MediaBuffer.h>
     25 #include <media/stagefright/MediaDebug.h>
     26 #include <media/stagefright/MetaData.h>
     27 
     28 namespace android {
     29 
     30 // XXX make this truly atomic.
     31 static int atomic_add(int *value, int delta) {
     32     int prev_value = *value;
     33     *value += delta;
     34 
     35     return prev_value;
     36 }
     37 
     38 MediaBuffer::MediaBuffer(void *data, size_t size)
     39     : mObserver(NULL),
     40       mNextBuffer(NULL),
     41       mRefCount(0),
     42       mData(data),
     43       mSize(size),
     44       mRangeOffset(0),
     45       mRangeLength(size),
     46       mOwnsData(false),
     47       mMetaData(new MetaData),
     48       mOriginal(NULL) {
     49 }
     50 
     51 MediaBuffer::MediaBuffer(size_t size)
     52     : mObserver(NULL),
     53       mNextBuffer(NULL),
     54       mRefCount(0),
     55       mData(malloc(size)),
     56       mSize(size),
     57       mRangeOffset(0),
     58       mRangeLength(size),
     59       mOwnsData(true),
     60       mMetaData(new MetaData),
     61       mOriginal(NULL) {
     62 }
     63 
     64 void MediaBuffer::release() {
     65     if (mObserver == NULL) {
     66         CHECK_EQ(mRefCount, 0);
     67         delete this;
     68         return;
     69     }
     70 
     71     int prevCount = atomic_add(&mRefCount, -1);
     72     if (prevCount == 1) {
     73         if (mObserver == NULL) {
     74             delete this;
     75             return;
     76         }
     77 
     78         mObserver->signalBufferReturned(this);
     79     }
     80     CHECK(prevCount > 0);
     81 }
     82 
     83 void MediaBuffer::claim() {
     84     CHECK(mObserver != NULL);
     85     CHECK_EQ(mRefCount, 1);
     86 
     87     mRefCount = 0;
     88 }
     89 
     90 void MediaBuffer::add_ref() {
     91     atomic_add(&mRefCount, 1);
     92 }
     93 
     94 void *MediaBuffer::data() const {
     95     return mData;
     96 }
     97 
     98 size_t MediaBuffer::size() const {
     99     return mSize;
    100 }
    101 
    102 size_t MediaBuffer::range_offset() const {
    103     return mRangeOffset;
    104 }
    105 
    106 size_t MediaBuffer::range_length() const {
    107     return mRangeLength;
    108 }
    109 
    110 void MediaBuffer::set_range(size_t offset, size_t length) {
    111     if (offset + length > mSize) {
    112         LOGE("offset = %d, length = %d, mSize = %d", offset, length, mSize);
    113     }
    114     CHECK(offset + length <= mSize);
    115 
    116     mRangeOffset = offset;
    117     mRangeLength = length;
    118 }
    119 
    120 sp<MetaData> MediaBuffer::meta_data() {
    121     return mMetaData;
    122 }
    123 
    124 void MediaBuffer::reset() {
    125     mMetaData->clear();
    126     set_range(0, mSize);
    127 }
    128 
    129 MediaBuffer::~MediaBuffer() {
    130     CHECK_EQ(mObserver, NULL);
    131 
    132     if (mOwnsData && mData != NULL) {
    133         free(mData);
    134         mData = NULL;
    135     }
    136 
    137     if (mOriginal != NULL) {
    138         mOriginal->release();
    139         mOriginal = NULL;
    140     }
    141 }
    142 
    143 void MediaBuffer::setObserver(MediaBufferObserver *observer) {
    144     CHECK(observer == NULL || mObserver == NULL);
    145     mObserver = observer;
    146 }
    147 
    148 void MediaBuffer::setNextBuffer(MediaBuffer *buffer) {
    149     mNextBuffer = buffer;
    150 }
    151 
    152 MediaBuffer *MediaBuffer::nextBuffer() {
    153     return mNextBuffer;
    154 }
    155 
    156 int MediaBuffer::refcount() const {
    157     return mRefCount;
    158 }
    159 
    160 MediaBuffer *MediaBuffer::clone() {
    161     MediaBuffer *buffer = new MediaBuffer(mData, mSize);
    162     buffer->set_range(mRangeOffset, mRangeLength);
    163     buffer->mMetaData = new MetaData(*mMetaData.get());
    164 
    165     add_ref();
    166     buffer->mOriginal = this;
    167 
    168     return buffer;
    169 }
    170 
    171 }  // namespace android
    172 
    173