/**********
This library is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation; either version 3 of the License, or (at your
option) any later version. (See <http://www.gnu.org/copyleft/lesser.html>.)

This library is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General Public License
along with this library; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
**********/
// "liveMedia"
// Copyright (c) 1996-2020 Live Networks, Inc.  All rights reserved.
// A 'ServerMediaSubsession' object that creates new, unicast, "RTPSink"s
// on demand, from a MPEG-2 Transport Stream file.
// Implementation

#include "MPEG2TransportFileServerMediaSubsession.hh"
#include "SimpleRTPSink.hh"

MPEG2TransportFileServerMediaSubsession*
MPEG2TransportFileServerMediaSubsession::createNew(UsageEnvironment& env,
						   char const* fileName,
						   char const* indexFileName,
						   Boolean reuseFirstSource) {
  MPEG2TransportStreamIndexFile* indexFile;
  if (indexFileName != NULL && reuseFirstSource) {
    // It makes no sense to support trick play if all clients use the same source.  Fix this:
    env << "MPEG2TransportFileServerMediaSubsession::createNew(): ignoring the index file name, because \"reuseFirstSource\" is set\n";
    indexFile = NULL;
  } else {
    indexFile = MPEG2TransportStreamIndexFile::createNew(env, indexFileName);
  }
  return new MPEG2TransportFileServerMediaSubsession(env, fileName, indexFile,
						     reuseFirstSource);
}

MPEG2TransportFileServerMediaSubsession
::MPEG2TransportFileServerMediaSubsession(UsageEnvironment& env,
					  char const* fileName,
					  MPEG2TransportStreamIndexFile* indexFile,
					  Boolean reuseFirstSource)
  : FileServerMediaSubsession(env, fileName, reuseFirstSource),
    fIndexFile(indexFile), fDuration(0.0), fClientSessionHashTable(NULL) {
  if (fIndexFile != NULL) { // we support 'trick play'
    fDuration = fIndexFile->getPlayingDuration();
    fClientSessionHashTable = HashTable::create(ONE_WORD_HASH_KEYS);
  }
}

MPEG2TransportFileServerMediaSubsession
::~MPEG2TransportFileServerMediaSubsession() {
  if (fIndexFile != NULL) { // we support 'trick play'
    Medium::close(fIndexFile);

    // Clean out the client session hash table:
    while (1) {
      ClientTrickPlayState* client
	= (ClientTrickPlayState*)(fClientSessionHashTable->RemoveNext());
      if (client == NULL) break;
      delete client;
    }
    delete fClientSessionHashTable;
  }
}

#define TRANSPORT_PACKET_SIZE 188
#define TRANSPORT_PACKETS_PER_NETWORK_PACKET 7
// The product of these two numbers must be enough to fit within a network packet

void MPEG2TransportFileServerMediaSubsession
::startStream(unsigned clientSessionId, void* streamToken, TaskFunc* rtcpRRHandler,
	      void* rtcpRRHandlerClientData, unsigned short& rtpSeqNum,
	      unsigned& rtpTimestamp,
	      ServerRequestAlternativeByteHandler* serverRequestAlternativeByteHandler,
	      void* serverRequestAlternativeByteHandlerClientData) {
  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,
					     serverRequestAlternativeByteHandler, serverRequestAlternativeByteHandlerClientData);
}

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
::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
::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
::deleteStream(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::deleteStream(clientSessionId, streamToken);
}

ClientTrickPlayState* MPEG2TransportFileServerMediaSubsession::newClientTrickPlayState() {
  return new ClientTrickPlayState(fIndexFile);
}

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 = newClientTrickPlayState();
      fClientSessionHashTable->Add((char const*)clientSessionId, client);
    }
    client->setSource(framer);
  }

  return framer;
}

RTPSink* MPEG2TransportFileServerMediaSubsession
::createNewRTPSink(Groupsock* rtpGroupsock,
		   unsigned char /*rtpPayloadTypeIfDynamic*/,
		   FramedSource* /*inputSource*/) {
  return SimpleRTPSink::createNew(envir(), rtpGroupsock,
				  33, 90000, "video", "MP2T",
				  1, True, False /*no 'M' bit*/);
}

void MPEG2TransportFileServerMediaSubsession::testScaleFactor(float& scale) {
  if (fIndexFile != NULL && fDuration > 0.0) {
    // We support any integral scale, other than 0
    int iScale = scale < 0.0 ? (int)(scale - 0.5f) : (int)(scale + 0.5f); // round
    if (iScale == 0) iScale = 1;
    scale = (float)iScale;
  } else {
    scale = 1.0f;
  }
}

float MPEG2TransportFileServerMediaSubsession::duration() const {
  return fDuration;
}

ClientTrickPlayState* MPEG2TransportFileServerMediaSubsession
::lookupClient(unsigned clientSessionId) {
  return (ClientTrickPlayState*)(fClientSessionHashTable->Lookup((char const*)clientSessionId));
}


////////// ClientTrickPlayState implementation //////////

ClientTrickPlayState::ClientTrickPlayState(MPEG2TransportStreamIndexFile* indexFile)
  : fIndexFile(indexFile),
    fOriginalTransportStreamSource(NULL),
    fTrickModeFilter(NULL), fTrickPlaySource(NULL),
    fFramer(NULL),
    fScale(1.0f), fNextScale(1.0f), fNPT(0.0f),
    fTSRecordNum(0), fIxRecordNum(0) {
}

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::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);
  }
}

void ClientTrickPlayState::updateStateOnPlayChange(Boolean reverseToPreviousVSH) {
  updateTSRecordNum();
  if (fTrickPlaySource == NULL) {
    // We were in regular (1x) play. Use the index file to look up the
    // index record number and npt from the current transport number:
    fIndexFile->lookupPCRFromTSPacketNum(fTSRecordNum, reverseToPreviousVSH, fNPT, fIxRecordNum);
  } else {
    // We were in trick mode, and so already have the index record number.
    // Get the transport record number and npt from this:
    fIxRecordNum = fTrickModeFilter->nextIndexRecordNum();
    if ((long)fIxRecordNum < 0) fIxRecordNum = 0; // we were at the start of the file
    unsigned long transportRecordNum;
    float pcr;
    u_int8_t offset, size, recordType; // all dummy
    if (fIndexFile->readIndexRecordValues(fIxRecordNum, transportRecordNum,
					  offset, size, pcr, recordType)) {
      fTSRecordNum = transportRecordNum;
      fNPT = pcr;
    }
  }
}

void ClientTrickPlayState::setSource(MPEG2TransportStreamFramer* framer) {
  fFramer = framer;
  fOriginalTransportStreamSource = (ByteStreamFileSource*)(framer->inputSource());
}

void ClientTrickPlayState::updateTSRecordNum(){
  if (fFramer != NULL) fTSRecordNum += (unsigned long)(fFramer->tsPacketCount());
}

void ClientTrickPlayState::reseekOriginalTransportStreamSource() {
  u_int64_t tsRecordNum64 = (u_int64_t)fTSRecordNum;
  fOriginalTransportStreamSource->seekToByteAbsolute(tsRecordNum64*TRANSPORT_PACKET_SIZE);
}
