00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "MediaSink.hh"
00022 #include "GroupsockHelper.hh"
00023 #include <string.h>
00024
00026
00027 MediaSink::MediaSink(UsageEnvironment& env)
00028 : Medium(env), fSource(NULL) {
00029 }
00030
00031 MediaSink::~MediaSink() {
00032 stopPlaying();
00033 }
00034
00035 Boolean MediaSink::isSink() const {
00036 return True;
00037 }
00038
00039 Boolean MediaSink::lookupByName(UsageEnvironment& env, char const* sinkName,
00040 MediaSink*& resultSink) {
00041 resultSink = NULL;
00042
00043 Medium* medium;
00044 if (!Medium::lookupByName(env, sinkName, medium)) return False;
00045
00046 if (!medium->isSink()) {
00047 env.setResultMsg(sinkName, " is not a media sink");
00048 return False;
00049 }
00050
00051 resultSink = (MediaSink*)medium;
00052 return True;
00053 }
00054
00055 Boolean MediaSink::sourceIsCompatibleWithUs(MediaSource& source) {
00056
00057 return source.isFramedSource();
00058 }
00059
00060 Boolean MediaSink::startPlaying(MediaSource& source,
00061 afterPlayingFunc* afterFunc,
00062 void* afterClientData) {
00063
00064 if (fSource != NULL) {
00065 envir().setResultMsg("This sink is already being played");
00066 return False;
00067 }
00068
00069
00070 if (!sourceIsCompatibleWithUs(source)) {
00071 envir().setResultMsg("MediaSink::startPlaying(): source is not compatible!");
00072 return False;
00073 }
00074 fSource = (FramedSource*)&source;
00075
00076 fAfterFunc = afterFunc;
00077 fAfterClientData = afterClientData;
00078 return continuePlaying();
00079 }
00080
00081 void MediaSink::stopPlaying() {
00082
00083 if (fSource != NULL) fSource->stopGettingFrames();
00084
00085
00086 envir().taskScheduler().unscheduleDelayedTask(nextTask());
00087 nextTask() = NULL;
00088
00089 fSource = NULL;
00090 fAfterFunc = NULL;
00091 }
00092
00093 void MediaSink::onSourceClosure(void* clientData) {
00094 MediaSink* sink = (MediaSink*)clientData;
00095 sink->fSource = NULL;
00096 if (sink->fAfterFunc != NULL) {
00097 (*(sink->fAfterFunc))(sink->fAfterClientData);
00098 }
00099 }
00100
00101 Boolean MediaSink::isRTPSink() const {
00102 return False;
00103 }
00104
00106
00107 unsigned OutPacketBuffer::maxSize = 60000;
00108
00109 OutPacketBuffer::OutPacketBuffer(unsigned preferredPacketSize,
00110 unsigned maxPacketSize)
00111 : fPreferred(preferredPacketSize), fMax(maxPacketSize),
00112 fOverflowDataSize(0) {
00113 unsigned maxNumPackets = (maxSize + (maxPacketSize-1))/maxPacketSize;
00114 fLimit = maxNumPackets*maxPacketSize;
00115 fBuf = new unsigned char[fLimit];
00116 resetPacketStart();
00117 resetOffset();
00118 resetOverflowData();
00119 }
00120
00121 OutPacketBuffer::~OutPacketBuffer() {
00122 delete[] fBuf;
00123 }
00124
00125 void OutPacketBuffer::enqueue(unsigned char const* from, unsigned numBytes) {
00126 if (numBytes > totalBytesAvailable()) {
00127 #ifdef DEBUG
00128 fprintf(stderr, "OutPacketBuffer::enqueue() warning: %d > %d\n", numBytes, totalBytesAvailable());
00129 #endif
00130 numBytes = totalBytesAvailable();
00131 }
00132
00133 if (curPtr() != from) memmove(curPtr(), from, numBytes);
00134 increment(numBytes);
00135 }
00136
00137 void OutPacketBuffer::enqueueWord(unsigned word) {
00138 unsigned nWord = htonl(word);
00139 enqueue((unsigned char*)&nWord, 4);
00140 }
00141
00142 void OutPacketBuffer::insert(unsigned char const* from, unsigned numBytes,
00143 unsigned toPosition) {
00144 unsigned realToPosition = fPacketStart + toPosition;
00145 if (realToPosition + numBytes > fLimit) {
00146 if (realToPosition > fLimit) return;
00147 numBytes = fLimit - realToPosition;
00148 }
00149
00150 memmove(&fBuf[realToPosition], from, numBytes);
00151 if (toPosition + numBytes > fCurOffset) {
00152 fCurOffset = toPosition + numBytes;
00153 }
00154 }
00155
00156 void OutPacketBuffer::insertWord(unsigned word, unsigned toPosition) {
00157 unsigned nWord = htonl(word);
00158 insert((unsigned char*)&nWord, 4, toPosition);
00159 }
00160
00161 void OutPacketBuffer::extract(unsigned char* to, unsigned numBytes,
00162 unsigned fromPosition) {
00163 unsigned realFromPosition = fPacketStart + fromPosition;
00164 if (realFromPosition + numBytes > fLimit) {
00165 if (realFromPosition > fLimit) return;
00166 numBytes = fLimit - realFromPosition;
00167 }
00168
00169 memmove(to, &fBuf[realFromPosition], numBytes);
00170 }
00171
00172 unsigned OutPacketBuffer::extractWord(unsigned fromPosition) {
00173 unsigned nWord;
00174 extract((unsigned char*)&nWord, 4, fromPosition);
00175 return ntohl(nWord);
00176 }
00177
00178 void OutPacketBuffer::skipBytes(unsigned numBytes) {
00179 if (numBytes > totalBytesAvailable()) {
00180 numBytes = totalBytesAvailable();
00181 }
00182
00183 increment(numBytes);
00184 }
00185
00186 void OutPacketBuffer
00187 ::setOverflowData(unsigned overflowDataOffset,
00188 unsigned overflowDataSize,
00189 struct timeval const& presentationTime,
00190 unsigned durationInMicroseconds) {
00191 fOverflowDataOffset = overflowDataOffset;
00192 fOverflowDataSize = overflowDataSize;
00193 fOverflowPresentationTime = presentationTime;
00194 fOverflowDurationInMicroseconds = durationInMicroseconds;
00195 }
00196
00197 void OutPacketBuffer::useOverflowData() {
00198 enqueue(&fBuf[fPacketStart + fOverflowDataOffset], fOverflowDataSize);
00199 fCurOffset -= fOverflowDataSize;
00200 resetOverflowData();
00201 }
00202
00203 void OutPacketBuffer::adjustPacketStart(unsigned numBytes) {
00204 fPacketStart += numBytes;
00205 if (fOverflowDataOffset >= numBytes) {
00206 fOverflowDataOffset -= numBytes;
00207 } else {
00208 fOverflowDataOffset = 0;
00209 fOverflowDataSize = 0;
00210 }
00211 }
00212
00213 void OutPacketBuffer::resetPacketStart() {
00214 if (fOverflowDataSize > 0) {
00215 fOverflowDataOffset += fPacketStart;
00216 }
00217 fPacketStart = 0;
00218 }