/**********
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 class that encapsulates an Ogg file.
// Implementation

#include "OggFileParser.hh"
#include "OggDemuxedTrack.hh"
#include "ByteStreamFileSource.hh"
#include "VorbisAudioRTPSink.hh"
#include "SimpleRTPSink.hh"
#include "TheoraVideoRTPSink.hh"

////////// OggTrackTable definition /////////

// For looking up and iterating over the file's tracks:

class OggTrackTable {
public:
  OggTrackTable();
  virtual ~OggTrackTable();

  void add(OggTrack* newTrack);
  OggTrack* lookup(u_int32_t trackNumber);

  unsigned numTracks() const;

private:
  friend class OggTrackTableIterator;
  HashTable* fTable;
};


////////// OggFile implementation //////////

void OggFile::createNew(UsageEnvironment& env, char const* fileName,
			onCreationFunc* onCreation, void* onCreationClientData) {
  new OggFile(env, fileName, onCreation, onCreationClientData);
}

OggTrack* OggFile::lookup(u_int32_t trackNumber) {
  return fTrackTable->lookup(trackNumber);
}

OggDemux* OggFile::newDemux() {
  OggDemux* demux = new OggDemux(*this);
  fDemuxesTable->Add((char const*)demux, demux);

  return demux;
}

unsigned OggFile::numTracks() const {
  return fTrackTable->numTracks();
}

FramedSource* OggFile
::createSourceForStreaming(FramedSource* baseSource, u_int32_t trackNumber,
                           unsigned& estBitrate, unsigned& numFiltersInFrontOfTrack) {
  if (baseSource == NULL) return NULL;

  FramedSource* result = baseSource; // by default
  numFiltersInFrontOfTrack = 0; // by default

  // Look at the track's MIME type to set its estimated bitrate (for use by RTCP).
  // (Later, try to be smarter about figuring out the bitrate.) #####
  // Some MIME types also require adding a special 'framer' in front of the source.
  OggTrack* track = lookup(trackNumber);
  if (track != NULL) { // should always be true
    estBitrate = track->estBitrate;
  }

  return result;
}

RTPSink* OggFile
::createRTPSinkForTrackNumber(u_int32_t trackNumber, Groupsock* rtpGroupsock,
                              unsigned char rtpPayloadTypeIfDynamic) {
  OggTrack* track = lookup(trackNumber);
  if (track == NULL || track->mimeType == NULL) return NULL;

  RTPSink* result = NULL; // default value for unknown media types

  if (strcmp(track->mimeType, "audio/VORBIS") == 0) {
    // For Vorbis audio, we use the special "identification", "comment", and "setup" headers
    // that we read when we initially read the headers at the start of the file:
    result = VorbisAudioRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
					   track->samplingFrequency, track->numChannels,
					   track->vtoHdrs.header[0], track->vtoHdrs.headerSize[0],
					   track->vtoHdrs.header[1], track->vtoHdrs.headerSize[1],
					   track->vtoHdrs.header[2], track->vtoHdrs.headerSize[2]);
  } else if (strcmp(track->mimeType, "audio/OPUS") == 0) {
    result = SimpleRTPSink
      ::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
		  48000, "audio", "OPUS", 2, False/*only 1 Opus 'packet' in each RTP packet*/);
  } else if (strcmp(track->mimeType, "video/THEORA") == 0) {
    // For Theora video, we use the special "identification", "comment", and "setup" headers
    // that we read when we initially read the headers at the start of the file:
    result = TheoraVideoRTPSink::createNew(envir(), rtpGroupsock, rtpPayloadTypeIfDynamic,
					   track->vtoHdrs.header[0], track->vtoHdrs.headerSize[0],
					   track->vtoHdrs.header[1], track->vtoHdrs.headerSize[1],
					   track->vtoHdrs.header[2], track->vtoHdrs.headerSize[2]);
  }

  return result;
}


