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