channels/tsmf: add new callback interface

This commit is contained in:
Marc-André Moreau 2014-11-07 18:33:45 -05:00
parent bfdd3bd606
commit a6bb185760
7 changed files with 317 additions and 271 deletions

View File

@ -21,14 +21,11 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <winpr/cmdline.h>
#include <winpr/stream.h>
#include <freerdp/client/tsmf.h>
#include "tsmf_types.h"
#include "tsmf_constants.h"
@ -37,43 +34,6 @@
#include "tsmf_main.h"
typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin *plugin;
IWTSVirtualChannelManager *channel_mgr;
IWTSVirtualChannel *channel;
BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
struct _TSMF_PLUGIN
{
IWTSPlugin iface;
TSMF_LISTENER_CALLBACK *listener_callback;
const char *decoder_name;
const char *audio_name;
const char *audio_device;
};
void tsmf_playback_ack(IWTSVirtualChannelCallback *pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size)
{
@ -322,41 +282,58 @@ static int tsmf_on_new_channel_connection(IWTSListenerCallback *pListenerCallbac
int *pbAccept,
IWTSVirtualChannelCallback **ppCallback)
{
TSMF_CHANNEL_CALLBACK *callback;
TSMF_LISTENER_CALLBACK *listener_callback = (TSMF_LISTENER_CALLBACK *) pListenerCallback;
TSMF_CHANNEL_CALLBACK* callback;
TSMF_LISTENER_CALLBACK* listener_callback = (TSMF_LISTENER_CALLBACK*) pListenerCallback;
DEBUG_TSMF("");
callback = (TSMF_CHANNEL_CALLBACK *) malloc(sizeof(TSMF_CHANNEL_CALLBACK));
ZeroMemory(callback, sizeof(TSMF_CHANNEL_CALLBACK));
callback = (TSMF_CHANNEL_CALLBACK*) calloc(1, sizeof(TSMF_CHANNEL_CALLBACK));
if (!callback)
return -1;
callback->iface.OnDataReceived = tsmf_on_data_received;
callback->iface.OnClose = tsmf_on_close;
callback->iface.OnOpen = NULL;
callback->plugin = listener_callback->plugin;
callback->channel_mgr = listener_callback->channel_mgr;
callback->channel = pChannel;
*ppCallback = (IWTSVirtualChannelCallback *) callback;
*ppCallback = (IWTSVirtualChannelCallback*) callback;
return 0;
}
static int tsmf_plugin_initialize(IWTSPlugin *pPlugin, IWTSVirtualChannelManager *pChannelMgr)
static int tsmf_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr)
{
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
DEBUG_TSMF("");
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK *) malloc(sizeof(TSMF_LISTENER_CALLBACK));
ZeroMemory(tsmf->listener_callback, sizeof(TSMF_LISTENER_CALLBACK));
tsmf->listener_callback = (TSMF_LISTENER_CALLBACK*) calloc(1, sizeof(TSMF_LISTENER_CALLBACK));
if (!tsmf->listener_callback)
return -1;
tsmf->listener_callback->iface.OnNewChannelConnection = tsmf_on_new_channel_connection;
tsmf->listener_callback->plugin = pPlugin;
tsmf->listener_callback->channel_mgr = pChannelMgr;
return pChannelMgr->CreateListener(pChannelMgr, "TSMF", 0,
(IWTSListenerCallback *) tsmf->listener_callback, NULL);
(IWTSListenerCallback*) tsmf->listener_callback, NULL);
}
static int tsmf_plugin_terminated(IWTSPlugin *pPlugin)
static int tsmf_plugin_terminated(IWTSPlugin* pPlugin)
{
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
DEBUG_TSMF("");
if(tsmf->listener_callback)
if (tsmf->listener_callback)
free(tsmf->listener_callback);
free(tsmf);
return 0;
}
@ -372,12 +349,15 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
{
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A *arg;
TSMF_PLUGIN *tsmf = (TSMF_PLUGIN *) pPlugin;
COMMAND_LINE_ARGUMENT_A* arg;
TSMF_PLUGIN* tsmf = (TSMF_PLUGIN*) pPlugin;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char **) args->argv,
tsmf_args, flags, tsmf, NULL, NULL);
tsmf_args, flags, tsmf, NULL, NULL);
arg = tsmf_args;
do
{
if(!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
@ -407,25 +387,41 @@ static void tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
#define DVCPluginEntry tsmf_DVCPluginEntry
#endif
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS *pEntryPoints)
int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
int status = 0;
TSMF_PLUGIN *tsmf;
tsmf = (TSMF_PLUGIN *) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if(tsmf == NULL)
TSMF_PLUGIN* tsmf;
TsmfClientContext* context;
tsmf = (TSMF_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "tsmf");
if (!tsmf)
{
tsmf = (TSMF_PLUGIN *) malloc(sizeof(TSMF_PLUGIN));
ZeroMemory(tsmf, sizeof(TSMF_PLUGIN));
tsmf = (TSMF_PLUGIN*) calloc(1, sizeof(TSMF_PLUGIN));
if (!tsmf)
return -1;
tsmf->iface.Initialize = tsmf_plugin_initialize;
tsmf->iface.Connected = NULL;
tsmf->iface.Disconnected = NULL;
tsmf->iface.Terminated = tsmf_plugin_terminated;
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin *) tsmf);
status = pEntryPoints->RegisterPlugin(pEntryPoints, "tsmf", (IWTSPlugin*) tsmf);
context = (TsmfClientContext*) calloc(1, sizeof(TsmfClientContext));
context->handle = (void*) context;
tsmf->iface.pInterface = (void*) context;
tsmf_media_init();
}
if(status == 0)
if (status == 0)
{
tsmf_process_addin_args((IWTSPlugin *) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
tsmf_process_addin_args((IWTSPlugin*) tsmf, pEntryPoints->GetPluginData(pEntryPoints));
}
return status;
}

