FileSource.cpp revision dcd25efb46c41c8d24a0a9cf61fb57f84149709e
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
20namespace android {
21
22FileSource::FileSource(const char *filename)
23    : mFile(fopen(filename, "rb")),
24      mFd(fileno(mFile)),
25      mOffset(0),
26      mLength(-1),
27      mDecryptHandle(NULL),
28      mDrmManagerClient(NULL),
29      mDrmBufOffset(0),
30      mDrmBufSize(0),
31      mDrmBuf(NULL){
32}
33
34FileSource::FileSource(int fd, int64_t offset, int64_t length)
35    : mFile(fdopen(fd, "rb")),
36      mFd(fd),
37      mOffset(offset),
38      mLength(length),
39      mDecryptHandle(NULL),
40      mDrmManagerClient(NULL),
41      mDrmBufOffset(0),
42      mDrmBufSize(0),
43      mDrmBuf(NULL){
44    CHECK(offset >= 0);
45    CHECK(length >= 0);
46}
47
48FileSource::~FileSource() {
49    if (mFile != NULL) {
50        fclose(mFile);
51        mFile = NULL;
52    }
53
54    if (mDrmBuf != NULL) {
55        delete[] mDrmBuf;
56        mDrmBuf = NULL;
57    }
58    if (mDecryptHandle != NULL) {
59        mDrmManagerClient->closeDecryptSession(mDecryptHandle);
60    }
61}
62
63status_t FileSource::initCheck() const {
64    return mFile != NULL ? OK : NO_INIT;
65}
66
67ssize_t FileSource::readAt(off_t offset, void *data, size_t size) {
68    Mutex::Autolock autoLock(mLock);
69
70    if (mLength >= 0) {
71        if (offset >= mLength) {
72            return 0;  // read beyond EOF.
73        }
74        int64_t numAvailable = mLength - offset;
75        if ((int64_t)size > numAvailable) {
76            size = numAvailable;
77        }
78    }
79
80    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
81            == mDecryptHandle->decryptApiType) {
82        return readAtDRM(offset, data, size);
83   } else {
84        int err = fseeko(mFile, offset + mOffset, SEEK_SET);
85        if (err < 0) {
86            LOGE("seek to %lld failed", offset + mOffset);
87            return UNKNOWN_ERROR;
88        }
89
90        return fread(data, 1, size, mFile);
91    }
92}
93
94status_t FileSource::getSize(off_t *size) {
95    if (mLength >= 0) {
96        *size = mLength;
97
98        return OK;
99    }
100
101    fseek(mFile, 0, SEEK_END);
102    *size = ftello(mFile);
103
104    return OK;
105}
106
107DecryptHandle* FileSource::DrmInitialization(DrmManagerClient* client) {
108    mDrmManagerClient = client;
109    if (mDecryptHandle == NULL) {
110        mDecryptHandle = mDrmManagerClient->openDecryptSession(
111                mFd, mOffset, mLength);
112    }
113
114    if (mDecryptHandle == NULL) {
115        mDrmManagerClient = NULL;
116    }
117
118    return mDecryptHandle;
119}
120
121void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
122    *handle = mDecryptHandle;
123
124    *client = mDrmManagerClient;
125}
126
127ssize_t FileSource::readAtDRM(off_t offset, void *data, size_t size) {
128    size_t DRM_CACHE_SIZE = 1024;
129    if (mDrmBuf == NULL) {
130        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
131    }
132
133    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
134            && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
135        /* Use buffered data */
136        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
137        return size;
138    } else if (size <= DRM_CACHE_SIZE) {
139        /* Buffer new data */
140        mDrmBufOffset =  offset + mOffset;
141        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
142                DRM_CACHE_SIZE, offset + mOffset);
143        if (mDrmBufSize > 0) {
144            int64_t dataRead = 0;
145            dataRead = size > mDrmBufSize ? mDrmBufSize : size;
146            memcpy(data, (void*)mDrmBuf, dataRead);
147            return dataRead;
148        } else {
149            return mDrmBufSize;
150        }
151    } else {
152        /* Too big chunk to cache. Call DRM directly */
153        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
154    }
155}
156}  // namespace android
157