00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ByteStreamFileSource.hh"
00022 #include "InputFile.hh"
00023 #include "GroupsockHelper.hh"
00024
00026
00027 ByteStreamFileSource*
00028 ByteStreamFileSource::createNew(UsageEnvironment& env, char const* fileName,
00029 unsigned preferredFrameSize,
00030 unsigned playTimePerFrame) {
00031 FILE* fid = OpenInputFile(env, fileName);
00032 if (fid == NULL) return NULL;
00033
00034 ByteStreamFileSource* newSource
00035 = new ByteStreamFileSource(env, fid, preferredFrameSize, playTimePerFrame);
00036 newSource->fFileSize = GetFileSize(fileName, fid);
00037
00038 return newSource;
00039 }
00040
00041 ByteStreamFileSource*
00042 ByteStreamFileSource::createNew(UsageEnvironment& env, FILE* fid,
00043 unsigned preferredFrameSize,
00044 unsigned playTimePerFrame) {
00045 if (fid == NULL) return NULL;
00046
00047 ByteStreamFileSource* newSource = new ByteStreamFileSource(env, fid, preferredFrameSize, playTimePerFrame);
00048 newSource->fFileSize = GetFileSize(NULL, fid);
00049
00050 return newSource;
00051 }
00052
00053 void ByteStreamFileSource::seekToByteAbsolute(u_int64_t byteNumber, u_int64_t numBytesToStream) {
00054 SeekFile64(fFid, (int64_t)byteNumber, SEEK_SET);
00055
00056 fNumBytesToStream = numBytesToStream;
00057 fLimitNumBytesToStream = fNumBytesToStream > 0;
00058 }
00059
00060 void ByteStreamFileSource::seekToByteRelative(int64_t offset) {
00061 SeekFile64(fFid, offset, SEEK_CUR);
00062 }
00063
00064 void ByteStreamFileSource::seekToEnd() {
00065 SeekFile64(fFid, 0, SEEK_END);
00066 }
00067
00068 ByteStreamFileSource::ByteStreamFileSource(UsageEnvironment& env, FILE* fid,
00069 unsigned preferredFrameSize,
00070 unsigned playTimePerFrame)
00071 : FramedFileSource(env, fid), fFileSize(0), fPreferredFrameSize(preferredFrameSize),
00072 fPlayTimePerFrame(playTimePerFrame), fLastPlayTime(0),
00073 fHaveStartedReading(False), fLimitNumBytesToStream(False), fNumBytesToStream(0) {
00074 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
00075 makeSocketNonBlocking(fileno(fFid));
00076 #endif
00077
00078
00079 fFidIsSeekable = FileIsSeekable(fFid);
00080 }
00081
00082 ByteStreamFileSource::~ByteStreamFileSource() {
00083 if (fFid == NULL) return;
00084
00085 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
00086 envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
00087 #endif
00088
00089 CloseInputFile(fFid);
00090 }
00091
00092 void ByteStreamFileSource::doGetNextFrame() {
00093 if (feof(fFid) || ferror(fFid) || (fLimitNumBytesToStream && fNumBytesToStream == 0)) {
00094 handleClosure(this);
00095 return;
00096 }
00097
00098 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
00099 doReadFromFile();
00100 #else
00101 if (!fHaveStartedReading) {
00102
00103 envir().taskScheduler().turnOnBackgroundReadHandling(fileno(fFid),
00104 (TaskScheduler::BackgroundHandlerProc*)&fileReadableHandler, this);
00105 fHaveStartedReading = True;
00106 }
00107 #endif
00108 }
00109
00110 void ByteStreamFileSource::doStopGettingFrames() {
00111 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
00112 envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
00113 fHaveStartedReading = False;
00114 #endif
00115 }
00116
00117 void ByteStreamFileSource::fileReadableHandler(ByteStreamFileSource* source, int ) {
00118 if (!source->isCurrentlyAwaitingData()) {
00119 source->doStopGettingFrames();
00120 return;
00121 }
00122 source->doReadFromFile();
00123 }
00124
00125 static Boolean const readFromFilesSynchronously
00126 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
00127 = True;
00128 #else
00129 = False;
00130 #endif
00131
00132 void ByteStreamFileSource::doReadFromFile() {
00133
00134 if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
00135 fMaxSize = (unsigned)fNumBytesToStream;
00136 }
00137 if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
00138 fMaxSize = fPreferredFrameSize;
00139 }
00140 if (readFromFilesSynchronously || fFidIsSeekable) {
00141 fFrameSize = fread(fTo, 1, fMaxSize, fFid);
00142 } else {
00143
00144 fFrameSize = read(fileno(fFid), fTo, fMaxSize);
00145 }
00146 if (fFrameSize == 0) {
00147 handleClosure(this);
00148 return;
00149 }
00150 fNumBytesToStream -= fFrameSize;
00151
00152
00153 if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {
00154 if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
00155
00156 gettimeofday(&fPresentationTime, NULL);
00157 } else {
00158
00159 unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;
00160 fPresentationTime.tv_sec += uSeconds/1000000;
00161 fPresentationTime.tv_usec = uSeconds%1000000;
00162 }
00163
00164
00165 fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;
00166 fDurationInMicroseconds = fLastPlayTime;
00167 } else {
00168
00169
00170 gettimeofday(&fPresentationTime, NULL);
00171 }
00172
00173
00174 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
00175
00176 nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00177 (TaskFunc*)FramedSource::afterGetting, this);
00178 #else
00179
00180
00181 FramedSource::afterGetting(this);
00182 #endif
00183 }