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