View File

@ -20,10 +20,46 @@
#ifndef __TSMF_MAIN_H
#define __TSMF_MAIN_H
typedef struct _TSMF_LISTENER_CALLBACK TSMF_LISTENER_CALLBACK;
typedef struct _TSMF_CHANNEL_CALLBACK TSMF_CHANNEL_CALLBACK;
typedef struct _TSMF_PLUGIN TSMF_PLUGIN;
struct _TSMF_LISTENER_CALLBACK
{
IWTSListenerCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
};
struct _TSMF_CHANNEL_CALLBACK
{
IWTSVirtualChannelCallback iface;
IWTSPlugin* plugin;
IWTSVirtualChannelManager* channel_mgr;
IWTSVirtualChannel* channel;
BYTE presentation_id[GUID_SIZE];
UINT32 stream_id;
};
struct _TSMF_PLUGIN
{
IWTSPlugin iface;
TSMF_LISTENER_CALLBACK* listener_callback;
const char* decoder_name;
const char* audio_name;
const char* audio_device;
};
void tsmf_playback_ack(IWTSVirtualChannelCallback* pChannelCallback,
UINT32 message_id, UINT64 duration, UINT32 data_size);
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback,
wMessage* event);
UINT32 message_id, UINT64 duration, UINT32 data_size);
BOOL tsmf_push_event(IWTSVirtualChannelCallback* pChannelCallback, wMessage* event);
#endif

View File

