in src/client/src/Stream.c [445:550]
STATUS stopStream(PKinesisVideoStream pKinesisVideoStream)
{
ENTERS();
STATUS retStatus = STATUS_SUCCESS;
PKinesisVideoClient pKinesisVideoClient;
UINT64 duration, viewByteSize;
UINT32 i, sessionCount;
BOOL streamLocked = FALSE, clientLocked = FALSE, streamsListLock = FALSE, notSent = FALSE;
PUploadHandleInfo pUploadHandleInfo = NULL;
UINT64 item;
CHK(pKinesisVideoStream != NULL && pKinesisVideoStream->pKinesisVideoClient != NULL, STATUS_NULL_ARG);
pKinesisVideoClient = pKinesisVideoStream->pKinesisVideoClient;
retStatus = frameOrderCoordinatorFlush(pKinesisVideoStream);
if (STATUS_FAILED(retStatus)) {
DLOGE("frameOrderCoordinatorFlush failed with 0x%08x", retStatus);
retStatus = STATUS_SUCCESS;
}
// Lock the stream
pKinesisVideoClient->clientCallbacks.lockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);
streamLocked = TRUE;
// It's a no-op if stop has been called
CHK(!pKinesisVideoStream->streamStopped, retStatus);
// Set the stream end flag
pKinesisVideoStream->streamStopped = TRUE;
// Notify in case of an OFFLINE stream
if (IS_OFFLINE_STREAMING_MODE(pKinesisVideoStream->streamInfo.streamCaps.streamingType)) {
pKinesisVideoClient->clientCallbacks.signalConditionVariableFn(pKinesisVideoClient->clientCallbacks.customData,
pKinesisVideoStream->bufferAvailabilityCondition);
}
// Lock the client
pKinesisVideoClient->clientCallbacks.lockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoClient->base.lock);
clientLocked = TRUE;
// Get the duration from current point to the head
// Get the size of the allocation from current point to the head
CHK_STATUS(getAvailableViewSize(pKinesisVideoStream, &duration, &viewByteSize));
// Pulse the data available callback so the callee will know of a state change
CHK_STATUS(stackQueueGetCount(pKinesisVideoStream->pUploadInfoQueue, &sessionCount));
// Check if we have any content left and whether we have any metadata left to be send
CHK_STATUS(checkForNotSentMetadata(pKinesisVideoStream, ¬Sent));
// Package the frames if needed to be sent
if (notSent) {
CHK_STATUS(packageNotSentMetadata(pKinesisVideoStream));
}
for (i = 0; i < sessionCount; i++) {
CHK_STATUS(stackQueueGetAt(pKinesisVideoStream->pUploadInfoQueue, i, &item));
pUploadHandleInfo = (PUploadHandleInfo) item;
CHK(pUploadHandleInfo != NULL, STATUS_INTERNAL_ERROR);
// Call the notification callback to unblock potentially blocked listener for the first non terminated upload handle
// The unblocked handle will unblock subsequent handles once it's done. Therefore break the loop
if (pUploadHandleInfo->state != UPLOAD_HANDLE_STATE_TERMINATED) {
// If we have sent all the data but still have metadata then we will
// "mock" some duration and set the size to the not sent metadata size
// in order not to close the network upload handler.
if (notSent && (duration == 0)) {
duration = 1;
viewByteSize = pKinesisVideoStream->metadataTracker.size + pKinesisVideoStream->eosTracker.size;
}
CHK_STATUS(pKinesisVideoClient->clientCallbacks.streamDataAvailableFn(
pKinesisVideoClient->clientCallbacks.customData, TO_STREAM_HANDLE(pKinesisVideoStream), pKinesisVideoStream->streamInfo.name,
pUploadHandleInfo->handle, duration,
viewByteSize + pKinesisVideoStream->curViewItem.viewItem.length - pKinesisVideoStream->curViewItem.offset));
break;
}
}
// Check if we need to call stream closed callback
if (!notSent && viewByteSize == 0 && sessionCount == 0 && // If we have active handle, then eventually one of the handle will call streamClosedFn
!pKinesisVideoStream->metadataTracker.send && !pKinesisVideoStream->eosTracker.send) {
CHK_STATUS(notifyStreamClosed(pKinesisVideoStream, pUploadHandleInfo == NULL ? INVALID_UPLOAD_HANDLE_VALUE : pUploadHandleInfo->handle));
}
// Unlock the client as we no longer need it locked
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoClient->base.lock);
clientLocked = FALSE;
// Unlock the stream (even though it will be unlocked in the cleanup)
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);
streamLocked = FALSE;
CleanUp:
if (clientLocked) {
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoClient->base.lock);
}
if (streamLocked) {
pKinesisVideoClient->clientCallbacks.unlockMutexFn(pKinesisVideoClient->clientCallbacks.customData, pKinesisVideoStream->base.lock);
}
LEAVES();
return retStatus;
}