Exemple #1
0
void MediaSink::stopPlaying() {
  // First, tell the source that we're no longer interested:
  if (fSource != NULL) fSource->stopGettingFrames();

  // Cancel any pending tasks:
  envir().taskScheduler().unscheduleDelayedTask(nextTask());
  nextTask() = NULL;

  fSource = NULL; // indicates that we can be played again
  fAfterFunc = NULL;
}
void MultiFramedRTPSink::buildAndSendPacket(Boolean isFirstPacket) {
  nextTask() = NULL;
  fIsFirstPacket = isFirstPacket;

  // Set up the RTP header:
  unsigned rtpHdr = 0x80000000; // RTP version 2; marker ('M') bit not set (by default; it can be set later)
  rtpHdr |= (fRTPPayloadType<<16);
  rtpHdr |= fSeqNo; // sequence number
  fOutBuf->enqueueWord(rtpHdr);

  // Note where the RTP timestamp will go.
  // (We can't fill this in until we start packing payload frames.)
  fTimestampPosition = fOutBuf->curPacketSize();
  fOutBuf->skipBytes(4); // leave a hole for the timestamp

  fOutBuf->enqueueWord(SSRC());

  // Allow for a special, payload-format-specific header following the
  // RTP header:
  fSpecialHeaderPosition = fOutBuf->curPacketSize();
  fSpecialHeaderSize = specialHeaderSize();
  fOutBuf->skipBytes(fSpecialHeaderSize);

  // Begin packing as many (complete) frames into the packet as we can:
  fTotalFrameSpecificHeaderSizes = 0;
  fNoFramesLeft = False;
  fNumFramesUsedSoFar = 0;
  packFrame();
}
void BasicUDPSink::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
				      unsigned durationInMicroseconds) {
  if (numTruncatedBytes > 0) {
    envir() << "BasicUDPSink::afterGettingFrame1(): The input frame data was too large for our spcified maximum payload size ("
	    << fMaxPayloadSize << ").  "
	    << numTruncatedBytes << " bytes of trailing data was dropped!\n";
  }

  // Send the packet:
  fGS->output(envir(), fGS->ttl(), fOutputBuffer, frameSize);

  // Figure out the time at which the next packet should be sent, based
  // on the duration of the payload that we just read:
  fNextSendTime.tv_usec += durationInMicroseconds;
  fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;
  fNextSendTime.tv_usec %= 1000000;

  struct timeval timeNow;
  gettimeofday(&timeNow, NULL);
  int uSecondsToGo;
  if (fNextSendTime.tv_sec < timeNow.tv_sec) {
    uSecondsToGo = 0; // prevents integer underflow if too far behind
  } else {
    uSecondsToGo = (fNextSendTime.tv_sec - timeNow.tv_sec)*1000000
      + (fNextSendTime.tv_usec - timeNow.tv_usec);
  }

  // Delay this amount of time:
  nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,
							   (TaskFunc*)sendNext, this);
}
Exemple #4
0
void BasicUDPSink::afterGettingFrame1(unsigned frameSize, unsigned numTruncatedBytes,
                                      unsigned durationInMicroseconds) {
  if (numTruncatedBytes > 0) {
    envir() << "BasicUDPSink::afterGettingFrame1(): The input frame data was too large for our spcified maximum payload size ("
            << fMaxPayloadSize << ").  "
            << numTruncatedBytes << " bytes of trailing data was dropped!\n";
  }

  // Send the packet:
  fGS->output(envir(), fOutputBuffer, frameSize);

  // Figure out the time at which the next packet should be sent, based
  // on the duration of the payload that we just read:
  fNextSendTime.tv_usec += durationInMicroseconds;
  fNextSendTime.tv_sec += fNextSendTime.tv_usec/1000000;
  fNextSendTime.tv_usec %= 1000000;

  struct timeval timeNow;
  gettimeofday(&timeNow, NULL);
  int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
  int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
  if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
    uSecondsToGo = 0;
  }

  // Delay this amount of time:
  nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo,
                                                           (TaskFunc*)sendNext, this);
}
void QueueServerMediaSubsession::afterPlayingDummy1()
{
    // Unschedule any pending 'checking' task:
    envir().taskScheduler().unscheduleDelayedTask(nextTask());
    // Signal the event loop that we're done:
    setDoneFlag();
}
void ByteStreamFileSource::doStopGettingFrames() {
  envir().taskScheduler().unscheduleDelayedTask(nextTask());
#ifndef READ_FROM_FILES_SYNCHRONOUSLY
  envir().taskScheduler().turnOffBackgroundReadHandling(fileno(fFid));
  fHaveStartedReading = False;
#endif
}
// Note: We should change the following to use asynchronous file reading, #####
// as we now do with ByteStreamFileSource. #####
void AMRAudioFileSource::doGetNextFrame() {
  if (feof(fFid) || ferror(fFid)) {
    handleClosure(this);
    return;
  }

  // Begin by reading the 1-byte frame header (and checking it for validity)
  while (1) {
    if (fread(&fLastFrameHeader, 1, 1, fFid) < 1) {
      handleClosure(this);
      return;
    }
    if ((fLastFrameHeader&0x83) != 0) {
#ifdef DEBUG
      fprintf(stderr, "Invalid frame header 0x%02x (padding bits (0x83) are not zero)\n", fLastFrameHeader);
#endif
    } else {
      unsigned char ft = (fLastFrameHeader&0x78)>>3;
      fFrameSize = fIsWideband ? frameSizeWideband[ft] : frameSize[ft];
      if (fFrameSize == FT_INVALID) {
#ifdef DEBUG
	fprintf(stderr, "Invalid FT field %d (from frame header 0x%02x)\n",
		ft, fLastFrameHeader);
#endif
      } else {
	// The frame header is OK
#ifdef DEBUG
	fprintf(stderr, "Valid frame header 0x%02x -> ft %d -> frame size %d\n", fLastFrameHeader, ft, fFrameSize);
#endif
	break;
      }
    }
  } 
      
  // Next, read the frame-block into the buffer provided:
  fFrameSize *= fNumChannels; // because multiple channels make up a frame-block
  if (fFrameSize > fMaxSize) {
    fNumTruncatedBytes = fFrameSize - fMaxSize;
    fFrameSize = fMaxSize;
  }
  fFrameSize = fread(fTo, 1, fFrameSize, fFid);

  // Set the 'presentation time':
  if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
    // This is the first frame, so use the current time:
    gettimeofday(&fPresentationTime, NULL);
  } else {
    // Increment by the play time of the previous frame (20 ms)
    unsigned uSeconds	= fPresentationTime.tv_usec + 20000;
    fPresentationTime.tv_sec += uSeconds/1000000;
    fPresentationTime.tv_usec = uSeconds%1000000;
  }

  fDurationInMicroseconds = 20000; // each frame is 20 ms

  // Switch to another task, and inform the reader that he has data:
  nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
				(TaskFunc*)FramedSource::afterGetting, this);
 }
