1c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown/* 2c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * Copyright (C) 2012 The Android Open Source Project 3c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * 4c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License"); 5c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * you may not use this file except in compliance with the License. 6c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * You may obtain a copy of the License at 7c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * 8c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * http://www.apache.org/licenses/LICENSE-2.0 9c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * 10c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * Unless required by applicable law or agreed to in writing, software 11c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS, 12c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * See the License for the specific language governing permissions and 14c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown * limitations under the License. 15c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown */ 16c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 17c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown//#define LOG_NDEBUG 0 18c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown#define LOG_TAG "SkipCutBuffer" 19a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn#include <utils/Log.h> 207b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock 21c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown#include <media/stagefright/foundation/ADebug.h> 22c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown#include <media/stagefright/MediaBuffer.h> 23c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown#include <media/stagefright/SkipCutBuffer.h> 24c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 25c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brownnamespace android { 26c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 27c2346134bb519a54d50655cbef940fc3fdec60a9Jeff BrownSkipCutBuffer::SkipCutBuffer(int32_t skip, int32_t cut) { 28c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mFrontPadding = mSkip = skip; 29c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mBackPadding = cut; 30c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mWriteHead = 0; 31c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mReadHead = 0; 32c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mCapacity = cut + 4096; 33c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mCutBuffer = new char[mCapacity]; 34c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown ALOGV("skipcutbuffer %d %d %d", skip, cut, mCapacity); 35a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn} 36a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn 37a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne HackbornSkipCutBuffer::~SkipCutBuffer() { 38a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn delete[] mCutBuffer; 39a06de0f29b58df9246779cc4bfd8f06f7205ddb6Dianne Hackborn} 401af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock 41c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brownvoid SkipCutBuffer::submit(MediaBuffer *buffer) { 42c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t offset = buffer->range_offset(); 43c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t buflen = buffer->range_length(); 44c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 45c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // drop the initial data from the buffer if needed 46c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown if (mFrontPadding > 0) { 47c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // still data left to drop 48c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding; 49c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown offset += to_drop; 50c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown buflen -= to_drop; 51c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown buffer->set_range(offset, buflen); 52c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mFrontPadding -= to_drop; 53c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown } 54c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 55c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 56c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // append data to cutbuffer 57c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown char *src = ((char*) buffer->data()) + offset; 58f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn write(src, buflen); 59f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 60f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn 61f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn // the mediabuffer is now empty. Fill it from cutbuffer, always leaving 627b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock // at least mBackPadding bytes in the cutbuffer 63c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown char *dst = (char*) buffer->data(); 64c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown size_t copied = read(dst, buffer->size()); 65c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown buffer->set_range(0, copied); 66c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown} 67c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 687b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockvoid SkipCutBuffer::submit(const sp<ABuffer>& buffer) { 69c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t offset = buffer->offset(); 70c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t buflen = buffer->size(); 71c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 72c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // drop the initial data from the buffer if needed 73c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown if (mFrontPadding > 0) { 74f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn // still data left to drop 75f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding; 76f265ea9d8307282ff1da3915978625a94fc2859eDianne Hackborn offset += to_drop; 77c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown buflen -= to_drop; 788fd7f1ed7c11d35b3f2a97878e68ee38a551dd15Christoph Studer buffer->setRange(offset, buflen); 797b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock mFrontPadding -= to_drop; 80c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown } 81c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 82c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 83c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // append data to cutbuffer 84c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown char *src = (char*) buffer->data(); 85c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown write(src, buflen); 86c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 87c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 88c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // the mediabuffer is now empty. Fill it from cutbuffer, always leaving 897b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock // at least mBackPadding bytes in the cutbuffer 901af30c7ac480e5d335f267a3ac3b2e6c748ce240John Spurlock char *dst = (char*) buffer->base(); 91c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown size_t copied = read(dst, buffer->capacity()); 92c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown buffer->setRange(0, copied); 93c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown} 94c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 95c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brownvoid SkipCutBuffer::clear() { 96c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mWriteHead = mReadHead = 0; 97c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mFrontPadding = mSkip; 98c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown} 997b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock 1007b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlockvoid SkipCutBuffer::write(const char *src, size_t num) { 1017b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock int32_t sizeused = (mWriteHead - mReadHead); 1027b41467704f941b11af6aace3e40993afc7f6c6fJohn Spurlock if (sizeused < 0) sizeused += mCapacity; 103c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 104c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // Everything must fit. Make sure the buffer is a little larger than needed, 105c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer 106c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown // full or empty 107c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown size_t available = mCapacity - sizeused - 32; 108c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown if (available < num) { 109c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown int32_t newcapacity = mCapacity + (num - available); 110c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown char * newbuffer = new char[newcapacity]; 111c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown memcpy(newbuffer, mCutBuffer, mCapacity); 112c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown delete [] mCutBuffer; 113c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown mCapacity = newcapacity; 114c2346134bb519a54d50655cbef940fc3fdec60a9Jeff Brown 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