/**********
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.
// An class that can be used to create (possibly multiple) 'replicas' of an incoming stream.
// Implementation.

#include "StreamReplicator.hh"

////////// Definition of "StreamReplica": The class that implements each stream replica //////////

class StreamReplica: public FramedSource {
protected:
  friend class StreamReplicator;
  StreamReplica(StreamReplicator& ourReplicator); // called only by "StreamReplicator::createStreamReplica()"
  virtual ~StreamReplica();

private: // redefined virtual functions:
  virtual void doGetNextFrame();
  virtual void doStopGettingFrames();

private:
  static void copyReceivedFrame(StreamReplica* toReplica, StreamReplica* fromReplica);

private:
  StreamReplicator& fOurReplicator;
  int fFrameIndex; // 0 or 1, depending upon which frame we're currently requesting; could also be -1 if we've stopped playing

  // Replicas that are currently awaiting data are kept in a (singly-linked) list:
  StreamReplica* fNext;
};


////////// StreamReplicator implementation //////////

StreamReplicator* StreamReplicator::createNew(UsageEnvironment& env, FramedSource* inputSource, Boolean deleteWhenLastReplicaDies) {
  return new StreamReplicator(env, inputSource, deleteWhenLastReplicaDies);
}

StreamReplicator::StreamReplicator(UsageEnvironment& env, FramedSource* inputSource, Boolean deleteWhenLastReplicaDies)
  : Medium(env),
    fInputSource(inputSource), fDeleteWhenLastReplicaDies(deleteWhenLastReplicaDies), fInputSourceHasClosed(False),
    fNumReplicas(0), fNumActiveReplicas(0), fNumDeliveriesMadeSoFar(0),
    fFrameIndex(0), fMasterReplica(NULL), fReplicasAwaitingCurrentFrame(NULL), fReplicasAwaitingNextFrame(NULL) {
}

StreamReplicator::~StreamReplicator() {
  Medium::close(fInputSource);
}

FramedSource* StreamReplicator::createStreamReplica() {
  ++fNumReplicas;
  return new StreamReplica(*this);
}

void StreamReplicator::getNextFrame(StreamReplica* replica) {
  if (fInputSourceHasClosed) { // handle closure instead
    replica->handleClosure();
    return;
  }

  if (replica->fFrameIndex == -1) {
    // This replica had stopped playing (or had just been created), but is now actively reading.  Note this:
    replica->fFrameIndex = fFrameIndex;
    ++fNumActiveReplicas;
  }

  if (fMasterReplica == NULL) {
    // This is the first replica to request the next unread frame.  Make it the 'master' replica - meaning that we read the frame
    // into its buffer, and then copy from this into the other replicas' buffers.
    fMasterReplica = replica;

    // Arrange to read the next frame into this replica's buffer:
    if (fInputSource != NULL) fInputSource->getNextFrame(fMasterReplica->fTo, fMasterReplica->fMaxSize,
							 afterGettingFrame, this, onSourceClosure, this);
  } else if (replica->fFrameIndex != fFrameIndex) {
    // This replica is already asking for the next frame (because it has already received the current frame).  Enqueue it:
    replica->fNext = fReplicasAwaitingNextFrame;
    fReplicasAwaitingNextFrame = replica;
  } else {
    // This replica is asking for the current frame.  Enqueue it:
    replica->fNext = fReplicasAwaitingCurrentFrame;
    fReplicasAwaitingCurrentFrame = replica;

    if (fInputSource != NULL && !fInputSource->isCurrentlyAwaitingData()) {
      // The current frame has already arrived, so deliver it to this replica now:
      deliverReceivedFrame();
    }
  }
}

void StreamReplicator::deactivateStreamReplica(StreamReplica* replicaBeingDeactivated) {
  if (replicaBeingDeactivated->fFrameIndex == -1) return; // this replica has already been deactivated (or was never activated at all)

  // Assert: fNumActiveReplicas > 0
  if (fNumActiveReplicas == 0) fprintf(stderr, "StreamReplicator::deactivateStreamReplica() Internal Error!\n"); // should not happen
  --fNumActiveReplicas;

  // Forget about any frame delivery that might have just been made to this replica:
  if (replicaBeingDeactivated->fFrameIndex != fFrameIndex && fNumDeliveriesMadeSoFar > 0) --fNumDeliveriesMadeSoFar;

  replicaBeingDeactivated->fFrameIndex = -1;

  // Check whether the replica being deactivated is the 'master' replica, or is enqueued awaiting a frame:
  if (replicaBeingDeactivated == fMasterReplica) {
    // We need to replace the 'master replica', if we can:
    if (fReplicasAwaitingCurrentFrame == NULL) {
      // There's currently no replacement 'master replica'
      fMasterReplica = NULL;
    } else {
      // There's another replica that we can use as a replacement 'master replica':
      fMasterReplica = fReplicasAwaitingCurrentFrame;
      fReplicasAwaitingCurrentFrame = fReplicasAwaitingCurrentFrame->fNext;
      fMasterReplica->fNext = NULL;
    }

    // Check whether the read into the old master replica's buffer is still pending, or has completed:
    if (fInputSource != NULL) {
      if (fInputSource->isCurrentlyAwaitingData()) {
	// We have a pending read into the old master replica's buffer.
	// We need to stop it, and retry the read with a new master (if available)
	fInputSource->stopGettingFrames();

	if (fMasterReplica != NULL) {
	  fInputSource->getNextFrame(fMasterReplica->fTo, fMasterReplica->fMaxSize,
				     afterGettingFrame, this, onSourceClosure, this);
	}
      } else {
	// The read into the old master replica's buffer has already completed.  Copy the data to the new master replica (if any):
	if (fMasterReplica != NULL) {
	  StreamReplica::copyReceivedFrame(fMasterReplica, replicaBeingDeactivated);
	} else {
	  // We don't have a new master replica, so we can't copy the received frame to any new replica that might ask for it.
	  // Fortunately this should be a very rare occurrence.
	}
      }
    }
  } else {
    // The replica that's being removed was not our 'master replica', but make sure it's not on either of our queues:
    if (fReplicasAwaitingCurrentFrame != NULL) {
      if (replicaBeingDeactivated == fReplicasAwaitingCurrentFrame) {
	fReplicasAwaitingCurrentFrame = replicaBeingDeactivated->fNext;
	replicaBeingDeactivated->fNext = NULL;
      }
      else {
	for (StreamReplica* r1 = fReplicasAwaitingCurrentFrame; r1->fNext != NULL; r1 = r1->fNext) {
	  if (r1->fNext == replicaBeingDeactivated) {
	    r1->fNext = replicaBeingDeactivated->fNext;
	    replicaBeingDeactivated->fNext = NULL;
	    break;
	  }
	}
      }
    }
    if (fReplicasAwaitingNextFrame != NULL) {
      if (replicaBeingDeactivated == fReplicasAwaitingNextFrame) {
	fReplicasAwaitingNextFrame = replicaBeingDeactivated->fNext;
	replicaBeingDeactivated->fNext = NULL;
      }
      else {
	for (StreamReplica* r2 = fReplicasAwaitingNextFrame; r2->fNext != NULL; r2 = r2->fNext) {
	  if (r2->fNext == replicaBeingDeactivated) {
	    r2->fNext = replicaBeingDeactivated->fNext;
	    replicaBeingDeactivated->fNext = NULL;
	    break;
	  }
	}
      }
    }

    // Check for the possibility that - now that a replica has been deactivated - all other
    // replicas have received the current frame, and so now we need to complete delivery to
    // the master replica:
    if (fMasterReplica != NULL && fInputSource != NULL && !fInputSource->isCurrentlyAwaitingData()) deliverReceivedFrame();
  }

  if (fNumActiveReplicas == 0 && fInputSource != NULL) fInputSource->stopGettingFrames(); // tell our source to stop too
}

void StreamReplicator::removeStreamReplica(StreamReplica* replicaBeingRemoved) {
  // First, handle the replica that's being removed the same way that we would if it were merely being deactivated:
  deactivateStreamReplica(replicaBeingRemoved);

  // Assert: fNumReplicas > 0
  if (fNumReplicas == 0) fprintf(stderr, "StreamReplicator::removeStreamReplica() Internal Error!\n"); // should not happen
  --fNumReplicas;

  // If this was the last replica, then delete ourselves (if we were set up to do so):
  if (fNumReplicas == 0 && fDeleteWhenLastReplicaDies) {
    Medium::close(this);
    return;
  }
}

void StreamReplicator::afterGettingFrame(void* clientData, unsigned frameSize, unsigned numTruncatedBytes,
					 struct timeval presentationTime, unsigned durationInMicroseconds) {
  ((StreamReplicator*)clientData)->afterGettingFrame(frameSize, numTruncatedBytes, presentationTime, durationInMicroseconds);
}

void StreamReplicator::afterGettingFrame(unsigned frameSize, unsigned numTruncatedBytes,
					 struct timeval presentationTime, unsigned durationInMicroseconds) {
  // The frame was read into our master replica's buffer.  Update the master replica's state, but don't complete delivery to it
  // just yet.  We do that later, after we're sure that we've delivered it to all other replicas.
  fMasterReplica->fFrameSize = frameSize;
  fMasterReplica->fNumTruncatedBytes = numTruncatedBytes;
  fMasterReplica->fPresentationTime = presentationTime;
  fMasterReplica->fDurationInMicroseconds = durationInMicroseconds;

  deliverReceivedFrame();
}

void StreamReplicator::onSourceClosure(void* clientData) {
  ((StreamReplicator*)clientData)->onSourceClosure();
}

void StreamReplicator::onSourceClosure() {
  fInputSourceHasClosed = True;

  // Signal the closure to each replica that is currently awaiting a frame:
  StreamReplica* replica;
  while ((replica = fReplicasAwaitingCurrentFrame) != NULL) {
    fReplicasAwaitingCurrentFrame = replica->fNext;
    replica->fNext = NULL;
    replica->handleClosure();
  }
  while ((replica = fReplicasAwaitingNextFrame) != NULL) {
    fReplicasAwaitingNextFrame = replica->fNext;
    replica->fNext = NULL;
    replica->handleClosure();
  }
  if ((replica = fMasterReplica) != NULL) {
    fMasterReplica = NULL;
    replica->handleClosure();
  }
}

void StreamReplicator::deliverReceivedFrame() {
  // The 'master replica' has received its copy of the current frame.
  // Copy it (and complete delivery) to any other replica that has requested this frame.
  // Then, if no more requests for this frame are expected, complete delivery to the 'master replica' itself.
  StreamReplica* replica;
  while ((replica = fReplicasAwaitingCurrentFrame) != NULL) {
    fReplicasAwaitingCurrentFrame = replica->fNext;
    replica->fNext = NULL;
    
    // Assert: fMasterReplica != NULL
    if (fMasterReplica == NULL) fprintf(stderr, "StreamReplicator::deliverReceivedFrame() Internal Error 1!\n"); // shouldn't happen
    StreamReplica::copyReceivedFrame(replica, fMasterReplica);
    replica->fFrameIndex = 1 - replica->fFrameIndex; // toggle it (0<->1), because this replica no longer awaits the current frame
    ++fNumDeliveriesMadeSoFar;

    // Assert: fNumDeliveriesMadeSoFar < fNumActiveReplicas; // because we still have the 'master replica' to deliver to
    if (!(fNumDeliveriesMadeSoFar < fNumActiveReplicas)) fprintf(stderr, "StreamReplicator::deliverReceivedFrame() Internal Error 2(%d,%d)!\n", fNumDeliveriesMadeSoFar, fNumActiveReplicas); // should not happen

    // Complete delivery to this replica:
    FramedSource::afterGetting(replica);
  }

  if (fNumDeliveriesMadeSoFar == fNumActiveReplicas - 1 && fMasterReplica != NULL) {
    // No more requests for this frame are expected, so complete delivery to the 'master replica':
    replica = fMasterReplica;
    fMasterReplica = NULL;
    replica->fFrameIndex = 1 - replica->fFrameIndex; // toggle it (0<->1), because this replica no longer awaits the current frame
    fFrameIndex = 1 - fFrameIndex; // toggle it (0<->1) for the next frame
    fNumDeliveriesMadeSoFar = 0; // reset for the next frame

    if (fReplicasAwaitingNextFrame != NULL) {
      // One of the other replicas has already requested the next frame, so make it the next 'master replica':
      fMasterReplica = fReplicasAwaitingNextFrame;
      fReplicasAwaitingNextFrame = fReplicasAwaitingNextFrame->fNext;
      fMasterReplica->fNext = NULL;

      // Arrange to read the next frame into this replica's buffer:
      if (fInputSource != NULL) fInputSource->getNextFrame(fMasterReplica->fTo, fMasterReplica->fMaxSize,
							   afterGettingFrame, this, onSourceClosure, this);
    }      

    // Move any other replicas that had already requested the next frame to the 'requesting current frame' list:
    // Assert: fReplicasAwaitingCurrentFrame == NULL;
    if (!(fReplicasAwaitingCurrentFrame == NULL)) fprintf(stderr, "StreamReplicator::deliverReceivedFrame() Internal Error 3!\n"); // should not happen
    fReplicasAwaitingCurrentFrame = fReplicasAwaitingNextFrame;
    fReplicasAwaitingNextFrame = NULL;
    
    // Complete delivery to the 'master' replica (thereby completing all deliveries for this frame):
    FramedSource::afterGetting(replica);
  }
}


////////// StreamReplica implementation //////////

StreamReplica::StreamReplica(StreamReplicator& ourReplicator)
  : FramedSource(ourReplicator.envir()),
    fOurReplicator(ourReplicator),
    fFrameIndex(-1/*we haven't started playing yet*/), fNext(NULL) {
}

StreamReplica::~StreamReplica() {
  fOurReplicator.removeStreamReplica(this);
}

void StreamReplica::doGetNextFrame() {
  fOurReplicator.getNextFrame(this);
}

void StreamReplica::doStopGettingFrames() {
  fOurReplicator.deactivateStreamReplica(this);
}

void StreamReplica::copyReceivedFrame(StreamReplica* toReplica, StreamReplica* fromReplica) {
  // First, figure out how much data to copy.  ("toReplica" might have a smaller buffer than "fromReplica".)
  unsigned numNewBytesToTruncate
    = toReplica->fMaxSize < fromReplica->fFrameSize ? fromReplica->fFrameSize - toReplica->fMaxSize : 0;
  toReplica->fFrameSize = fromReplica->fFrameSize - numNewBytesToTruncate;
  toReplica->fNumTruncatedBytes = fromReplica->fNumTruncatedBytes + numNewBytesToTruncate;

  memmove(toReplica->fTo, fromReplica->fTo, toReplica->fFrameSize);
  toReplica->fPresentationTime = fromReplica->fPresentationTime;
  toReplica->fDurationInMicroseconds = fromReplica->fDurationInMicroseconds;
}
