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