void tsmf_stream_free(TSMF_STREAM* stream) { TSMF_PRESENTATION* presentation = stream->presentation; tsmf_stream_stop(stream); tsmf_stream_flush(stream); WaitForSingleObject(presentation->mutex, INFINITE); list_remove(presentation->stream_list, stream); ReleaseMutex(presentation->mutex); Queue_Free(stream->sample_list); Queue_Free(stream->sample_ack_list); if (stream->decoder) { stream->decoder->Free(stream->decoder); stream->decoder = 0; } SetEvent(stream->thread); free(stream); stream = 0; }
void _tsmf_stream_free(TSMF_STREAM *stream) { assert(stream); tsmf_stream_stop(stream); tsmf_stream_flush(stream); SetEvent(stream->stopEvent); if (stream->play_thread) { WaitForSingleObject(stream->play_thread, INFINITE); CloseHandle(stream->play_thread); stream->play_thread = NULL; } if (stream->ack_thread) { WaitForSingleObject(stream->ack_thread, INFINITE); CloseHandle(stream->ack_thread); stream->ack_thread = NULL; } Queue_Free(stream->sample_list); Queue_Free(stream->sample_ack_list); if (stream->decoder && stream->decoder->Free) { stream->decoder->Free(stream->decoder); stream->decoder = NULL; } CloseHandle(stream->stopEvent); CloseHandle(stream->ready); memset(stream, 0, sizeof(TSMF_STREAM)); free(stream); }
void tsmf_presentation_flush(TSMF_PRESENTATION* presentation) { LIST_ITEM* item; TSMF_STREAM * stream; for (item = presentation->stream_list->head; item; item = item->next) { stream = (TSMF_STREAM*) item->data; tsmf_stream_flush(stream); } presentation->eos = 0; presentation->audio_start_time = 0; presentation->audio_end_time = 0; }
void _tsmf_stream_free(TSMF_STREAM* stream) { if (!stream) return; if (tsmf_stream_stop(stream)) tsmf_stream_flush(stream); SetEvent(stream->stopEvent); if (stream->play_thread) { if (WaitForSingleObject(stream->play_thread, INFINITE) == WAIT_FAILED) { WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); return; } CloseHandle(stream->play_thread); stream->play_thread = NULL; } if (stream->ack_thread) { if (WaitForSingleObject(stream->ack_thread, INFINITE) == WAIT_FAILED) { WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError()); return; } CloseHandle(stream->ack_thread); stream->ack_thread = NULL; } Queue_Free(stream->sample_list); Queue_Free(stream->sample_ack_list); if (stream->decoder && stream->decoder->Free) { stream->decoder->Free(stream->decoder); stream->decoder = NULL; } CloseHandle(stream->stopEvent); CloseHandle(stream->ready); ZeroMemory(stream, sizeof(TSMF_STREAM)); free(stream); }
void tsmf_presentation_flush(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); for (index = 0; index < count; index++) { stream = (TSMF_STREAM*) ArrayList_GetItem(presentation->stream_list, index); tsmf_stream_flush(stream); } ArrayList_Unlock(presentation->stream_list); presentation->eos = 0; presentation->audio_start_time = 0; presentation->audio_end_time = 0; }
static BOOL tsmf_stream_stop(TSMF_STREAM* stream) { if (!stream || !stream->decoder || !stream->decoder->Control) return TRUE; /* If stopping after eos - we delay until the eos has been processed * this allows us to process any buffers that have been acked even though * they have not actually been completely processes by the decoder */ if (stream->eos) { DEBUG_TSMF("Setting up a delayed stop for once the eos has been processed."); stream->delayed_stop = 1; return TRUE; } /* Otherwise force stop immediately */ else { DEBUG_TSMF("Stop with no pending eos response, so do it immediately."); tsmf_stream_flush(stream); return stream->decoder->Control(stream->decoder, Control_Stop, NULL); } }
/** * Function description * * @return 0 on success, otherwise a Win32 error code */ UINT tsmf_ifman_on_flush(TSMF_IFMAN* ifman) { UINT32 StreamId; TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; if (Stream_GetRemainingLength(ifman->input) < 20) return ERROR_INVALID_DATA; Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); DEBUG_TSMF("StreamId %d", StreamId); presentation = tsmf_presentation_find_by_id(ifman->presentation_id); if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); return ERROR_NOT_FOUND; } /* Flush message is for a stream, not the entire presentation * therefore we only flush the stream as intended per the MS-RDPEV spec */ stream = tsmf_stream_find_by_id(presentation, StreamId); if (stream) { if (!tsmf_stream_flush(stream)) return ERROR_INVALID_OPERATION; } else WLog_ERR(TAG, "unknown stream id"); ifman->output_pending = TRUE; return CHANNEL_RC_OK; }
static void* tsmf_stream_ack_func(void *arg) { HANDLE hdl[2]; TSMF_STREAM* stream = (TSMF_STREAM*) arg; UINT error = CHANNEL_RC_OK; DEBUG_TSMF("in %d", stream->stream_id); hdl[0] = stream->stopEvent; hdl[1] = Queue_Event(stream->sample_ack_list); while (1) { DWORD ev = WaitForMultipleObjects(2, hdl, FALSE, 1000); if (ev == WAIT_FAILED) { error = GetLastError(); WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu!", error); break; } if (stream->decoder) if (stream->decoder->BufferLevel) stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); if (stream->eos) { while ((stream->currentBufferLevel > 0) || !(tsmf_stream_process_ack(stream, TRUE))) { DEBUG_TSMF("END OF STREAM PROCESSING!"); if (stream->decoder->BufferLevel) stream->currentBufferLevel = stream->decoder->BufferLevel(stream->decoder); else stream->currentBufferLevel = 1; USleep(1000); } tsmf_send_eos_response(stream->eos_channel_callback, stream->eos_message_id); stream->eos = 0; if (stream->delayed_stop) { DEBUG_TSMF("Finishing delayed stream stop, now that eos has processed."); tsmf_stream_flush(stream); if (stream->decoder->Control) stream->decoder->Control(stream->decoder, Control_Stop, NULL); } } /* Stream stopped force all of the acks to happen */ if (ev == WAIT_OBJECT_0) { DEBUG_TSMF("ack: Stream stopped!"); while(1) { if (tsmf_stream_process_ack(stream, TRUE)) break; USleep(1000); } break; } if (tsmf_stream_process_ack(stream, FALSE)) continue; if (stream->currentBufferLevel > stream->minBufferLevel) USleep(1000); } if (error && stream->rdpcontext) setChannelError(stream->rdpcontext, error, "tsmf_stream_ack_func reported an error"); DEBUG_TSMF("out %d", stream->stream_id); ExitThread(0); return NULL; }