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 25namespace android { 26 27SkipCutBuffer::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 37SkipCutBuffer::~SkipCutBuffer() { 38 delete[] mCutBuffer; 39} 40 41void 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 68void 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 95void SkipCutBuffer::clear() { 96 mWriteHead = mReadHead = 0; 97 mFrontPadding = mSkip; 98} 99 100void 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 134size_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 163size_t SkipCutBuffer::size() { 164 int32_t available = (mWriteHead - mReadHead); 165 if (available < 0) available += mCapacity; 166 return available; 167} 168 169} // namespace android 170