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