00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "T140TextRTPSink.hh"
00022 #include <GroupsockHelper.hh>
00023
00025
00026 T140TextRTPSink::T140TextRTPSink(UsageEnvironment& env, Groupsock* RTPgs, unsigned char rtpPayloadFormat)
00027 : TextRTPSink(env, RTPgs, rtpPayloadFormat, 1000, "T140"),
00028 fOurIdleFilter(NULL), fAreInIdlePeriod(True) {
00029 }
00030
00031 T140TextRTPSink::~T140TextRTPSink() {
00032 fSource = fOurIdleFilter;
00033 stopPlaying();
00034
00035
00036 Medium::close(fOurIdleFilter);
00037 fSource = NULL;
00038 }
00039
00040 T140TextRTPSink*
00041 T140TextRTPSink::createNew(UsageEnvironment& env, Groupsock* RTPgs,
00042 unsigned char rtpPayloadFormat) {
00043 return new T140TextRTPSink(env, RTPgs, rtpPayloadFormat);
00044 }
00045
00046 Boolean T140TextRTPSink::continuePlaying() {
00047
00048 if (fOurIdleFilter == NULL) {
00049 fOurIdleFilter = new T140IdleFilter(envir(), fSource);
00050 } else {
00051 fOurIdleFilter->reassignInputSource(fSource);
00052 }
00053 fSource = fOurIdleFilter;
00054
00055
00056 return MultiFramedRTPSink::continuePlaying();
00057 }
00058
00059 void T140TextRTPSink::doSpecialFrameHandling(unsigned ,
00060 unsigned char* ,
00061 unsigned numBytesInFrame,
00062 struct timeval framePresentationTime,
00063 unsigned ) {
00064
00065 if (fAreInIdlePeriod && numBytesInFrame > 0) setMarkerBit();
00066 fAreInIdlePeriod = numBytesInFrame == 0;
00067
00068 setTimestamp(framePresentationTime);
00069 }
00070
00071 Boolean T140TextRTPSink::frameCanAppearAfterPacketStart(unsigned char const* , unsigned ) const {
00072 return False;
00073 }
00074
00075
00077
00078 T140IdleFilter::T140IdleFilter(UsageEnvironment& env, FramedSource* inputSource)
00079 : FramedFilter(env, inputSource),
00080 fIdleTimerTask(NULL),
00081 fBufferSize(OutPacketBuffer::maxSize), fNumBufferedBytes(0) {
00082 fBuffer = new char[fBufferSize];
00083 }
00084
00085 T140IdleFilter::~T140IdleFilter() {
00086 envir().taskScheduler().unscheduleDelayedTask(fIdleTimerTask);
00087
00088 delete[] fBuffer;
00089 detachInputSource();
00090 }
00091
00092 #define IDLE_TIMEOUT_MICROSECONDS 300000
00093
00094 void T140IdleFilter::doGetNextFrame() {
00095
00096 if (fNumBufferedBytes > 0) {
00097 deliverFromBuffer();
00098 return;
00099 }
00100
00101
00102
00103 fIdleTimerTask = envir().taskScheduler().scheduleDelayedTask(IDLE_TIMEOUT_MICROSECONDS, handleIdleTimeout, this);
00104 if (fInputSource != NULL && !fInputSource->isCurrentlyAwaitingData()) {
00105 fInputSource->getNextFrame((unsigned char*)fBuffer, fBufferSize, afterGettingFrame, this, onSourceClosure, this);
00106 }
00107 }
00108
00109 void T140IdleFilter::afterGettingFrame(void* clientData, unsigned frameSize,
00110 unsigned numTruncatedBytes,
00111 struct timeval presentationTime,
00112 unsigned durationInMicroseconds) {
00113 ((T140IdleFilter*)clientData)->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
00114 }
00115
00116 void T140IdleFilter::afterGettingFrame(unsigned frameSize,
00117 unsigned numTruncatedBytes,
00118 struct timeval presentationTime,
00119 unsigned durationInMicroseconds) {
00120
00121 envir().taskScheduler().unscheduleDelayedTask(fIdleTimerTask);
00122
00123
00124 fNumBufferedBytes = frameSize;
00125 fBufferedNumTruncatedBytes = numTruncatedBytes;
00126 fBufferedDataPresentationTime = presentationTime;
00127 fBufferedDataDurationInMicroseconds = durationInMicroseconds;
00128
00129
00130 if (isCurrentlyAwaitingData()) (void)deliverFromBuffer();
00131 }
00132
00133 void T140IdleFilter::doStopGettingFrames() {
00134
00135 envir().taskScheduler().unscheduleDelayedTask(fIdleTimerTask);
00136
00137
00138 FramedFilter::doStopGettingFrames();
00139 }
00140
00141 void T140IdleFilter::handleIdleTimeout(void* clientData) {
00142 ((T140IdleFilter*)clientData)->handleIdleTimeout();
00143 }
00144
00145 void T140IdleFilter::handleIdleTimeout() {
00146
00147
00148 deliverEmptyFrame();
00149 }
00150
00151 void T140IdleFilter::deliverFromBuffer() {
00152 if (fNumBufferedBytes <= fMaxSize) {
00153 fNumTruncatedBytes = fBufferedNumTruncatedBytes;
00154 fFrameSize = fNumBufferedBytes;
00155 } else {
00156 fNumTruncatedBytes = fBufferedNumTruncatedBytes + fNumBufferedBytes - fMaxSize;
00157 fFrameSize = fMaxSize;
00158 }
00159
00160 memmove(fTo, fBuffer, fFrameSize);
00161 fPresentationTime = fBufferedDataPresentationTime;
00162 fDurationInMicroseconds = fBufferedDataDurationInMicroseconds;
00163
00164 fNumBufferedBytes = 0;
00165
00166 FramedSource::afterGetting(this);
00167 }
00168
00169 void T140IdleFilter::deliverEmptyFrame() {
00170 fFrameSize = fNumTruncatedBytes = 0;
00171 gettimeofday(&fPresentationTime, NULL);
00172 FramedSource::afterGetting(this);
00173 }
00174
00175 void T140IdleFilter::onSourceClosure(void* clientData) {
00176 ((T140IdleFilter*)clientData)->onSourceClosure();
00177 }
00178
00179 void T140IdleFilter::onSourceClosure() {
00180 envir().taskScheduler().unscheduleDelayedTask(fIdleTimerTask);
00181 fIdleTimerTask = NULL;
00182
00183 FramedSource::handleClosure(this);
00184 }