void BasicUDPSink::continuePlaying1() {
  nextTask() = NULL;
  if (fSource != NULL) {
    fSource->getNextFrame(fOutputBuffer, fMaxPayloadSize,
			  afterGettingFrame, this,
			  onSourceClosure, this);
  }
}
void MediaSink::onSourceClosure() {
  // Cancel any pending tasks:
  envir().taskScheduler().unscheduleDelayedTask(nextTask());

  fSource = NULL; // indicates that we can be played again
  if (fAfterFunc != NULL) {
    (*fAfterFunc)(fAfterClientData);
  }
}
void ByteStreamFileSource::doReadFromFile() {
  // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
  if (fLimitNumBytesToStream && fNumBytesToStream < (u_int64_t)fMaxSize) {
    fMaxSize = (unsigned)fNumBytesToStream;
  }
  if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
    fMaxSize = fPreferredFrameSize;
  }
#ifdef READ_FROM_FILES_SYNCHRONOUSLY
  fFrameSize = fread(fTo, 1, fMaxSize, fFid);
#else
  if (fFidIsSeekable) {
    fFrameSize = fread(fTo, 1, fMaxSize, fFid);
  } else {
    // For non-seekable files (e.g., pipes), call "read()" rather than "fread()", to ensure that the read doesn't block:
    fFrameSize = read(fileno(fFid), fTo, fMaxSize);
  }
