FileSource.cpp revision a9741a9232c81eaf59179acef91f5be46c42264e
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    if (mFile == NULL) {
69        return NO_INIT;
70    }
71
72    Mutex::Autolock autoLock(mLock);
73
74    if (mLength >= 0) {
75        if (offset >= mLength) {
76            return 0;  // read beyond EOF.
77        }
78        int64_t numAvailable = mLength - offset;
79        if ((int64_t)size > numAvailable) {
80            size = numAvailable;
81        }
82    }
83
84    if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
85            == mDecryptHandle->decryptApiType) {
86        return readAtDRM(offset, data, size);
87   } else {
88        int err = fseeko(mFile, offset + mOffset, SEEK_SET);
89        if (err < 0) {
90            LOGE("seek to %lld failed", offset + mOffset);
91            return UNKNOWN_ERROR;
92        }
93
94        return fread(data, 1, size, mFile);
95    }
96}
97
98status_t FileSource::getSize(off_t *size) {
99    if (mFile == NULL) {
100        return NO_INIT;
101    }
102
103    if (mLength >= 0) {
104        *size = mLength;
105
106        return OK;
107    }
108
109    fseek(mFile, 0, SEEK_END);
110    *size = ftello(mFile);
111
112    return OK;
113}
114
115DecryptHandle* FileSource::DrmInitialization(DrmManagerClient* client) {
116    mDrmManagerClient = client;
117    if (mDecryptHandle == NULL) {
118        mDecryptHandle = mDrmManagerClient->openDecryptSession(
119                mFd, mOffset, mLength);
120    }
121
122    if (mDecryptHandle == NULL) {
123        mDrmManagerClient = NULL;
124    }
125
126    return mDecryptHandle;
127}
128
129void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
130    *handle = mDecryptHandle;
131
132    *client = mDrmManagerClient;
133}
134
135ssize_t FileSource::readAtDRM(off_t offset, void *data, size_t size) {
136    size_t DRM_CACHE_SIZE = 1024;
137    if (mDrmBuf == NULL) {
138        mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
139    }
140
141    if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
142            && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
143        /* Use buffered data */
144        memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
145        return size;
146    } else if (size <= DRM_CACHE_SIZE) {
147        /* Buffer new data */
148        mDrmBufOffset =  offset + mOffset;
149        mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
150                DRM_CACHE_SIZE, offset + mOffset);
151        if (mDrmBufSize > 0) {
152            int64_t dataRead = 0;
153            dataRead = size > mDrmBufSize ? mDrmBufSize : size;
154            memcpy(data, (void*)mDrmBuf, dataRead);
155            return dataRead;
156        } else {
157            return mDrmBufSize;
158        }
159    } else {
160        /* Too big chunk to cache. Call DRM directly */
161        return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
162    }
163}
164}  // namespace android
165