CallbackDataSource.cpp revision 83d9698ce5825566a8621f93c58721d0745fd55f
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(); 3769d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen mName = String8::format("CallbackDataSource(%s)", mIDataSource->toString().string()); 3869d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen 3999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 4099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 4199f31604136d66ae10e20669fb6b5716f342bde0Chris WatkinsCallbackDataSource::~CallbackDataSource() { 4299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ALOGV("~CallbackDataSource"); 43fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen close(); 4499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 4599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 4699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::initCheck() const { 4799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mMemory == NULL) { 4899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return UNKNOWN_ERROR; 4999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 5099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 5199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 5299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) { 5499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (mMemory == NULL) { 5599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return -1; 5699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 5799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 5899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource can only read up to mMemory->size() bytes at a time, but this 5999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // method should be able to read any number of bytes, so read in a loop. 6099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t totalNumRead = 0; 6199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numLeft = size; 6299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins const size_t bufferSize = mMemory->size(); 6399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 6499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins while (numLeft > 0) { 6599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins size_t numToRead = std::min(numLeft, bufferSize); 6699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins ssize_t numRead = 6799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins mIDataSource->readAt(offset + totalNumRead, numToRead); 6899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A negative return value represents an error. Pass it on. 6999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead < 0) { 7040a3f52cc7d4f657f963d9c2b47007fdfd3fc9ddRobert Shih return numRead == ERROR_END_OF_STREAM && totalNumRead > 0 ? totalNumRead : numRead; 7199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 7299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // A zero return value signals EOS. Return the bytes read so far. 7399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (numRead == 0) { 7499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 7599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 76da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > numToRead) { 77da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 78da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 79da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(numRead >= 0 && (size_t)numRead <= bufferSize); 8099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead); 8199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins numLeft -= numRead; 8299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins totalNumRead += numRead; 8399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 8499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return totalNumRead; 8699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 8799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 8899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkinsstatus_t CallbackDataSource::getSize(off64_t *size) { 8999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins status_t err = mIDataSource->getSize(size); 9099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (err != OK) { 9199f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return err; 9299f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins if (*size < 0) { 9499f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // IDataSource will set size to -1 to indicate unknown size, but 9599f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins // DataSource returns ERROR_UNSUPPORTED for that. 9699f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return ERROR_UNSUPPORTED; 9799f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins } 9899f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins return OK; 9999f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} 10099f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins 10110551fcd58b3807fc7351d88e6127ec227b993d1Wei Jiauint32_t CallbackDataSource::flags() { 10210551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia return mIDataSource->getFlags(); 10310551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia} 10410551fcd58b3807fc7351d88e6127ec227b993d1Wei Jia 105fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissenvoid CallbackDataSource::close() { 106fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen if (!mIsClosed) { 107fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIDataSource->close(); 108fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen mIsClosed = true; 109fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen } 110fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen} 111fbe7fcfe818b6f68e352c7c450d4fe15a543b801Marco Nelissen 11283d9698ce5825566a8621f93c58721d0745fd55fWei Jiasp<DecryptHandle> CallbackDataSource::DrmInitialization(const char *mime) { 11383d9698ce5825566a8621f93c58721d0745fd55fWei Jia return mIDataSource->DrmInitialization(mime); 11483d9698ce5825566a8621f93c58721d0745fd55fWei Jia} 11583d9698ce5825566a8621f93c58721d0745fd55fWei Jia 116da7e453e1d1c77959822cf9602ddfed1c50be445Chris WatkinsTinyCacheSource::TinyCacheSource(const sp<DataSource>& source) 117da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins : mSource(source), mCachedOffset(0), mCachedSize(0) { 11869d3d8a9540b0da787ea0beccad2517f057dd54dMarco Nelissen mName = String8::format("TinyCacheSource(%s)", mSource->toString().string()); 119da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 120da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 121da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::initCheck() const { 122da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->initCheck(); 123da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 124da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 125da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) { 126da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (size >= kCacheSize) { 127da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->readAt(offset, data, size); 128da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 129da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 130da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Check if the cache satisfies the read. 13171ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim if (mCachedOffset <= offset 13271ec3dfc1d8d53bdc8f99b69286b60ecb926d7ffWonsik Kim && offset < (off64_t) (mCachedOffset + mCachedSize)) { 13306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (offset + size <= mCachedOffset + mCachedSize) { 13406ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], size); 13506ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return size; 13606ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } else { 13706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // If the cache hits only partially, flush the cache and read the 13806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // remainder. 13906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim 14006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // This value is guaranteed to be greater than 0 because of the 14106ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim // enclosing if statement. 14206ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t remaining = mCachedOffset + mCachedSize - offset; 14306ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim memcpy(data, &mCache[offset - mCachedOffset], remaining); 14406ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim const ssize_t readMore = readAt(offset + remaining, 14506ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim (uint8_t*)data + remaining, size - remaining); 14606ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim if (readMore < 0) { 14706ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return readMore; 14806ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 14906ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim return remaining + readMore; 15006ec7f3ef28ee68714d323ca9e2d3cab2165dfe8Wonsik Kim } 151da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 152da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 15383d9698ce5825566a8621f93c58721d0745fd55fWei Jia 154da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins // Fill the cache and copy to the caller. 155da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize); 156da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if (numRead <= 0) { 15783d9698ce5825566a8621f93c58721d0745fd55fWei Jia // Flush cache on error 15883d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedSize = 0; 15983d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedOffset = 0; 160da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numRead; 161da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 162da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins if ((size_t)numRead > kCacheSize) { 16383d9698ce5825566a8621f93c58721d0745fd55fWei Jia // Flush cache on error 16483d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedSize = 0; 16583d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedOffset = 0; 166da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return ERROR_OUT_OF_RANGE; 167da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins } 168da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 169da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedSize = numRead; 170da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins mCachedOffset = offset; 171da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0); 172da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins const size_t numToReturn = std::min(size, (size_t)numRead); 173da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins memcpy(data, mCache, numToReturn); 174da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 175da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return numToReturn; 176da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 177da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 178da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsstatus_t TinyCacheSource::getSize(off64_t *size) { 179da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->getSize(size); 180da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 181da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 182da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkinsuint32_t TinyCacheSource::flags() { 183da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins return mSource->flags(); 184da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins} 185da7e453e1d1c77959822cf9602ddfed1c50be445Chris Watkins 18683d9698ce5825566a8621f93c58721d0745fd55fWei Jiasp<DecryptHandle> TinyCacheSource::DrmInitialization(const char *mime) { 18783d9698ce5825566a8621f93c58721d0745fd55fWei Jia // flush cache when DrmInitialization occurs since decrypted 18883d9698ce5825566a8621f93c58721d0745fd55fWei Jia // data may differ from what is in cache. 18983d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedOffset = 0; 19083d9698ce5825566a8621f93c58721d0745fd55fWei Jia mCachedSize = 0; 19183d9698ce5825566a8621f93c58721d0745fd55fWei Jia return mSource->DrmInitialization(mime); 19283d9698ce5825566a8621f93c58721d0745fd55fWei Jia} 19399f31604136d66ae10e20669fb6b5716f342bde0Chris Watkins} // namespace android 194