#endif
  if (fFrameSize == 0) {
    handleClosure();
    return;
  }
  fNumBytesToStream -= fFrameSize;

  // Set the 'presentation time':
  if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) {
    if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
      // This is the first frame, so use the current time:
      gettimeofday(&fPresentationTime, NULL);
    } else {
      // Increment by the play time of the previous data:
      unsigned uSeconds	= fPresentationTime.tv_usec + fLastPlayTime;
      fPresentationTime.tv_sec += uSeconds/1000000;
      fPresentationTime.tv_usec = uSeconds%1000000;
    }

    // Remember the play time of this data:
    fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;
    fDurationInMicroseconds = fLastPlayTime;
  } else {
    // We don't know a specific play time duration for this data,
    // so just record the current time as being the 'presentation time':
    gettimeofday(&fPresentationTime, NULL);
  }

  // Inform the reader that he has data:
#ifdef READ_FROM_FILES_SYNCHRONOUSLY
  // To avoid possible infinite recursion, we need to return to the event loop to do this:
  nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
				(TaskFunc*)FramedSource::afterGetting, this);
#else
  // Because the file read was done from the event loop, we can call the
  // 'after getting' function directly, without risk of infinite recursion:
  FramedSource::afterGetting(this);
#endif
}
void MultiFramedRTPSource::doStopGettingFrames() {
  if (fPacketReadInProgress != NULL) {
    fReorderingBuffer->freePacket(fPacketReadInProgress);
    fPacketReadInProgress = NULL;
  }
  envir().taskScheduler().unscheduleDelayedTask(nextTask());
  fRTPInterface.stopNetworkReading();
  fReorderingBuffer->reset();
  reset();
}
void MPEG4VideoFileServerMediaSubsession::checkForAuxSDPLine1() {
  nextTask() = NULL;

  char const* dasl;
  if (fAuxSDPLine != NULL) {
    // Signal the event loop that we're done:
    setDoneFlag();
  } else if (fDummyRTPSink != NULL && (dasl = fDummyRTPSink->auxSDPLine()) != NULL) {
    fAuxSDPLine= strDup(dasl);
    fDummyRTPSink = NULL;

    // Signal the event loop that we're done:
    setDoneFlag();
  } else if (!fDoneFlag) {
    // try again after a brief delay:
    int uSecsToDelay = 100000; // 100 ms
    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
			      (TaskFunc*)checkForAuxSDPLine, this);
  }
}
//从文件中读取fMaxSize个字节到fTo
void ByteStreamFileSource::doReadFromFile() {
  // Try to read as many bytes as will fit in the buffer provided
  // (or "fPreferredFrameSize" if less)
  if (fPreferredFrameSize > 0 && fPreferredFrameSize < fMaxSize) {
    fMaxSize = fPreferredFrameSize;
  }
  
  DEBUG_LOG(INF, "Read file: start = %ld, size= %u; Write to %p", ftell(fFid), fMaxSize, fTo);
  
  fFrameSize = fread(fTo, 1, fMaxSize, fFid);//fread(buffer,size,count,fp);
  if (fFrameSize == 0) {
    handleClosure(this);
    return;
  }

  // 设置图像时间,Set the 'presentation time':
  if (fPlayTimePerFrame > 0 && fPreferredFrameSize > 0) 
  {
    if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) 
    {
      // fPresentationTime为零,表示这是第一帧,This is the first frame, so use the current time:
      gettimeofday(&fPresentationTime, NULL);
    } 
    else 
    {
      // Increment by the play time of the previous data:
      // 根据上次的fPresentationTime和上次的持续时间计算新的fPresentationTime
      unsigned uSeconds	= fPresentationTime.tv_usec + fLastPlayTime;
      fPresentationTime.tv_sec += uSeconds/1000000;
      fPresentationTime.tv_usec = uSeconds%1000000;
    }

    // Remember the play time of this data:
    fLastPlayTime = (fPlayTimePerFrame*fFrameSize)/fPreferredFrameSize;
    fDurationInMicroseconds = fLastPlayTime;
  } 
  else 
  {
    // We don't know a specific play time duration for this data,
    // so just record the current time as being the 'presentation time':
    gettimeofday(&fPresentationTime, NULL);
  }

  // Inform the reader that he has data:
#ifdef READ_FROM_FILES_SYNCHRONOUSLY
  // To avoid possible infinite recursion, we need to return to the event loop to do this:
  nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
				(TaskFunc*)FramedSource::afterGetting, this);
#else
  // Because the file read was done from the event loop, we can call the
  // 'after getting' function directly, without risk of infinite recursion:
  FramedSource::afterGetting(this);
