blob: 02a78c9eef60b40cd78d45578c41aa3b5538c7fb [file] [log] [blame]
Andreas Hubere46b7be2009-07-14 16:56:47 -07001/*
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>
Andreas Huberb5ceb9e2009-08-26 14:48:20 -070018#include <media/stagefright/MediaDebug.h>
James Dongb1262a82010-11-16 14:04:54 -080019#include <sys/types.h>
20#include <unistd.h>
James Dong2747e0e2010-11-18 20:59:13 -080021#include <sys/types.h>
22#include <sys/stat.h>
23#include <fcntl.h>
Andreas Hubere46b7be2009-07-14 16:56:47 -070024
25namespace android {
26
27FileSource::FileSource(const char *filename)
James Dong2747e0e2010-11-18 20:59:13 -080028 : mFd(-1),
Andreas Huber744043f2009-11-16 15:34:01 -080029 mOffset(0),
Gloria Wangd5770912010-06-22 13:55:38 -070030 mLength(-1),
31 mDecryptHandle(NULL),
32 mDrmManagerClient(NULL),
33 mDrmBufOffset(0),
34 mDrmBufSize(0),
35 mDrmBuf(NULL){
James Dong2747e0e2010-11-18 20:59:13 -080036
37 mFd = open(filename, O_LARGEFILE | O_RDONLY);
Andreas Huber744043f2009-11-16 15:34:01 -080038}
39
40FileSource::FileSource(int fd, int64_t offset, int64_t length)
James Dong2747e0e2010-11-18 20:59:13 -080041 : mFd(fd),
Andreas Huber744043f2009-11-16 15:34:01 -080042 mOffset(offset),
Gloria Wangd5770912010-06-22 13:55:38 -070043 mLength(length),
44 mDecryptHandle(NULL),
45 mDrmManagerClient(NULL),
46 mDrmBufOffset(0),
47 mDrmBufSize(0),
48 mDrmBuf(NULL){
Andreas Huber744043f2009-11-16 15:34:01 -080049 CHECK(offset >= 0);
50 CHECK(length >= 0);
Andreas Hubere46b7be2009-07-14 16:56:47 -070051}
52
53FileSource::~FileSource() {
James Dong2747e0e2010-11-18 20:59:13 -080054 if (mFd >= 0) {
55 close(mFd);
56 mFd = -1;
Andreas Hubere46b7be2009-07-14 16:56:47 -070057 }
Gloria Wangd5770912010-06-22 13:55:38 -070058
59 if (mDrmBuf != NULL) {
60 delete[] mDrmBuf;
61 mDrmBuf = NULL;
62 }
Gloria Wangc2dc4722011-02-07 11:41:11 -080063
64 if (mDecryptHandle != NULL) {
65 // To release mDecryptHandle
Gloria Wangadc4d9c2011-02-08 13:24:08 -080066 CHECK(mDrmManagerClient);
Gloria Wangc2dc4722011-02-07 11:41:11 -080067 mDrmManagerClient->closeDecryptSession(mDecryptHandle);
68 mDecryptHandle = NULL;
69 }
70
71 if (mDrmManagerClient != NULL) {
72 delete mDrmManagerClient;
73 mDrmManagerClient = NULL;
74 }
Andreas Hubere46b7be2009-07-14 16:56:47 -070075}
76
Andreas Huber9a12baf2009-10-23 10:22:30 -070077status_t FileSource::initCheck() const {
James Dong2747e0e2010-11-18 20:59:13 -080078 return mFd >= 0 ? OK : NO_INIT;
Andreas Hubere46b7be2009-07-14 16:56:47 -070079}
80
James Dongb1262a82010-11-16 14:04:54 -080081ssize_t FileSource::readAt(off64_t offset, void *data, size_t size) {
James Dong2747e0e2010-11-18 20:59:13 -080082 if (mFd < 0) {
Andreas Hubercbcf8f62010-05-24 09:18:36 -070083 return NO_INIT;
84 }
85
Andreas Hubere46b7be2009-07-14 16:56:47 -070086 Mutex::Autolock autoLock(mLock);
87
Andreas Huber744043f2009-11-16 15:34:01 -080088 if (mLength >= 0) {
89 if (offset >= mLength) {
90 return 0; // read beyond EOF.
91 }
92 int64_t numAvailable = mLength - offset;
93 if ((int64_t)size > numAvailable) {
94 size = numAvailable;
95 }
96 }
97
Gloria Wangd5770912010-06-22 13:55:38 -070098 if (mDecryptHandle != NULL && DecryptApiType::CONTAINER_BASED
99 == mDecryptHandle->decryptApiType) {
100 return readAtDRM(offset, data, size);
101 } else {
James Dongb1262a82010-11-16 14:04:54 -0800102 off64_t result = lseek64(mFd, offset + mOffset, SEEK_SET);
103 if (result == -1) {
Gloria Wangd5770912010-06-22 13:55:38 -0700104 LOGE("seek to %lld failed", offset + mOffset);
105 return UNKNOWN_ERROR;
106 }
Andreas Hubere46b7be2009-07-14 16:56:47 -0700107
James Dongb1262a82010-11-16 14:04:54 -0800108 return ::read(mFd, data, size);
Gloria Wangd5770912010-06-22 13:55:38 -0700109 }
Andreas Huber744043f2009-11-16 15:34:01 -0800110}
Andreas Hubere46b7be2009-07-14 16:56:47 -0700111
James Dongb1262a82010-11-16 14:04:54 -0800112status_t FileSource::getSize(off64_t *size) {
James Dong2747e0e2010-11-18 20:59:13 -0800113 if (mFd < 0) {
Andreas Hubercbcf8f62010-05-24 09:18:36 -0700114 return NO_INIT;
115 }
116
Andreas Huber744043f2009-11-16 15:34:01 -0800117 if (mLength >= 0) {
118 *size = mLength;
119
120 return OK;
121 }
122
James Dongb1262a82010-11-16 14:04:54 -0800123 *size = lseek64(mFd, 0, SEEK_END);
Andreas Huber744043f2009-11-16 15:34:01 -0800124
125 return OK;
Andreas Hubere46b7be2009-07-14 16:56:47 -0700126}
127
Gloria Wangc2dc4722011-02-07 11:41:11 -0800128DecryptHandle* FileSource::DrmInitialization() {
129 if (mDrmManagerClient == NULL) {
130 mDrmManagerClient = new DrmManagerClient();
131 }
132
133 if (mDrmManagerClient == NULL) {
Gloria Wangc2c22e72010-11-01 15:53:16 -0700134 return NULL;
135 }
Gloria Wangc2c22e72010-11-01 15:53:16 -0700136
Gloria Wangd5770912010-06-22 13:55:38 -0700137 if (mDecryptHandle == NULL) {
138 mDecryptHandle = mDrmManagerClient->openDecryptSession(
139 mFd, mOffset, mLength);
140 }
141
142 if (mDecryptHandle == NULL) {
Gloria Wangc2dc4722011-02-07 11:41:11 -0800143 delete mDrmManagerClient;
Gloria Wangd5770912010-06-22 13:55:38 -0700144 mDrmManagerClient = NULL;
145 }
146
147 return mDecryptHandle;
148}
149
150void FileSource::getDrmInfo(DecryptHandle **handle, DrmManagerClient **client) {
151 *handle = mDecryptHandle;
152
153 *client = mDrmManagerClient;
154}
155
James Dongb1262a82010-11-16 14:04:54 -0800156ssize_t FileSource::readAtDRM(off64_t offset, void *data, size_t size) {
Gloria Wangd5770912010-06-22 13:55:38 -0700157 size_t DRM_CACHE_SIZE = 1024;
158 if (mDrmBuf == NULL) {
159 mDrmBuf = new unsigned char[DRM_CACHE_SIZE];
160 }
161
162 if (mDrmBuf != NULL && mDrmBufSize > 0 && (offset + mOffset) >= mDrmBufOffset
163 && (offset + mOffset + size) <= (mDrmBufOffset + mDrmBufSize)) {
164 /* Use buffered data */
165 memcpy(data, (void*)(mDrmBuf+(offset+mOffset-mDrmBufOffset)), size);
166 return size;
167 } else if (size <= DRM_CACHE_SIZE) {
168 /* Buffer new data */
169 mDrmBufOffset = offset + mOffset;
170 mDrmBufSize = mDrmManagerClient->pread(mDecryptHandle, mDrmBuf,
171 DRM_CACHE_SIZE, offset + mOffset);
172 if (mDrmBufSize > 0) {
173 int64_t dataRead = 0;
174 dataRead = size > mDrmBufSize ? mDrmBufSize : size;
175 memcpy(data, (void*)mDrmBuf, dataRead);
176 return dataRead;
177 } else {
178 return mDrmBufSize;
179 }
180 } else {
181 /* Too big chunk to cache. Call DRM directly */
182 return mDrmManagerClient->pread(mDecryptHandle, data, size, offset + mOffset);
183 }
184}
Andreas Hubere46b7be2009-07-14 16:56:47 -0700185} // namespace android