diff --git a/channels/tsmf/client/alsa/tsmf_alsa.c b/channels/tsmf/client/alsa/tsmf_alsa.c index dec1e3443..5d8b68575 100644 --- a/channels/tsmf/client/alsa/tsmf_alsa.c +++ b/channels/tsmf/client/alsa/tsmf_alsa.c @@ -182,15 +182,14 @@ static BOOL tsmf_alsa_play(ITSMFAudioDevice *audio, BYTE *data, UINT32 data_size snd_pcm_recover(alsa->out_handle, error, 0); error = 0; } - else - if(error < 0) - { - DEBUG_TSMF("error len %d", error); - snd_pcm_close(alsa->out_handle); - alsa->out_handle = 0; - tsmf_alsa_open_device(alsa); - break; - } + else if(error < 0) + { + DEBUG_TSMF("error len %d", error); + snd_pcm_close(alsa->out_handle); + alsa->out_handle = 0; + tsmf_alsa_open_device(alsa); + break; + } DEBUG_TSMF("%d frames played.", error); if(error == 0) break; @@ -215,8 +214,9 @@ static UINT64 tsmf_alsa_get_latency(ITSMFAudioDevice *audio) return latency; } -static void tsmf_alsa_flush(ITSMFAudioDevice *audio) +static BOOL tsmf_alsa_flush(ITSMFAudioDevice *audio) { + return TRUE; } static void tsmf_alsa_free(ITSMFAudioDevice *audio) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index 2537068b7..d0880e78b 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -139,35 +139,44 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP UINT32 size; const BYTE *s; TSMFFFmpegDecoder* mdecoder = (TSMFFFmpegDecoder*) decoder; + mdecoder->codec = avcodec_find_decoder(mdecoder->codec_id); if (!mdecoder->codec) { WLog_ERR(TAG, "avcodec_find_decoder failed."); return FALSE; } + mdecoder->codec_context->codec_id = mdecoder->codec_id; mdecoder->codec_context->codec_type = mdecoder->media_type; - if (mdecoder->media_type == AVMEDIA_TYPE_VIDEO) + switch(mdecoder->media_type) { - if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) - return FALSE; - } - else - if (mdecoder->media_type == AVMEDIA_TYPE_AUDIO) - { + case AVMEDIA_TYPE_VIDEO: + if (!tsmf_ffmpeg_init_video_stream(decoder, media_type)) + return FALSE; + break; + case AVMEDIA_TYPE_AUDIO: if (!tsmf_ffmpeg_init_audio_stream(decoder, media_type)) return FALSE; - } + break; + default: + WLog_ERR(TAG, "unknown media_type %d", mdecoder->media_type); + break; + } + if (media_type->ExtraData) { + /* Add a padding to avoid invalid memory read in some codec */ + mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; + mdecoder->codec_context->extradata = calloc(1, mdecoder->codec_context->extradata_size); + if (!mdecoder->codec_context->extradata) + return FALSE; + if (media_type->SubType == TSMF_SUB_TYPE_AVC1 && media_type->FormatType == TSMF_FORMAT_TYPE_MPEG2VIDEOINFO) { /* The extradata format that FFmpeg uses is following CodecPrivate in Matroska. See http://haali.su/mkv/codecs.pdf */ - mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; - mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size); - ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size); p = mdecoder->codec_context->extradata; *p++ = 1; /* Reserved? */ *p++ = media_type->ExtraData[8]; /* Profile */ @@ -186,14 +195,11 @@ static BOOL tsmf_ffmpeg_init_stream(ITSMFDecoder* decoder, const TS_AM_MEDIA_TYP } else { - /* Add a padding to avoid invalid memory read in some codec */ - mdecoder->codec_context->extradata_size = media_type->ExtraDataSize + 8; - mdecoder->codec_context->extradata = malloc(mdecoder->codec_context->extradata_size); - ZeroMemory(mdecoder->codec_context->extradata, mdecoder->codec_context->extradata_size); memcpy(mdecoder->codec_context->extradata, media_type->ExtraData, media_type->ExtraDataSize); memset(mdecoder->codec_context->extradata + media_type->ExtraDataSize, 0, 8); } } + if (mdecoder->codec->capabilities & CODEC_CAP_TRUNCATED) mdecoder->codec_context->flags |= CODEC_FLAG_TRUNCATED; return TRUE; @@ -318,8 +324,10 @@ static BOOL tsmf_ffmpeg_decode_video(ITSMFDecoder* decoder, const BYTE *data, UI mdecoder->codec_context->width, mdecoder->codec_context->height); mdecoder->decoded_size = avpicture_get_size(mdecoder->codec_context->pix_fmt, mdecoder->codec_context->width, mdecoder->codec_context->height); - mdecoder->decoded_data = malloc(mdecoder->decoded_size); - ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size); + mdecoder->decoded_data = calloc(1, mdecoder->decoded_size); + if (!mdecoder->decoded_data) + return FALSE; + frame = avcodec_alloc_frame(); avpicture_fill((AVPicture*) frame, mdecoder->decoded_data, mdecoder->codec_context->pix_fmt, @@ -354,8 +362,11 @@ static BOOL tsmf_ffmpeg_decode_audio(ITSMFDecoder* decoder, const BYTE *data, UI #endif if (mdecoder->decoded_size_max == 0) mdecoder->decoded_size_max = MAX_AUDIO_FRAME_SIZE + 16; - mdecoder->decoded_data = malloc(mdecoder->decoded_size_max); - ZeroMemory(mdecoder->decoded_data, mdecoder->decoded_size_max); + + mdecoder->decoded_data = calloc(1, mdecoder->decoded_size_max); + if (!mdecoder->decoded_data) + return FALSE; + /* align the memory for SSE2 needs */ dst = (BYTE *)(((uintptr_t) mdecoder->decoded_data + 15) & ~ 0x0F); dst_offset = dst - mdecoder->decoded_data; diff --git a/channels/tsmf/client/gstreamer/tsmf_X11.c b/channels/tsmf/client/gstreamer/tsmf_X11.c index e678f88a5..c3950f066 100644 --- a/channels/tsmf/client/gstreamer/tsmf_X11.c +++ b/channels/tsmf/client/gstreamer/tsmf_X11.c @@ -246,67 +246,67 @@ int tsmf_window_resize(TSMFGstreamerDecoder* decoder, int x, int y, int width, { return -3; } - else + +#if GST_VERSION_MAJOR > 0 + GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink); +#else + GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink); +#endif + if (!decoder) + return -1; + + if (!decoder->platform) + return -1; + + hdl = (struct X11Handle*) decoder->platform; + DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height); + +#if GST_VERSION_MAJOR > 0 + + if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height)) { -#if GST_VERSION_MAJOR > 0 - GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink); + WLog_ERR(TAG, "Could not resize overlay!"); + } + + gst_video_overlay_expose(overlay); #else - GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink); -#endif - if (!decoder) - return -1; + if (!gst_x_overlay_set_render_rectangle(overlay, 0, 0, width, height)) + { + WLog_ERR(TAG, "Could not resize overlay!"); + } - if (!decoder->platform) - return -1; - - hdl = (struct X11Handle*) decoder->platform; - DEBUG_TSMF("resize: x=%d, y=%d, w=%d, h=%d", x, y, width, height); - -#if GST_VERSION_MAJOR > 0 - - if (!gst_video_overlay_set_render_rectangle(overlay, 0, 0, width, height)) - { - WLog_ERR(TAG, "Could not resize overlay!"); - } - - gst_video_overlay_expose(overlay); -#else - if (!gst_x_overlay_set_render_rectangle(overlay, 0, 0, width, height)) - { - WLog_ERR(TAG, "Could not resize overlay!"); - } - - gst_x_overlay_expose(overlay); + gst_x_overlay_expose(overlay); #endif - if (hdl->subwin) - { - XMoveResizeWindow(hdl->disp, hdl->subwin, x, y, width, height); + if (hdl->subwin) + { + XMoveResizeWindow(hdl->disp, hdl->subwin, x, y, width, height); #if defined(WITH_XEXT) - if (hdl->has_shape) + if (hdl->has_shape) + { + int i; + XRectangle *xrects = calloc(nr_rects, sizeof(XRectangle)); + if (!xrects) + return -1; + + for (i = 0; i < nr_rects; i++) { - int i; - XRectangle *xrects = calloc(nr_rects, sizeof(XRectangle)); - - for (i=0; idisp, hdl->subwin, ShapeBounding, x, y, xrects, nr_rects, ShapeSet, 0); - free(xrects); + xrects[i].x = rects[i].x - x; + xrects[i].y = rects[i].y - y; + xrects[i].width = rects[i].width; + xrects[i].height = rects[i].height; } -#endif - XSync(hdl->disp, FALSE); + XShapeCombineRectangles(hdl->disp, hdl->subwin, ShapeBounding, x, y, xrects, nr_rects, ShapeSet, 0); + free(xrects); } - return 0; +#endif + XSync(hdl->disp, FALSE); } + + return 0; } int tsmf_window_pause(TSMFGstreamerDecoder* decoder) diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index d40cccacf..56a3d1ef5 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -585,15 +585,15 @@ static BOOL tsmf_gstreamer_decodeEx(ITSMFDecoder* decoder, const BYTE *data, UIN return TRUE; } -static void tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume, UINT32 muted) +static BOOL tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume, UINT32 muted) { TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; if (!mdecoder || !mdecoder->pipe) - return; + return FALSE; if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO) - return; + return TRUE; mdecoder->gstMuted = (BOOL) muted; DEBUG_TSMF("mute=[%d]", mdecoder->gstMuted); @@ -601,21 +601,22 @@ static void tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume DEBUG_TSMF("gst_new_vol=[%f]", mdecoder->gstVolume); if (!mdecoder->volume) - return; + return FALSE; if (!G_IS_OBJECT(mdecoder->volume)) - return; + return FALSE; g_object_set(mdecoder->volume, "mute", mdecoder->gstMuted, NULL); g_object_set(mdecoder->volume, "volume", mdecoder->gstVolume, NULL); + return TRUE; } -static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg control_msg, UINT32 *arg) +static BOOL tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg control_msg, UINT32 *arg) { TSMFGstreamerDecoder* mdecoder = (TSMFGstreamerDecoder *) decoder; if (!mdecoder) - return; + return FALSE; if (control_msg == Control_Pause) { @@ -624,7 +625,7 @@ static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg contro if (mdecoder->paused) { WLog_ERR(TAG, "%s: Ignoring control PAUSE, already received!", get_type(mdecoder)); - return; + return TRUE; } tsmf_gstreamer_pipeline_set_state(mdecoder, GST_STATE_PAUSED); @@ -640,7 +641,7 @@ static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg contro if (!mdecoder->paused && !mdecoder->shutdown) { WLog_ERR(TAG, "%s: Ignoring control RESUME, already received!", get_type(mdecoder)); - return; + return TRUE; } mdecoder->paused = FALSE; @@ -658,7 +659,7 @@ static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg contro if (mdecoder->shutdown) { WLog_ERR(TAG, "%s: Ignoring control STOP, already received!", get_type(mdecoder)); - return; + return TRUE; } mdecoder->shutdown = TRUE; @@ -672,6 +673,8 @@ static void tsmf_gstreamer_control(ITSMFDecoder* decoder, ITSMFControlMsg contro } else WLog_ERR(TAG, "Unknown control message %08x", control_msg); + + return TRUE; } static BOOL tsmf_gstreamer_buffer_filled(ITSMFDecoder* decoder) @@ -731,7 +734,7 @@ static UINT64 tsmf_gstreamer_get_running_time(ITSMFDecoder* decoder) return pos/100; } -static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder, +static BOOL tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles) { @@ -741,9 +744,11 @@ static void tsmf_gstreamer_update_rendering_area(ITSMFDecoder* decoder, if (mdecoder->media_type == TSMF_MAJOR_TYPE_VIDEO) { - tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight, - numRectangles, rectangles); + return tsmf_window_resize(mdecoder, newX, newY, newWidth, newHeight, + numRectangles, rectangles) == 0; } + + return TRUE; } BOOL tsmf_gstreamer_ack(ITSMFDecoder* decoder, BOOL (*cb)(void *, BOOL), void *stream) @@ -801,7 +806,11 @@ ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) decoder->gstMuted = FALSE; decoder->state = GST_STATE_VOID_PENDING; /* No real state yet */ - tsmf_platform_create(decoder); + if (tsmf_platform_create(decoder) < 0) + { + free(decoder); + return NULL; + } return (ITSMFDecoder*) decoder; } diff --git a/channels/tsmf/client/pulse/tsmf_pulse.c b/channels/tsmf/client/pulse/tsmf_pulse.c index f35f24902..c0d6caaf3 100644 --- a/channels/tsmf/client/pulse/tsmf_pulse.c +++ b/channels/tsmf/client/pulse/tsmf_pulse.c @@ -325,13 +325,14 @@ static UINT64 tsmf_pulse_get_latency(ITSMFAudioDevice *audio) return latency; } -static void tsmf_pulse_flush(ITSMFAudioDevice *audio) +static BOOL tsmf_pulse_flush(ITSMFAudioDevice *audio) { TSMFPulseAudioDevice *pulse = (TSMFPulseAudioDevice *) audio; pa_threaded_mainloop_lock(pulse->mainloop); tsmf_pulse_wait_for_operation(pulse, pa_stream_flush(pulse->stream, tsmf_pulse_stream_success_callback, pulse)); pa_threaded_mainloop_unlock(pulse->mainloop); + return TRUE; } static void tsmf_pulse_free(ITSMFAudioDevice *audio) @@ -364,8 +365,10 @@ static void tsmf_pulse_free(ITSMFAudioDevice *audio) ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) { TSMFPulseAudioDevice *pulse; - pulse = (TSMFPulseAudioDevice *) malloc(sizeof(TSMFPulseAudioDevice)); - ZeroMemory(pulse, sizeof(TSMFPulseAudioDevice)); + + pulse = (TSMFPulseAudioDevice *) calloc(1, sizeof(TSMFPulseAudioDevice)); + if (!pulse) + return NULL; pulse->iface.Open = tsmf_pulse_open; pulse->iface.SetFormat = tsmf_pulse_set_format; pulse->iface.Play = tsmf_pulse_play; diff --git a/channels/tsmf/client/tsmf_audio.h b/channels/tsmf/client/tsmf_audio.h index 98af8013d..ac90ee289 100644 --- a/channels/tsmf/client/tsmf_audio.h +++ b/channels/tsmf/client/tsmf_audio.h @@ -35,9 +35,9 @@ struct _ITSMFAudioDevice /* Get the latency of the last written sample, in 100ns */ UINT64 (*GetLatency) (ITSMFAudioDevice* audio); /* Change the playback volume level */ - void (*ChangeVolume) (ITSMFAudioDevice* audio, UINT32 newVolume, UINT32 muted); + BOOL (*ChangeVolume) (ITSMFAudioDevice* audio, UINT32 newVolume, UINT32 muted); /* Flush queued audio data */ - void (*Flush) (ITSMFAudioDevice* audio); + BOOL (*Flush) (ITSMFAudioDevice* audio); /* Free the audio device */ void (*Free) (ITSMFAudioDevice* audio); }; diff --git a/channels/tsmf/client/tsmf_codec.c b/channels/tsmf/client/tsmf_codec.c index e4ae51a30..7ae5e283d 100644 --- a/channels/tsmf/client/tsmf_codec.c +++ b/channels/tsmf/client/tsmf_codec.c @@ -288,30 +288,18 @@ static const TSMFMediaTypeMap tsmf_format_type_map[] = static void tsmf_print_guid(const BYTE* guid) { #ifdef WITH_DEBUG_TSMF - int i; + char guidString[37]; - for (i = 3; i >= 0; i--) - WLog_INFO(TAG, "%02X", guid[i]); + snprintf(guidString, sizeof(guidString), "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", + guid[3], guid[2], guid[1], guid[0], + guid[5], guid[4], + guid[7], guid[6], + guid[8], guid[9], + guid[10], guid[11], guid[12], guid[13], guid[14], guid[15] + ); - WLog_INFO(TAG, "-"); - for (i = 5; i >= 4; i--) - WLog_INFO(TAG, "%02X", guid[i]); - - WLog_INFO(TAG, "-"); - - for (i = 7; i >= 6; i--) - WLog_INFO(TAG, "%02X", guid[i]); - - WLog_INFO(TAG, "-"); - - for (i = 8; i < 16; i++) - { - WLog_INFO(TAG, "%02X", guid[i]); - - if (i == 9) - WLog_INFO(TAG, "-"); - } + WLog_INFO(TAG, "%s", guidString); #endif } @@ -321,6 +309,9 @@ static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wSt UINT32 biSize; UINT32 biWidth; UINT32 biHeight; + + if (Stream_GetRemainingLength(s) < 40) + return 0; Stream_Read_UINT32(s, biSize); Stream_Read_UINT32(s, biWidth); Stream_Read_UINT32(s, biHeight); @@ -333,6 +324,9 @@ static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wSt mediatype->Height = biHeight; /* Assume there will be no color table for video? */ + if ((biSize < 40) || (Stream_GetRemainingLength(s) < (biSize-40))) + return 0; + if (bypass && biSize > 40) Stream_Seek(s, biSize - 40); @@ -343,7 +337,11 @@ static UINT32 tsmf_codec_parse_BITMAPINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wSt static UINT32 tsmf_codec_parse_VIDEOINFOHEADER2(TS_AM_MEDIA_TYPE* mediatype, wStream* s) { UINT64 AvgTimePerFrame; + /* VIDEOINFOHEADER2.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ + if (Stream_GetRemainingLength(s) < 72) + return 0; + Stream_Seek_UINT32(s); Stream_Seek_UINT32(s); Stream_Read_UINT32(s, mediatype->Width); @@ -377,6 +375,10 @@ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStr } VIDEOINFOHEADER; */ UINT64 AvgTimePerFrame; + + if (Stream_GetRemainingLength(s) < 48) + return 0; + /* VIDEOINFOHEADER.rcSource, RECT(LONG left, LONG top, LONG right, LONG bottom) */ Stream_Seek_UINT32(s); Stream_Seek_UINT32(s); @@ -395,76 +397,17 @@ static UINT32 tsmf_codec_parse_VIDEOINFOHEADER(TS_AM_MEDIA_TYPE* mediatype, wStr return 48; } -BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s) +static BOOL tsmf_read_format_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s, UINT32 cbFormat) { - int i; - UINT32 cbFormat; - BOOL ret = TRUE; - memset(mediatype, 0, sizeof(TS_AM_MEDIA_TYPE)); - /* MajorType */ - DEBUG_TSMF("MajorType:"); - tsmf_print_guid(Stream_Pointer(s)); - - for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++) - { - if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0) - break; - } - - mediatype->MajorType = tsmf_major_type_map[i].type; - - if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN) - ret = FALSE; - - DEBUG_TSMF("MajorType %s", tsmf_major_type_map[i].name); - Stream_Seek(s, 16); - /* SubType */ - DEBUG_TSMF("SubType:"); - tsmf_print_guid(Stream_Pointer(s)); - - for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++) - { - if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0) - break; - } - - mediatype->SubType = tsmf_sub_type_map[i].type; - - if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN) - ret = FALSE; - - DEBUG_TSMF("SubType %s", tsmf_sub_type_map[i].name); - Stream_Seek(s, 16); - /* bFixedSizeSamples, bTemporalCompression, SampleSize */ - Stream_Seek(s, 12); - /* FormatType */ - DEBUG_TSMF("FormatType:"); - tsmf_print_guid(Stream_Pointer(s)); - - for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++) - { - if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0) - break; - } - - mediatype->FormatType = tsmf_format_type_map[i].type; - - if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN) - ret = FALSE; - - DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name); - Stream_Seek(s, 16); - /* cbFormat */ - Stream_Read_UINT32(s, cbFormat); - DEBUG_TSMF("cbFormat %d", cbFormat); -#ifdef WITH_DEBUG_TSMF - winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s), cbFormat); -#endif + int i, j; switch (mediatype->FormatType) { case TSMF_FORMAT_TYPE_MFVIDEOFORMAT: /* http://msdn.microsoft.com/en-us/library/aa473808.aspx */ + if (Stream_GetRemainingLength(s) < 176) + return FALSE; + Stream_Seek(s, 8); /* dwSize and ? */ Stream_Read_UINT32(s, mediatype->Width); /* videoInfo.dwWidth */ Stream_Read_UINT32(s, mediatype->Height); /* videoInfo.dwHeight */ @@ -481,10 +424,13 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s) mediatype->ExtraDataSize = cbFormat - 176; mediatype->ExtraData = Stream_Pointer(s); } - break; + case TSMF_FORMAT_TYPE_WAVEFORMATEX: /* http://msdn.microsoft.com/en-us/library/dd757720.aspx */ + if (Stream_GetRemainingLength(s) < 18) + return FALSE; + Stream_Seek_UINT16(s); Stream_Read_UINT16(s, mediatype->Channels); Stream_Read_UINT32(s, mediatype->SamplesPerSecond.Numerator); @@ -496,47 +442,156 @@ BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s) Stream_Read_UINT16(s, mediatype->ExtraDataSize); if (mediatype->ExtraDataSize > 0) + { + if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize) + return FALSE; mediatype->ExtraData = Stream_Pointer(s); - + } break; + case TSMF_FORMAT_TYPE_MPEG1VIDEOINFO: /* http://msdn.microsoft.com/en-us/library/dd390700.aspx */ i = tsmf_codec_parse_VIDEOINFOHEADER(mediatype, s); - i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); + if (!i) + return FALSE; + j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); + if (!j) + return FALSE; + i += j; if (cbFormat > i) { mediatype->ExtraDataSize = cbFormat - i; + if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize) + return FALSE; mediatype->ExtraData = Stream_Pointer(s); } - break; + case TSMF_FORMAT_TYPE_MPEG2VIDEOINFO: /* http://msdn.microsoft.com/en-us/library/dd390707.aspx */ i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); - i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); + if (!i) + return FALSE; + j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, TRUE); + if (!j) + return FALSE; + i += j; if (cbFormat > i) { mediatype->ExtraDataSize = cbFormat - i; + if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize) + return FALSE; mediatype->ExtraData = Stream_Pointer(s); } - break; + case TSMF_FORMAT_TYPE_VIDEOINFO2: i = tsmf_codec_parse_VIDEOINFOHEADER2(mediatype, s); - i += tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE); + if (!i) + return FALSE; + j = tsmf_codec_parse_BITMAPINFOHEADER(mediatype, s, FALSE); + if (!j) + return FALSE; + i += j; if (cbFormat > i) { mediatype->ExtraDataSize = cbFormat - i; + if (Stream_GetRemainingLength(s) < mediatype->ExtraDataSize) + return FALSE; mediatype->ExtraData = Stream_Pointer(s); } - break; + default: + WLog_INFO(TAG, "unhandled format type 0x%x", mediatype->FormatType); break; } + return TRUE; +} + +BOOL tsmf_codec_parse_media_type(TS_AM_MEDIA_TYPE* mediatype, wStream* s) +{ + UINT32 cbFormat; + BOOL ret = TRUE; + int i; + + ZeroMemory(mediatype, sizeof(TS_AM_MEDIA_TYPE)); + + /* MajorType */ + DEBUG_TSMF("MediaMajorType:"); + if (Stream_GetRemainingLength(s) < 16) + return FALSE; + tsmf_print_guid(Stream_Pointer(s)); + + for (i = 0; tsmf_major_type_map[i].type != TSMF_MAJOR_TYPE_UNKNOWN; i++) + { + if (memcmp(tsmf_major_type_map[i].guid, Stream_Pointer(s), 16) == 0) + break; + } + + mediatype->MajorType = tsmf_major_type_map[i].type; + if (mediatype->MajorType == TSMF_MAJOR_TYPE_UNKNOWN) + ret = FALSE; + + DEBUG_TSMF("MediaMajorType %s", tsmf_major_type_map[i].name); + Stream_Seek(s, 16); + + /* SubType */ + DEBUG_TSMF("MediaSubType:"); + if (Stream_GetRemainingLength(s) < 16) + return FALSE; + tsmf_print_guid(Stream_Pointer(s)); + + for (i = 0; tsmf_sub_type_map[i].type != TSMF_SUB_TYPE_UNKNOWN; i++) + { + if (memcmp(tsmf_sub_type_map[i].guid, Stream_Pointer(s), 16) == 0) + break; + } + + mediatype->SubType = tsmf_sub_type_map[i].type; + if (mediatype->SubType == TSMF_SUB_TYPE_UNKNOWN) + ret = FALSE; + + DEBUG_TSMF("MediaSubType %s", tsmf_sub_type_map[i].name); + Stream_Seek(s, 16); + + /* bFixedSizeSamples, bTemporalCompression, SampleSize */ + if (Stream_GetRemainingLength(s) < 12) + return FALSE; + Stream_Seek(s, 12); + + /* FormatType */ + DEBUG_TSMF("FormatType:"); + if (Stream_GetRemainingLength(s) < 16) + return FALSE; + tsmf_print_guid(Stream_Pointer(s)); + + for (i = 0; tsmf_format_type_map[i].type != TSMF_FORMAT_TYPE_UNKNOWN; i++) + { + if (memcmp(tsmf_format_type_map[i].guid, Stream_Pointer(s), 16) == 0) + break; + } + + mediatype->FormatType = tsmf_format_type_map[i].type; + if (mediatype->FormatType == TSMF_FORMAT_TYPE_UNKNOWN) + ret = FALSE; + + DEBUG_TSMF("FormatType %s", tsmf_format_type_map[i].name); + Stream_Seek(s, 16); + + /* cbFormat */ + if (Stream_GetRemainingLength(s) < 4) + return FALSE; + Stream_Read_UINT32(s, cbFormat); + DEBUG_TSMF("cbFormat %d", cbFormat); +#ifdef WITH_DEBUG_TSMF + winpr_HexDump(TAG, WLOG_DEBUG, Stream_Pointer(s), cbFormat); +#endif + + ret = tsmf_read_format_type(mediatype, s, cbFormat); if (mediatype->SamplesPerSecond.Numerator == 0) mediatype->SamplesPerSecond.Numerator = 1; diff --git a/channels/tsmf/client/tsmf_decoder.h b/channels/tsmf/client/tsmf_decoder.h index 1215d0e98..d507b9e1b 100644 --- a/channels/tsmf/client/tsmf_decoder.h +++ b/channels/tsmf/client/tsmf_decoder.h @@ -47,16 +47,16 @@ struct _ITSMFDecoder /* Free the decoder */ void (*Free)(ITSMFDecoder *decoder); /* Optional Contol function */ - void (*Control)(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg); + BOOL (*Control)(ITSMFDecoder *decoder, ITSMFControlMsg control_msg, UINT32 *arg); /* Decode a sample with extended interface. */ int (*DecodeEx)(ITSMFDecoder *decoder, const BYTE *data, UINT32 data_size, UINT32 extensions, UINT64 start_time, UINT64 end_time, UINT64 duration); /* Get current play time */ UINT64(*GetRunningTime)(ITSMFDecoder *decoder); /* Update Gstreamer Rendering Area */ - void (*UpdateRenderingArea)(ITSMFDecoder *decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles); + BOOL (*UpdateRenderingArea)(ITSMFDecoder *decoder, int newX, int newY, int newWidth, int newHeight, int numRectangles, RDP_RECT *rectangles); /* Change Gstreamer Audio Volume */ - void (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted); + BOOL (*ChangeVolume)(ITSMFDecoder *decoder, UINT32 newVolume, UINT32 muted); /* Check buffer level */ BOOL (*BufferFilled)(ITSMFDecoder *decoder); /* Register a callback for frame ack. */ diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index a5c65fe2f..93bd1a77b 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -37,23 +37,25 @@ #include "tsmf_ifman.h" -int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 CapabilityValue; + if (Stream_GetRemainingLength(ifman->input) < 4) + return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->input, CapabilityValue); DEBUG_TSMF("server CapabilityValue %d", CapabilityValue); if (!Stream_EnsureRemainingCapacity(ifman->output, 8)) - return -1; + return ERROR_INVALID_DATA; Stream_Write_UINT32(ifman->output, 1); /* CapabilityValue */ Stream_Write_UINT32(ifman->output, 0); /* Result */ - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) { UINT32 i; UINT32 v; @@ -63,32 +65,48 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) UINT32 numHostCapabilities; if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4)) - return -1; + return ERROR_OUTOFMEMORY; pos = Stream_GetPosition(ifman->output); Stream_Copy(ifman->output, ifman->input, ifman->input_size); Stream_SetPosition(ifman->output, pos); + + if (Stream_GetRemainingLength(ifman->output) < 4) + return ERROR_INVALID_DATA; Stream_Read_UINT32(ifman->output, numHostCapabilities); for (i = 0; i < numHostCapabilities; i++) { + if (Stream_GetRemainingLength(ifman->output) < 8) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(ifman->output, CapabilityType); Stream_Read_UINT32(ifman->output, cbCapabilityLength); + + if (Stream_GetRemainingLength(ifman->output) < cbCapabilityLength) + return ERROR_INVALID_DATA; + pos = Stream_GetPosition(ifman->output); switch (CapabilityType) { case 1: /* Protocol version request */ + if (Stream_GetRemainingLength(ifman->output) < 4) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(ifman->output, v); DEBUG_TSMF("server protocol version %d", v); break; case 2: /* Supported platform */ + if (Stream_GetRemainingLength(ifman->output) < 4) + return ERROR_INVALID_DATA; + Stream_Peek_UINT32(ifman->output, v); DEBUG_TSMF("server supported platform %d", v); /* Claim that we support both MF and DShow platforms. */ Stream_Write_UINT32(ifman->output, MMREDIR_CAPABILITY_PLATFORM_MF | MMREDIR_CAPABILITY_PLATFORM_DSHOW); break; default: - WLog_ERR(TAG, "unknown capability type %d", CapabilityType); + WLog_ERR(TAG, "skipping unknown capability type %d", CapabilityType); break; } Stream_SetPosition(ifman->output, pos + cbCapabilityLength); @@ -97,15 +115,18 @@ int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) { UINT32 numMediaType; UINT32 PlatformCookie; UINT32 FormatSupported = 1; + if (Stream_GetRemainingLength(ifman->input) < 12) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(ifman->input, PlatformCookie); Stream_Seek_UINT32(ifman->input); /* NoRolloverFlags (4 bytes) */ Stream_Read_UINT32(ifman->input, numMediaType); @@ -125,29 +146,32 @@ int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman) Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) { - int status = 0; + WIN32ERROR status = CHANNEL_RC_OK; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); if (presentation) { DEBUG_TSMF("Presentation already exists"); ifman->output_pending = FALSE; - return 0; + return CHANNEL_RC_OK; } presentation = tsmf_presentation_new(Stream_Pointer(ifman->input), ifman->channel_callback); if (!presentation) - status = 1; + status = ERROR_OUTOFMEMORY; else tsmf_presentation_set_audio_device(presentation, ifman->audio_name, ifman->audio_device); @@ -156,61 +180,72 @@ int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman) return status; } -int tsmf_ifman_add_stream(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; - int status = 0; + WIN32ERROR status = CHANNEL_RC_OK; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - Stream_Seek(ifman->input, 16); + Stream_Seek(ifman->input, GUID_SIZE); if (!presentation) { - status = 1; + status = ERROR_NOT_FOUND; } else { Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numMediaType */ stream = tsmf_stream_new(presentation, StreamId); - if (stream) - tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input); + if (!stream) + return ERROR_OUTOFMEMORY; + + if (!tsmf_stream_set_format(stream, ifman->decoder_name, ifman->input)) + return ERROR_OUTOFMEMORY; } + ifman->output_pending = TRUE; return status; } -int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); if (!Stream_EnsureRemainingCapacity(ifman->output, 8)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, 1); /* TopologyReady */ Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) { - int status = 0; + int status = CHANNEL_RC_OK; UINT32 StreamId; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); + if (Stream_GetRemainingLength(ifman->input) < 20) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - Stream_Seek(ifman->input, 16); + Stream_Seek(ifman->input, GUID_SIZE); if (!presentation) { - status = 1; + status = ERROR_NOT_FOUND; } else { @@ -220,7 +255,7 @@ int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman) if (stream) tsmf_stream_free(stream); else - status = 1; + status = ERROR_NOT_FOUND; } ifman->output_pending = TRUE; @@ -237,22 +272,25 @@ float tsmf_stream_read_float(wStream *s) return fValue; } -int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman) { - int status = 0; + WIN32ERROR status = CHANNEL_RC_OK; float Left, Top; float Right, Bottom; TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); + if (Stream_GetRemainingLength(ifman->input) < 32) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - Stream_Seek(ifman->input, 16); + Stream_Seek(ifman->input, GUID_SIZE); if (!presentation) { - status = 1; + status = ERROR_NOT_FOUND; } else { @@ -269,62 +307,76 @@ int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman) return status; } -int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); - presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); if (presentation) tsmf_presentation_free(presentation); else + { WLog_ERR(TAG, "unknown presentation id"); + return ERROR_NOT_FOUND; + } if (!Stream_EnsureRemainingCapacity(ifman->output, 4)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, 0); /* Result */ ifman->output_interface_id = TSMF_INTERFACE_DEFAULT | STREAM_ID_STUB; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; + UINT32 newVolume; + UINT32 muted; + DEBUG_TSMF("on stream volume"); + + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if (presentation) - { - UINT32 newVolume; - UINT32 muted; - Stream_Seek(ifman->input, 16); - Stream_Read_UINT32(ifman->input, newVolume); - DEBUG_TSMF("on stream volume: new volume=[%d]", newVolume); - Stream_Read_UINT32(ifman->input, muted); - DEBUG_TSMF("on stream volume: muted=[%d]", muted); - tsmf_presentation_volume_changed(presentation, newVolume, muted); - } - else + if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); + return ERROR_NOT_FOUND; } + Stream_Seek(ifman->input, 16); + Stream_Read_UINT32(ifman->input, newVolume); + DEBUG_TSMF("on stream volume: new volume=[%d]", newVolume); + Stream_Read_UINT32(ifman->input, muted); + DEBUG_TSMF("on stream volume: muted=[%d]", muted); + + if (!tsmf_presentation_volume_changed(presentation, newVolume, muted)) + return ERROR_INVALID_OPERATION; + ifman->output_pending = TRUE; return 0; } -int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_TSMF("on channel volume"); - presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 8) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); if (presentation) { UINT32 channelVolume; @@ -338,17 +390,17 @@ int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman) ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_set_video_window(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; UINT32 numGeometryInfo; @@ -359,10 +411,17 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) UINT32 cbVisibleRect; RDP_RECT *rects = NULL; int num_rects = 0; - int error = 0; + WIN32ERROR error = CHANNEL_RC_OK; int i; int pos; + + if (Stream_GetRemainingLength(ifman->input) < GUID_SIZE + 32) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); + if (!presentation) + return ERROR_NOT_FOUND; + Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, numGeometryInfo); pos = Stream_GetPosition(ifman->input); @@ -371,61 +430,57 @@ int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman) Stream_Read_UINT32(ifman->input, Height); Stream_Read_UINT32(ifman->input, Left); Stream_Read_UINT32(ifman->input, Top); + Stream_SetPosition(ifman->input, pos + numGeometryInfo); Stream_Read_UINT32(ifman->input, cbVisibleRect); num_rects = cbVisibleRect / 16; DEBUG_TSMF("numGeometryInfo %d Width %d Height %d Left %d Top %d cbVisibleRect %d num_rects %d", numGeometryInfo, Width, Height, Left, Top, cbVisibleRect, num_rects); - if (presentation == NULL) + + if (num_rects > 0) { - error = 1; - } - else - { - if (num_rects > 0) + rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT)); + + for (i = 0; i < num_rects; i++) { - rects = (RDP_RECT*) calloc(num_rects, sizeof(RDP_RECT)); - - for (i = 0; i < num_rects; i++) - { - Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */ - Stream_Seek_UINT16(ifman->input); - Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */ - Stream_Seek_UINT16(ifman->input); - Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */ - Stream_Seek_UINT16(ifman->input); - Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */ - Stream_Seek_UINT16(ifman->input); - rects[i].width -= rects[i].x; - rects[i].height -= rects[i].y; - DEBUG_TSMF("rect %d: %d %d %d %d", i, - rects[i].x, rects[i].y, rects[i].width, rects[i].height); - } + Stream_Read_UINT16(ifman->input, rects[i].y); /* Top */ + Stream_Seek_UINT16(ifman->input); + Stream_Read_UINT16(ifman->input, rects[i].x); /* Left */ + Stream_Seek_UINT16(ifman->input); + Stream_Read_UINT16(ifman->input, rects[i].height); /* Bottom */ + Stream_Seek_UINT16(ifman->input); + Stream_Read_UINT16(ifman->input, rects[i].width); /* Right */ + Stream_Seek_UINT16(ifman->input); + rects[i].width -= rects[i].x; + rects[i].height -= rects[i].y; + DEBUG_TSMF("rect %d: %d %d %d %d", i, + rects[i].x, rects[i].y, rects[i].width, rects[i].height); } - - tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects); } + if (!tsmf_presentation_set_geometry_info(presentation, Left, Top, Width, Height, num_rects, rects)) + return ERROR_INVALID_OPERATION; + ifman->output_pending = TRUE; return error; } -int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_set_allocator(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_sample(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; TSMF_STREAM* stream; @@ -436,6 +491,8 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) UINT32 SampleExtensions; UINT32 cbData; + if (Stream_GetRemainingLength(ifman->input) < 60) + return ERROR_INVALID_DATA; Stream_Seek(ifman->input, 16); Stream_Read_UINT32(ifman->input, StreamId); Stream_Seek_UINT32(ifman->input); /* numSample */ @@ -446,6 +503,9 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) Stream_Read_UINT32(ifman->input, SampleExtensions); Stream_Read_UINT32(ifman->input, cbData); + if (Stream_GetRemainingLength(ifman->input) < cbData) + return ERROR_INVALID_DATA; + DEBUG_TSMF("MessageId %d StreamId %d SampleStartTime %d SampleEndTime %d " "ThrottleDuration %d SampleExtensions %d cbData %d", ifman->message_id, StreamId, (int)SampleStartTime, (int)SampleEndTime, @@ -456,7 +516,7 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) if (!presentation) { WLog_ERR(TAG, "unknown presentation id"); - return 1; + return ERROR_NOT_FOUND; } stream = tsmf_stream_find_by_id(presentation, StreamId); @@ -464,49 +524,59 @@ int tsmf_ifman_on_sample(TSMF_IFMAN* ifman) if (!stream) { WLog_ERR(TAG, "unknown stream id"); - return 1; + return ERROR_NOT_FOUND; } - tsmf_stream_push_sample(stream, ifman->channel_callback, + if (!tsmf_stream_push_sample(stream, ifman->channel_callback, ifman->message_id, SampleStartTime, SampleEndTime, - ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input)); + ThrottleDuration, SampleExtensions, cbData, Stream_Pointer(ifman->input))) + { + WLog_ERR(TAG, "unable to push sample"); + return ERROR_OUTOFMEMORY; + } tsmf_presentation_sync(presentation); ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_flush(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_flush(TSMF_IFMAN* ifman) { UINT32 StreamId; TSMF_PRESENTATION* presentation; + 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 1; + return ERROR_NOT_FOUND; } - tsmf_presentation_flush(presentation); + if (!tsmf_presentation_flush(presentation)) + return ERROR_INVALID_OPERATION; ifman->output_pending = TRUE; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) { UINT32 StreamId; TSMF_STREAM* stream; TSMF_PRESENTATION* presentation; + if (Stream_GetRemainingLength(ifman->input) < 20) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); Stream_Seek(ifman->input, 16); @@ -522,22 +592,26 @@ int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman) DEBUG_TSMF("StreamId %d", StreamId); if (!Stream_EnsureRemainingCapacity(ifman->output, 16)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, StreamId); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_ENDOFSTREAM); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ - ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; - return 0; + ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); + if (Stream_GetRemainingLength(ifman->input) < 16) + return ERROR_INVALID_DATA; + presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); if (presentation) @@ -546,17 +620,18 @@ int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman) WLog_ERR(TAG, "unknown presentation id"); if (!Stream_EnsureRemainingCapacity(ifman->output, 16)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_START_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; @@ -567,14 +642,17 @@ int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman) presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); if (presentation) - tsmf_presentation_paused(presentation); + { + if (!tsmf_presentation_paused(presentation)) + return ERROR_INVALID_OPERATION; + } else WLog_ERR(TAG, "unknown presentation id"); - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; @@ -583,48 +661,55 @@ int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman) /* Added restart control so gstreamer pipeline can be resumed accordingly */ presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if (presentation) - tsmf_presentation_restarted(presentation); + { + if (!tsmf_presentation_restarted(presentation)) + return ERROR_INVALID_OPERATION; + } else WLog_ERR(TAG, "unknown presentation id"); - return 0; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman) { TSMF_PRESENTATION* presentation; DEBUG_TSMF(""); presentation = tsmf_presentation_find_by_id(Stream_Pointer(ifman->input)); - if (presentation) - tsmf_presentation_stop(presentation); + { + if (!tsmf_presentation_stop(presentation)) + return ERROR_INVALID_OPERATION; + } else WLog_ERR(TAG, "unknown presentation id"); if (!Stream_EnsureRemainingCapacity(ifman->output, 16)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_STOP_COMPLETED); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ - ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; - return 0; + ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; + return CHANNEL_RC_OK; } -int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman) +WIN32ERROR tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman) { DEBUG_TSMF(""); + if (!Stream_EnsureRemainingCapacity(ifman->output, 16)) - return -1; + return ERROR_OUTOFMEMORY; + Stream_Write_UINT32(ifman->output, CLIENT_EVENT_NOTIFICATION); /* FunctionId */ Stream_Write_UINT32(ifman->output, 0); /* StreamId */ Stream_Write_UINT32(ifman->output, TSMM_CLIENT_EVENT_MONITORCHANGED); /* EventId */ Stream_Write_UINT32(ifman->output, 0); /* cbData */ ifman->output_interface_id = TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY; - return 0; + return CHANNEL_RC_OK; } diff --git a/channels/tsmf/client/tsmf_ifman.h b/channels/tsmf/client/tsmf_ifman.h index 56ae4c5e7..c5e2cb837 100644 --- a/channels/tsmf/client/tsmf_ifman.h +++ b/channels/tsmf/client/tsmf_ifman.h @@ -38,29 +38,29 @@ struct _TSMF_IFMAN UINT32 output_interface_id; }; -int tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman); -int tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman); -int tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman); -int tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman); -int tsmf_ifman_add_stream(TSMF_IFMAN* ifman); -int tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman); -int tsmf_ifman_remove_stream(TSMF_IFMAN* ifman); -int tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman); -int tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman); -int tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman); -int tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman); -int tsmf_ifman_set_video_window(TSMF_IFMAN* ifman); -int tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman); -int tsmf_ifman_set_allocator(TSMF_IFMAN* ifman); -int tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman); -int tsmf_ifman_on_sample(TSMF_IFMAN* ifman); -int tsmf_ifman_on_flush(TSMF_IFMAN* ifman); -int tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman); -int tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman); -int tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman); -int tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman); -int tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman); -int tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_rim_exchange_capability_request(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_check_format_support_request(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_new_presentation(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_add_stream(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_set_topology_request(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_remove_stream(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_set_source_video_rect(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_shutdown_presentation(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_stream_volume(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_channel_volume(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_set_video_window(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_update_geometry_info(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_set_allocator(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_notify_preroll(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_sample(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_flush(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_end_of_stream(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_playback_started(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_playback_paused(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_playback_restarted(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_playback_stopped(TSMF_IFMAN* ifman); +WIN32ERROR tsmf_ifman_on_playback_rate_changed(TSMF_IFMAN* ifman); #endif diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 8079a7cc8..930f1a19e 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -34,7 +34,7 @@ #include "tsmf_main.h" -void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, +BOOL tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, UINT32 message_id, UINT64 duration, UINT32 data_size) { wStream *s; @@ -42,6 +42,8 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, TSMF_CHANNEL_CALLBACK *callback = (TSMF_CHANNEL_CALLBACK *) pChannelCallback; s = Stream_New(NULL, 32); + if (!s) + return FALSE; Stream_Write_UINT32(s, TSMF_INTERFACE_CLIENT_NOTIFICATIONS | STREAM_ID_PROXY); Stream_Write_UINT32(s, message_id); @@ -70,6 +72,7 @@ void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback, } Stream_Free(s, TRUE); + return (status == 0); } static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) @@ -95,6 +98,8 @@ static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCall input = data; output = Stream_New(NULL, 256); + if (!output) + return ERROR_OUTOFMEMORY; Stream_Seek(output, 8); Stream_Read_UINT32(input, InterfaceId); /* InterfaceId (4 bytes) */ Stream_Read_UINT32(input, MessageId); /* MessageId (4 bytes) */ @@ -140,6 +145,11 @@ static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCall switch (FunctionId) { case SET_CHANNEL_PARAMS: + if (Stream_GetRemainingLength(input) < GUID_SIZE + 4) + { + error = ERROR_INVALID_DATA; + goto out; + } CopyMemory(callback->presentation_id, Stream_Pointer(input), GUID_SIZE); Stream_Seek(input, GUID_SIZE); Stream_Read_UINT32(input, callback->stream_id); @@ -292,6 +302,7 @@ static WIN32ERROR tsmf_on_data_received(IWTSVirtualChannelCallback* pChannelCall } } +out: Stream_Free(output, TRUE); return error; } @@ -392,7 +403,7 @@ COMMAND_LINE_ARGUMENT_A tsmf_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) +static WIN32ERROR tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) { int status; DWORD flags; @@ -403,6 +414,9 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, tsmf_args, flags, tsmf, NULL, NULL); + if (status != 0) + return ERROR_INVALID_DATA; + arg = tsmf_args; do @@ -413,14 +427,20 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) CommandLineSwitchCase(arg, "audio") { tsmf->audio_name = _strdup(arg->Value); + if (!tsmf->audio_name) + return ERROR_OUTOFMEMORY; } CommandLineSwitchCase(arg, "audio-dev") { tsmf->audio_device = _strdup(arg->Value); + if (!tsmf->audio_device) + return ERROR_OUTOFMEMORY; } CommandLineSwitchCase(arg, "decoder") { tsmf->decoder_name = _strdup(arg->Value); + if (!tsmf->decoder_name) + return ERROR_OUTOFMEMORY; } CommandLineSwitchDefault(arg) { @@ -428,17 +448,20 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) CommandLineSwitchEnd(arg) } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + + return CHANNEL_RC_OK; } #ifdef STATIC_CHANNELS #define DVCPluginEntry tsmf_DVCPluginEntry #endif -int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) +WIN32ERROR DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - int status = 0; + WIN32ERROR status = 0; TSMF_PLUGIN* tsmf; TsmfClientContext* context; + WIN32ERROR error = ERROR_OUTOFMEMORY; tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf"); @@ -446,7 +469,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN)); if (!tsmf) - return -1; + return ERROR_OUTOFMEMORY; tsmf->iface.Initialize = tsmf_plugin_initialize; tsmf->iface.Connected = NULL; @@ -461,14 +484,17 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) tsmf->iface.pInterface = (void*) context; if (!tsmf_media_init()) + { + error = ERROR_INVALID_OPERATION; goto error_init; + } status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf); } if (status == 0) { - tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); + status = tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints)); } return status; @@ -477,5 +503,5 @@ error_init: free(context); error_context: free(tsmf); - return -1; + return error; } diff --git a/channels/tsmf/client/tsmf_main.h b/channels/tsmf/client/tsmf_main.h index 8c287c932..04f8f4c61 100644 --- a/channels/tsmf/client/tsmf_main.h +++ b/channels/tsmf/client/tsmf_main.h @@ -58,7 +58,7 @@ struct _TSMF_PLUGIN const char* audio_device; }; -void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, +BOOL tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback, UINT32 message_id, UINT64 duration, UINT32 data_size); #endif diff --git a/channels/tsmf/client/tsmf_media.c b/channels/tsmf/client/tsmf_media.c index 40155655b..6ab2d7355 100644 --- a/channels/tsmf/client/tsmf_media.c +++ b/channels/tsmf/client/tsmf_media.c @@ -219,23 +219,23 @@ static void tsmf_sample_free(void *arg) free(sample); } -static void tsmf_sample_ack(TSMF_SAMPLE* sample) +static BOOL tsmf_sample_ack(TSMF_SAMPLE* sample) { if (!sample) - return; + return FALSE; - tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); + return tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size); } -static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample) +static BOOL tsmf_sample_queue_ack(TSMF_SAMPLE* sample) { if (!sample) - return; + return FALSE; if (!sample->stream) - return; + return FALSE; - Queue_Enqueue(sample->stream->sample_ack_list, sample); + return Queue_Enqueue(sample->stream->sample_ack_list, sample); } static BOOL tsmf_stream_process_ack(void* arg, BOOL force) @@ -263,8 +263,11 @@ static BOOL tsmf_stream_process_ack(void* arg, BOOL force) } sample = Queue_Dequeue(stream->sample_ack_list); - tsmf_sample_ack(sample); - tsmf_sample_free(sample); + if (sample) + { + rc = tsmf_sample_ack(sample); + tsmf_sample_free(sample); + } finally: Queue_Unlock(stream->sample_ack_list); @@ -349,7 +352,7 @@ TSMF_PRESENTATION* tsmf_presentation_find_by_id(const BYTE *guid) return (found) ? presentation : NULL; } -static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) +static BOOL tsmf_sample_playback_video(TSMF_SAMPLE* sample) { UINT64 t; TSMF_VIDEO_FRAME_EVENT event; @@ -414,19 +417,21 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE* sample) free(event.frameData); } + return TRUE; } -static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample) +static BOOL tsmf_sample_playback_audio(TSMF_SAMPLE* sample) { UINT64 latency = 0; TSMF_STREAM* stream = sample->stream; + BOOL ret; DEBUG_TSMF("MessageId %d EndTime %d consumed.", sample->sample_id, (int)sample->end_time); if (sample->stream->audio && sample->data) { - sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size); + ret = sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size); sample->data = NULL; sample->decoded_size = 0; @@ -435,6 +440,7 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample) } else { + ret = TRUE; latency = 0; } @@ -442,9 +448,10 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE* sample) stream->last_end_time = sample->end_time + latency; stream->presentation->audio_start_time = sample->start_time + latency; stream->presentation->audio_end_time = sample->end_time + latency; + return ret; } -static void tsmf_sample_playback(TSMF_SAMPLE* sample) +static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample) { BOOL ret = FALSE; UINT32 width; @@ -467,8 +474,11 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample) if (!ret) { - tsmf_sample_queue_ack(sample); - return; + WLog_ERR(TAG, "decode error"); + if (!tsmf_sample_queue_ack(sample)) + return FALSE; + + return TRUE; } free(sample->data); @@ -482,8 +492,12 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample) if (pixfmt == ((UINT32) -1)) { - tsmf_sample_queue_ack(sample); - return; + WLog_ERR(TAG, "unable to decode video format"); + if (!tsmf_sample_queue_ack(sample)) + { + WLog_ERR(TAG, "error acking sample"); + } + return FALSE; } sample->pixfmt = pixfmt; @@ -511,13 +525,13 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample) switch (sample->stream->major_type) { case TSMF_MAJOR_TYPE_VIDEO: - tsmf_sample_playback_video(sample); - tsmf_sample_queue_ack(sample); + ret = tsmf_sample_playback_video(sample) && + tsmf_sample_queue_ack(sample); break; case TSMF_MAJOR_TYPE_AUDIO: - tsmf_sample_playback_audio(sample); - tsmf_sample_queue_ack(sample); + ret = tsmf_sample_playback_audio(sample) && + tsmf_sample_queue_ack(sample); break; } } @@ -572,8 +586,10 @@ static void tsmf_sample_playback(TSMF_SAMPLE* sample) } sample->ack_time = ack_anticipation_time; - tsmf_sample_queue_ack(sample); + ret = tsmf_sample_queue_ack(sample); } + + return ret; } static void* tsmf_stream_ack_func(void *arg) @@ -642,8 +658,11 @@ static void* tsmf_stream_playback_func(void *arg) { sample = tsmf_stream_pop_sample(stream, 0); - if (sample) - tsmf_sample_playback(sample); + if (sample && !tsmf_sample_playback(sample)) + { + WLog_ERR(TAG, "error playing sample"); + break; + } } if (stream->audio) @@ -657,139 +676,142 @@ static void* tsmf_stream_playback_func(void *arg) return NULL; } -static void tsmf_stream_start(TSMF_STREAM* stream) +static BOOL tsmf_stream_start(TSMF_STREAM* stream) { - if (!stream || !stream->presentation || !stream->decoder) - return; + if (!stream || !stream->presentation || !stream->decoder || !stream->decoder->Control) + return TRUE; - if (stream->decoder->Control) - { - stream->decoder->Control(stream->decoder, Control_Resume, NULL); - } + return stream->decoder->Control(stream->decoder, Control_Resume, NULL); } -static void tsmf_stream_stop(TSMF_STREAM* stream) +static BOOL tsmf_stream_stop(TSMF_STREAM* stream) { - if (!stream || !stream->decoder) - return; + if (!stream || !stream->decoder || !stream->decoder->Control) + return TRUE; - if (stream->decoder->Control) - { - stream->decoder->Control(stream->decoder, Control_Stop, NULL); - } + return stream->decoder->Control(stream->decoder, Control_Stop, NULL); } -static void tsmf_stream_pause(TSMF_STREAM* stream) +static BOOL tsmf_stream_pause(TSMF_STREAM* stream) { - if (!stream || !stream->decoder) - return; + if (!stream || !stream->decoder || !stream->decoder->Control) + return TRUE; - if (stream->decoder->Control) - { - stream->decoder->Control(stream->decoder, Control_Pause, NULL); - } + return stream->decoder->Control(stream->decoder, Control_Pause, NULL); } -static void tsmf_stream_restart(TSMF_STREAM* stream) +static BOOL tsmf_stream_restart(TSMF_STREAM* stream) { - if (!stream || !stream->decoder) - return; + if (!stream || !stream->decoder || !stream->decoder->Control) + return TRUE; - if (stream->decoder->Control) - { - stream->decoder->Control(stream->decoder, Control_Resume, NULL); - } + return stream->decoder->Control(stream->decoder, Control_Resume, NULL); } -static void tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted) +static BOOL tsmf_stream_change_volume(TSMF_STREAM* stream, UINT32 newVolume, UINT32 muted) { if (!stream || !stream->decoder) - return; + return TRUE; if (stream->decoder != NULL && stream->decoder->ChangeVolume) { - stream->decoder->ChangeVolume(stream->decoder, newVolume, muted); + return stream->decoder->ChangeVolume(stream->decoder, newVolume, muted); } else if (stream->audio != NULL && stream->audio->ChangeVolume) { - stream->audio->ChangeVolume(stream->audio, newVolume, muted); + return stream->audio->ChangeVolume(stream->audio, newVolume, muted); } + return TRUE; } -void tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted) +BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION* presentation, UINT32 newVolume, UINT32 muted) { UINT32 index; UINT32 count; TSMF_STREAM* stream; + BOOL ret = TRUE; + presentation->volume = newVolume; presentation->muted = muted; - ArrayList_Lock(presentation->stream_list); - count = ArrayList_Count(presentation->stream_list); + 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_change_volume(stream, newVolume, muted); + ret &= tsmf_stream_change_volume(stream, newVolume, muted); } ArrayList_Unlock(presentation->stream_list); + return ret; } -void tsmf_presentation_paused(TSMF_PRESENTATION* presentation) +BOOL tsmf_presentation_paused(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; + BOOL ret = TRUE; + 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_pause(stream); + ret &= tsmf_stream_pause(stream); } ArrayList_Unlock(presentation->stream_list); + return ret; } -void tsmf_presentation_restarted(TSMF_PRESENTATION* presentation) +BOOL tsmf_presentation_restarted(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; + BOOL ret = TRUE; + 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_restart(stream); + ret &= tsmf_stream_restart(stream); } ArrayList_Unlock(presentation->stream_list); + return ret; } -void tsmf_presentation_start(TSMF_PRESENTATION* presentation) +BOOL tsmf_presentation_start(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; + BOOL ret = TRUE; + 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_start(stream); + ret &= tsmf_stream_start(stream); } ArrayList_Unlock(presentation->stream_list); + return ret; } void tsmf_presentation_sync(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; + ArrayList_Lock(presentation->stream_list); count = ArrayList_Count(presentation->stream_list); @@ -802,46 +824,51 @@ void tsmf_presentation_sync(TSMF_PRESENTATION* presentation) ArrayList_Unlock(presentation->stream_list); } -void tsmf_presentation_stop(TSMF_PRESENTATION* presentation) +BOOL tsmf_presentation_stop(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; - tsmf_presentation_flush(presentation); + BOOL ret = TRUE; + + ret &= tsmf_presentation_flush(presentation); + 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_stop(stream); + ret &= tsmf_stream_stop(stream); } ArrayList_Unlock(presentation->stream_list); + return ret; } -void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, +BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects) { UINT32 index; UINT32 count; TSMF_STREAM* stream; void *tmp_rects; + BOOL ret = TRUE; if (num_rects < 1 || !rects) - return; + return TRUE; /* The server may send messages with invalid width / height. * Ignore those messages. */ if (!width || !height) - return; + return TRUE; if ((width == presentation->width) && (height == presentation->height) && (x == presentation->x) && (y == presentation->y) && (num_rects == presentation->nr_rects) && (0 == memcmp(rects, presentation->rects, num_rects * sizeof(RDP_RECT)))) { - return; + return TRUE; } presentation->x = x; @@ -851,7 +878,7 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, tmp_rects = realloc(presentation->rects, sizeof(RDP_RECT) * num_rects); if (!tmp_rects) - return; + return FALSE; presentation->nr_rects = num_rects; presentation->rects = tmp_rects; @@ -869,11 +896,12 @@ void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION* presentation, if (stream->decoder->UpdateRenderingArea) { - stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height, num_rects, rects); + ret = stream->decoder->UpdateRenderingArea(stream->decoder, x, y, width, height, num_rects, rects); } } ArrayList_Unlock(presentation->stream_list); + return ret; } void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const char *name, const char *device) @@ -882,12 +910,14 @@ void tsmf_presentation_set_audio_device(TSMF_PRESENTATION* presentation, const c presentation->audio_device = device; } -static void tsmf_stream_flush(TSMF_STREAM* stream) +static BOOL tsmf_stream_flush(TSMF_STREAM* stream) { + BOOL ret = TRUE; + //TSMF_SAMPLE* sample; /* TODO: free lists */ if (stream->audio) - stream->audio->Flush(stream->audio); + ret = stream->audio->Flush(stream->audio); stream->eos = 0; stream->last_end_time = 0; @@ -898,26 +928,31 @@ static void tsmf_stream_flush(TSMF_STREAM* stream) stream->presentation->audio_start_time = 0; stream->presentation->audio_end_time = 0; } + return TRUE; } -void tsmf_presentation_flush(TSMF_PRESENTATION* presentation) +BOOL tsmf_presentation_flush(TSMF_PRESENTATION* presentation) { UINT32 index; UINT32 count; TSMF_STREAM* stream; + BOOL ret = TRUE; + 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); + ret &= tsmf_stream_flush(stream); } ArrayList_Unlock(presentation->stream_list); presentation->eos = 0; presentation->audio_start_time = 0; presentation->audio_end_time = 0; + + return ret; } void _tsmf_presentation_free(TSMF_PRESENTATION* presentation) @@ -1034,17 +1069,19 @@ static void tsmf_stream_resync(void *arg) ResetEvent(stream->ready); } -void tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s) +BOOL tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s) { TS_AM_MEDIA_TYPE mediatype; + BOOL ret = TRUE; if (stream->decoder) { WLog_ERR(TAG, "duplicated call"); - return; + return FALSE; } - tsmf_codec_parse_media_type(&mediatype, s); + if (!tsmf_codec_parse_media_type(&mediatype, s)) + return FALSE; if (mediatype.MajorType == TSMF_MAJOR_TYPE_VIDEO) { @@ -1070,16 +1107,17 @@ void tsmf_stream_set_format(TSMF_STREAM* stream, const char *name, wStream *s) stream->width = mediatype.Width; stream->height = mediatype.Height; stream->decoder = tsmf_load_decoder(name, &mediatype); - tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted); + ret &= tsmf_stream_change_volume(stream, stream->presentation->volume, stream->presentation->muted); if (!stream->decoder) - return; + return FALSE; if (stream->decoder->SetAckFunc) - stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream); + ret &= stream->decoder->SetAckFunc(stream->decoder, tsmf_stream_process_ack, stream); if (stream->decoder->SetSyncFunc) - stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream); + ret &= stream->decoder->SetSyncFunc(stream->decoder, tsmf_stream_resync, stream); + return ret; } void tsmf_stream_end(TSMF_STREAM* stream) @@ -1096,8 +1134,8 @@ void _tsmf_stream_free(TSMF_STREAM* stream) if (!stream) return; - tsmf_stream_stop(stream); - tsmf_stream_flush(stream); + if (tsmf_stream_stop(stream)) + tsmf_stream_flush(stream); SetEvent(stream->stopEvent); if (stream->play_thread) @@ -1135,7 +1173,7 @@ void tsmf_stream_free(TSMF_STREAM* stream) ArrayList_Remove(presentation->stream_list, stream); } -void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pChannelCallback, +BOOL tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pChannelCallback, UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions, UINT32 data_size, BYTE *data) { @@ -1143,14 +1181,13 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pC SetEvent(stream->ready); if (TERMINATING) - return; + return TRUE; sample = (TSMF_SAMPLE*) calloc(1, sizeof(TSMF_SAMPLE)); - if (!sample) { - WLog_ERR(TAG, "calloc failed!"); - return; + WLog_ERR(TAG, "calloc sample failed!"); + return FALSE; } sample->sample_id = sample_id; @@ -1165,13 +1202,13 @@ void tsmf_stream_push_sample(TSMF_STREAM* stream, IWTSVirtualChannelCallback *pC if (!sample->data) { - WLog_ERR(TAG, "calloc failed!"); + WLog_ERR(TAG, "calloc sample->data failed!"); free(sample); - return; + return FALSE; } CopyMemory(sample->data, data, data_size); - Queue_Enqueue(stream->sample_list, sample); + return Queue_Enqueue(stream->sample_list, sample); } #ifndef _WIN32 diff --git a/channels/tsmf/client/tsmf_media.h b/channels/tsmf/client/tsmf_media.h index 9ccdd34ac..f26f16a98 100644 --- a/channels/tsmf/client/tsmf_media.h +++ b/channels/tsmf/client/tsmf_media.h @@ -34,27 +34,27 @@ typedef struct _TSMF_SAMPLE TSMF_SAMPLE; TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback); TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid); -void tsmf_presentation_start(TSMF_PRESENTATION *presentation); -void tsmf_presentation_stop(TSMF_PRESENTATION *presentation); +BOOL tsmf_presentation_start(TSMF_PRESENTATION *presentation); +BOOL tsmf_presentation_stop(TSMF_PRESENTATION *presentation); void tsmf_presentation_sync(TSMF_PRESENTATION *presentation); -void tsmf_presentation_paused(TSMF_PRESENTATION *presentation); -void tsmf_presentation_restarted(TSMF_PRESENTATION *presentation); -void tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted); -void tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation, +BOOL tsmf_presentation_paused(TSMF_PRESENTATION *presentation); +BOOL tsmf_presentation_restarted(TSMF_PRESENTATION *presentation); +BOOL tsmf_presentation_volume_changed(TSMF_PRESENTATION *presentation, UINT32 newVolume, UINT32 muted); +BOOL tsmf_presentation_set_geometry_info(TSMF_PRESENTATION *presentation, UINT32 x, UINT32 y, UINT32 width, UINT32 height, int num_rects, RDP_RECT *rects); void tsmf_presentation_set_audio_device(TSMF_PRESENTATION *presentation, const char *name, const char *device); -void tsmf_presentation_flush(TSMF_PRESENTATION *presentation); +BOOL tsmf_presentation_flush(TSMF_PRESENTATION *presentation); void tsmf_presentation_free(TSMF_PRESENTATION *presentation); TSMF_STREAM *tsmf_stream_new(TSMF_PRESENTATION *presentation, UINT32 stream_id); TSMF_STREAM *tsmf_stream_find_by_id(TSMF_PRESENTATION *presentation, UINT32 stream_id); -void tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s); +BOOL tsmf_stream_set_format(TSMF_STREAM *stream, const char *name, wStream *s); void tsmf_stream_end(TSMF_STREAM *stream); void tsmf_stream_free(TSMF_STREAM *stream); -void tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback, +BOOL tsmf_stream_push_sample(TSMF_STREAM *stream, IWTSVirtualChannelCallback *pChannelCallback, UINT32 sample_id, UINT64 start_time, UINT64 end_time, UINT64 duration, UINT32 extensions, UINT32 data_size, BYTE *data);