#endif
}
void WISH264VideoServerMediaSubsession::checkForAuxSDPLine1() {
  if (fDummyRTPSink->auxSDPLine() != NULL) {
    // Signal the event loop that we're done:
    setDoneFlag();
  } else {
    // try again after a brief delay:
    int uSecsToDelay = 100000; // 100 ms
    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
			      (TaskFunc*)checkForAuxSDPLine, this);
  }
}
Exemple #15
0
void RTCPInstance::schedule(double nextTime) {
  fNextReportTime = nextTime;

  double secondsToDelay = nextTime - dTimeNow();
#ifdef DEBUG
  fprintf(stderr, "schedule(%f->%f)\n", secondsToDelay, nextTime);
#endif
  int usToGo = (int)(secondsToDelay * 1000000);
  nextTask() = envir().taskScheduler().scheduleDelayedTask(usToGo,
				(TaskFunc*)RTCPInstance::onExpire, this);
}
Exemple #16
0
	void chkForAuxSDPLine1 ()
	{
		fprintf(stderr, "[%d] %s .... calling\n", gettid(), __func__);
		if (mp_dummy_rtpsink->auxSDPLine())
			m_done = 0xff;
		else {
			int delay = 100*1000;	// 100ms
			nextTask() = envir().taskScheduler().scheduleDelayedTask(delay,
					chkForAuxSDPLine, this);
		}
	}