@ -220,13 +220,13 @@ static void tsmf_sample_free(void *arg)
free(sample);
}
static void tsmf_sample_ack(TSMF_SAMPLE *sample)
static void tsmf_sample_ack(TSMF_SAMPLE* sample)
{
assert(sample);
tsmf_playback_ack(sample->channel_callback, sample->sample_id, sample->duration, sample->data_size);
}
static void tsmf_sample_queue_ack(TSMF_SAMPLE *sample)
static void tsmf_sample_queue_ack(TSMF_SAMPLE* sample)
{
assert(sample);
assert(sample->stream);
@ -262,7 +262,7 @@ finally:
return rc;
}
TSMF_PRESENTATION *tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback)
TSMF_PRESENTATION* tsmf_presentation_new(const BYTE *guid, IWTSVirtualChannelCallback *pChannelCallback)
{
TSMF_PRESENTATION *presentation;
assert(guid);
@ -325,12 +325,14 @@ TSMF_PRESENTATION *tsmf_presentation_find_by_id(const BYTE *guid)
return (found) ? presentation : NULL;
}
static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
static void tsmf_sample_playback_video(TSMF_SAMPLE* sample)
{
UINT64 t;
RDP_VIDEO_FRAME_EVENT *vevent;
TSMF_STREAM *stream = sample->stream;
TSMF_PRESENTATION *presentation = stream->presentation;
TSMF_STREAM* stream = sample->stream;
TSMF_PRESENTATION* presentation = stream->presentation;
TSMF_CHANNEL_CALLBACK* callback = (TSMF_CHANNEL_CALLBACK*) sample->channel_callback;
TsmfClientContext* tsmf = (TsmfClientContext*) callback->plugin->pInterface;
DEBUG_TSMF("MessageId %d EndTime %d data_size %d consumed.",
sample->sample_id, (int)sample->end_time, sample->data_size);
@ -346,20 +348,46 @@ static void tsmf_sample_playback_video(TSMF_SAMPLE *sample)
}
stream->next_start_time = t + sample->duration - 50000;
vevent = (RDP_VIDEO_FRAME_EVENT *) freerdp_event_new(TsmfChannel_Class, TsmfChannel_VideoFrame,
NULL, NULL);
vevent->frame_data = sample->data;
vevent->frame_size = sample->decoded_size;
vevent->frame_pixfmt = sample->pixfmt;
vevent->frame_width = sample->stream->width;
vevent->frame_height = sample->stream->height;
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL;
sample->decoded_size = 0;
if (!tsmf_push_event(sample->channel_callback, (wMessage *) vevent))
if (!tsmf->custom)
{
freerdp_event_free((wMessage *) vevent);
RDP_VIDEO_FRAME_EVENT* vevent;
vevent = (RDP_VIDEO_FRAME_EVENT*) freerdp_event_new(TsmfChannel_Class,
TsmfChannel_VideoFrame, NULL, NULL);
vevent->frame_data = sample->data;
vevent->frame_size = sample->decoded_size;
vevent->frame_pixfmt = sample->pixfmt;
vevent->frame_width = sample->stream->width;
vevent->frame_height = sample->stream->height;
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL;
sample->decoded_size = 0;
if (!tsmf_push_event(sample->channel_callback, (wMessage*) vevent))
{
freerdp_event_free((wMessage*) vevent);
}
}
else
{
TSMF_VIDEO_FRAME_EVENT event;
ZeroMemory(&event, sizeof(TSMF_VIDEO_FRAME_EVENT));
event.frameData = sample->data;
event.frameSize = sample->decoded_size;
event.framePixFmt = sample->pixfmt;
event.frameWidth = sample->stream->width;
event.frameHeight = sample->stream->height;
/* The frame data ownership is passed to the event object, and is freed after the event is processed. */
sample->data = NULL;
sample->decoded_size = 0;
if (tsmf->FrameEvent)
tsmf->FrameEvent(tsmf, &event);
}
#if 0
@ -396,8 +424,7 @@ static void tsmf_sample_playback_audio(TSMF_SAMPLE *sample)
if (sample->stream->audio && sample->data)
{
sample->stream->audio->Play(sample->stream->audio,
sample->data, sample->decoded_size);
sample->stream->audio->Play(sample->stream->audio, sample->data, sample->decoded_size);
sample->data = NULL;
sample->decoded_size = 0;

View File

@ -65,127 +65,7 @@ struct xf_xv_context
#define DEBUG_XV(fmt, ...) do { } while (0)
#endif
void xf_tsmf_init(xfContext* xfc, long xv_port)
{
int ret;
unsigned int i;
unsigned int version;
unsigned int release;
unsigned int event_base;
unsigned int error_base;
unsigned int request_base;
unsigned int num_adaptors;
xfXvContext* xv;
XvAdaptorInfo* ai;
XvAttribute* attr;
XvImageFormatValues* fo;
xv = (xfXvContext*) malloc(sizeof(xfXvContext));
ZeroMemory(xv, sizeof(xfXvContext));
xfc->xv_context = xv;
xv->xv_colorkey_atom = None;
xv->xv_image_size = 0;
xv->xv_port = xv_port;
if (!XShmQueryExtension(xfc->display))
{
DEBUG_XV("no shmem available.");
return;
}
ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base);
if (ret != Success)
{
DEBUG_XV("XvQueryExtension failed %d.", ret);
return;
}
DEBUG_XV("version %u release %u", version, release);
ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display),
&num_adaptors, &ai);
if (ret != Success)
{
DEBUG_XV("XvQueryAdaptors failed %d.", ret);
return;
}
for (i = 0; i < num_adaptors; i++)
{
DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id,
ai[i].base_id + ai[i].num_ports - 1, ai[i].name);
if (xv->xv_port == 0 && i == num_adaptors - 1)
xv->xv_port = ai[i].base_id;
}
if (num_adaptors > 0)
XvFreeAdaptorInfo(ai);
if (xv->xv_port == 0)
{
DEBUG_XV("no adapter selected, video frames will not be processed.");
return;
}
DEBUG_XV("selected %ld", xv->xv_port);
attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret);
for (i = 0; i < (unsigned int)ret; i++)
{
if (strcmp(attr[i].name, "XV_COLORKEY") == 0)
{
xv->xv_colorkey_atom = XInternAtom(xfc->display, "XV_COLORKEY", FALSE);
XvSetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, attr[i].min_value + 1);
break;
}
}
XFree(attr);
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "xf_tsmf_init: pixel format ");
#endif
fo = XvListImageFormats(xfc->display, xv->xv_port, &ret);
if (ret > 0)
{
xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32));
ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32));
for (i = 0; i < ret; i++)
{
xv->xv_pixfmts[i] = fo[i].id;
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1],
((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]);
#endif
}
xv->xv_pixfmts[i] = 0;
}
XFree(fo);
}
void xf_tsmf_uninit(xfContext* xfc)
{
xfXvContext* xv = (xfXvContext*) xfc->xv_context;
if (xv)
{
if (xv->xv_image_size > 0)
{
shmdt(xv->xv_shmaddr);
shmctl(xv->xv_shmid, IPC_RMID, NULL);
}
if (xv->xv_pixfmts)
{
free(xv->xv_pixfmts);
xv->xv_pixfmts = NULL;
}
free(xv);
xfc->xv_context = NULL;
}
}
static BOOL
xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt)
static BOOL xf_tsmf_is_format_supported(xfXvContext* xv, UINT32 pixfmt)
{
int i;
@ -367,12 +247,12 @@ static void xf_process_tsmf_video_frame_event(xfContext* xfc, RDP_VIDEO_FRAME_EV
XFree(image);
}
static void xf_process_tsmf_redraw_event(xfContext* xfc, RDP_REDRAW_EVENT* revent)
int xf_tsmf_video_frame_event(TsmfClientContext* tsmf, TSMF_VIDEO_FRAME_EVENT* event)
{
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
revent->x, revent->y, revent->width, revent->height, revent->x, revent->y);
//xfContext* xfc = (xfContext*) tsmf->custom;
//xfXvContext* xv = (xfXvContext*) xfc->xv_context;
return 1;
}
void xf_process_tsmf_event(xfContext* xfc, wMessage* event)
@ -380,13 +260,134 @@ void xf_process_tsmf_event(xfContext* xfc, wMessage* event)
switch (GetMessageType(event->id))
{
case TsmfChannel_VideoFrame:
fprintf(stderr, "TsmfVideoFrame\n");
xf_process_tsmf_video_frame_event(xfc, (RDP_VIDEO_FRAME_EVENT*) event);
break;
}
}
case TsmfChannel_Redraw:
xf_process_tsmf_redraw_event(xfc, (RDP_REDRAW_EVENT*) event);
void xf_tsmf_init(xfContext* xfc, long xv_port)
{
int ret;
unsigned int i;
unsigned int version;
unsigned int release;
unsigned int event_base;
unsigned int error_base;
unsigned int request_base;
unsigned int num_adaptors;
xfXvContext* xv;
XvAdaptorInfo* ai;
XvAttribute* attr;
XvImageFormatValues* fo;
xv = (xfXvContext*) calloc(1, sizeof(xfXvContext));
if (!xv)
return;
xfc->xv_context = xv;
xv->xv_colorkey_atom = None;
xv->xv_image_size = 0;
xv->xv_port = xv_port;
if (!XShmQueryExtension(xfc->display))
{
DEBUG_XV("no xshm available.");
return;
}
ret = XvQueryExtension(xfc->display, &version, &release, &request_base, &event_base, &error_base);
if (ret != Success)
{
DEBUG_XV("XvQueryExtension failed %d.", ret);
return;
}
DEBUG_XV("version %u release %u", version, release);
ret = XvQueryAdaptors(xfc->display, DefaultRootWindow(xfc->display),
&num_adaptors, &ai);
if (ret != Success)
{
DEBUG_XV("XvQueryAdaptors failed %d.", ret);
return;
}
for (i = 0; i < num_adaptors; i++)
{
DEBUG_XV("adapter port %ld-%ld (%s)", ai[i].base_id,
ai[i].base_id + ai[i].num_ports - 1, ai[i].name);
if (xv->xv_port == 0 && i == num_adaptors - 1)
xv->xv_port = ai[i].base_id;
}
if (num_adaptors > 0)
XvFreeAdaptorInfo(ai);
if (xv->xv_port == 0)
{
DEBUG_XV("no adapter selected, video frames will not be processed.");
return;
}
DEBUG_XV("selected %ld", xv->xv_port);
attr = XvQueryPortAttributes(xfc->display, xv->xv_port, &ret);
for (i = 0; i < (unsigned int)ret; i++)
{
if (strcmp(attr[i].name, "XV_COLORKEY") == 0)
{
xv->xv_colorkey_atom = XInternAtom(xfc->display, "XV_COLORKEY", FALSE);
XvSetPortAttribute(xfc->display, xv->xv_port, xv->xv_colorkey_atom, attr[i].min_value + 1);
break;
}
}
XFree(attr);
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "xf_tsmf_init: pixel format ");
#endif
fo = XvListImageFormats(xfc->display, xv->xv_port, &ret);
if (ret > 0)
{
xv->xv_pixfmts = (UINT32*) malloc((ret + 1) * sizeof(UINT32));
ZeroMemory(xv->xv_pixfmts, (ret + 1) * sizeof(UINT32));
for (i = 0; i < ret; i++)
{
xv->xv_pixfmts[i] = fo[i].id;
#ifdef WITH_DEBUG_XV
WLog_DBG(TAG, "%c%c%c%c ", ((char*)(xv->xv_pixfmts + i))[0], ((char*)(xv->xv_pixfmts + i))[1],
((char*)(xv->xv_pixfmts + i))[2], ((char*)(xv->xv_pixfmts + i))[3]);
#endif
}
xv->xv_pixfmts[i] = 0;
}
XFree(fo);
}
void xf_tsmf_uninit(xfContext* xfc)
{
xfXvContext* xv = (xfXvContext*) xfc->xv_context;
if (xv)
{
if (xv->xv_image_size > 0)
{
shmdt(xv->xv_shmaddr);
shmctl(xv->xv_shmid, IPC_RMID, NULL);
}
if (xv->xv_pixfmts)
{
free(xv->xv_pixfmts);
xv->xv_pixfmts = NULL;
}
free(xv);
xfc->xv_context = NULL;
}
}

