CallbackDataSource.cpp revision fbe7fcfe818b6f68e352c7c450d4fe15a543b801
187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines/*
287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Copyright 2015 The Android Open Source Project
387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *
487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * Licensed under the Apache License, Version 2.0 (the "License");
587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * you may not use this file except in compliance with the License.
687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * You may obtain a copy of the License at
787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *
887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines *      http://www.apache.org/licenses/LICENSE-2.0
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines *
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines * Unless required by applicable law or agreed to in writing, software
1187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * distributed under the License is distributed on an "AS IS" BASIS,
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines * See the License for the specific language governing permissions and
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines * limitations under the License.
1587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines */
1687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
1787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//#define LOG_NDEBUG 0
1887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#define LOG_TAG "CallbackDataSource"
1987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <utils/Log.h>
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "include/CallbackDataSource.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <binder/IMemory.h>
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include <media/IDataSource.h>
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <media/stagefright/foundation/ADebug.h>
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <algorithm>
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace android {
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3187f34658dec9097d987d254a990ea7f311bfc95fStephen HinesCallbackDataSource::CallbackDataSource(
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const sp<IDataSource>& binderDataSource)
3387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    : mIDataSource(binderDataSource),
3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      mIsClosed(false) {
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hines    // Set up the buffer to read into.
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    mMemory = mIDataSource->getIMemory();
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
3887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3937b74a387bb3993387029859c2d9d051c41c724eStephen HinesCallbackDataSource::~CallbackDataSource() {
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ALOGV("~CallbackDataSource");
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    close();
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatus_t CallbackDataSource::initCheck() const {
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (mMemory == NULL) {
4637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        return UNKNOWN_ERROR;
47    }
48    return OK;
49}
50
51ssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) {
52    if (mMemory == NULL) {
53        return -1;
54    }
55
56    // IDataSource can only read up to mMemory->size() bytes at a time, but this
57    // method should be able to read any number of bytes, so read in a loop.
58    size_t totalNumRead = 0;
59    size_t numLeft = size;
60    const size_t bufferSize = mMemory->size();
61
62    while (numLeft > 0) {
63        size_t numToRead = std::min(numLeft, bufferSize);
64        ssize_t numRead =
65            mIDataSource->readAt(offset + totalNumRead, numToRead);
66        // A negative return value represents an error. Pass it on.
67        if (numRead < 0) {
68            return numRead == ERROR_END_OF_STREAM && totalNumRead > 0 ? totalNumRead : numRead;
69        }
70        // A zero return value signals EOS. Return the bytes read so far.
71        if (numRead == 0) {
72            return totalNumRead;
73        }
74        if ((size_t)numRead > numToRead) {
75            return ERROR_OUT_OF_RANGE;
76        }
77        CHECK(numRead >= 0 && (size_t)numRead <= bufferSize);
78        memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead);
79        numLeft -= numRead;
80        totalNumRead += numRead;
81    }
82
83    return totalNumRead;
84}
85
86status_t CallbackDataSource::getSize(off64_t *size) {
87    status_t err = mIDataSource->getSize(size);
88    if (err != OK) {
89        return err;
90    }
91    if (*size < 0) {
92        // IDataSource will set size to -1 to indicate unknown size, but
93        // DataSource returns ERROR_UNSUPPORTED for that.
94        return ERROR_UNSUPPORTED;
95    }
96    return OK;
97}
98
99uint32_t CallbackDataSource::flags() {
100    return mIDataSource->getFlags();
101}
102
103void CallbackDataSource::close() {
104    if (!mIsClosed) {
105        mIDataSource->close();
106        mIsClosed = true;
107    }
108}
109
110TinyCacheSource::TinyCacheSource(const sp<DataSource>& source)
111    : mSource(source), mCachedOffset(0), mCachedSize(0) {
112}
113
114status_t TinyCacheSource::initCheck() const {
115    return mSource->initCheck();
116}
117
118ssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) {
119    if (size >= kCacheSize) {
120        return mSource->readAt(offset, data, size);
121    }
122
123    // Check if the cache satisfies the read.
124    if (mCachedOffset <= offset
125            && offset < (off64_t) (mCachedOffset + mCachedSize)) {
126        if (offset + size <= mCachedOffset + mCachedSize) {
127            memcpy(data, &mCache[offset - mCachedOffset], size);
128            return size;
129        } else {
130            // If the cache hits only partially, flush the cache and read the
131            // remainder.
132
133            // This value is guaranteed to be greater than 0 because of the
134            // enclosing if statement.
135            const ssize_t remaining = mCachedOffset + mCachedSize - offset;
136            memcpy(data, &mCache[offset - mCachedOffset], remaining);
137            const ssize_t readMore = readAt(offset + remaining,
138                    (uint8_t*)data + remaining, size - remaining);
139            if (readMore < 0) {
140                return readMore;
141            }
142            return remaining + readMore;
143        }
144    }
145
146    // Fill the cache and copy to the caller.
147    const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize);
148    if (numRead <= 0) {
149        return numRead;
150    }
151    if ((size_t)numRead > kCacheSize) {
152        return ERROR_OUT_OF_RANGE;
153    }
154
155    mCachedSize = numRead;
156    mCachedOffset = offset;
157    CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0);
158    const size_t numToReturn = std::min(size, (size_t)numRead);
159    memcpy(data, mCache, numToReturn);
160
161    return numToReturn;
162}
163
164status_t TinyCacheSource::getSize(off64_t *size) {
165    return mSource->getSize(size);
166}
167
168uint32_t TinyCacheSource::flags() {
169    return mSource->flags();
170}
171
172} // namespace android
173