Home | History | Annotate | Download | only in libstagefright
      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/foundation/ADebug.h>
     18 #include <media/stagefright/FileSource.h>
     19 #include <sys/types.h>
     20 #include <unistd.h>
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 #include <fcntl.h>
     24 
     25 namespace android {
     26 
     27 FileSource::FileSource(const char *filename)
     28     : mFd(-1),
     29       mOffset(0),
     30       mLength(-1),
     31       mDecryptHandle(NULL),
     32       mDrmManagerClient(NULL),
     33       mDrmBufOffset(0),
     34       mDrmBufSize(0),
     35       mDrmBuf(NULL){
     36 
     37     mFd = open(filename, O_LARGEFILE | O_RDONLY);
     38 
     39     if (mFd >= 0) {
     40         mLength = lseek64(mFd, 0, SEEK_END);
     41     } else {
     42         ALOGE("Failed to open file '%s'. (%s)", filename, strerror(errno));
     43     }
     44 }
     45 
     46 FileSource::FileSource(int fd, int64_t offset, int64_t length)
     47     : mFd(fd),
     48       mOffset(offset),
     49       mLength(length),
     50       mDecryptHandle(NULL),
     51       mDrmManagerClient(NULL),
     52       mDrmBufOffset(0),
     53       mDrmBufSize(0),
     54       mDrmBuf(NULL){
     55     CHECK(offset >= 0);
     56     CHECK(length >= 0);
     57 }
     58 
     59 FileSource::~FileSource() {
     60     if (mFd >= 0) {
     61         close(mFd);
     62         mFd = -1;
     63     }
     64 
     65     if (mDrmBuf != NULL) {
     66         delete[] mDrmBuf;
     67         mDrmBuf = NULL;
     68     }
     69 
     70     if (mDecryptHandle != NULL) {
     71         // To release mDecryptHandle
     72         CHECK(mDrmManagerClient);
     73         mDrmManagerClient->closeDecryptSession(mDecryptHandle);
     74         mDecryptHandle = NULL;
     75     }
     76 
     77     if (mDrmManagerClient != NULL) {
     78         delete mDrmManagerClient;
     79         mDrmManagerClient = NULL;
     80     }
     81 }
     82 
     83 status_t FileSource::initCheck() const {
     84     return mFd >= 0 ? OK : NO_INIT;
     85 }
     86 
     87 ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
     88     if (mFd < 0) {
     89         return NO_INIT;
     90     }
     91 
     92     Mutex::Autolock autoLock(mLock);
     93 
     94     if (mLength >= 0) {
     95         if (offset >= mLength) {
     96             return 0;  // read beyond EOF.
     97         }
     98         int64_t numAvailable = mLength - offset;
     99         if ((int64_t)size > numAvailable) {
    100             size = numAvailable;
    101         }
    102     }
    103 
    104     if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
    105             == mDecryptHandle->decryptApiType) {
    106         return readAtDRM(offset, data, size);
    107    } else {
    108         off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
    109         if (result == -1) {
    110             ALOGE("seek to %lld failed", offset + mOffset);
    111             return UNKNOWN_ERROR;
    112         }
    113 
    114         return ::read(mFd, data, size);
    115     }
    116 }
    117 
    118 status_t FileSource::getSize(off64_t *size) {
    119     Mutex::Autolock autoLock(mLock);
    120 
    121     if (mFd < 0) {
    122         return NO_INIT;
    123     }
    124 
    125     *size = mLength;
    126 
    127     return OK;
    128 }
    129 
    130 sp<DecryptHandle> FileSource::DrmInitialization(const char *mime) {
    131     if (mDrmManagerClient == NULL) {
    132         mDrmManagerClient = new DrmManagerClient();
    133     }
    134 
    135     if (mDrmManagerClient == NULL) {
    136         return NULL;
    137     }
    138 
    139     if (mDecryptHandle == NULL) {
    140         mDecryptHandle = mDrmManagerClient->openDecryptSession(
    141                 mFd, mOffset, mLength, mime);
    142     }
    143 
    144     if (mDecryptHandle == NULL) {
    145         delete mDrmManagerClient;
    146         mDrmManagerClient = NULL;
    147     }
    148 
    149     return mDecryptHandle;
    150 }
    151 
    152 void FileSource::getDrmInfo(sp<DecryptHandle> &handle, DrmManagerClient **client) {
    153     handle = mDecryptHandle;
    154 
    155     *client = mDrmManagerClient;
    156 }
    157 
    158 ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) {
    159     size_t DRM_CACHE_SIZE = 1024;
    160     if (mDrmBuf == NULL) {
    161         mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
    162     }
    163 
    164     if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
    165             && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
    166         /* Use buffered data */
    167         memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
    168         return size;
    169     } else if (size <= DRM_CACHE_SIZE) {
    170         /* Buffer new data */
    171         mDrmBufOffset =  offset + mOffset;
    172         mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
    173                 DRM_CACHE_SIZE, offset + mOffset);
    174         if (mDrmBufSize > 0) {
    175             int64_t dataRead = 0;
    176             dataRead = size > mDrmBufSize ? mDrmBufSize : size;
    177             memcpy(data, (void*)mDrmBuf, dataRead);
    178             return dataRead;
    179         } else {
    180             return mDrmBufSize;
    181         }
    182     } else {
    183         /* Too big chunk to cache. Call DRM directly */
    184         return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
    185     }
    186 }
    187 }  // namespace android
    188