View File

@ -18,46 +18,11 @@
* limitations under the License.
*/
#ifndef _TSMF_H_
#define _TSMF_H_
#ifndef FREERDP_CHANNEL_TSMF_H
#define FREERDP_CHANNEL_TSMF_H
#include <freerdp/types.h>
/* Callback function setup order:
*
* When the channel is loaded, it calls TSMF_REGISTER to register the
* decoder handle with the client.
* The client then stores the handle and calls TSMF_REGISTER_INSTANCE
* to give the channel the current handle to the session necessary
* to call other functions.
* After this initial setup the other functions can be used.
*/
/* Functions called from client -> registered by channel */
#define TSMF_GET_INSTANCE "tsmf_get_instance"
typedef void (*tsmf_get_instance)(void *instance, void *decoder);
#define TSMF_ADD_WINDOW_HANDLE "tsmf_add_window_handle"
typedef void (*tsmf_add_window_handle)(void *instance, void *decoder, void *window);
#define TSMF_DEL_WINDOW_HANDLE "tsmf_del_window_handle"
typedef void (*tsmf_del_window_handle)(void *instance, void *decoder);
/* Functions called from channel -> registered by client */
#define TSMF_REGISTER "tsmf_register"
typedef void (*tsmf_register)(void *instance, void *decoder);
#define TSMF_DESTROY "tsmf_destroy"
typedef void (*tsmf_destroy)(void *instance, void *decoder);
#define TSMF_PLAY "tsmf_play"
typedef void (*tsmf_play)(void *instance, void *decoder);
#define TSMF_PAUSE "tsmf_pause"
typedef void (*tsmf_pause)(void *instance, void *decoder);
#define TSMF_RESIZE_WINDOW "tsmf_resize_window"
typedef void (*tsmf_resize_window)(void *instance, void *decoder, int x, int y, int width,
int height, int nr_rect, RDP_RECT *visible);
#endif
#define TSMF_DVC_CHANNEL_NAME "TSMF"
#endif /* FREERDP_CHANNEL_TSMF_H */

