// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
//
#include "mp4file.h"
#include "mp4memwrap.h"
#include "mp4atom.h"
#include <stdio.h>
#include <string.h>
#include <sys/unistd.h>
#include <sys/reent.h>
#include <f32file.h>
#include <f32file64.h>
#include <e32des16.h>
#include <caf/caf.h>
using namespace ContentAccess;
// Debug print macro
#ifdef _DEBUG
#include <e32svr.h>
#define PRINT(x) //comment this line and uncomment the line below to enable logging for this file
//#define PRINT(x) RDebug::Print x
#else
#define PRINT(x)
#endif
_LIT(KTmpDirectoryName, "\\System\\Temp\\3GPLibTmpDir\\"); // Temporary output directory name
/*
* Function:
*
* mp4_i32 saveFileName(MP4FileName filename,
* MP4HandleImp handle)
*
* Description:
*
* Save file name for later use.
*
* Parameters:
*
* filename Filename
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 saveFileName(MP4FileName filename, MP4HandleImp handle)
{
handle->fileName = (MP4FileName)mp4malloc(2 * wcslen(filename) + 2);
if (handle->fileName == NULL)
return -1;
wcscat(handle->fileName, filename);
return 0;
}
/*
* Function:
*
* mp4_i32 initFileRead(MP4FileName filename,
* MP4HandleImp handle)
*
* Description:
*
* Open a file for reading.
*
* Note: filename is a Unicode string in Symbian OS.
*
* Parameters:
*
* filename Filename
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 initFileRead(MP4FileName filename, MP4HandleImp handle)
{
RFs *fs;
RFile64 *file;
fs = new(RFs);
handle->fs = (void *)fs;
if (fs == NULL)
return -1;
if (fs->Connect() != KErrNone)
return -1;
file = new(RFile64);
handle->rfile = (void *)file;
if (file == NULL)
return -1;
if (file->Open(*fs, TPtrC((const TUint16 *)filename), EFileRead | EFileShareAny) != KErrNone)
{
// for compatibility, if opening in Any mode fails try more restrictive approach.
if (file->Open(*fs, TPtrC((const TUint16 *)filename), EFileRead | EFileShareReadersOnly) != KErrNone)
{
return -1;
}
}
handle->file = handle->rfile;
return 0;
}
/*
* Function:
*
* mp4_i32 initFileWrite(MP4FileName filename,
* MP4HandleImp handle)
*
* Description:
*
* Open a file for writing.
*
* Note: filename is a Unicode string in Symbian OS.
*
* Parameters:
*
* filename Filename
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 initFileWrite(MP4FileName filename, MP4HandleImp handle)
{
RFs *fs;
RFile64 *file;
TParse fp;
TFileName path;
TInt error;
fs = new(RFs);
handle->fs = (void *)fs;
if (fs == NULL)
return -1;
if (fs->Connect() != KErrNone)
return -1;
file = new(RFile64);
handle->rfile = (void *)file;
if (file == NULL)
return -1;
if (((RFs *)(handle->fs))->Parse(TPtrC((const TUint16 *)filename), fp) != KErrNone)
return -1;
path.Insert(0, fp.DriveAndPath() );
error = ((RFs *)(handle->fs))->MkDirAll(path);
if (error != KErrNone && error != KErrAlreadyExists)
return -1;
if (file->Replace(*fs, TPtrC((const TUint16 *)filename), EFileWrite|EFileShareExclusive ) != KErrNone)
{
return -1;
}
handle->file = handle->rfile;
TRAP(error, handle->filewriter = CFileWriter::NewL( *file ));
if ( error != KErrNone )
{
return -1;
}
return 0;
}
/*
* Function:
*
* mp4_i32 initTmpFileWrite(MP4FileName filename,
* MP4HandleImp handle)
*
* Description:
*
* Open a temporary file for writing.
*
* Note: filename is a Unicode string in Symbian OS.
*
* Parameters:
*
* filename Filename
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 initTmpFileWrite(MP4FileName filename, MP4HandleImp handle)
{
TInt err;
RFile64 * file = new RFile64;
TBuf16<KMaxFileName> name(reinterpret_cast<const TUint16*>(filename));
ASSERT(handle->fs != NULL);
err = file->Replace(*(RFs*)(handle->fs), name, EFileStream | EFileRead | EFileWrite);
if (err != KErrNone)
{
delete file;
return -1;
}
handle->tmpfile = (void *)file;
return 0;
}
/*
* Function:
*
* mp4_i32 closeFile(MP4HandleImp handle)
*
* Description:
*
* Close a file.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
*
*/
mp4_i32 closeFile(MP4HandleImp handle)
{
PRINT((_L("e_closefile 1")));
if (handle->rfile)
{
if (handle->filewriter)
{
PRINT((_L("e_closefile_flush_filewriter 1")));
(handle->filewriter)->Flush(KNullDesC8);
PRINT((_L("e_closefile_flush_filewriter 0")));
delete handle->filewriter;
handle->filewriter = NULL;
}
}
if (handle->asyncReader)
{
delete handle->asyncReader;
handle->asyncReader = NULL;
}
if (handle->rfile)
{
if ( !handle->FileHandleFromOutside )
{
PRINT((_L("e_closefile_close_file 1")));
((RFile64 *)(handle->rfile))->Close();
PRINT((_L("e_closefile_close_file 0")));
PRINT((_L("e_closefile_delete_fileptr 1")));
delete(handle->rfile);
PRINT((_L("e_closefile_delete_fileptr 0")));
}
handle->rfile = NULL;
}
if (handle->cfile)
{
if ( !handle->FileHandleFromOutside )
{
delete(handle->cfile);
}
handle->cfile = NULL;
}
PRINT((_L("e_closefile_close_rfs 1")));
if (handle->fs)
{
((RFs *)(handle->fs))->Close();
delete(handle->fs);
handle->fs = NULL;
}
PRINT((_L("e_closefile_close_rfs 0")));
handle->file = NULL;
PRINT((_L("e_closefile 0")));
return 0;
}
/*
* Function:
*
* mp4_i32 closeTmpFile(MP4HandleImp handle)
*
* Description:
*
* Close a temporary file.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
*
*/
mp4_i32 closeTmpFile(MP4HandleImp handle)
{
if (handle->tmpfile)
((RFile64*)handle->tmpfile)->Close();
handle->tmpfile = NULL;
return 0;
}
/*
* Function:
*
* mp4_i32 deleteTmpFile(MP4HandleImp handle)
*
* Description:
*
* Remove a temporary file.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 deleteTmpFile(MP4HandleImp handle)
{
if (handle->tmpFileName)
{
TInt err;
TBuf<KMaxFileName> name(reinterpret_cast<const TUint16*>(handle->tmpFileName));
ASSERT(handle->fs != NULL);
err = ((RFs*)handle->fs)->Delete(name);
if (err != KErrNone)
return -1;
}
return 0;
}
/*
* Function:
*
* mp4_i32 readFile(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestoread)
*
* Description:
*
* Read data from a file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer to read data into
* bytestoread Number of bytes to read from file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Requested number of bytes could not be read
*
*/
mp4_i32 readFile(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestoread)
{
return bufferedRead(handle, buffer, bytestoread);
}
/*
* Function:
*
* mp4_i32 readTmpFile(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestoread)
*
* Description:
*
* Read data from a temporary file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer to read data into
* bytestoread Number of bytes to read from file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Requested number of bytes could not be read
*
*/
mp4_i32 readTmpFile(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestoread)
{
if (!handle->tmpfile)
return -1;
TInt err;
TPtr8 ptrBuffer(buffer, bytestoread);
err = ((RFile64*)handle->tmpfile)->Read(ptrBuffer, bytestoread);
if (err != KErrNone)
return -2;
if (ptrBuffer.Length() != bytestoread)
return -2;
return 0;
}
/*
* Function:
*
* mp4_i32 peekFile(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestoread)
*
* Description:
*
* Read data from a file but don't move the current position in the file
* forward.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer to read data into
* bytestoread Number of bytes to read from file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Requested number of bytes could not be read
* -3 Current position in the file could not be set to original
* value
*
*/
mp4_i32 peekFile(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestoread)
{
mp4_i32 ret;
mp4_i32 amount;
ret = bufferedRead(handle, buffer, bytestoread);
if (ret != 0)
return ret;
amount = -(mp4_i32)bytestoread;
ret = bufferedSeek(handle, amount);
if (ret != 0)
return ret;
return 0;
}
/*
* Function:
*
* mp4_i32 seekFile(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek in a file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from current position
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekFile(MP4HandleImp handle, mp4_i64 amount)
{
return bufferedSeek(handle, amount);
}
/*
* Function:
*
* mp4_i32 seekFileAbs(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek from the beginning of a file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from the beginning of the file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekFileAbs(MP4HandleImp handle, mp4_i64 amount)
{
return bufferedSeekAbs(handle, amount);
}
/*
* Function:
*
* mp4_i32 seekFileWrite(MP4HandleImp handle,
* mp4_i64 amount)
*
* Description:
*
* Seek in a file that has been opened for writing.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from current position
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Can't write buffers to file
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekFileWrite(MP4HandleImp handle, mp4_i64 amount)
{
if (!handle->rfile)
return -1;
if ( handle->filewriter )
{
PRINT((_L("e_seekfilewrite_flush_filewriter 1")));
if ( (handle->filewriter)->Flush(KNullDesC8) != KErrNone )
{
PRINT((_L("e_seekfilewrite_flush_filewriter 0")));
return -2;
}
PRINT((_L("e_seekfilewrite_flush_filewriter 0")));
}
else
{
return -1;
}
PRINT((_L("e_seekfilewrite_seek_rfile 1")));
if (((RFile64 *)(handle->rfile))->Seek(ESeekCurrent,amount) != KErrNone)
{
return -3;
}
PRINT((_L("e_seekfilewrite_seek_rfile 0")));
return 0;
}
/*
* Function:
*
* mp4_i32 seekFileAbsWrite(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek from the beginning of a file that has been opened for writing.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from the beginning of the file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Can't write buffers to file
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekFileAbsWrite(MP4HandleImp handle, mp4_i64 amount)
{
if (!handle->rfile)
return -1;
if ( handle->filewriter )
{
PRINT((_L("e_seekfileabswrite_flush 1")));
if ( (handle->filewriter)->Flush(KNullDesC8) != KErrNone )
{
PRINT((_L("e_seekfileabswrite_flush 0")));
return -2;
}
PRINT((_L("e_seekfileabswrite_flush 0")));
}
else
{
return -1;
}
PRINT((_L("e_seekfileabswrite_seek 1")));
if (((RFile64 *)(handle->rfile))->Seek(ESeekStart, amount) != KErrNone)
{
return -3;
}
PRINT((_L("e_seekfileabswrite_seek 0")));
return 0;
}
/*
* Function:
*
* mp4_i32 seekTmpFileAbs(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek from the beginning of a temporary file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from the beginning of the file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekTmpFileAbs(MP4HandleImp handle, mp4_i64 amount)
{
if (!handle->tmpfile)
return -1;
TInt err;
TInt64 amount64 = amount;
err = ((RFile64*)handle->tmpfile)->Seek(ESeekStart, amount64);
if (err != KErrNone)
return -3;
return 0;
}
/*
* Function:
*
* mp4_i32 writeFile(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestowrite)
*
* Description:
*
* Write data into a file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer containing the data
* bytestowrite Number of bytes to write
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Number of bytes written is not equal to bytestowrite
*
*/
mp4_i32 writeFile(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestowrite)
{
return bufferedWrite(handle, buffer, bytestowrite);
}
/*
* Function:
*
* mp4_i32 writeFileUnbuffered(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestowrite)
*
* Description:
*
* Write data into a file without buffering.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer containing the data
* bytestowrite Number of bytes to write
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Number of bytes written is not equal to bytestowrite
*
*/
mp4_i32 writeFileUnbuffered(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestowrite)
{
if(handle->bufferWrite)
{
mp4memcpy(handle->composeBuffer+FTYP_SIZE + handle->ftypdelta,buffer,bytestowrite);
return 0;
}
if (!handle->rfile)
return -1;
if ( handle->filewriter )
{
TPtrC8 buf = TPtrC8((TUint8 *)(buffer), bytestowrite);
PRINT((_L("e_writefileunbuffered_flush 1")));
if ( (handle->filewriter)->Flush( buf ) != KErrNone )
{
PRINT((_L("e_writefileunbuffered_flush 0")));
return -2;
}
PRINT((_L("e_writefileunbuffered_flush 0")));
}
else
{
return -1;
}
return 0;
}
/*
* Function:
*
* mp4_i32 writeTmpFile(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestowrite)
*
* Description:
*
* Write data into a temporary file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer containing the data
* bytestowrite Number of bytes to write
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Number of bytes written is not equal to bytestowrite
*
*/
mp4_i32 writeTmpFile(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestowrite)
{
if (!handle->tmpfile)
return -1;
TInt err;
TPtrC8 ptrBuffer(buffer, bytestowrite);
err = ((RFile64*)handle->tmpfile)->Write(ptrBuffer, bytestowrite);
if (err != KErrNone)
return -2;
if (ptrBuffer.Length() != bytestowrite)
return -2;
handle->bytesInTmpFile += bytestowrite;
return 0;
}
/*
* Function:
*
* mp4_i32 createTmpFileName(MP4FileName filename,
* MP4FileName *tmpfilename)
*
* Description:
*
* Create a temporary file name by adding .tmp to the end of a file name.
*
* Parameters:
*
* filename Original file name
* tmpfilename Temporary file name is returned here
*
* Return value:
*
* 0 Success
* -1 Memory could not be allocated for the new name
*
*/
mp4_i32 createTmpFileName(MP4FileName filename, MP4FileName *tmpfilename)
{
*tmpfilename = (MP4FileName)mp4malloc(2 * wcslen(filename) + 10);
if (*tmpfilename == NULL)
return -1;
wcscat(*tmpfilename, filename);
wcscat(*tmpfilename, L".tmp");
return 0;
}
/*
* Function:
*
* mp4_i32 freeTmpFileName(MP4FileName filename)
*
* Description:
*
* Free memory allocated for the temporary file name.
*
* Parameters:
*
* filename Buffer containing file name
*
* Return value:
*
* 0 Success
*
*/
mp4_i32 freeTmpFileName(MP4FileName filename)
{
if (filename)
mp4free(filename);
return 0;
}
/*
* Function:
*
* void closeStdlib()
*
* Description:
*
* Free memory allocated by stdlib wrapper functions (Symbian OS only).
*
* Parameters:
*
* None
*
* Return value:
*
* None
*
*/
void closeStdlib()
{
// retrieves the TLS which stores the number of currently active instances of
// composer/parser
TInt p = (TInt) Dll::Tls();
// decrement the counter as one instance is being closed at this point
p--;
Dll::SetTls((TAny*) p);
if (p == 0)
{
// Since memory allocated for stdlib is shared amongst all composers and/or parsers
// within a thread, stdlib close should ONLY be called for the last instance of
// composer / parser.
//
// If there are no other active instances other than this,
// the memory allocated for stdlib for this thread can now be released.
Dll::FreeTls();
CloseSTDLIB();
}
}
/*
* Function:
*
* void openStdlib()
*
* Description:
*
* Register the use of stdlib.
*
* Parameters:
*
* None
*
* Return value:
*
* 0 Success
*
*/
mp4_i32 openStdlib()
{
// retrieve the the value stored in TLS for this DLL
TInt p = (TInt) Dll::Tls();
// increment it. This becomes a reference counter of
// how many instances of the composer/parser is currently active
p++;
return (Dll::SetTls((TAny*) p));
}
/*
* Function:
*
* mp4_i32 bufferedRead(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestoread)
*
* Description:
*
* Read data from a file in a buffered manner.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer to read data into
* bytestoread Number of bytes to read from file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Requested number of bytes could not be read
*
*/
mp4_i32 bufferedRead(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestoread)
{
mp4_u32 bytesread = 0;
if (!handle->file)
return -1;
while (bytesread < bytestoread)
{
mp4_u32 available;
available = handle->diskReadSize - handle->diskReadBufPos;
if (available > bytestoread - bytesread)
available = bytestoread - bytesread;
if (available > 0) /* Copy data from memory buffer */
{
mp4memcpy(buffer + bytesread, handle->diskReadBuf + handle->diskReadBufPos, available);
handle->diskReadBufPos += available;
bytesread += available;
}
else /* Read more data from file into memory buffer */
{
TInt readBufferSize = 0;
if ( handle->readBufferSize == 0)
{
readBufferSize = READBUFSIZE;
}
else
{
readBufferSize = handle->readBufferSize;
}
TPtr8 buf = TPtr8((TUint8 *)(handle->diskReadBuf), readBufferSize);
switch (handle->sourceType)
{
case MP4_SOURCE_RFILE:
if (((RFile64 *)(handle->rfile))->Read(buf, readBufferSize) != KErrNone)
return -2;
break;
case MP4_SOURCE_CAF:
handle->cafError = handle->cfile->Read(buf, readBufferSize);
if ( handle->cafError != KErrNone)
return -2;
break;
default:
return -1;
}
if ((mp4_u32)buf.Length() == 0) /* EOF or error */
return -2;
handle->diskReadBufPos = 0;
handle->diskReadSize = (mp4_u32)buf.Length();
handle->diskReadBufStart = handle->diskReadPos;
handle->diskReadPos += handle->diskReadSize;
}
}
return 0;
}
/*
* Function:
*
* mp4_i32 bufferedSeek(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek in a buffered file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from current position
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 bufferedSeek(MP4HandleImp handle, mp4_i64 amount)
{
if (!handle->file)
return -1;
/* Is the new seek point inside the current memory buffer? */
if ((mp4_i32)handle->diskReadBufPos + amount >= 0 &&
handle->diskReadBufPos + amount < handle->diskReadSize)
{
/* Yes */
handle->diskReadBufPos += amount;
}
else
{
/* No */
TInt64 am;
am = amount - ((mp4_i32)handle->diskReadSize - (mp4_i32)handle->diskReadBufPos);
if ( handle->rfile )
{
mp4_i64 maxsize = 0;
((RFile64 *)(handle->rfile))->Size(maxsize);
maxsize -= (mp4_i64)handle->diskReadPos;
if (am > maxsize)
{
return -3;
}
}
// Coverity thinks that cfile can never be not NULL, which is incorrect; it can be a proper value. The comment below silences the Coverity warning
//coverity[var_compare_op]
else if ( handle->cfile )
{
mp4_i64 maxsize = 0;
TRAPD(caferr, handle->cfile->DataSize64L(maxsize));
maxsize -= (mp4_i64)handle->diskReadPos;
if (!caferr && am > maxsize)
{
return -3;
}
}
switch (handle->sourceType)
{
case MP4_SOURCE_RFILE:
{
PRINT((_L("e_bufferedseek_seek_rfile 1")));
if (((RFile64 *)(handle->rfile))->Seek(ESeekCurrent, am) != KErrNone)
{
return -3;
}
PRINT((_L("e_bufferedseek_seek_rfile 0")));
break;
}
case MP4_SOURCE_CAF:
PRINT((_L("e_bufferedseek_seek_cfile 1")));
// See comment on handle->cfile dereference above on why the coverity[] comment below is needed
//coverity[var_deref_model]
handle->cafError = handle->cfile->Seek64(ESeekCurrent, am);
if ( handle->cafError != KErrNone)
return -3;
PRINT((_L("e_bufferedseek_seek_cfile 0")));
break;
default:
return -1;
}
handle->diskReadPos = handle->diskReadBufStart + handle->diskReadBufPos + amount;
handle->diskReadBufPos = 0;
handle->diskReadBufStart = 0;
handle->diskReadSize = 0;
}
return 0;
}
/*
* Function:
*
* mp4_i32 bufferedSeekAbs(MP4HandleImp handle,
* mp4_i32 amount)
*
* Description:
*
* Seek in a buffered file from the start of the file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from start of the file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 bufferedSeekAbs(MP4HandleImp handle, mp4_i64 amount)
{
if (!handle->file)
return -1;
/* Is the new seek point inside the current memory buffer? */
if (handle->diskReadBufStart <= (mp4_u64)amount &&
handle->diskReadBufStart + handle->diskReadSize > (mp4_u64)amount)
{
/* Yes */
handle->diskReadBufPos = amount - handle->diskReadBufStart;
}
else
{
/* No */
mp4_i64 am = amount;
switch (handle->sourceType)
{
case MP4_SOURCE_RFILE:
{
PRINT((_L("e_bufferedseekabs_seek_rfile 1")));
if (((RFile64 *)(handle->rfile))->Seek(ESeekStart, am) != KErrNone)
{
return -3;
}
PRINT((_L("e_bufferedseekabs_seek_rfile 0")));
break;
}
case MP4_SOURCE_CAF:
PRINT((_L("e_bufferedseekabs_seek_cfile 1")));
handle->cafError = handle->cfile->Seek64(ESeekStart, am);
PRINT((_L("e_bufferedseekabs_seek_cfile 0")));
if ( handle->cafError != KErrNone)
return -3;
break;
default:
return -1;
}
handle->diskReadPos = (mp4_u64)amount;
handle->diskReadBufPos = 0;
handle->diskReadBufStart = 0;
handle->diskReadSize = 0;
}
return 0;
}
/*
* Function:
*
* mp4_i32 bufferedWrite(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestowrite)
*
* Description:
*
* Write data into a file in a buffered manner.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer containing the data
* bytestowrite Number of bytes to write
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Number of bytes written is not equal to bytestowrite
*
*/
mp4_i32 bufferedWrite(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestowrite)
{
if(handle->bufferWrite)
{
if(handle->bytesProgressed+bytestowrite > *(handle->composedSize))
{
return MP4_OUTPUT_BUFFER_TOO_SMALL; //-1;
}
else
{
mp4memcpy(handle->composeBuffer+handle->bytesProgressed,buffer,bytestowrite);
handle->bytesProgressed+=bytestowrite;
return 0;
}
}
if (!handle->rfile)
return -1;
if ( handle->filewriter )
{
TPtrC8 buf = TPtrC8((TUint8 *)(buffer), bytestowrite);
PRINT((_L("e_file_bufferedwrite_write 1")));
if ( (handle->filewriter)->Write( buf ) != KErrNone )
{
return -2;
}
PRINT((_L("e_file_bufferedwrite_write 0")));
}
else
{
return -1;
}
return 0;
}
/*
* Function:
*
* mp4_i32 initMetaDataFiles(MP4HandleImp handle)
*
* Description:
*
* Open temporary files for writing.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 General Error
* MP4_OUT_OF_MEMORY Out of memory
*
*/
mp4_i32 initMetaDataFiles(MP4HandleImp handle)
{
PRINT(_L("3GPLib::initMetaDataFiles() in"));
TFileName filename;
TFileName path;
TInt error;
// Create a directory for the files
if ( handle->fileName )
{
filename = (TText *)handle->fileName;
TParse fp;
path = KTmpDirectoryName;
if (((RFs *)(handle->fs))->Parse(filename, fp) != KErrNone)
return -1;
path.Insert(0, fp.Drive());
}
else
{
TChar drive;
if (((RFs *)(handle->fs))->DriveToChar(handle->fileHandleDrive, drive ) != KErrNone )
return -1;
path.Append( drive );
path.Append( _L(":") );
path.Append( KTmpDirectoryName );
}
// Try to delete the temp folder from leftovers
// If other instance is using it then delete will just fail
PRINT((_L("e_initmetadatafiles_newl_fileman 1")));
CFileMan* fileMan = 0;
TRAP( error, fileMan = CFileMan::NewL(*(RFs *)(handle->fs)));
if ( error )
{
return -1;
}
PRINT((_L("e_initmetadatafiles_newl_fileman 0")));
PRINT((_L("e_initmetadatafiles_deletedirectory 1")));
error = fileMan->RmDir( path ); // Delete directory + all files
delete( fileMan );
PRINT((_L("e_initmetadatafiles_deletedirectory 0")));
error = ((RFs *)(handle->fs))->MkDirAll(path);
if (error != KErrNone && error != KErrAlreadyExists)
return -1;
((RFs *)(handle->fs))->SetEntry(path, TTime(0), KEntryAttHidden, NULL);
// Create files
TFileName metadatafilename;
for (TUint i = 0; i < NUM_MDF; i++)
{
handle->metaDataFile[i] = (void *)new(RFile64);
if (handle->metaDataFile[i] == NULL)
return MP4_OUT_OF_MEMORY;
if (((RFile64 *)(handle->metaDataFile[i]))->Temp(*((RFs *)(handle->fs)), path, metadatafilename, EFileWrite | EFileShareExclusive) != KErrNone)
return -1;
handle->metaDataFileEmpty[i] = EFalse;
// save file name, used later for deleting
handle->metaDataFileName[i] = (MP4FileName)mp4malloc(2 * wcslen((MP4FileName)metadatafilename.Ptr()) + 2);
if (handle->metaDataFileName[i] == NULL)
return -1;
wcscat(handle->metaDataFileName[i], (MP4FileName)metadatafilename.Ptr());
handle->metaDataFileName[i][metadatafilename.Length()] = 0;
PRINT((_L("3GPLib::initMetaDataFiles() handle->metaDataFileName[%d]=%s, length=%d "),i, handle->metaDataFileName[i], metadatafilename.Length()));
}
PRINT(_L("3GPLib::initMetaDataFiles() creating MetaDataWriter"));
TRAPD(err, handle->metadatafilewriter = CMetaDataFileWriter::NewL());
if ( err != KErrNone )
{
PRINT((_L("3GPLib::initMetaDataFiles() MetaDataWriter creation error: %d"), err));
if ( err == KErrNoMemory )
{
return MP4_OUT_OF_MEMORY;
}
else
{
return -1;
}
}
PRINT(_L("3GPLib::initMetaDataFiles() MetaDataWriter created"));
PRINT(_L("3GPLib::initMetaDataFiles() out"));
return 0;
}
/*
* Function:
*
* mp4_i32 writeMetaDataFileNum(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestowrite,
* mp4_u32 filenumber)
*
* Description:
*
* Write data into a numbered file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer containing the data
* bytestowrite Number of bytes to write
* filenumber Index of temporary file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Number of bytes written is not equal to bytestowrite
*
*/
mp4_i32 writeMetaDataFileNum(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestowrite, mp4_u32 filenumber)
{
PRINT(_L("3GPLib::writeMetaDataFileNum() in"));
if (!handle->metaDataFile[filenumber])
return -1;
if ( handle->metadatafilewriter )
{
TPtrC8 buf = TPtrC8((TUint8 *)(buffer), bytestowrite);
PRINT((_L("e_file_writeMetaDataFileNum_write 1")));
if ( (handle->metadatafilewriter)->Write( *((RFile64 *)(handle->metaDataFile[filenumber])),
filenumber,
buf ) != KErrNone )
{
return -2;
}
PRINT((_L("e_file_writeMetaDataFileNum_write 0")));
}
else
{
return -1;
}
PRINT(_L("3GPLib::writeMetaDataFileNum() out"));
return 0;
}
/*
* Function:
*
* mp4_i32 seekMetaDataFileNumAbs(MP4HandleImp handle,
* mp4_i32 amount,
* mp4_u32 filenumber)
*
* Description:
*
* Seek from the beginning of a numbered file.
*
* Parameters:
*
* handle MP4 library handle
* amount Amount to seek from the beginning of the file
* filenumber Index of temporary file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -3 Current position in the file could not be set
*
*/
mp4_i32 seekMetaDataFileNumAbs(MP4HandleImp handle, mp4_i64 amount, mp4_u32 filenumber)
{
PRINT(_L("3GPLib::seekMetaDataFileNumAbs() in"));
if (!handle->metaDataFile[filenumber])
return -1;
if ( handle->metadatafilewriter )
{
PRINT((_L("e_seekmetadatafilenumabs_flush 1")));
if ( (handle->metadatafilewriter)->Flush() != KErrNone )
{
PRINT((_L("e_seekmetadatafilenumabs_flush 0")));
return -2;
}
PRINT((_L("e_seekmetadatafilenumabs_flush 0")));
}
PRINT((_L("e_seekmetadatafilenumabs_seek 1")));
if (((RFile64 *)(handle->metaDataFile[filenumber]))->Seek(ESeekStart, amount) != KErrNone)
{
return -3;
}
PRINT((_L("e_seekmetadatafilenumabs_seek 0")));
PRINT(_L("3GPLib::seekMetaDataFileNumAbs() out"));
return 0;
}
/*
* Function:
*
* mp4_i32 readMetaDataFileNum(MP4HandleImp handle,
* mp4_u8 *buffer,
* mp4_u32 bytestoread,
* mp4_u32 filenumber)
*
* Description:
*
* Read data from a numbered file.
*
* Parameters:
*
* handle MP4 library handle
* buffer Buffer to read data into
* bytestoread Number of bytes to read from file
* filenumber Index of temporary file
*
* Return value:
*
* 0 Success
* -1 File has not been opened
* -2 Requested number of bytes could not be read
*
*/
mp4_i32 readMetaDataFileNum(MP4HandleImp handle, mp4_u8 *buffer, mp4_u32 bytestoread, mp4_u32 filenumber)
{
PRINT(_L("3GPLib::readMetaDataFileNum() in"));
PRINT((_L("e_readmetadatafiles 1")));
mp4_u32 bytesread = 0;
TPtr8 buf = TPtr8((TUint8 *)buffer, bytestoread);
if (!handle->metaDataFile[filenumber])
return -1;
if ( handle->metadatafilewriter )
{
PRINT((_L("e_readmetadatafiles_flush 1")));
if ( (handle->metadatafilewriter)->Flush() != KErrNone )
{
return -2;
}
PRINT((_L("e_readmetadatafiles_flush 0")));
}
PRINT((_L("e_readmetadatafiles_read 1")));
if (handle->metaDataFileEmpty[filenumber])
{
if (handle->metadatafilewriter)
{
// if the file is empty, then read the data from temp buffer
bytesread = (handle->metadatafilewriter)->ReadBuffer( filenumber, buf, bytestoread);
}
if ( bytesread != bytestoread )
return -2;
}
else if (((RFile64 *)(handle->metaDataFile[filenumber]))->Read(buf, bytestoread) != KErrNone)
{
handle->metaDataFileEmpty[filenumber] = ETrue;
// if the file is empty, then read the data from temp buffer
if (handle->metadatafilewriter)
{
bytesread = (handle->metadatafilewriter)->ReadBuffer( filenumber, buf, bytestoread);
}
if ( bytesread != bytestoread )
return -2;
}
else if ( buf.Length() < bytestoread ) // Got only part of data from file, rest is in buffer
{
handle->metaDataFileEmpty[filenumber] = ETrue;
// if the file is empty, then read the data from temp buffer
if (handle->metadatafilewriter)
{
bytesread = (handle->metadatafilewriter)->ReadBuffer( filenumber, buf, bytestoread - buf.Length());
}
if ( buf.Length() != bytestoread )
return -2;
}
PRINT((_L("e_readmetadatafiles_read 0")));
if ((mp4_u32)buf.Length() == 0) /* EOF or error */
return -2;
PRINT(_L("3GPLib::readMetaDataFileNum() out"));
PRINT((_L("e_readmetadatafiles 0")));
return 0;
}
/*
* Function:
*
* mp4_i32 deleteMetaDataFiles(MP4HandleImp handle)
*
* Description:
*
* Remove a numbered temporary file.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
* -1 Error
*
*/
mp4_i32 deleteMetaDataFiles(MP4HandleImp handle)
{
PRINT(_L("3GPLib::deleteMetaDataFiles() in"));
PRINT((_L("e_deletemetadatafiles 1")));
TFileName filename;
TFileName path;
TInt err;
if ( handle->metadatafilewriter )
{
PRINT((_L("e_deletemetadatafiles_flush 1")));
if ( (handle->metadatafilewriter)->Flush() != KErrNone )
{
PRINT((_L("e_deletemetadatafiles_flush 0")));
return -2;
}
PRINT((_L("e_deletemetadatafiles_flush 0")));
delete handle->metadatafilewriter;
handle->metadatafilewriter = NULL;
}
/* Determine file names */
PRINT((_L("e_deletemetadatafiles_determinenames 1")));
if ( handle->fileName )
{
filename = (TText *)handle->fileName;
path = KTmpDirectoryName;
TParse fp;
if (((RFs *)(handle->fs))->Parse(filename, fp) != KErrNone)
return -1;
path.Insert(0, fp.Drive());
}
else
{
TChar drive;
if (((RFs *)(handle->fs))->DriveToChar(handle->fileHandleDrive, drive ) != KErrNone )
return -1;
path.Append( drive );
path.Append( _L(":") );
path.Append( KTmpDirectoryName );
}
PRINT((_L("e_deletemetadatafiles_determinenames 0")));
PRINT((_L("e_deletemetadatafiles_deletemetadatafilenames 1")));
for (TUint i = 0; i < NUM_MDF; i++)
{
if (handle->metaDataFileName[i])
{
// check if client has defined async delete observer
if ( handle->tempFileRemoverObserver )
{
PRINT((_L("3GPLib::deleteMetaDataFiles() nro=%d sending %x to observer: %s"), i,handle->metaDataFileName[i], handle->metaDataFileName[i]));
handle->tempFileRemoverObserver->M3GPMP4LibDeleteTempFileName( handle->metaDataFileName[i] );
}
else // no observer, delete right here, ignore errors
{
PRINT((_L("3GPLib::deleteMetaDataFiles() nro=%d wremove: %s"), i, handle->metaDataFileName[i]));
err = wremove(handle->metaDataFileName[i]);
PRINT((_L("3GPLib::deleteMetaDataFiles() wremove err=%d"), err));
err++; // to remove compile warnings
mp4free(handle->metaDataFileName[i]);
}
handle->metaDataFileName[i] = 0;
}
PRINT((_L("e_deletemetadatafiles_deletemetadatafilenames 0")));
}
PRINT(_L("3GPLib::deleteMetaDataFiles() out"));
PRINT((_L("e_deletemetadatafiles 0")));
return 0;
}
/*
* Function:
*
* mp4_i32 closeMetaDataFiles(MP4HandleImp handle)
*
* Description:
*
* Close numbered tmp files.
*
* Parameters:
*
* handle MP4 library handle
*
* Return value:
*
* 0 Success
*
*/
mp4_i32 closeMetaDataFiles(MP4HandleImp handle)
{
PRINT(_L("3GPLib::closeMetaDataFiles() in"));
PRINT((_L("e_close_metadatafiles 1")));
if ( handle->metadatafilewriter )
{
PRINT((_L("e_close_metadatafiles_flush 1")));
if ( (handle->metadatafilewriter)->Flush() != KErrNone )
{
PRINT((_L("e_close_metadatafiles_flush 0")));
return -2;
}
PRINT((_L("e_close_metadatafiles_flush 0")));
}
for (TUint i = 0; i < NUM_MDF; i++)
{
if (handle->metaDataFile[i])
{
PRINT((_L("e_close_metadatafiles_closefile 1")));
((RFile64 *)(handle->metaDataFile[i]))->Close();
PRINT((_L("e_close_metadatafiles_closefile 0")));
PRINT((_L("e_close_metadatafiles_delfile 1")));
delete((RFile64 *)(handle->metaDataFile[i]));
PRINT((_L("e_close_metadatafiles_delfile 0")));
handle->metaDataFile[i] = NULL;
}
}
PRINT(_L("3GPLib::closeMetaDataFiles() out"));
PRINT((_L("e_close_metadatafiles 0")));
return 0;
}
// End of File