Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2012 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_NDEBUG 0
     18 #define LOG_TAG "SkipCutBuffer"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/foundation/ADebug.h>
     22 #include <media/stagefright/MediaBuffer.h>
     23 #include <media/stagefright/SkipCutBuffer.h>
     24 
     25 namespace android {
     26 
     27 SkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut) {
     28     mFrontPadding = mSkip = skip;
     29     mBackPadding = cut;
     30     mWriteHead = 0;
     31     mReadHead = 0;
     32     mCapacity = cut + 4096;
     33     mCutBuffer = new char[mCapacity];
     34     ALOGV("skipcutbuffer %d %d %d", skip, cut, mCapacity);
     35 }
     36 
     37 SkipCutBuffer::~SkipCutBuffer() {
     38     delete[] mCutBuffer;
     39 }
     40 
     41 void SkipCutBuffer::submit(MediaBuffer *buffer) {
     42     int32_t offset = buffer->range_offset();
     43     int32_t buflen = buffer->range_length();
     44 
     45     // drop the initial data from the buffer if needed
     46     if (mFrontPadding > 0) {
     47         // still data left to drop
     48         int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
     49         offset += to_drop;
     50         buflen -= to_drop;
     51         buffer->set_range(offset, buflen);
     52         mFrontPadding -= to_drop;
     53     }
     54 
     55 
     56     // append data to cutbuffer
     57     char *src = ((char*) buffer->data()) + offset;
     58     write(src, buflen);
     59 
     60 
     61     // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
     62     // at least mBackPadding bytes in the cutbuffer
     63     char *dst = (char*) buffer->data();
     64     size_t copied = read(dst, buffer->size());
     65     buffer->set_range(0, copied);
     66 }
     67 
     68 void SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
     69     int32_t offset = buffer->offset();
     70     int32_t buflen = buffer->size();
     71 
     72     // drop the initial data from the buffer if needed
     73     if (mFrontPadding > 0) {
     74         // still data left to drop
     75         int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
     76         offset += to_drop;
     77         buflen -= to_drop;
     78         buffer->setRange(offset, buflen);
     79         mFrontPadding -= to_drop;
     80     }
     81 
     82 
     83     // append data to cutbuffer
     84     char *src = (char*) buffer->data();
     85     write(src, buflen);
     86 
     87 
     88     // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
     89     // at least mBackPadding bytes in the cutbuffer
     90     char *dst = (char*) buffer->base();
     91     size_t copied = read(dst, buffer->capacity());
     92     buffer->setRange(0, copied);
     93 }
     94 
     95 void SkipCutBuffer::clear() {
     96     mWriteHead = mReadHead = 0;
     97     mFrontPadding = mSkip;
     98 }
     99 
    100 void SkipCutBuffer::write(const char *src, size_t num) {
    101     int32_t sizeused = (mWriteHead - mReadHead);
    102     if (sizeused < 0) sizeused += mCapacity;
    103 
    104     // Everything must fit. Make sure the buffer is a little larger than needed,
    105     // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer
    106     // full or empty
    107     size_t available = mCapacity - sizeused - 32;
    108     if (available < num) {
    109         int32_t newcapacity = mCapacity + (num - available);
    110         char * newbuffer = new char[newcapacity];
    111         memcpy(newbuffer, mCutBuffer, mCapacity);
    112         delete [] mCutBuffer;
    113         mCapacity = newcapacity;
    114         mCutBuffer = newbuffer;
    115         ALOGV("reallocated buffer at size %d", newcapacity);
    116     }
    117 
    118     size_t copyfirst = (mCapacity - mWriteHead);
    119     if (copyfirst > num) copyfirst = num;
    120     if (copyfirst) {
    121         memcpy(mCutBuffer + mWriteHead, src, copyfirst);
    122         num -= copyfirst;
    123         src += copyfirst;
    124         mWriteHead += copyfirst;
    125         CHECK_LE(mWriteHead, mCapacity);
    126         if (mWriteHead == mCapacity) mWriteHead = 0;
    127         if (num) {
    128             memcpy(mCutBuffer, src, num);
    129             mWriteHead += num;
    130         }
    131     }
    132 }
    133 
    134 size_t SkipCutBuffer::read(char *dst, size_t num) {
    135     int32_t available = (mWriteHead - mReadHead);
    136     if (available < 0) available += mCapacity;
    137 
    138     available -= mBackPadding;
    139     if (available <=0) {
    140         return 0;
    141     }
    142     if (available < int32_t(num)) {
    143         num = available;
    144     }
    145 
    146     size_t copyfirst = (mCapacity - mReadHead);
    147     if (copyfirst > num) copyfirst = num;
    148     if (copyfirst) {
    149         memcpy(dst, mCutBuffer + mReadHead, copyfirst);
    150         num -= copyfirst;
    151         dst += copyfirst;
    152         mReadHead += copyfirst;
    153         CHECK_LE(mReadHead, mCapacity);
    154         if (mReadHead == mCapacity) mReadHead = 0;
    155         if (num) {
    156             memcpy(dst, mCutBuffer, num);
    157             mReadHead += num;
    158         }
    159     }
    160     return available;
    161 }
    162 
    163 size_t SkipCutBuffer::size() {
    164     int32_t available = (mWriteHead - mReadHead);
    165     if (available < 0) available += mCapacity;
    166     return available;
    167 }
    168 
    169 }  // namespace android
    170