View File

@ -20,6 +20,15 @@
#ifndef FREERDP_CHANNEL_CLIENT_TSMF_H
#define FREERDP_CHANNEL_CLIENT_TSMF_H
#include <freerdp/codec/region.h>
#include <freerdp/channels/tsmf.h>
/* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */
/* http://www.fourcc.org/yuv.php */
#define RDP_PIXFMT_I420 0x30323449
#define RDP_PIXFMT_YV12 0x32315659
struct _RDP_VIDEO_FRAME_EVENT
{
wMessage event;
@ -37,19 +46,36 @@ struct _RDP_VIDEO_FRAME_EVENT
};
typedef struct _RDP_VIDEO_FRAME_EVENT RDP_VIDEO_FRAME_EVENT;
struct _RDP_REDRAW_EVENT
struct _TSMF_VIDEO_FRAME_EVENT
{
wMessage event;
BYTE* frameData;
UINT32 frameSize;
UINT32 framePixFmt;
INT16 frameWidth;
INT16 frameHeight;
INT16 x;
INT16 y;
INT16 width;
INT16 height;
UINT16 numVisibleRects;
RECTANGLE_16* visibleRects;
};
typedef struct _RDP_REDRAW_EVENT RDP_REDRAW_EVENT;
typedef struct _TSMF_VIDEO_FRAME_EVENT TSMF_VIDEO_FRAME_EVENT;
/* RDP_VIDEO_FRAME_EVENT.frame_pixfmt */
/* http://www.fourcc.org/yuv.php */
#define RDP_PIXFMT_I420 0x30323449
#define RDP_PIXFMT_YV12 0x32315659
/**
* Client Interface
*/
typedef struct _tsmf_client_context TsmfClientContext;
typedef int (*pcTsmfFrameEvent)(TsmfClientContext* context, TSMF_VIDEO_FRAME_EVENT* event);
struct _tsmf_client_context
{
void* handle;
void* custom;
pcTsmfFrameEvent FrameEvent;
};
#endif /* FREERDP_CHANNEL_CLIENT_TSMF_H */

View File

@ -118,6 +118,7 @@ static wMessage* freerdp_tsmf_event_new(UINT16 event_type)
} event;
event.m = NULL;
switch (event_type)
{
case TsmfChannel_VideoFrame:
@ -125,12 +126,6 @@ static wMessage* freerdp_tsmf_event_new(UINT16 event_type)
ZeroMemory(event.v, sizeof(RDP_VIDEO_FRAME_EVENT));
event.m->id = MakeMessageId(TsmfChannel, VideoFrame);
break;
case TsmfChannel_Redraw:
event.v = malloc(sizeof(RDP_REDRAW_EVENT));
ZeroMemory(event.v, sizeof(RDP_REDRAW_EVENT));
event.m->id = MakeMessageId(TsmfChannel, Redraw);
break;
}
return event.v;