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 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
00015 **********/
00016 // "liveMedia"
00017 // Copyright (c) 1996-2013 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 
00088   fSource = NULL; // indicates that we can be played again
00089   fAfterFunc = NULL;
00090 }
00091 
00092 void MediaSink::onSourceClosure(void* clientData) {
00093   MediaSink* sink = (MediaSink*)clientData;
00094   sink->fSource = NULL; // indicates that we can be played again
00095   if (sink->fAfterFunc != NULL) {
00096     (*(sink->fAfterFunc))(sink->fAfterClientData);
00097   }
00098 }
00099 
00100 Boolean MediaSink::isRTPSink() const {
00101   return False; // default implementation
00102 }
00103 
00105 
00106 unsigned OutPacketBuffer::maxSize = 60000; // by default
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; // we can't do this
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) { // sanity check
00164     if (realFromPosition > fLimit) return; // we can't do this
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; // undoes increment performed by "enqueue"
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; // an error otherwise
00209   }
00210 }
00211 
00212 void OutPacketBuffer::resetPacketStart() {
00213   if (fOverflowDataSize > 0) {
00214     fOverflowDataOffset += fPacketStart;
00215   }
00216   fPacketStart = 0;
00217 }

Generated on Mon Apr 29 13:28:01 2013 for live by  doxygen 1.5.2