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
00088 fSource = NULL;
00089 fAfterFunc = NULL;
00090 }
00091
00092 void MediaSink::onSourceClosure(void* clientData) {
00093 MediaSink* sink = (MediaSink*)clientData;
00094 sink->fSource = NULL;
00095 if (sink->fAfterFunc != NULL) {
00096 (*(sink->fAfterFunc))(sink->fAfterClientData);
00097 }
00098 }
00099
00100 Boolean MediaSink::isRTPSink() const {
00101 return False;
00102 }
00103
00105
00106 unsigned OutPacketBuffer::maxSize = 60000;
00107
00108 OutPacketBuffer::OutPacketBuffer(unsigned preferredPacketSize,
00109 unsigned maxPacketSize)
00110 : fPreferred(preferredPacketSize), fMax(maxPacketSize),
00111 fOverflowDataSize(0) {
00112 unsigned maxNumPackets = (maxSize + (maxPacketSize-1))/maxPacketSize;
00113 fLimit = maxNumPackets*maxPacketSize;
00114 fBuf = new unsigned char[fLimit];
00115 resetPacketStart();
00116 resetOffset();
00117 resetOverflowData();
00118 }
00119
00120 OutPacketBuffer::~OutPacketBuffer() {
00121 delete[] fBuf;
00122 }
00123
00124 void OutPacketBuffer::enqueue(unsigned char const* from, unsigned numBytes) {
00125 if (numBytes > totalBytesAvailable()) {
00126 #ifdef DEBUG
00127 fprintf(stderr, "OutPacketBuffer::enqueue() warning: %d > %d\n", numBytes, totalBytesAvailable());
00128 #endif
00129 numBytes = totalBytesAvailable();
00130 }
00131
00132 if (curPtr() != from) memmove(curPtr(), from, numBytes);
00133 increment(numBytes);
00134 }
00135
00136 void OutPacketBuffer::enqueueWord(u_int32_t word) {
00137 u_int32_t nWord = htonl(word);
00138 enqueue((unsigned char*)&nWord, 4);
00139 }
00140
00141 void OutPacketBuffer::insert(unsigned char const* from, unsigned numBytes,
00142 unsigned toPosition) {
00143 unsigned realToPosition = fPacketStart + toPosition;
00144 if (realToPosition + numBytes > fLimit) {
00145 if (realToPosition > fLimit) return;
00146 numBytes = fLimit - realToPosition;
00147 }
00148
00149 memmove(&fBuf[realToPosition], from, numBytes);
00150 if (toPosition + numBytes > fCurOffset) {
00151 fCurOffset = toPosition + numBytes;
00152 }
00153 }
00154
00155 void OutPacketBuffer::insertWord(u_int32_t word, unsigned toPosition) {
00156 u_int32_t nWord = htonl(word);
00157 insert((unsigned char*)&nWord, 4, toPosition);
00158 }
00159
00160 void OutPacketBuffer::extract(unsigned char* to, unsigned numBytes,
00161 unsigned fromPosition) {
00162 unsigned realFromPosition = fPacketStart + fromPosition;
00163 if (realFromPosition + numBytes > fLimit) {
00164 if (realFromPosition > fLimit) return;
00165 numBytes = fLimit - realFromPosition;
00166 }
00167
00168 memmove(to, &fBuf[realFromPosition], numBytes);
00169 }
00170
00171 u_int32_t OutPacketBuffer::extractWord(unsigned fromPosition) {
00172 u_int32_t nWord;
00173 extract((unsigned char*)&nWord, 4, fromPosition);
00174 return ntohl(nWord);
00175 }
00176
00177 void OutPacketBuffer::skipBytes(unsigned numBytes) {
00178 if (numBytes > totalBytesAvailable()) {
00179 numBytes = totalBytesAvailable();
00180 }
00181
00182 increment(numBytes);
00183 }
00184
00185 void OutPacketBuffer
00186 ::setOverflowData(unsigned overflowDataOffset,
00187 unsigned overflowDataSize,
00188 struct timeval const& presentationTime,
00189 unsigned durationInMicroseconds) {
00190 fOverflowDataOffset = overflowDataOffset;
00191 fOverflowDataSize = overflowDataSize;
00192 fOverflowPresentationTime = presentationTime;
00193 fOverflowDurationInMicroseconds = durationInMicroseconds;
00194 }
00195
00196 void OutPacketBuffer::useOverflowData() {
00197 enqueue(&fBuf[fPacketStart + fOverflowDataOffset], fOverflowDataSize);
00198 fCurOffset -= fOverflowDataSize;
00199 resetOverflowData();
00200 }
00201
00202 void OutPacketBuffer::adjustPacketStart(unsigned numBytes) {
00203 fPacketStart += numBytes;
00204 if (fOverflowDataOffset >= numBytes) {
00205 fOverflowDataOffset -= numBytes;
00206 } else {
00207 fOverflowDataOffset = 0;
00208 fOverflowDataSize = 0;
00209 }
00210 }
00211
00212 void OutPacketBuffer::resetPacketStart() {
00213 if (fOverflowDataSize > 0) {
00214 fOverflowDataOffset += fPacketStart;
00215 }
00216 fPacketStart = 0;
00217 }