1 /* ------------------------------------------------------------------
2 * Copyright (C) 1998-2009 PacketVideo
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
13 * express or implied.
14 * See the License for the specific language governing permissions
15 * and limitations under the License.
16 * -------------------------------------------------------------------
17 */
18 /*! \file oscl_file_native.cpp
19 \brief This file contains file io APIs
20 */
21
22 #include "oscl_file_native.h"
23 #include "oscl_stdstring.h"
24 #include "oscl_utf8conv.h"
25 #include "oscl_int64_utils.h"
26
27 #ifdef ENABLE_SHAREDFD_PLAYBACK
28 #undef LOG_TAG
29 #define LOG_TAG "OsclNativeFile"
30 #include <utils/Log.h>
31 #endif
32 #include "oscl_mem.h"
33 #include "oscl_file_types.h"
34 #include "oscl_file_handle.h"
35
36 // FIXME:
37 // Is 100 milliseconds a good choice for writing out a single
38 // compressed video frame?
39 static const int FILE_WRITER_SPEED_TOLERANCE_IN_MILLISECONDS = 100;
40
OsclNativeFile()41 OsclNativeFile::OsclNativeFile()
42 {
43 iOpenFileHandle = false;
44 iMode = 0;
45
46 iFile = 0;
47 #ifdef ENABLE_SHAREDFD_PLAYBACK
48 iSharedFd = -1;
49 #endif
50
51 }
52
~OsclNativeFile()53 OsclNativeFile::~OsclNativeFile()
54 {
55 }
56
Open(const OsclFileHandle & aHandle,uint32 mode,const OsclNativeFileParams & params,Oscl_FileServer & fileserv)57 int32 OsclNativeFile::Open(const OsclFileHandle& aHandle, uint32 mode
58 , const OsclNativeFileParams& params
59 , Oscl_FileServer& fileserv)
60 {
61 //open with an external file handle
62
63 OSCL_UNUSED_ARG(fileserv);
64
65 iMode = mode;
66 iOpenFileHandle = true;
67
68 {
69 OSCL_UNUSED_ARG(params);
70 //Just save the open file handle
71 iFile = aHandle.Handle();
72 }
73
74 return 0;
75 }
76
OpenModeToString(uint32 mode,char mode_str[4])77 static void OpenModeToString(uint32 mode, char mode_str[4])
78 {
79 uint32 index = 0;
80
81 if (mode & Oscl_File::MODE_READWRITE)
82 {
83 if (mode & Oscl_File::MODE_APPEND)
84 {
85 mode_str[index++] = 'a';
86 mode_str[index++] = '+';
87 }
88 else
89 {
90 mode_str[index++] = 'w';
91 mode_str[index++] = '+';
92 }
93 }
94 else if (mode & Oscl_File::MODE_APPEND)
95 {
96 mode_str[index++] = 'a';
97 mode_str[index++] = '+';
98 }
99 else if (mode & Oscl_File::MODE_READ)
100 {
101 mode_str[index++] = 'r';
102 }
103 else if (mode & Oscl_File::MODE_READ_PLUS)
104 {
105 mode_str[index++] = 'r';
106 mode_str[index++] = '+';
107 }
108
109 if (mode & Oscl_File::MODE_TEXT)
110 {
111 mode_str[index++] = 't';
112 }
113 else
114 {
115 mode_str[index++] = 'b';
116 }
117
118 mode_str[index++] = '\0';
119 }
120
OpenFileOrSharedFd(const char * filename,const char * openmode)121 int32 OsclNativeFile::OpenFileOrSharedFd(
122 const char *filename, const char *openmode)
123 {
124 #ifdef ENABLE_SHAREDFD_PLAYBACK
125 int fd;
126 long long offset;
127 long long len;
128 if (sscanf(filename, "sharedfd://%d:%lld:%lld", &fd, &offset, &len) == 3)
129 {
130 iSharedFd = fd;
131 iSharedFilePosition = 0;
132 iSharedFileOffset = offset;
133 long long size = lseek64(iSharedFd, 0, SEEK_END);
134 lseek64(iSharedFd, 0, SEEK_SET);
135 size -= offset;
136 iSharedFileSize = size < len ? size : len;
137 }
138 else
139 #endif
140 {
141 if ((iFile = fopen(filename, openmode)) == NULL)
142 {
143 return -1;
144 }
145 }
146
147 return 0;
148 }
149
Open(const oscl_wchar * filename,uint32 mode,const OsclNativeFileParams & params,Oscl_FileServer & fileserv)150 int32 OsclNativeFile::Open(const oscl_wchar *filename, uint32 mode
151 , const OsclNativeFileParams& params
152 , Oscl_FileServer& fileserv)
153 {
154 iMode = mode;
155 iOpenFileHandle = false;
156
157 {
158 OSCL_UNUSED_ARG(fileserv);
159 OSCL_UNUSED_ARG(params);
160
161 if (!filename || *filename == '\0') return -1; // Null string not supported in fopen, error out
162
163 char openmode[4];
164
165 OpenModeToString(mode, openmode);
166
167 #ifdef _UNICODE
168 oscl_wchar convopenmode[4];
169 if (0 == oscl_UTF8ToUnicode(openmode, oscl_strlen(openmode), convopenmode, 4))
170 {
171 return -1;
172 }
173
174 if ((iFile = _wfopen(filename, convopenmode)) == NULL)
175 {
176 return -1;
177 }
178 #else
179 //Convert to UTF8
180 char convfilename[OSCL_IO_FILENAME_MAXLEN];
181 if (0 == oscl_UnicodeToUTF8(filename, oscl_strlen(filename), convfilename, OSCL_IO_FILENAME_MAXLEN))
182 {
183 return -1;
184 }
185 return OpenFileOrSharedFd(convfilename, openmode);
186 #endif
187 }
188
189 }
190
Open(const char * filename,uint32 mode,const OsclNativeFileParams & params,Oscl_FileServer & fileserv)191 int32 OsclNativeFile::Open(const char *filename, uint32 mode
192 , const OsclNativeFileParams& params
193 , Oscl_FileServer& fileserv)
194 {
195 iMode = mode;
196 iOpenFileHandle = false;
197
198 OSCL_UNUSED_ARG(fileserv);
199 OSCL_UNUSED_ARG(params);
200
201 if (!filename || *filename == '\0') return -1; // Null string not supported in fopen, error out
202
203 char openmode[4];
204
205 OpenModeToString(mode, openmode);
206
207 return OpenFileOrSharedFd(filename, openmode);
208
209 }
210
Size()211 TOsclFileOffset OsclNativeFile::Size()
212 {
213 //this is the default for platforms with no
214 //native size query.
215 //Just do seek to end, tell, then seek back.
216 TOsclFileOffset curPos = Tell();
217 if (curPos >= 0
218 && Seek(0, Oscl_File::SEEKEND) == 0)
219 {
220 TOsclFileOffset endPos = Tell();
221 if (Seek(curPos, Oscl_File::SEEKSET) == 0)
222 {
223 return endPos;
224 }
225 else
226 {
227 return (-1);
228 }
229 }
230 return (-1);
231 }
232
Close()233 int32 OsclNativeFile::Close()
234 {
235 int32 closeret = 0;
236
237 {
238 if (iOpenFileHandle)
239 closeret = Flush();
240 else if (iFile != NULL)
241 {
242 closeret = fclose(iFile);
243 iFile = NULL;
244 }
245 #ifdef ENABLE_SHAREDFD_PLAYBACK
246 else if (iSharedFd >= 0)
247 {
248 // we don't need to, and in fact MUST NOT, close mSharedFd here,
249 // since it might still be shared by another OsclFileNative, and
250 // will be closed by the playerdriver when we're done with it.
251 closeret = 0;
252 }
253 #endif
254 else
255 {
256 return -1; //Linux Porting : Fix 1
257 }
258 }
259
260 return closeret;
261 }
262
263
Read(OsclAny * buffer,uint32 size,uint32 numelements)264 uint32 OsclNativeFile::Read(OsclAny *buffer, uint32 size, uint32 numelements)
265 {
266 #ifdef ENABLE_SHAREDFD_PLAYBACK
267 if (iSharedFd >= 0)
268 {
269 // restore position, no locking is needed because all access to the
270 // shared filedescriptor is done by the same thread.
271 lseek64(iSharedFd, iSharedFilePosition + iSharedFileOffset, SEEK_SET);
272 uint32 count = size * numelements;
273 if (iSharedFilePosition + count > iSharedFileSize)
274 {
275 count = iSharedFileSize - iSharedFilePosition;
276 }
277 ssize_t numread = read(iSharedFd, buffer, count);
278 // unlock
279 long long curpos = lseek64(iSharedFd, 0, SEEK_CUR);
280 if (curpos >= 0)
281 {
282 iSharedFilePosition = curpos - iSharedFileOffset;
283 }
284 if (numread < 0)
285 {
286 return numread;
287 }
288 return numread / size;
289 }
290 #endif
291
292 if (iFile)
293 {
294 return fread(buffer, OSCL_STATIC_CAST(int32, size), OSCL_STATIC_CAST(int32, numelements), iFile);
295 }
296 return 0;
297 }
298
HasAsyncRead()299 bool OsclNativeFile::HasAsyncRead()
300 {
301 return false;//not supported.
302 }
303
ReadAsync(OsclAny * buffer,uint32 size,uint32 numelements,OsclAOStatus & status)304 int32 OsclNativeFile::ReadAsync(OsclAny*buffer, uint32 size, uint32 numelements, OsclAOStatus& status)
305 {
306 OSCL_UNUSED_ARG(buffer);
307 OSCL_UNUSED_ARG(size);
308 OSCL_UNUSED_ARG(numelements);
309 OSCL_UNUSED_ARG(status);
310 return -1;//not supported
311 }
312
ReadAsyncCancel()313 void OsclNativeFile::ReadAsyncCancel()
314 {
315 }
316
GetReadAsyncNumElements()317 uint32 OsclNativeFile::GetReadAsyncNumElements()
318 {
319 return 0;//not supported
320 }
321
322
323
Write(const OsclAny * buffer,uint32 size,uint32 numelements)324 uint32 OsclNativeFile::Write(const OsclAny *buffer, uint32 size, uint32 numelements)
325 {
326 #ifdef ENABLE_SHAREDFD_PLAYBACK
327 if (iSharedFd >= 0)
328 return 0;
329 #endif
330 if (iFile)
331 {
332 struct timeval startTimeVal, endTimeVal;
333 gettimeofday(&startTimeVal, NULL);
334 uint32 items = fwrite(buffer, OSCL_STATIC_CAST(int32, size), OSCL_STATIC_CAST(int32, numelements), iFile);
335 gettimeofday(&endTimeVal, NULL);
336 long long timeInMicroSeconds = (endTimeVal.tv_sec - startTimeVal.tv_sec) * 1000000LL + (endTimeVal.tv_usec - startTimeVal.tv_usec);
337 if (timeInMicroSeconds/1000 > FILE_WRITER_SPEED_TOLERANCE_IN_MILLISECONDS) {
338 LOGW("writing %d bytes takes too long (%lld micro seconds)", items, timeInMicroSeconds);
339 }
340 return items;
341 }
342 return 0;
343 }
344
Seek(TOsclFileOffset offset,Oscl_File::seek_type origin)345 int32 OsclNativeFile::Seek(TOsclFileOffset offset, Oscl_File::seek_type origin)
346 {
347
348 {
349 #ifdef ENABLE_SHAREDFD_PLAYBACK
350 if (iSharedFd >= 0)
351 {
352 int newpos = iSharedFilePosition;
353 if (origin == Oscl_File::SEEKCUR) newpos = newpos + offset;
354 else if (origin == Oscl_File::SEEKSET) newpos = offset;
355 else if (origin == Oscl_File::SEEKEND) newpos = iSharedFileSize + offset;
356 if (newpos < 0)
357 return EINVAL;
358 if (newpos > iSharedFileSize) // is this valid?
359 newpos = iSharedFileSize;
360 iSharedFilePosition = newpos;
361 return 0;
362 }
363 #endif
364 if (iFile)
365 {
366 int32 seekmode = SEEK_CUR;
367
368 if (origin == Oscl_File::SEEKCUR)
369 seekmode = SEEK_CUR;
370 else if (origin == Oscl_File::SEEKSET)
371 seekmode = SEEK_SET;
372 else if (origin == Oscl_File::SEEKEND)
373 seekmode = SEEK_END;
374 #if OSCL_HAS_LARGE_FILE_SUPPORT
375 return fseeko(iFile, offset, seekmode);
376 #else
377 return fseek(iFile, offset, seekmode);
378 #endif
379 }
380 }
381 return -1;
382 }
383
384
Tell()385 TOsclFileOffset OsclNativeFile::Tell()
386 {
387 TOsclFileOffset result = -1;
388 #ifdef ENABLE_SHAREDFD_PLAYBACK
389 if (iSharedFd >= 0)
390 return iSharedFilePosition;
391 #endif
392 if (iFile)
393 {
394 #if OSCL_HAS_LARGE_FILE_SUPPORT
395 result = ftello(iFile);
396 #else
397 result = ftell(iFile);
398 #endif
399 }
400 return result;
401 }
402
403
404
Flush()405 int32 OsclNativeFile::Flush()
406 {
407 #ifdef ENABLE_SHAREDFD_PLAYBACK
408 if (iSharedFd >= 0)
409 return iSharedFilePosition >= iSharedFileSize;
410 #endif
411 if (iFile)
412 return fflush(iFile);
413 return EOF;
414 }
415
416
417
EndOfFile()418 int32 OsclNativeFile::EndOfFile()
419 {
420 #ifdef ENABLE_SHAREDFD_PLAYBACK
421 if (iSharedFd >= 0)
422 return iSharedFilePosition >= iSharedFileSize;
423 #endif
424 if (iFile)
425 return feof(iFile);
426 return 0;
427 }
428
429
GetError()430 int32 OsclNativeFile::GetError()
431 {
432 //FIXME ENABLE_SHAREDFD_PLAYBACK
433 if (iFile)
434 return ferror(iFile);
435 return 0;
436 }
437
438