Exemple #17
0
void DefaultSource::doGetNextFrame()
{
    auto const CODE = _reader->read(fTo, fMaxSize, &fFrameSize, &fPresentationTime);
    if (isFailure(CODE)) {
        handleClosure();
        return;
    }

    // Inform the reader that he has data:
    // To avoid possible infinite recursion, we need to return to the event loop to do this:
    nextTask() = envir().taskScheduler().scheduleDelayedTask(0, (TaskFunc*)FramedSource::afterGetting, this);
}
void MultiFramedRTPSink::sendPacketIfNecessary() {
  if (fNumFramesUsedSoFar > 0) {
    // Send the packet:
#ifdef TEST_LOSS
    if ((our_random()%10) != 0) // simulate 10% packet loss #####
#endif
      if (!fRTPInterface.sendPacket(fOutBuf->packet(), fOutBuf->curPacketSize())) {
	// if failure handler has been specified, call it
	if (fOnSendErrorFunc != NULL) (*fOnSendErrorFunc)(fOnSendErrorData);
      }
    ++fPacketCount;
    fTotalOctetCount += fOutBuf->curPacketSize();
    fOctetCount += fOutBuf->curPacketSize()
      - rtpHeaderSize - fSpecialHeaderSize - fTotalFrameSpecificHeaderSizes;

    ++fSeqNo; // for next time
  }

  if (fOutBuf->haveOverflowData()
      && fOutBuf->totalBytesAvailable() > fOutBuf->totalBufferSize()/2) {
    // Efficiency hack: Reset the packet start pointer to just in front of
    // the overflow data (allowing for the RTP header and special headers),
    // so that we probably don't have to "memmove()" the overflow data
    // into place when building the next packet:
    unsigned newPacketStart = fOutBuf->curPacketSize()
      - (rtpHeaderSize + fSpecialHeaderSize + frameSpecificHeaderSize());
    fOutBuf->adjustPacketStart(newPacketStart);
  } else {
    // Normal case: Reset the packet start pointer back to the start:
    fOutBuf->resetPacketStart();
  }
  fOutBuf->resetOffset();
  fNumFramesUsedSoFar = 0;

  if (fNoFramesLeft) {
    // We're done:
    onSourceClosure();
  } else {
    // We have more frames left to send.  Figure out when the next frame
    // is due to start playing, then make sure that we wait this long before
    // sending the next packet.
    struct timeval timeNow;
    gettimeofday(&timeNow, NULL);
    int secsDiff = fNextSendTime.tv_sec - timeNow.tv_sec;
    int64_t uSecondsToGo = secsDiff*1000000 + (fNextSendTime.tv_usec - timeNow.tv_usec);
    if (uSecondsToGo < 0 || secsDiff < 0) { // sanity check: Make sure that the time-to-delay is non-negative:
      uSecondsToGo = 0;
    }

    // Delay this amount of time:
    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToGo, (TaskFunc*)sendNext, this);
  }
}
Exemple #19
0
void H264LiveServerMediaSession::checkForAuxSDPLine1() {
	char const* dasl;
	if (fAuxSDPLine != NULL) {
		setDoneFlag();
	} else if (fDummySink != NULL && (dasl = fDummySink->auxSDPLine()) != NULL) {
		fAuxSDPLine = strDup(dasl);
		fDummySink = NULL;
		setDoneFlag();
	} else {
		int uSecsDelay = 100000;
		nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsDelay, (TaskFunc*) checkForAuxSDPLine, this);
	}
}
void StreamDeviceSource::deliverFrame() {
  // This function is called when new frame data is available from the device.
  // We deliver this data by copying it to the 'downstream' object, using the following parameters (class members):
  // 'in' parameters (these should *not* be modified by this function):
  //     fTo: The frame data is copied to this address.
  //         (Note that the variable "fTo" is *not* modified.  Instead,
  //          the frame data is copied to the address pointed to by "fTo".)
  //     fMaxSize: This is the maximum number of bytes that can be copied
  //         (If the actual frame is larger than this, then it should
  //          be truncated, and "fNumTruncatedBytes" set accordingly.)
  // 'out' parameters (these are modified by this function):
  //     fFrameSize: Should be set to the delivered frame size (<= fMaxSize).
  //     fNumTruncatedBytes: Should be set iff the delivered frame would have been
  //         bigger than "fMaxSize", in which case it's set to the number of bytes
  //         that have been omitted.
  //     fPresentationTime: Should be set to the frame's presentation time
  //         (seconds, microseconds).  This time must be aligned with 'wall-clock time' - i.e., the time that you would get
  //         by calling "gettimeofday()".
  //     fDurationInMicroseconds: Should be set to the frame's duration, if known.
  //         If, however, the device is a 'live source' (e.g., encoded from a camera or microphone), then we probably don't need
  //         to set this variable, because - in this case - data will never arrive 'early'.
  // Note the code below.
    
  if (isCurrentlyAwaitingData()) return; // we're not ready for the data yet

    // allocate temporary buffer
    static void *buffer = NULL;
    if (NULL == buffer) {
        buffer = malloc(8192);
    }
    // by specifying length = 8192 we telling to discardBytesFromGlobalCircularBuffer that it may copy maximum 8192 bytes
    int32_t length  = 8192;
    discardBytesFromGlobalCircularBuffer(&buffer, &length);
    
    u_int8_t* newFrameDataStart = (u_int8_t*)buffer;
    unsigned newFrameSize = length;

  // Deliver the data here:
  if (newFrameSize > fMaxSize) {
    fFrameSize = fMaxSize;
    fNumTruncatedBytes = newFrameSize - fMaxSize;
  } else {
    fFrameSize = newFrameSize;
  }
  gettimeofday(&fPresentationTime, NULL); // If you have a more accurate time - e.g., from an encoder - then use that instead.
  // If the device is *not* a 'live source' (e.g., it comes instead from a file or buffer), then set "fDurationInMicroseconds" here.
  memmove(fTo, newFrameDataStart, fFrameSize);

    // After delivering the data, inform the reader that it is now available:
    nextTask() = envir().taskScheduler().scheduleDelayedTask(0, (TaskFunc*)FramedSource::afterGetting, this);
}
Exemple #21
0
/** resets the current state, creates a new task and count the last task as
 * wrong, if it wasn't solved (in _NEXT_TASK state) yet
 * mainly used after changing the task parameters */
