Hardened TSMF channel
This patch adds some checks for the TSMF channel: * checks malloc / calloc / strdup / _strdup return value * checks for available bytew before reading in a stream
This commit is contained in:
parent
a8fefae3a1
commit
ea679b2d8b
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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; i<nr_rects; i++)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
XShapeCombineRectangles(hdl->disp, 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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user