FileSource.cpp revision c7fc37a3dab9bd1f96713649f351b5990e6316ff
1/* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include <media/stagefright/FileSource.h> 18#include <media/stagefright/MediaDebug.h> 19#include <sys/types.h> 20#include <unistd.h> 21 22namespace android { 23 24FileSource::FileSource(const char *filename) 25 : mFile(fopen(filename, "rb")), 26 mFd(mFile == NULL ? -1 : fileno(mFile)), 27 mOffset(0), 28 mLength(-1), 29 mDecryptHandle(NULL), 30 mDrmManagerClient(NULL), 31 mDrmBufOffset(0), 32 mDrmBufSize(0), 33 mDrmBuf(NULL){ 34} 35 36FileSource::FileSource(int fd, int64_t offset, int64_t length) 37 : mFile(fdopen(fd, "rb")), 38 mFd(fd), 39 mOffset(offset), 40 mLength(length), 41 mDecryptHandle(NULL), 42 mDrmManagerClient(NULL), 43 mDrmBufOffset(0), 44 mDrmBufSize(0), 45 mDrmBuf(NULL){ 46 CHECK(offset >= 0); 47 CHECK(length >= 0); 48} 49 50FileSource::~FileSource() { 51 if (mFile != NULL) { 52 fclose(mFile); 53 mFile = NULL; 54 } 55 56 if (mDrmBuf != NULL) { 57 delete[] mDrmBuf; 58 mDrmBuf = NULL; 59 } 60} 61 62status_t FileSource::initCheck() const { 63 return mFile != NULL ? OK : NO_INIT; 64} 65 66ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) { 67 if (mFile == NULL) { 68 return NO_INIT; 69 } 70 71 Mutex::Autolock autoLock(mLock); 72 73 if (mLength >= 0) { 74 if (offset >= mLength) { 75 return 0; // read beyond EOF. 76 } 77 int64_t numAvailable = mLength - offset; 78 if ((int64_t)size > numAvailable) { 79 size = numAvailable; 80 } 81 } 82 83 if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED 84 == mDecryptHandle->decryptApiType) { 85 return readAtDRM(offset, data, size); 86 } else { 87 off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET); 88 if (result == -1) { 89 LOGE("seek to %lld failed", offset + mOffset); 90 return UNKNOWN_ERROR; 91 } 92 93 return ::read(mFd, data, size); 94 } 95} 96 97status_t FileSource::getSize(off64_t *size) { 98 if (mFile == NULL) { 99 return NO_INIT; 100 } 101 102 if (mLength >= 0) { 103 *size = mLength; 104 105 return OK; 106 } 107 108 *size = lseek64(mFd, 0, SEEK_END); 109 110 return OK; 111} 112 113DecryptHandle* FileSource::DrmInitialization(DrmManagerClient* client) { 114 if (client == NULL) { 115 return NULL; 116 } 117 mDrmManagerClient = client; 118 119 if (mDecryptHandle == NULL) { 120 mDecryptHandle = mDrmManagerClient->openDecryptSession( 121 mFd, mOffset, mLength); 122 } 123 124 if (mDecryptHandle == NULL) { 125 mDrmManagerClient = NULL; 126 } 127 128 return mDecryptHandle; 129} 130 131void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) { 132 *handle = mDecryptHandle; 133 134 *client = mDrmManagerClient; 135} 136 137ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) { 138 size_t DRM_CACHE_SIZE = 1024; 139 if (mDrmBuf == NULL) { 140 mDrmBuf = new unsigned char[DRM_CACHE_SIZE]; 141 } 142 143 if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset 144 && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) { 145 /* Use buffered data */ 146 memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size); 147 return size; 148 } else if (size <= DRM_CACHE_SIZE) { 149 /* Buffer new data */ 150 mDrmBufOffset = offset + mOffset; 151 mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf, 152 DRM_CACHE_SIZE, offset + mOffset); 153 if (mDrmBufSize > 0) { 154 int64_t dataRead = 0; 155 dataRead = size > mDrmBufSize ? mDrmBufSize : size; 156 memcpy(data, (void*)mDrmBuf, dataRead); 157 return dataRead; 158 } else { 159 return mDrmBufSize; 160 } 161 } else { 162 /* Too big chunk to cache. Call DRM directly */ 163 return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset); 164 } 165} 166} // namespace android 167