void ClientTrickPlayState::updateStateOnScaleChange()
{
    fScale = fNextScale;

    // Change our source objects to reflect the change in scale:
    // First, close the existing trick play source (if any):
    if (fTrickPlaySource != NULL)
    {
        fTrickModeFilter->forgetInputSource();
        // so that the underlying Transport Stream source doesn't get deleted by:
        Medium::close(fTrickPlaySource);
        fTrickPlaySource = NULL;
        fTrickModeFilter = NULL;
    }
    if (fNextScale != 1.0f)
    {
        // Create a new trick play filter from the original Transport Stream source:
        UsageEnvironment &env = fIndexFile->envir(); // alias
        fTrickModeFilter = MPEG2TransportStreamTrickModeFilter
                           ::createNew(env, fOriginalTransportStreamSource, fIndexFile, int(fNextScale));
        fTrickModeFilter->seekTo(fTSRecordNum, fIxRecordNum);

        // And generate a Transport Stream from this:
        fTrickPlaySource = MPEG2TransportStreamFromESSource::createNew(env);
        fTrickPlaySource->addNewVideoSource(fTrickModeFilter, fIndexFile->mpegVersion());

        fFramer->changeInputSource(fTrickPlaySource);
    }
    else
    {
        // Switch back to the original Transport Stream source:
        reseekOriginalTransportStreamSource();
        fFramer->changeInputSource(fOriginalTransportStreamSource);
    }
}
unsigned long ClientTrickPlayState::updateStateFromNPT(double npt, double streamDuration) {
  fNPT = (float)npt;
  // Map "fNPT" to the corresponding Transport Stream and Index record numbers:
  unsigned long tsRecordNum, ixRecordNum;
  fIndexFile->lookupTSPacketNumFromNPT(fNPT, tsRecordNum, ixRecordNum);

  updateTSRecordNum();
  if (tsRecordNum != fTSRecordNum) {
    fTSRecordNum = tsRecordNum;
    fIxRecordNum = ixRecordNum;

    // Seek the source to the new record number:
    reseekOriginalTransportStreamSource();
    // Note: We assume that we're asked to seek only in normal
    // (i.e., non trick play) mode, so we don't seek within the trick
    // play source (if any).

    fFramer->clearPIDStatusTable();
  }

  unsigned long numTSRecordsToStream = 0;
  float pcrLimit = 0.0;
  if (streamDuration > 0.0) {
    // fNPT might have changed when we looked it up in the index file.  Adjust "streamDuration" accordingly:
    streamDuration += npt - (double)fNPT;

    if (streamDuration > 0.0) {
      // Specify that we want to stream no more data than this.

      if (fNextScale == 1.0f) {
	// We'll be streaming from the original file.
	// Use the index file to figure out how many Transport Packets we get to stream:
	unsigned long toTSRecordNum, toIxRecordNum;    
	float toNPT = (float)(fNPT + streamDuration);
	fIndexFile->lookupTSPacketNumFromNPT(toNPT, toTSRecordNum, toIxRecordNum);
	if (toTSRecordNum > tsRecordNum) { // sanity check
	  numTSRecordsToStream = toTSRecordNum - tsRecordNum;
	}
      } else {
	// We'll be streaming from the trick play stream.  
	// It'd be difficult to figure out how many Transport Packets we need to stream, so instead set a PCR
	// limit in the trick play stream.  (We rely upon the fact that PCRs in the trick play stream start at 0.0)
	int direction = fNextScale < 0.0 ? -1 : 1;
	pcrLimit = (float)(streamDuration/(fNextScale*direction));
      }
    }
  }
  fFramer->setNumTSPacketsToStream(numTSRecordsToStream);
  fFramer->setPCRLimit(pcrLimit);

  return numTSRecordsToStream;
}
void ClientTrickPlayState::updateStateFromNPT(double npt) {
  fNPT = (float)npt;
  // Map "fNPT" to the corresponding Transport Stream and Index record numbers:
  unsigned long tsRecordNum, ixRecordNum;
  fIndexFile->lookupTSPacketNumFromNPT(fNPT, tsRecordNum, ixRecordNum);

  updateTSRecordNum();
  if (tsRecordNum != fTSRecordNum) {
    fTSRecordNum = tsRecordNum;
    fIxRecordNum = ixRecordNum;

    // Seek the source to the new record number:
    reseekOriginalTransportStreamSource();
    // Note: We assume that we're asked to seek only in normal
    // (i.e., non trick play) mode, so we don't seek within the trick
    // play source (if any).

    fFramer->clearPIDStatusTable();
  }
}
unsigned long ClientTrickPlayState::updateStateFromNPT(double npt, double streamDuration) {
  fNPT = (float)npt;
  // Map "fNPT" to the corresponding Transport Stream and Index record numbers:
  unsigned long tsRecordNum, ixRecordNum;
  fIndexFile->lookupTSPacketNumFromNPT(fNPT, tsRecordNum, ixRecordNum);

  updateTSRecordNum();
  if (tsRecordNum != fTSRecordNum) {
    fTSRecordNum = tsRecordNum;
    fIxRecordNum = ixRecordNum;

    // Seek the source to the new record number:
    reseekOriginalTransportStreamSource();
    // Note: We assume that we're asked to seek only in normal
    // (i.e., non trick play) mode, so we don't seek within the trick
    // play source (if any).

    fFramer->clearPIDStatusTable();
  }

  // NPT might have changed when we looked it up in the index file.  Adjust "streamDuration" accordingly:
  streamDuration += npt - (double)fNPT;

  unsigned long numTSRecordsToStream = 0;
  if (streamDuration > 0.0) {
    // Use the index file to figure out how many Transport Packets we get to stream:
    unsigned long toTSRecordNum, toIxRecordNum;    
    float toNPT = (float)(fNPT + streamDuration);
    fIndexFile->lookupTSPacketNumFromNPT(toNPT, toTSRecordNum, toIxRecordNum);
    if (toTSRecordNum > tsRecordNum) { // sanity check
      numTSRecordsToStream = toTSRecordNum - tsRecordNum;
    }
  }
  fFramer->setNumTSPacketsToStream(numTSRecordsToStream);

  return numTSRecordsToStream;
}