void ExerciseCompare::forceNewTask()
{
#ifdef DEBUG
    qDebug() << QStringLiteral("forceNewTask ExerciseCompare()");
#endif

    if (m_currentState == _CHECK_TASK) {
        // emit the signal for skipped
        signalExerciseSkipped();
    }
    m_currentState = _CHECK_TASK;

    // generate next task
    (void) nextTask();
}
Exemple #22
0
void ExerciseCompare::slotSkipButtonClicked()
{
#ifdef DEBUG
    qDebug() << "ExerciseCompare::slotSkipButtonClicked()";
#endif
    if (m_currentState == _CHECK_TASK) {
        forceNewTask();
    } else {
        m_currentState = _CHECK_TASK;
        m_skipButton->setText(i18n("&Skip"));
        m_resultWidget->setResult(m_firstRatio, -1);
        nextTask();
    }

    return;
}
void RTCPInstance::schedule(double nextTime) {
	fNextReportTime = nextTime;

	double secondsToDelay = nextTime - dTimeNow();
	if (secondsToDelay < 0) secondsToDelay = 0;
#ifdef DEBUG
#ifdef __LINUX__
	fprintf(stderr, "schedule(%f->%f)\n", secondsToDelay, nextTime);
#else
	fprintf(stderr, "schedule(%ld->%ld) us\n", (int64_t)(secondsToDelay*1000000), (int64_t)(nextTime*1000000));
#endif
#endif
	int64_t usToGo = (int64_t)(secondsToDelay * 1000000);
	nextTask() = envir().taskScheduler().scheduleDelayedTask(usToGo,
			(TaskFunc*)RTCPInstance::onExpire, this);
}
Exemple #24
0
	void chk_sdp_done1 ()
	{
		if (mp_sdp_line) {
			m_done = 1;
		}
		else if (mp_dump_sink && mp_dump_sink->auxSDPLine()) {
			mp_sdp_line = strdup(mp_dump_sink->auxSDPLine());
			mp_dump_sink = 0;
			m_done = 1;
		}
		else {
			// try again
			nextTask() = envir().taskScheduler().scheduleDelayedTask(100000,	// 100ms
					chk_sdp_done, this);
		}
	}
Exemple #25
0
/** resets the current state, creates a new task and count the last task as
 * wrong, if it wasn't solved (in _NEXT_TASK state) yet
 * mainly used after changing the task parameters */
void TaskView::forceNewTask()
{
#ifdef DEBUG
	kdDebug() << "forceNewTask TaskView()" << endl;
#endif

	if (m_currentState == _CHECK_TASK)
	{
		// emit the signal for wrong
		signalTaskSolvedWrong();
	}
	m_currentState = _CHECK_TASK;
	m_checkButton->setText(i18n("&Check Task"));

	// generate next task
	(void) nextTask();
}
Exemple #26
0
void TaskView::slotCheckButtonClicked()
{
	if (m_currentState == _CHECK_TASK)
	{
		// if nothing has been entered by the user, we don't check the result yet
		if (numer_edit->text().isEmpty() == true && deno_edit->text().isEmpty() ==
true)
			return;
		m_currentState = _NEXT_TASK;
		m_checkButton->setText(i18n("N&ext Task"));
		(void) showResult();
	} else {
		m_currentState = _CHECK_TASK;
		m_checkButton->setText(i18n("&Check Task"));
		(void) nextTask();
	}
}
void H264VideoFileServerMediaSubsession::checkForAuxSDPLine1()
{
    // If encode stream is mjpeg, the done flag is also needed to be set.
    // If not set for mjpeg, rtsp_server will not come out of  DESBRIBE command processing from client
    // Modified by Zhaoyang
    //if (fDummyRTPSink->auxSDPLine() != NULL) {
#if defined( USE_V3_3_CODE )
    if (fEncType == IAV_ENCODE_MJPEG || fDummyRTPSink->auxSDPLine() != NULL)
    {
#else
    if (fDummyRTPSink->auxSDPLine() != NULL)
    {
#endif
        // Signal the event loop that we're done:
        setDoneFlag();
    }
    else
    {
        // try again after a brief delay:
        int uSecsToDelay = 100000; // 100 ms
        nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecsToDelay,
                     (TaskFunc*)checkForAuxSDPLine, this);
    }
}

