channels/tsmf: add new callback interface
This commit is contained in:
parent
bfdd3bd606
commit
a6bb185760
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user