liveMedia/MediaSink.cpp

Go to the documentation of this file.
00001 /**********
00002 This library is free software; you can redistribute it and/or modify it under
00003 the terms of the GNU Lesser General Public License as published by the
00004 Free Software Foundation; either version 2.1 of the License, or (at your
00005 option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)
00006 
00007 This library is distributed in the hope that it will be useful, but WITHOUT
00008 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00009 FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
00010 more details.
00011 
00012 You should have received a copy of the GNU Lesser General Public License
00013 along with this library; if not, write to the Free Software Foundation, Inc.,
00014 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2008 Live Networks, Inc.  All rights reserved.
00018 // Media Sinks
00019 // Implementation
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; // unless we succeed
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   // We currently support only framed sources.
00057   return source.isFramedSource();
00058 }
00059 
00060 Boolean MediaSink::startPlaying(MediaSource& source,
00061                                 afterPlayingFunc* afterFunc,
00062                                 void* afterClientData) {
00063   // Make sure we're not already being played:
00064   if (fSource != NULL) {
00065     envir().setResultMsg("This sink is already being played");
00066     return False;
00067   }
00068 
00069   // Make sure our source is compatible:
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   // First, tell the source that we're no longer interested:
00083   if (fSource != NULL) fSource->stopGettingFrames();
00084 
00085   // Cancel any pending tasks:
00086   envir().taskScheduler().unscheduleDelayedTask(nextTask());
00087   nextTask() = NULL;
00088 
00089   fSource = NULL; // indicates that we can be played again
00090   fAfterFunc = NULL;
00091 }
00092 
00093 void MediaSink::onSourceClosure(void* clientData) {
00094   MediaSink* sink = (MediaSink*)clientData;
00095   sink->fSource = NULL; // indicates that we can be played again
00096   if (sink->fAfterFunc != NULL) {
00097     (*(sink->fAfterFunc))(sink->fAfterClientData);
00098   }
00099 }
00100 
00101 Boolean MediaSink::isRTPSink() const {
00102   return False; // default implementation
00103 }
00104 
00106 
00107 unsigned OutPacketBuffer::maxSize = 60000; // by default
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; // we can't do this
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) { // sanity check
00165     if (realFromPosition > fLimit) return; // we can't do this
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; // undoes increment performed by "enqueue"
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; // an error otherwise
00210   }
00211 }
00212 
00213 void OutPacketBuffer::resetPacketStart() {
00214   if (fOverflowDataSize > 0) {
00215     fOverflowDataOffset += fPacketStart;
00216   }
00217   fPacketStart = 0;
00218 }

Generated on Tue Jul 22 06:39:06 2008 for live by  doxygen 1.5.2