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