CallbackDataSource.cpp revision 69d3d8a9540b0da787ea0beccad2517f057dd54d
165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian/* 2d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * Copyright 2015 The Android Open Source Project 3d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * 4d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 5d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * you may not use this file except in compliance with the License. 6d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * You may obtain a copy of the License at 7d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * 8d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * http://www.apache.org/licenses/LICENSE-2.0 9d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * 10d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * Unless required by applicable law or agreed to in writing, software 11d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 12d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * See the License for the specific language governing permissions and 14d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk * limitations under the License. 15d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk */ 1665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 1765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian//#define LOG_NDEBUG 0 18a84bbe6b59721b1b963d65d270aa98d6513bbb78Eino-Ville Talvala#define LOG_TAG "CallbackDataSource" 198951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev#include <utils/Log.h> 2065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 21cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include "include/CallbackDataSource.h" 22cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 2365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <binder/IMemory.h> 24cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <media/IDataSource.h> 25cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk#include <media/stagefright/foundation/ADebug.h> 26cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 2765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian#include <algorithm> 28cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 2965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopiannamespace android { 3065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 31d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville TalvalaCallbackDataSource::CallbackDataSource( 32d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala const sp<IDataSource>& binderDataSource) 33d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala : mIDataSource(binderDataSource), 349c2a2c26c0d70de97f51063b06a5efc79b327eedAlex Deymo mIsClosed(false) { 35ceb388d6c03c38b96dc41c0ea4804b749aa077c4Eino-Ville Talvala // Set up the buffer to read into. 3665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mMemory = mIDataSource->getIMemory(); 3765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian mName = String8::format("CallbackDataSource(%s)", mIDataSource->toString().string()); 3865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 3965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 40cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk 4165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias AgopianCallbackDataSource::~CallbackDataSource() { 42b5ca4618a722a21f084fe8bfc1c2992749ccd3f0Nipun Kwatra ALOGV("~CallbackDataSource"); 43df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian close(); 4465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 45d89821ec5481e0640d84bfe3e29a1254a52ca683Eino-Ville Talvala 4665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopianstatus_t CallbackDataSource::initCheck() const { 471b86fe063badb5f28c467ade39be0f4008688947Andreas Huber if (mMemory == NULL) { 4865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return UNKNOWN_ERROR; 4999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk } 5065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return OK; 5165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian} 5265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 53d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunkssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) { 5498a668f6ea51e4d894d2ebb61a0e18287fb14008Chien-Yu Chen if (mMemory == NULL) { 55d1176ef16677b6c94fb893edb6a864cdccc0b190Ruben Brunk return -1; 56b2119af7f4ced0ecfefd4c7388f86b4e3a3ea7d8Ruben Brunk } 57b2119af7f4ced0ecfefd4c7388f86b4e3a3ea7d8Ruben Brunk 5865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // IDataSource can only read up to mMemory->size() bytes at a time, but this 5965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // method should be able to read any number of bytes, so read in a loop. 607b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala size_t totalNumRead = 0; 617b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala size_t numLeft = size; 627b82efe7a376c882f8f938e1c41b8311a8cdda4aEino-Ville Talvala const size_t bufferSize = mMemory->size(); 63ff3e31d2b100d8efd969b358b18e4405c49dd10dIgor Murashkin 6465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian while (numLeft > 0) { 650dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh size_t numToRead = std::min(numLeft, bufferSize); 660dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh ssize_t numRead = 670dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh mIDataSource->readAt(offset + totalNumRead, numToRead); 680dea57fd9fc4b2ccaab97d9477359fbd5a626f5cYin-Chia Yeh // A negative return value represents an error. Pass it on. 6965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if (numRead < 0) { 7065ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return numRead == ERROR_END_OF_STREAM && totalNumRead > 0 ? totalNumRead : numRead; 71d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 72d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala // A zero return value signals EOS. Return the bytes read so far. 73d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (numRead == 0) { 7465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return totalNumRead; 7565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 7665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian if ((size_t)numRead > numToRead) { 775e08d60617fc63c2e41f9069ff89f5c00db2617dEino-Ville Talvala return ERROR_OUT_OF_RANGE; 7865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 79b8a805261bf0282e992d3608035e47d05a898710Steve Block CHECK(numRead >= 0 && (size_t)numRead <= bufferSize); 80b8a805261bf0282e992d3608035e47d05a898710Steve Block memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead); 8165ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian numLeft -= numRead; 8265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian totalNumRead += numRead; 8365ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 8465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 8565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return totalNumRead; 86d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala} 87d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala 88d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvalastatus_t CallbackDataSource::getSize(off64_t *size) { 89d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala status_t err = mIDataSource->getSize(size); 90d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (err != OK) { 91d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return err; 92d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 93d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (*size < 0) { 94d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala // IDataSource will set size to -1 to indicate unknown size, but 95d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala // DataSource returns ERROR_UNSUPPORTED for that. 96d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return ERROR_UNSUPPORTED; 9765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 9865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return OK; 99cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin} 100cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin 101cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkinuint32_t CallbackDataSource::flags() { 102cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin return mIDataSource->getFlags(); 103cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin} 104cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin 105cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunkvoid CallbackDataSource::close() { 106cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin if (!mIsClosed) { 107e16d1165c5dccfb44753610f39b120938269cd3aBin Chen mIDataSource->close(); 108cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk mIsClosed = true; 109cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin } 1103068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen} 1113068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen 1123068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu ChenTinyCacheSource::TinyCacheSource(const sp<DataSource>& source) 1133068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen : mSource(source), mCachedOffset(0), mCachedSize(0) { 1143068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen mName = String8::format("TinyCacheSource(%s)", mSource->toString().string()); 1153068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen} 1163068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen 1173068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chenstatus_t TinyCacheSource::initCheck() const { 1183068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen return mSource->initCheck(); 1193068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen} 1203068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen 1213068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chenssize_t TinyCacheSource::readAt(off64_t offset, void* data, size_t size) { 122d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala if (size >= kCacheSize) { 1233068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen return mSource->readAt(offset, data, size); 12488da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen } 1253068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen 1263068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen // Check if the cache satisfies the read. 12788da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen if (mCachedOffset <= offset 12888da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen && offset < (off64_t) (mCachedOffset + mCachedSize)) { 12988da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen if (offset + size <= mCachedOffset + mCachedSize) { 13088da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen memcpy(data, &mCache[offset - mCachedOffset], size); 13188da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen return size; 1323068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen } else { 1333068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen // If the cache hits only partially, flush the cache and read the 1343068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen // remainder. 1353068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen 1363068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen // This value is guaranteed to be greater than 0 because of the 1373068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen // enclosing if statement. 1383068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen const ssize_t remaining = mCachedOffset + mCachedSize - offset; 13988da526d97442c80731e01bfc94c6b47c4b0c3c7Chien-Yu Chen memcpy(data, &mCache[offset - mCachedOffset], remaining); 1403068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen const ssize_t readMore = readAt(offset + remaining, 1413068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen (uint8_t*)data + remaining, size - remaining); 142cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin if (readMore < 0) { 143cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin return readMore; 14465ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 14565ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return remaining + readMore; 14665ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 14765ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian } 14865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian 14965ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian // Fill the cache and copy to the caller. 15049c9705a7987b94bd53fddd4834f5f534cf946f7Eino-Ville Talvala const ssize_t numRead = mSource->readAt(offset, mCache, kCacheSize); 15149c9705a7987b94bd53fddd4834f5f534cf946f7Eino-Ville Talvala if (numRead <= 0) { 152d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala return numRead; 153d56db1d2bee182d1851097a9c712712fc094d117Eino-Ville Talvala } 154df64d15042bbd5e0e4933ac49bf3c177dd94752cSteve Block if ((size_t)numRead > kCacheSize) { 1558951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev return ERROR_OUT_OF_RANGE; 156bfc9915f482520eb9676c6d2dbf7f1ac078d937dIgor Murashkin } 157cba2c163555cd329f49d40658ea3ee902e94dda3Igor Murashkin 1583068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen mCachedSize = numRead; 1593068d73c6c7e1f44523b1466b903a9c82408b258Chien-Yu Chen mCachedOffset = offset; 160cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk CHECK(mCachedSize <= kCacheSize && mCachedOffset >= 0); 1618951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev const size_t numToReturn = std::min(size, (size_t)numRead); 16265ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian memcpy(data, mCache, numToReturn); 1638951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev 1648951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchev return numToReturn; 165cc776718c0be7c31fe5ab4fc1446d377be60369fRuben Brunk} 166634a51509ee50475f3e9f8ccf897e90fc72ded31Igor Murashkin 1678951a97b1f8462c37e740ea5082eea0445d2c501Iliyan Malchevstatus_t TinyCacheSource::getSize(off64_t *size) { 16865ab47156e1c7dfcd8cc4266253a5ff30219e7f0Mathias Agopian return mSource->getSize(size); 16999e69716215cd0665379bc90d708f2ea8689831dRuben Brunk} 17099e69716215cd0665379bc90d708f2ea8689831dRuben Brunk 17199e69716215cd0665379bc90d708f2ea8689831dRuben Brunkuint32_t TinyCacheSource::flags() { 17299e69716215cd0665379bc90d708f2ea8689831dRuben Brunk return mSource->flags(); 17399e69716215cd0665379bc90d708f2ea8689831dRuben Brunk} 174e074a93046ebe5cea0b55c3a479e082a426e1e07Yin-Chia Yeh 1751527f07eb2b2b40f6b8f53a4644e6a400bddb460Eino-Ville Talvala} // namespace android 1761527f07eb2b2b40f6b8f53a4644e6a400bddb460Eino-Ville Talvala