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 #endif
00025 #include "FileSink.hh"
00026 #include "GroupsockHelper.hh"
00027 #include "OutputFile.hh"
00028
00030
00031 FileSink::FileSink(UsageEnvironment& env, FILE* fid, unsigned bufferSize,
00032 char const* perFrameFileNamePrefix)
00033 : MediaSink(env), fOutFid(fid), fBufferSize(bufferSize) {
00034 fBuffer = new unsigned char[bufferSize];
00035 if (perFrameFileNamePrefix != NULL) {
00036 fPerFrameFileNamePrefix = strDup(perFrameFileNamePrefix);
00037 fPerFrameFileNameBuffer = new char[strlen(perFrameFileNamePrefix) + 100];
00038 } else {
00039 fPerFrameFileNamePrefix = NULL;
00040 fPerFrameFileNameBuffer = NULL;
00041 }
00042 }
00043
00044 FileSink::~FileSink() {
00045 delete[] fPerFrameFileNameBuffer;
00046 delete[] fPerFrameFileNamePrefix;
00047 delete[] fBuffer;
00048 if (fOutFid != NULL) fclose(fOutFid);
00049 }
00050
00051 FileSink* FileSink::createNew(UsageEnvironment& env, char const* fileName,
00052 unsigned bufferSize, Boolean oneFilePerFrame) {
00053 do {
00054 FILE* fid;
00055 char const* perFrameFileNamePrefix;
00056 if (oneFilePerFrame) {
00057
00058 fid = NULL;
00059 perFrameFileNamePrefix = fileName;
00060 } else {
00061
00062 fid = OpenOutputFile(env, fileName);
00063 if (fid == NULL) break;
00064 perFrameFileNamePrefix = NULL;
00065 }
00066
00067 return new FileSink(env, fid, bufferSize, perFrameFileNamePrefix);
00068 } while (0);
00069
00070 return NULL;
00071 }
00072
00073 Boolean FileSink::continuePlaying() {
00074 if (fSource == NULL) return False;
00075
00076 fSource->getNextFrame(fBuffer, fBufferSize,
00077 afterGettingFrame, this,
00078 onSourceClosure, this);
00079
00080 return True;
00081 }
00082
00083 void FileSink::afterGettingFrame(void* clientData, unsigned frameSize,
00084 unsigned ,
00085 struct timeval presentationTime,
00086 unsigned ) {
00087 FileSink* sink = (FileSink*)clientData;
00088 sink->afterGettingFrame1(frameSize, presentationTime);
00089 }
00090
00091 void FileSink::addData(unsigned char* data, unsigned dataSize,
00092 struct timeval presentationTime) {
00093 if (fPerFrameFileNameBuffer != NULL) {
00094
00095 sprintf(fPerFrameFileNameBuffer, "%s-%lu.%06lu", fPerFrameFileNamePrefix,
00096 presentationTime.tv_sec, presentationTime.tv_usec);
00097 fOutFid = OpenOutputFile(envir(), fPerFrameFileNameBuffer);
00098 }
00099
00100
00101 #ifdef TEST_LOSS
00102 static unsigned const framesPerPacket = 10;
00103 static unsigned const frameCount = 0;
00104 static Boolean const packetIsLost;
00105 if ((frameCount++)%framesPerPacket == 0) {
00106 packetIsLost = (our_random()%10 == 0);
00107 }
00108
00109 if (!packetIsLost)
00110 #endif
00111 if (fOutFid != NULL && data != NULL) {
00112 fwrite(data, 1, dataSize, fOutFid);
00113 }
00114 }
00115
00116 void FileSink::afterGettingFrame1(unsigned frameSize,
00117 struct timeval presentationTime) {
00118 addData(fBuffer, frameSize, presentationTime);
00119
00120 if (fOutFid == NULL || fflush(fOutFid) == EOF) {
00121
00122
00123 onSourceClosure(this);
00124
00125 stopPlaying();
00126 return;
00127 }
00128
00129 if (fPerFrameFileNameBuffer != NULL) {
00130 if (fOutFid != NULL) { fclose(fOutFid); fOutFid = NULL; }
00131 }
00132
00133
00134 continuePlaying();
00135 }