1a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen/*
2a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Copyright (C) 2012 The Android Open Source Project
3a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
4a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
5a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * you may not use this file except in compliance with the License.
6a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * You may obtain a copy of the License at
7a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
8a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
9a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen *
10a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * Unless required by applicable law or agreed to in writing, software
11a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
12a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * See the License for the specific language governing permissions and
14a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen * limitations under the License.
15a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen */
16a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
17a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen//#define LOG_NDEBUG 0
18a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen#define LOG_TAG "SkipCutBuffer"
19a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen#include <utils/Log.h>
20a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
21a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen#include <media/stagefright/foundation/ADebug.h>
22a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen#include <media/stagefright/MediaBuffer.h>
23a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen#include <media/stagefright/SkipCutBuffer.h>
24a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
25a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissennamespace android {
26a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
27b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco NelissenSkipCutBuffer::SkipCutBuffer(size_t skip, size_t cut, size_t num16BitChannels) {
28d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissen
29b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    mWriteHead = 0;
30b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    mReadHead = 0;
31b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    mCapacity = 0;
32b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    mCutBuffer = NULL;
33b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen
34b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    if (num16BitChannels == 0 || num16BitChannels > INT32_MAX / 2) {
35b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        ALOGW("# channels out of range: %zu, using passthrough instead", num16BitChannels);
36b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        return;
37d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissen    }
38b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    size_t frameSize = num16BitChannels * 2;
39b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    if (skip > INT32_MAX / frameSize || cut > INT32_MAX / frameSize
40b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen            || cut * frameSize > INT32_MAX - 4096) {
41b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        ALOGW("out of range skip/cut: %zu/%zu, using passthrough instead",
42b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen                skip, cut);
43b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        return;
44b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    }
45b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    skip *= frameSize;
46b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    cut *= frameSize;
47d5fa8d5dcdf8742f03fdc165f7529d7627b0eb01Marco Nelissen
48a6cdabf38b29ee98bdb3e874b4e2978dbc409624Marco Nelissen    mFrontPadding = mSkip = skip;
49a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    mBackPadding = cut;
50cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    mCapacity = cut + 4096;
51b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    mCutBuffer = new (std::nothrow) char[mCapacity];
52b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    ALOGV("skipcutbuffer %zu %zu %d", skip, cut, mCapacity);
53a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
54a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
55a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco NelissenSkipCutBuffer::~SkipCutBuffer() {
56a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    delete[] mCutBuffer;
57a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
58a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
59a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenvoid SkipCutBuffer::submit(MediaBuffer *buffer) {
60b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    if (mCutBuffer == NULL) {
61b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        // passthrough mode
62b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        return;
63b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    }
64b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen
65a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    int32_t offset = buffer->range_offset();
66a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    int32_t buflen = buffer->range_length();
67a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
68a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    // drop the initial data from the buffer if needed
69a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (mFrontPadding > 0) {
70a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        // still data left to drop
71a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
72a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        offset += to_drop;
73a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        buflen -= to_drop;
74a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        buffer->set_range(offset, buflen);
75a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mFrontPadding -= to_drop;
76a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    }
77a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
78a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
79a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    // append data to cutbuffer
80a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    char *src = ((char*) buffer->data()) + offset;
81a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    write(src, buflen);
82a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
83a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
84a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
85a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    // at least mBackPadding bytes in the cutbuffer
86a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    char *dst = (char*) buffer->data();
87a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    size_t copied = read(dst, buffer->size());
88a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    buffer->set_range(0, copied);
89a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
90a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
917e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kimtemplate <typename T>
927e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kimvoid SkipCutBuffer::submitInternal(const sp<T>& buffer) {
93b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    if (mCutBuffer == NULL) {
94b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        // passthrough mode
95b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen        return;
96b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen    }
97b1cf03160fa7e7bc6e5cf138db07a7e1ab2ecb26Marco Nelissen
98cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    int32_t offset = buffer->offset();
99cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    int32_t buflen = buffer->size();
100cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
101cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // drop the initial data from the buffer if needed
102cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    if (mFrontPadding > 0) {
103cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        // still data left to drop
104cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        int32_t to_drop = (buflen < mFrontPadding) ? buflen : mFrontPadding;
105cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        offset += to_drop;
106cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        buflen -= to_drop;
107cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        buffer->setRange(offset, buflen);
108cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        mFrontPadding -= to_drop;
109cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    }
110cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
111cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
112cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // append data to cutbuffer
113cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    char *src = (char*) buffer->data();
114cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    write(src, buflen);
115cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
116cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
117cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // the mediabuffer is now empty. Fill it from cutbuffer, always leaving
118cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // at least mBackPadding bytes in the cutbuffer
119cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    char *dst = (char*) buffer->base();
120cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    size_t copied = read(dst, buffer->capacity());
121cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    buffer->setRange(0, copied);
122cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen}
123cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen
1247e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kimvoid SkipCutBuffer::submit(const sp<ABuffer>& buffer) {
1257e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    submitInternal(buffer);
1267e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim}
1277e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim
1287e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kimvoid SkipCutBuffer::submit(const sp<MediaCodecBuffer>& buffer) {
1297e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim    submitInternal(buffer);
1307e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim}
1317e34bf5af26f8752d4786d3098740cdf51e2438fWonsik Kim
132a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenvoid SkipCutBuffer::clear() {
133a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    mWriteHead = mReadHead = 0;
134a6cdabf38b29ee98bdb3e874b4e2978dbc409624Marco Nelissen    mFrontPadding = mSkip;
135a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
136a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
137a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissenvoid SkipCutBuffer::write(const char *src, size_t num) {
138a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    int32_t sizeused = (mWriteHead - mReadHead);
139a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (sizeused < 0) sizeused += mCapacity;
140a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
141cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // Everything must fit. Make sure the buffer is a little larger than needed,
142cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // so there is no ambiguity as to whether mWriteHead == mReadHead means buffer
143cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    // full or empty
144cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    size_t available = mCapacity - sizeused - 32;
145cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    if (available < num) {
146cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        int32_t newcapacity = mCapacity + (num - available);
147cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        char * newbuffer = new char[newcapacity];
148cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        memcpy(newbuffer, mCutBuffer, mCapacity);
149cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        delete [] mCutBuffer;
150cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        mCapacity = newcapacity;
151cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        mCutBuffer = newbuffer;
152cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen        ALOGV("reallocated buffer at size %d", newcapacity);
153cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    }
154a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
155a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    size_t copyfirst = (mCapacity - mWriteHead);
156a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (copyfirst > num) copyfirst = num;
157a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (copyfirst) {
158a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        memcpy(mCutBuffer + mWriteHead, src, copyfirst);
159a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        num -= copyfirst;
160a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        src += copyfirst;
161a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mWriteHead += copyfirst;
162a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        CHECK_LE(mWriteHead, mCapacity);
163a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (mWriteHead == mCapacity) mWriteHead = 0;
164a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (num) {
165a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            memcpy(mCutBuffer, src, num);
166a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            mWriteHead += num;
167a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        }
168a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    }
169a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
170a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
171a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissensize_t SkipCutBuffer::read(char *dst, size_t num) {
172a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    int32_t available = (mWriteHead - mReadHead);
173a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (available < 0) available += mCapacity;
174a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
175a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    available -= mBackPadding;
176a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (available <=0) {
177a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        return 0;
178a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    }
179cb5b766bb0a3ed992998a5bd66de0ee1d2223b81Marco Nelissen    if (available < int32_t(num)) {
180a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        num = available;
181a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    }
182a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
183a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    size_t copyfirst = (mCapacity - mReadHead);
184a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (copyfirst > num) copyfirst = num;
185a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (copyfirst) {
186a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        memcpy(dst, mCutBuffer + mReadHead, copyfirst);
187a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        num -= copyfirst;
188a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        dst += copyfirst;
189a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        mReadHead += copyfirst;
190a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        CHECK_LE(mReadHead, mCapacity);
191a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (mReadHead == mCapacity) mReadHead = 0;
192a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        if (num) {
193a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            memcpy(dst, mCutBuffer, num);
194a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen            mReadHead += num;
195a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen        }
196a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    }
197a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    return available;
198a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
199a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
200a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissensize_t SkipCutBuffer::size() {
201a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    int32_t available = (mWriteHead - mReadHead);
202a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    if (available < 0) available += mCapacity;
203a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen    return available;
204a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}
205a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen
206a98478bfbcc0f7fb4b164d3dce40ca96df75667dMarco Nelissen}  // namespace android
207