CallbackDataSource.cpp revision fbe7fcfe818b6f68e352c7c450d4fe15a543b801
199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins/* 299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Copyright 2015 The Android Open Source Project 399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Licensed under the Apache License, Version 2.0 (the "License"); 599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * you may not use this file except in compliance with the License. 699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * You may obtain a copy of the License at 799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * http://www.apache.org/licenses/LICENSE-2.0 999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * 1099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * Unless required by applicable law or agreed to in writing, software 1199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * distributed under the License is distributed on an "AS IS" BASIS, 1299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * See the License for the specific language governing permissions and 1499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins * limitations under the License. 1599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins */ 1699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 1799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins//#define LOG_NDEBUG 0 1899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#define LOG_TAG "CallbackDataSource" 1999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <utils/Log.h> 2099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include "include/CallbackDataSource.h" 2299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <binder/IMemory.h> 2499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <media/IDataSource.h> 2599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <media/stagefright/foundation/ADebug.h> 2699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins#include <algorithm> 2899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 2999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsnamespace android { 3099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 3199f31604136d66ae10e20669fb6b5716f342bde0Chris WatkinsCallbackDataSource::CallbackDataSource( 3299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const sp<IDataSource>& binderDataSource) 33fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen : mIDataSource(binderDataSource), 34fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIsClosed(false) { 3599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // Set up the buffer to read into. 3699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mMemory = mIDataSource->getIMemory(); 3799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 3899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 3999f31604136d66ae10e20669fb6b5716f342bde0Chris WatkinsCallbackDataSource::~CallbackDataSource() { 4099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ALOGV("~CallbackDataSource"); 41fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen close(); 4299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 4399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 4499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::initCheck() const { 4599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mMemory == NULL) { 4699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return UNKNOWN_ERROR; 4799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 4899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 4999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 5099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) { 5299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mMemory == NULL) { 5399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return -1; 5499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 5599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource can only read up to mMemory->size() bytes at a time, but this 5799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // method should be able to read any number of bytes, so read in a loop. 5899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t totalNumRead = 0; 5999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numLeft = size; 6099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const size_t bufferSize = mMemory->size(); 6199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 6299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins while (numLeft > 0) { 6399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numToRead = std::min(numLeft, bufferSize); 6499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ssize_t numRead = 6599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mIDataSource->readAt(offset + totalNumRead, numToRead); 6699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A negative return value represents an error. Pass it on. 6799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead < 0) { 6840a3f52cc7d4f657f963d9c2b47007fdfd3fc9ddRobert Shih return numRead == ERROR_END_OF_STREAM && totalNumRead > 0 ? totalNumRead : numRead; 6999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 7099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A zero return value signals EOS. Return the bytes read so far. 7199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead == 0) { 7299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 7399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 74da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > numToRead) { 75da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 76da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 77da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(numRead >= 0 && (size_t)numRead <= bufferSize); 7899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead); 7999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins numLeft -= numRead; 8099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins totalNumRead += numRead; 8199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 8299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 8499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 8599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::getSize(off64_t *size) { 8799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins status_t err = mIDataSource->getSize(size); 8899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (err != OK) { 8999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return err; 9099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (*size < 0) { 9299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource will set size to -1 to indicate unknown size, but 9399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // DataSource returns ERROR_UNSUPPORTED for that. 9499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return ERROR_UNSUPPORTED; 9599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 9799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 9899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 9910551fcd58b3807fc7351d88e6127ec227b993d1Wei Jiauint32_t CallbackDataSource::flags() { 10010551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia return mIDataSource->getFlags(); 10110551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia} 10210551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia 103fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissenvoid CallbackDataSource::close() { 104fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen if (!mIsClosed) { 105fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIDataSource->close(); 106fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIsClosed = true; 107fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen } 108fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen} 109fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen 110da7e453e1d1c77959822cf9602ddfed1c50be445Chris WatkinsTinyCacheSource::TinyCacheSource(const sp<DataSource>& source) 111da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins : mSource(source), mCachedOffset(0), mCachedSize(0) { 112da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 113da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 114da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::initCheck() const { 115da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->initCheck(); 116da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 117da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 118da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) { 119da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (size >= kCacheSize) { 120da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->readAt(offset, data, size); 121da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 122da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 123da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Check if the cache satisfies the read. 12471ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim if (mCachedOffset <= offset 12571ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim && offset < (off64_t) (mCachedOffset + mCachedSize)) { 12606ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (offset + size <= mCachedOffset + mCachedSize) { 12706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], size); 12806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return size; 12906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } else { 13006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // If the cache hits only partially, flush the cache and read the 13106ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // remainder. 13206ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim 13306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // This value is guaranteed to be greater than 0 because of the 13406ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // enclosing if statement. 13506ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t remaining = mCachedOffset + mCachedSize - offset; 13606ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], remaining); 13706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t readMore = readAt(offset + remaining, 13806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim (uint8_t*)data + remaining, size - remaining); 13906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (readMore < 0) { 14006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return readMore; 14106ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 14206ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return remaining + readMore; 14306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 144da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 145da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 146da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Fill the cache and copy to the caller. 147da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize); 148da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (numRead <= 0) { 149da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numRead; 150da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 151da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > kCacheSize) { 152da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 153da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 154da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 155da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedSize = numRead; 156da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedOffset = offset; 157da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0); 158da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const size_t numToReturn = std::min(size, (size_t)numRead); 159da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins memcpy(data, mCache, numToReturn); 160da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 161da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numToReturn; 162da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 163da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 164da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::getSize(off64_t *size) { 165da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->getSize(size); 166da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 167da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 168da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsuint32_t TinyCacheSource::flags() { 169da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->flags(); 170da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 171da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 17299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} // namespace android 173