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 envir().taskScheduler().unscheduleDelayedTask(nextTask());
00112 #ifndef READ_FROM_FILES_SYNCHRONOUSLY
00113 envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
00114 fHaveStartedReading = False;
00115 #endif
00116 }
00117
00118 void ByteStreamFileSource::fileReadableHandler(ByteStreamFileSource* source, int ) {
00119 if (!source->isCurrentlyAwaitingData()) {
00120 source->doStopGettingFrames();
00121 return;
00122 }
00123 source->doReadFromFile();
00124 }
00125
00126 void ByteStreamFileSource::doReadFromFile() {
00127
00128 if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
00129 fMaxSize = (unsigned)fNumBytesToStream;
00130 }
00131 if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
00132 fMaxSize = fPreferredFrameSize;
00133 }
00134 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
00135 fFrameSize = fread(fTo, 1, fMaxSize, fFid);
00136 #else
00137 if (fFidIsSeekable) {
00138 fFrameSize = fread(fTo, 1, fMaxSize, fFid);
00139 } else {
00140
00141 fFrameSize = read(fileno(fFid), fTo, fMaxSize);
00142 }
00143 #endif
00144 if (fFrameSize == 0) {
00145 handleClosure(this);
00146 return;
00147 }
00148 fNumBytesToStream -= fFrameSize;
00149
00150
00151 if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {
00152 if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
00153
00154 gettimeofday(&fPresentationTime, NULL);
00155 } else {
00156
00157 unsigned uSeconds = fPresentationTime.tv_usec + fLastPlayTime;
00158 fPresentationTime.tv_sec += uSeconds/1000000;
00159 fPresentationTime.tv_usec = uSeconds%1000000;
00160 }
00161
00162
00163 fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;
00164 fDurationInMicroseconds = fLastPlayTime;
00165 } else {
00166
00167
00168 gettimeofday(&fPresentationTime, NULL);
00169 }
00170
00171
00172 #ifdef READ_FROM_FILES_SYNCHRONOUSLY
00173
00174 nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
00175 (TaskFunc*)FramedSource::afterGetting, this);
00176 #else
00177
00178
00179 FramedSource::afterGetting(this);
00180 #endif
00181 }