char const* H264VideoFileServerMediaSubsession
::getAuxSDPLine(RTPSink* rtpSink, FramedSource* inputSource)
{
    // Note: For MPEG-4 video files, the 'config' information isn't known
    // until we start reading the file.  This means that "rtpSink"s
    // "auxSDPLine()" will be NULL initially, and we need to start reading
    // data from our file until this changes.
    fDummyRTPSink = rtpSink;

    // Start reading the file:
    fDummyRTPSink->startPlaying(*inputSource, afterPlayingDummy, this);

    // Check whether the sink's 'auxSDPLine()' is ready:
    checkForAuxSDPLine(this);

    envir().taskScheduler().doEventLoop(&fDoneFlag);

    char const* auxSDPLine = fDummyRTPSink->auxSDPLine();
    return auxSDPLine;
}
bool RenderThread::threadLoop() {
    setpriority(PRIO_PROCESS, 0, PRIORITY_DISPLAY);
    initThreadLocals();

    int timeoutMillis = -1;
    for (;;) {
        int result = mLooper->pollOnce(timeoutMillis);
        LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR,
                "RenderThread Looper POLL_ERROR!");

        nsecs_t nextWakeup;
        // Process our queue, if we have anything
        while (RenderTask* task = nextTask(&nextWakeup)) {
            task->run();
            // task may have deleted itself, do not reference it again
        }
        if (nextWakeup == LLONG_MAX) {
            timeoutMillis = -1;
        } else {
            nsecs_t timeoutNanos = nextWakeup - systemTime(SYSTEM_TIME_MONOTONIC);
            timeoutMillis = nanoseconds_to_milliseconds(timeoutNanos);
            if (timeoutMillis < 0) {
                timeoutMillis = 0;
            }
        }

        if (mPendingRegistrationFrameCallbacks.size() && !mFrameCallbackTaskPending) {
            drainDisplayEventQueue();
            mFrameCallbacks.insert(
                    mPendingRegistrationFrameCallbacks.begin(), mPendingRegistrationFrameCallbacks.end());
            mPendingRegistrationFrameCallbacks.clear();
            requestVsync();
        }

        if (!mFrameCallbackTaskPending && !mVsyncRequested && mFrameCallbacks.size()) {
            // TODO: Clean this up. This is working around an issue where a combination
            // of bad timing and slow drawing can result in dropping a stale vsync
            // on the floor (correct!) but fails to schedule to listen for the
            // next vsync (oops), so none of the callbacks are run.
            requestVsync();
        }
    }

    return false;
}
// Note: We should change the following to use asynchronous file reading, #####
// as we now do with ByteStreamFileSource. #####
void G711AudioStreamSource::doGetNextFrame() {
    // Try to read as many bytes as will fit in the buffer provided (or "fPreferredFrameSize" if less)
    if (fLimitNumBytesToStream && fNumBytesToStream < fMaxSize) {
        fMaxSize = fNumBytesToStream;
    }
    if (fPreferredFrameSize < fMaxSize) {
        fMaxSize = fPreferredFrameSize;
    }
    unsigned bytesPerSample = (fNumChannels*fBitsPerSample)/8;
    if (bytesPerSample == 0) bytesPerSample = 1; // because we can't read less than a byte at a time
    //unsigned bytesToRead = fMaxSize - fMaxSize%bytesPerSample;

    //fFrameSize : 1000
    audioGetOneFrame(fTo, &fFrameSize);

    // Set the 'presentation time' and 'duration' of this frame:
    if (fPresentationTime.tv_sec == 0 && fPresentationTime.tv_usec == 0) {
        // This is the first frame, so use the current time:
        gettimeofday(&fPresentationTime, NULL);
    } else {
        // Increment by the play time of the previous data:
        unsigned uSeconds	= fPresentationTime.tv_usec + fLastPlayTime;
        fPresentationTime.tv_sec += uSeconds/1000000;
        fPresentationTime.tv_usec = uSeconds%1000000;
    }

    // Remember the play time of this data:
    fDurationInMicroseconds = fLastPlayTime
        = (unsigned)((fPlayTimePerSample*fFrameSize)/bytesPerSample);

    // Switch to another task, and inform the reader that he has data:
#if defined(__WIN32__) || defined(_WIN32)
    // HACK: One of our applications that uses this source uses an
    // implementation of scheduleDelayedTask() that performs very badly
    // (chewing up lots of CPU time, apparently polling) on Windows.
    // Until this is fixed, we just call our "afterGetting()" function
    // directly.  This avoids infinite recursion, as long as our sink
    // is discontinuous, which is the case for the RTP sink that
    // this application uses. #####
    afterGetting(this);
#else
    nextTask() = envir().taskScheduler().scheduleDelayedTask(0,
            (TaskFunc*)FramedSource::afterGetting, this);
#endif
}
void WindowsAudioInputDevice_common::audioReadyPoller1() {
  if (readHead != NULL) {
    onceAudioIsReady();
  } else {
    unsigned const maxPollingDelay = (100 + fGranularityInMS)*1000;
    if (fTotalPollingDelay > maxPollingDelay) {
      // We've waited too long for the audio device - assume it's down:
      handleClosure(this);
      return;
    }

    // Try again after a short delay:
    unsigned const uSecondsToDelay = fGranularityInMS*1000;
    fTotalPollingDelay += uSecondsToDelay;
    nextTask() = envir().taskScheduler().scheduleDelayedTask(uSecondsToDelay,
							     (TaskFunc*)audioReadyPoller, this);
  }
}