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 = 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 }
     98 
     99 void SkipCutBuffer::write(const char *src, size_t num) {
    100     int32_t sizeused = (mWriteHead - mReadHead);
    101     if (sizeused < 0) sizeused += mCapacity;
    102 
    103     // Everything must fit. Make sure the buffer is a little larger than needed,
    104     // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer
    105     // full or empty
    106     size_t available = mCapacity - sizeused - 32;
    107     if (available < num) {
    108         int32_t newcapacity = mCapacity + (num - available);
    109         char * newbuffer = new char[newcapacity];
    110         memcpy(newbuffer, mCutBuffer, mCapacity);
    111         delete [] mCutBuffer;
    112         mCapacity = newcapacity;
    113         mCutBuffer = newbuffer;
    114         ALOGV("reallocated buffer at size %d", newcapacity);
    115     }
    116 
    117     size_t copyfirst = (mCapacity - mWriteHead);
    118     if (copyfirst > num) copyfirst = num;
    119     if (copyfirst) {
    120         memcpy(mCutBuffer + mWriteHead, src, copyfirst);
    121         num -= copyfirst;
    122         src += copyfirst;
    123         mWriteHead += copyfirst;
    124         CHECK_LE(mWriteHead, mCapacity);
    125         if (mWriteHead == mCapacity) mWriteHead = 0;
    126         if (num) {
    127             memcpy(mCutBuffer, src, num);
    128             mWriteHead += num;
    129         }
    130     }
    131 }
    132 
    133 size_t SkipCutBuffer::read(char *dst, size_t num) {
    134     int32_t available = (mWriteHead - mReadHead);
    135     if (available < 0) available += mCapacity;
    136 
    137     available -= mBackPadding;
    138     if (available <=0) {
    139         return 0;
    140     }
    141     if (available < int32_t(num)) {
    142         num = available;
    143     }
    144 
    145     size_t copyfirst = (mCapacity - mReadHead);
    146     if (copyfirst > num) copyfirst = num;
    147     if (copyfirst) {
    148         memcpy(dst, mCutBuffer + mReadHead, copyfirst);
    149         num -= copyfirst;
    150         dst += copyfirst;
    151         mReadHead += copyfirst;
    152         CHECK_LE(mReadHead, mCapacity);
    153         if (mReadHead == mCapacity) mReadHead = 0;
    154         if (num) {
    155             memcpy(dst, mCutBuffer, num);
    156             mReadHead += num;
    157         }
    158     }
    159     return available;
    160 }
    161 
    162 size_t SkipCutBuffer::size() {
    163     int32_t available = (mWriteHead - mReadHead);
    164     if (available < 0) available += mCapacity;
    165     return available;
    166 }
    167 
    168 }  // namespace android
    169