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