示例#1
0
void StreamReplicator::getNextFrame(StreamReplica* replica) {
  if (fInputSourceHasClosed) { // handle closure instead
    FramedSource::handleClosure(replica);
    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();
    }
  }
}
示例#2
0
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();
}
示例#3
0
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;
    replicaBeingDeactivated->fFrameIndex = -1;

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

    // 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
}