OggFile::OggFile(UsageEnvironment& env, char const* fileName,
		 onCreationFunc* onCreation, void* onCreationClientData)
  : Medium(env),
    fFileName(strDup(fileName)),
    fOnCreation(onCreation), fOnCreationClientData(onCreationClientData) {
  fTrackTable = new OggTrackTable;
  fDemuxesTable = HashTable::create(ONE_WORD_HASH_KEYS);

  FramedSource* inputSource = ByteStreamFileSource::createNew(envir(), fileName);
  if (inputSource == NULL) {
    // The specified input file does not exist!
    fParserForInitialization = NULL;
    handleEndOfBosPageParsing(); // we have no file, and thus no tracks, but we still need to signal this
  } else {
    // Initialize ourselves by parsing the file's headers:
    fParserForInitialization
      = new OggFileParser(*this, inputSource, handleEndOfBosPageParsing, this);
  }
}

OggFile::~OggFile() {
  delete fParserForInitialization;

  // Delete any outstanding "OggDemux"s, and the table for them:
  OggDemux* demux;
  while ((demux = (OggDemux*)fDemuxesTable->RemoveNext()) != NULL) {
    delete demux;
  }
  delete fDemuxesTable;
  delete fTrackTable;

  delete[] (char*)fFileName;
}

void OggFile::handleEndOfBosPageParsing(void* clientData) {
  ((OggFile*)clientData)->handleEndOfBosPageParsing();
}

void OggFile::handleEndOfBosPageParsing() {
  // Delete our parser, because it's done its job now:
  delete fParserForInitialization; fParserForInitialization = NULL;

  // Finally, signal our caller that we've been created and initialized:
  if (fOnCreation != NULL) (*fOnCreation)(this, fOnCreationClientData);
}

void OggFile::addTrack(OggTrack* newTrack) {
  fTrackTable->add(newTrack);
}

void OggFile::removeDemux(OggDemux* demux) {
  fDemuxesTable->Remove((char const*)demux);
}


////////// OggTrackTable implementation /////////

OggTrackTable::OggTrackTable()
  : fTable(HashTable::create(ONE_WORD_HASH_KEYS)) {
}

OggTrackTable::~OggTrackTable() {
  // Remove and delete all of our "OggTrack" descriptors, and the hash table itself:
  OggTrack* track;
  while ((track = (OggTrack*)fTable->RemoveNext()) != NULL) {
    delete track;
  }
  delete fTable;
}

void OggTrackTable::add(OggTrack* newTrack) {
  OggTrack* existingTrack
    = (OggTrack*)fTable->Add((char const*)newTrack->trackNumber, newTrack);
  delete existingTrack; // if any
}

OggTrack* OggTrackTable::lookup(u_int32_t trackNumber) {
  return (OggTrack*)fTable->Lookup((char const*)trackNumber);
}

unsigned OggTrackTable::numTracks() const { return fTable->numEntries(); }

OggTrackTableIterator::OggTrackTableIterator(OggTrackTable& ourTable) {
  fIter = HashTable::Iterator::create(*(ourTable.fTable));
}

OggTrackTableIterator::~OggTrackTableIterator() {
  delete fIter;
}

OggTrack* OggTrackTableIterator::next() {
  char const* key;
  return (OggTrack*)fIter->next(key);
}


////////// OggTrack implementation //////////

OggTrack::OggTrack()
  : trackNumber(0), mimeType(NULL),
    samplingFrequency(48000), numChannels(2), estBitrate(100) { // default settings
  vtoHdrs.header[0] = vtoHdrs.header[1] = vtoHdrs.header[2] = NULL;
  vtoHdrs.headerSize[0] = vtoHdrs.headerSize[1] = vtoHdrs.headerSize[2] = 0;

  vtoHdrs.vorbis_mode_count = 0;
  vtoHdrs.vorbis_mode_blockflag = NULL;
}

