void MPEG2TransportFileServerMediaSubsession
::pauseStream(unsigned clientSessionId, void* streamToken) {
  if (fIndexFile != NULL) { // we support 'trick play'
    ClientTrickPlayState* client = lookupClient(clientSessionId);
    if (client != NULL) {
      client->updateStateOnPlayChange(False);
    }
  }

  // Call the original, default version of this routine:
  OnDemandServerMediaSubsession::pauseStream(clientSessionId, streamToken);
}
void MPEG2TransportFileServerMediaSubsession
::setStreamScale(unsigned clientSessionId, void* streamToken, float scale) {
  if (fIndexFile != NULL) { // we support 'trick play'
    ClientTrickPlayState* client = lookupClient(clientSessionId);
    if (client != NULL) {
      client->setNextScale(scale); // scale won't take effect until the next "PLAY"
    }
  }

  // Call the original, default version of this routine:
  OnDemandServerMediaSubsession::setStreamScale(clientSessionId, streamToken, scale);
}
void MPEG2TransportFileServerMediaSubsession
::seekStream(unsigned clientSessionId, void* streamToken, float seekNPT) {
  if (fIndexFile != NULL) { // we support 'trick play'
    ClientTrickPlayState* client = lookupClient(clientSessionId);
    if (client != NULL) {
      client->updateStateFromNPT(seekNPT);
    }
  }

  // Call the original, default version of this routine:
  OnDemandServerMediaSubsession::seekStream(clientSessionId, streamToken, seekNPT);
}
void MPEG2TransportFileServerMediaSubsession
::seekStream(unsigned clientSessionId, void* streamToken, double& seekNPT, double streamDuration, u_int64_t& numBytes) {
  // Begin by calling the original, default version of this routine:
  OnDemandServerMediaSubsession::seekStream(clientSessionId, streamToken, seekNPT, streamDuration, numBytes);

  // Then, special handling specific to indexed Transport Stream files:
  if (fIndexFile != NULL) { // we support 'trick play'
    ClientTrickPlayState* client = lookupClient(clientSessionId);
    if (client != NULL) {
      unsigned long numTSPacketsToStream = client->updateStateFromNPT(seekNPT, streamDuration);
      numBytes = numTSPacketsToStream*TRANSPORT_PACKET_SIZE;
    }
  }
}
void MPEG2TransportFileServerMediaSubsession
::startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler,
	      void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum,
	      unsigned& rtpTimestamp) {
  if (fIndexFile != NULL) { // we support 'trick play'
    ClientTrickPlayState* client = lookupClient(clientSessionId);
    if (client != NULL && client->areChangingScale()) {
      // First, handle this like a "PAUSE", except that we back up to the previous VSH
      client->updateStateOnPlayChange(True);
      OnDemandServerMediaSubsession::pauseStream(clientSessionId, streamToken);

      // Then, adjust for the change of scale:
      client->updateStateOnScaleChange();
    }
  }

  // Call the original, default version of this routine:
  OnDemandServerMediaSubsession::startStream(clientSessionId, streamToken,
					     rtcpRRHandler, rtcpRRHandlerClientData,
					     rtpSeqNum, rtpTimestamp);
}
FramedSource *MPEG2TransportFileServerMediaSubsession
::createNewStreamSource(unsigned clientSessionId, unsigned &estBitrate)
{
    // Create the video source:
    unsigned const inputDataChunkSize
    = TRANSPORT_PACKETS_PER_NETWORK_PACKET * TRANSPORT_PACKET_SIZE;
    ByteStreamFileSource *fileSource
    = ByteStreamFileSource::createNew(envir(), fFileName, inputDataChunkSize);
    if (fileSource == NULL) return NULL;
    fFileSize = fileSource->fileSize();

    // Use the file size and the duration to estimate the stream's bitrate:
    if (fFileSize > 0 && fDuration > 0.0)
    {
        estBitrate = (unsigned)((int64_t)fFileSize / (125 * fDuration) + 0.5); // kbps, rounded
    }
    else
    {
        estBitrate = 5000; // kbps, estimate
    }


    // Create a framer for the Transport Stream:
    MPEG2TransportStreamFramer *framer
    = MPEG2TransportStreamFramer::createNew(envir(), fileSource);

    if (fIndexFile != NULL)   // we support 'trick play'
    {
        // Keep state for this client (if we don't already have it):
        ClientTrickPlayState *client = lookupClient(clientSessionId);
        if (client == NULL)
        {
            client = new ClientTrickPlayState(fIndexFile);
            fClientSessionHashTable->Add((char const *)clientSessionId, client);
        }
        client->setSource(framer);
    }

    return framer;
}