static int ogg_seek_func(void *datasource, ogg_int64_t offset, int whence) { imFileRef fp = static_cast<imFileRef>(datasource); #ifdef PRWIN_ENV LARGE_INTEGER lpos; lpos.QuadPart = offset; DWORD method = ( whence == SEEK_SET ? FILE_BEGIN : whence == SEEK_CUR ? FILE_CURRENT : whence == SEEK_END ? FILE_END : FILE_CURRENT ); #if _MSC_VER < 1300 DWORD pos = SetFilePointer(fp, lpos.u.LowPart, &lpos.u.HighPart, method); BOOL result = (pos != 0xFFFFFFFF || NO_ERROR == GetLastError()); #else BOOL result = SetFilePointerEx(fp, lpos, NULL, method); #endif return (result ? OV_OK : OV_FALSE); #else UInt16 positionMode = ( whence == SEEK_SET ? fsFromStart : whence == SEEK_CUR ? fsFromMark : whence == SEEK_END ? fsFromLEOF : fsFromMark ); OSErr result = FSSetForkPosition(CAST_REFNUM(fp), positionMode, offset); return (result == noErr ? OV_OK : OV_FALSE); #endif }
::FLAC__StreamDecoderReadStatus OurDecoder::read_callback(FLAC__byte buffer[], size_t *bytes) { #ifdef PRWIN_ENV DWORD count = *bytes, out; BOOL result = ReadFile(_fp, (LPVOID)buffer, count, &out, NULL); *bytes = out; if(!result) { DWORD err = GetLastError(); return (err == ERROR_HANDLE_EOF ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_ABORT); } return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; #else ByteCount count = *bytes, out = 0; OSErr result = FSReadFork(CAST_REFNUM(_fp), fsAtMark, 0, count, buffer, &out); *bytes = out; return (result == noErr ? FLAC__STREAM_DECODER_READ_STATUS_CONTINUE : result == eofErr ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_ABORT); #endif }
static prMALError SDKQuietFile( imStdParms *stdParms, imFileRef *SDKfileRef, void *privateData) { // "Quiet File" really means close the file handle, but we're still // using it and might open it again, so hold on to any stored data // structures you don't want to re-create. // If file has not yet been closed if(SDKfileRef && *SDKfileRef != imInvalidHandleValue) { ImporterLocalRec8H ldataH = reinterpret_cast<ImporterLocalRec8H>(privateData); stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(ldataH)); ImporterLocalRec8Ptr localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *ldataH ); if(localRecP->vf) { int clear_err = ov_clear(localRecP->vf); assert(clear_err == OV_OK); delete localRecP->vf; localRecP->vf = NULL; } if(localRecP->opus) { op_free(localRecP->opus); localRecP->opus = NULL; } if(localRecP->flac) { localRecP->flac->finish(); delete localRecP->flac; localRecP->flac = NULL; } stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(ldataH)); #ifdef PRWIN_ENV CloseHandle(*SDKfileRef); #else FSCloseFork( CAST_REFNUM(*SDKfileRef) ); #endif *SDKfileRef = imInvalidHandleValue; } return malNoError; }
static long ogg_tell_func(void *datasource) { imFileRef fp = static_cast<imFileRef>(datasource); #ifdef PRWIN_ENV long pos; LARGE_INTEGER lpos, zero; zero.QuadPart = 0; BOOL result = SetFilePointerEx(fp, zero, &lpos, FILE_CURRENT); pos = lpos.QuadPart; return pos; #else long pos; SInt64 lpos; OSErr result = FSGetForkPosition(CAST_REFNUM(fp), &lpos); pos = lpos; return pos; #endif }
AP4_Result My_ByteStream::GetSize(AP4_LargeSize &size) { #ifdef PRWIN_ENV size = GetFileSize(_fp, NULL); return AP4_SUCCESS; #else SInt64 fork_size = 0; OSErr result = FSGetForkSize(CAST_REFNUM(_fp), &fork_size); size = fork_size; return (result == noErr ? AP4_SUCCESS : AP4_FAILURE); #endif }
static size_t ogg_read_func(void *ptr, size_t size, size_t nmemb, void *datasource) { imFileRef fp = static_cast<imFileRef>(datasource); #ifdef PRWIN_ENV DWORD count = size * nmemb, out; BOOL result = ReadFile(fp, (LPVOID)ptr, count, &out, NULL); return (out / size); #else ByteCount count = size * nmemb, out = 0; OSErr result = FSReadFork(CAST_REFNUM(fp), fsAtMark, 0, count, ptr, &out); return (out / size); #endif }
static opus_int64 opusfile_tell_func(void *_stream) { imFileRef fp = static_cast<imFileRef>(_stream); #ifdef PRWIN_ENV LARGE_INTEGER lpos, zero; zero.QuadPart = 0; BOOL result = SetFilePointerEx(fp, zero, &lpos, FILE_CURRENT); return lpos.QuadPart; #else SInt64 lpos; OSErr result = FSGetForkPosition(CAST_REFNUM(fp), &lpos); return lpos; #endif }
::FLAC__StreamDecoderLengthStatus OurDecoder::length_callback(FLAC__uint64 *stream_length) { #ifdef PRWIN_ENV LARGE_INTEGER lpos; BOOL result = GetFileSizeEx(_fp, &lpos); *stream_length = lpos.QuadPart; return (result ? FLAC__STREAM_DECODER_LENGTH_STATUS_OK : FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR); #else SInt64 fork_size = 0; OSErr result = FSGetForkSize(CAST_REFNUM(_fp), &fork_size); *stream_length = fork_size; return (result == noErr ? FLAC__STREAM_DECODER_LENGTH_STATUS_OK : FLAC__STREAM_DECODER_LENGTH_STATUS_ERROR); #endif }
AP4_Result My_ByteStream::ReadPartial(void *buffer, AP4_Size bytes_to_read, AP4_Size &bytes_read) { #ifdef PRWIN_ENV DWORD count = bytes_to_read, out; BOOL result = ReadFile(_fp, buffer, count, &out, NULL); bytes_read = out; return (result ? AP4_SUCCESS : AP4_FAILURE); #else ByteCount count = bytes_to_read, out = 0; OSErr result = FSReadFork(CAST_REFNUM(_fp), fsAtMark, 0, count, buffer, &out); bytes_read = out; return (result == noErr ? AP4_SUCCESS : AP4_FAILURE); #endif }
::FLAC__StreamDecoderTellStatus OurDecoder::tell_callback(FLAC__uint64 *absolute_byte_offset) { #ifdef PRWIN_ENV LARGE_INTEGER lpos, zero; zero.QuadPart = 0; BOOL result = SetFilePointerEx(_fp, zero, &lpos, FILE_CURRENT); *absolute_byte_offset = lpos.QuadPart; return (result ? FLAC__STREAM_DECODER_TELL_STATUS_OK : FLAC__STREAM_DECODER_TELL_STATUS_ERROR); #else SInt64 lpos; OSErr result = FSGetForkPosition(CAST_REFNUM(_fp), &lpos); *absolute_byte_offset = lpos; return (result == noErr ? FLAC__STREAM_DECODER_TELL_STATUS_OK : FLAC__STREAM_DECODER_TELL_STATUS_ERROR); #endif }
AP4_Result My_ByteStream::Seek(AP4_Position position) { #ifdef PRWIN_ENV LARGE_INTEGER lpos; lpos.QuadPart = position; #if _MSC_VER < 1300 DWORD pos = SetFilePointer(_fp, lpos.u.LowPart, &lpos.u.HighPart, FILE_BEGIN); BOOL result = (pos != 0xFFFFFFFF || NO_ERROR == GetLastError()); #else BOOL result = SetFilePointerEx(_fp, lpos, NULL, FILE_BEGIN); #endif return (result ? AP4_SUCCESS : AP4_FAILURE); #else OSErr result = FSSetForkPosition(CAST_REFNUM(_fp), fsFromStart, position); return (result == noErr ? AP4_SUCCESS : AP4_FAILURE); #endif }
AP4_Result My_ByteStream::Tell(AP4_Position &position) { #ifdef PRWIN_ENV LARGE_INTEGER lpos, zero; zero.QuadPart = 0; BOOL result = SetFilePointerEx(_fp, zero, &lpos, FILE_CURRENT); position = lpos.QuadPart; return (result ? AP4_SUCCESS : AP4_FAILURE); #else long pos; SInt64 lpos; OSErr result = FSGetForkPosition(CAST_REFNUM(_fp), &lpos); position = lpos; return (result == noErr ? AP4_SUCCESS : AP4_FAILURE); #endif }
prMALError SDKOpenFile8( imStdParms *stdParms, imFileRef *SDKfileRef, imFileOpenRec8 *SDKfileOpenRec8) { prMALError result = malNoError; ImporterLocalRec8H localRecH = NULL; ImporterLocalRec8Ptr localRecP = NULL; if(SDKfileOpenRec8->privatedata) { localRecH = (ImporterLocalRec8H)SDKfileOpenRec8->privatedata; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); } else { localRecH = (ImporterLocalRec8H)stdParms->piSuites->memFuncs->newHandle(sizeof(ImporterLocalRec8)); SDKfileOpenRec8->privatedata = (PrivateDataPtr)localRecH; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); localRecP->vf = NULL; localRecP->opus = NULL; localRecP->flac = NULL; localRecP->importerID = SDKfileOpenRec8->inImporterID; localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; } SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = reinterpret_cast<imFileRef>(imInvalidHandleValue); if(localRecP) { const prUTF16Char *path = SDKfileOpenRec8->fileinfo.filepath; #ifdef PRWIN_ENV HANDLE fileH = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(fileH != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = fileH; } else result = imFileOpenFailed; #else FSIORefNum refNum = CAST_REFNUM(imInvalidHandleValue); CFStringRef filePathCFSR = CFStringCreateWithCharacters(NULL, path, prUTF16CharLength(path)); CFURLRef filePathURL = CFURLCreateWithFileSystemPath(NULL, filePathCFSR, kCFURLPOSIXPathStyle, false); if(filePathURL != NULL) { FSRef fileRef; Boolean success = CFURLGetFSRef(filePathURL, &fileRef); if(success) { HFSUniStr255 dataForkName; FSGetDataForkName(&dataForkName); OSErr err = FSOpenFork( &fileRef, dataForkName.length, dataForkName.unicode, fsRdWrPerm, &refNum); } CFRelease(filePathURL); } CFRelease(filePathCFSR); if(CAST_FILEREF(refNum) != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = CAST_FILEREF(refNum); } else result = imFileOpenFailed; #endif } if(result == malNoError) { localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; assert(0 == ogg_tell_func(static_cast<void *>(*SDKfileRef))); if(localRecP->fileType == Ogg_filetype) { localRecP->vf = new OggVorbis_File; OggVorbis_File &vf = *localRecP->vf; int ogg_err = ov_open_callbacks(static_cast<void *>(*SDKfileRef), &vf, NULL, 0, g_ov_callbacks); if(ogg_err == OV_OK) { if( ov_streams(&vf) == 0 ) { result = imFileHasNoImportableStreams; ov_clear(&vf); } else if( !ov_seekable(&vf) ) { result = imBadFile; } } else result = imBadHeader; } else if(localRecP->fileType == Opus_filetype) { int _error = 0; localRecP->opus = op_open_callbacks(static_cast<void *>(*SDKfileRef), &g_opusfile_callbacks, NULL, 0, &_error); if(localRecP->opus != NULL && _error == 0) { assert(op_link_count(localRecP->opus) == 1); // we're not really handling multi-link scenarios } else result = imBadHeader; } else if(localRecP->fileType == FLAC_filetype) { try { localRecP->flac = new OurDecoder(*SDKfileRef); localRecP->flac->set_md5_checking(true); FLAC__StreamDecoderInitStatus init_status = localRecP->flac->init(); assert(init_status == FLAC__STREAM_DECODER_INIT_STATUS_OK && localRecP->flac->is_valid()); bool ok = localRecP->flac->process_until_end_of_metadata(); assert(ok); } catch(...) { result = imBadHeader; } } } // close file and delete private data if we got a bad file if(result != malNoError) { if(SDKfileOpenRec8->privatedata) { stdParms->piSuites->memFuncs->disposeHandle(reinterpret_cast<PrMemoryHandle>(SDKfileOpenRec8->privatedata)); SDKfileOpenRec8->privatedata = NULL; } } else { stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(SDKfileOpenRec8->privatedata)); } return result; }
prMALError SDKOpenFile8( imStdParms *stdParms, imFileRef *SDKfileRef, imFileOpenRec8 *SDKfileOpenRec8) { prMALError result = malNoError; ImporterLocalRec8H localRecH = NULL; ImporterLocalRec8Ptr localRecP = NULL; if(SDKfileOpenRec8->privatedata) { localRecH = (ImporterLocalRec8H)SDKfileOpenRec8->privatedata; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); } else { localRecH = (ImporterLocalRec8H)stdParms->piSuites->memFuncs->newHandle(sizeof(ImporterLocalRec8)); SDKfileOpenRec8->privatedata = (PrivateDataPtr)localRecH; stdParms->piSuites->memFuncs->lockHandle(reinterpret_cast<char**>(localRecH)); localRecP = reinterpret_cast<ImporterLocalRec8Ptr>( *localRecH ); localRecP->reader = NULL; localRecP->file = NULL; localRecP->audio_track = NULL; localRecP->alac = NULL; localRecP->importerID = SDKfileOpenRec8->inImporterID; localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; } SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = reinterpret_cast<imFileRef>(imInvalidHandleValue); if(localRecP) { const prUTF16Char *path = SDKfileOpenRec8->fileinfo.filepath; #ifdef PRWIN_ENV HANDLE fileH = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(fileH != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = fileH; } else result = imFileOpenFailed; #else FSIORefNum refNum = CAST_REFNUM(imInvalidHandleValue); CFStringRef filePathCFSR = CFStringCreateWithCharacters(NULL, path, prUTF16CharLength(path)); CFURLRef filePathURL = CFURLCreateWithFileSystemPath(NULL, filePathCFSR, kCFURLPOSIXPathStyle, false); if(filePathURL != NULL) { FSRef fileRef; Boolean success = CFURLGetFSRef(filePathURL, &fileRef); if(success) { HFSUniStr255 dataForkName; FSGetDataForkName(&dataForkName); OSErr err = FSOpenFork( &fileRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &refNum); } CFRelease(filePathURL); } CFRelease(filePathCFSR); if(CAST_FILEREF(refNum) != imInvalidHandleValue) { SDKfileOpenRec8->fileinfo.fileref = *SDKfileRef = CAST_FILEREF(refNum); } else result = imFileOpenFailed; #endif } if(result == malNoError) { localRecP->fileType = SDKfileOpenRec8->fileinfo.filetype; try { localRecP->reader = new My_ByteStream(*SDKfileRef); localRecP->file = new AP4_File(*localRecP->reader); AP4_Track *audio_track = localRecP->file->GetMovie()->GetTrack(AP4_Track::TYPE_AUDIO); if(audio_track != NULL) { assert(audio_track->GetSampleDescriptionCount() == 1); AP4_SampleDescription *desc = audio_track->GetSampleDescription(0); AP4_AudioSampleDescription *audio_desc = AP4_DYNAMIC_CAST(AP4_AudioSampleDescription, desc); if(desc != NULL && desc->GetFormat() == AP4_SAMPLE_FORMAT_ALAC) { localRecP->audio_track = audio_track; ALAC_Atom *alac_atom = AP4_DYNAMIC_CAST(ALAC_Atom, desc->GetDetails().GetChild(AP4_SAMPLE_FORMAT_ALAC)); if(alac_atom != NULL) { size_t magic_cookie_size = 0; void *magic_cookie = alac_atom->GetMagicCookie(magic_cookie_size); if(magic_cookie != NULL && magic_cookie_size > 0) { localRecP->alac = new ALACDecoder(); int32_t alac_result = localRecP->alac->Init(magic_cookie, magic_cookie_size); if(alac_result != 0) { result = imBadHeader; } } else result = imBadHeader; } else result = imBadHeader; } else result = imUnsupportedCompression; } else result = imFileHasNoImportableStreams; } catch(...) { result = imBadFile; } } // close file and delete private data if we got a bad file if(result != malNoError) { if(SDKfileOpenRec8->privatedata) { stdParms->piSuites->memFuncs->disposeHandle(reinterpret_cast<PrMemoryHandle>(SDKfileOpenRec8->privatedata)); SDKfileOpenRec8->privatedata = NULL; } } else { stdParms->piSuites->memFuncs->unlockHandle(reinterpret_cast<char**>(SDKfileOpenRec8->privatedata)); } return result; }