OggTrack::~OggTrack() {
  delete[] vtoHdrs.header[0]; delete[] vtoHdrs.header[1]; delete[] vtoHdrs.header[2];
  delete[] vtoHdrs.vorbis_mode_blockflag;
}


///////// OggDemux implementation /////////

FramedSource* OggDemux::newDemuxedTrack(u_int32_t& resultTrackNumber) {
  OggTrack* nextTrack;
  do {
    nextTrack = fIter->next();
  } while (nextTrack != NULL && nextTrack->mimeType == NULL);

  if (nextTrack == NULL) { // no more tracks
    resultTrackNumber = 0;
    return NULL;
  }

  resultTrackNumber = nextTrack->trackNumber;
  FramedSource* trackSource = new OggDemuxedTrack(envir(), resultTrackNumber, *this);
  fDemuxedTracksTable->Add((char const*)resultTrackNumber, trackSource);
  return trackSource;
}

FramedSource* OggDemux::newDemuxedTrackByTrackNumber(unsigned trackNumber) {
  if (trackNumber == 0) return NULL;

  FramedSource* trackSource = new OggDemuxedTrack(envir(), trackNumber, *this);
  fDemuxedTracksTable->Add((char const*)trackNumber, trackSource);
  return trackSource;
}

OggDemuxedTrack* OggDemux::lookupDemuxedTrack(u_int32_t trackNumber) {
  return (OggDemuxedTrack*)fDemuxedTracksTable->Lookup((char const*)trackNumber);
}

OggDemux::OggDemux(OggFile& ourFile)
  : Medium(ourFile.envir()),
    fOurFile(ourFile), fDemuxedTracksTable(HashTable::create(ONE_WORD_HASH_KEYS)),
    fIter(new OggTrackTableIterator(*fOurFile.fTrackTable)) {
  FramedSource* fileSource = ByteStreamFileSource::createNew(envir(), ourFile.fileName());
  fOurParser = new OggFileParser(ourFile, fileSource, handleEndOfFile, this, this);
}

OggDemux::~OggDemux() {
  // Begin by acting as if we've reached the end of the source file.
  // This should cause all of our demuxed tracks to get closed.
  handleEndOfFile();

  // Then delete our table of "OggDemuxedTrack"s
  // - but not the "OggDemuxedTrack"s themselves; that should have already happened:
  delete fDemuxedTracksTable;

  delete fIter;
  delete fOurParser;
  fOurFile.removeDemux(this);
}

void OggDemux::removeTrack(u_int32_t trackNumber) {
  fDemuxedTracksTable->Remove((char const*)trackNumber);
  if (fDemuxedTracksTable->numEntries() == 0) {
    // We no longer have any demuxed tracks, so delete ourselves now:
    delete this;
  }
}

void OggDemux::continueReading() {
  fOurParser->continueParsing();
}

void OggDemux::handleEndOfFile(void* clientData) {
  ((OggDemux*)clientData)->handleEndOfFile();
}

void OggDemux::handleEndOfFile() {
  // Iterate through all of our 'demuxed tracks', handling 'end of input' on each one.
  // Hack: Because this can cause the hash table to get modified underneath us,
  // we don't call the handlers until after we've first iterated through all of the tracks.
  unsigned numTracks = fDemuxedTracksTable->numEntries();
  if (numTracks == 0) return;
  OggDemuxedTrack** tracks = new OggDemuxedTrack*[numTracks];

  HashTable::Iterator* iter = HashTable::Iterator::create(*fDemuxedTracksTable);
  unsigned i;
  char const* trackNumber;

  for (i = 0; i < numTracks; ++i) {
    tracks[i] = (OggDemuxedTrack*)iter->next(trackNumber);
  }
  delete iter;

  for (i = 0; i < numTracks; ++i) {
    if (tracks[i] == NULL) continue; // sanity check; shouldn't happen
    tracks[i]->handleClosure();
  }

  delete[] tracks;
}
