[client] transport: split video provider operations

This commit is contained in:
Geoffrey McRae
2026-08-11 15:05:00 +10:00
parent eb6bb78db9
commit 96a5cf4ce8
6 changed files with 177 additions and 98 deletions

View File

@@ -236,31 +236,9 @@ LG_TransportControl;
typedef uint64_t LG_TransportControlToken; typedef uint64_t LG_TransportControlToken;
typedef struct LG_TransportOps typedef struct LG_FrameOps
{ {
const char * name;
void (*setup)(void);
bool (*create)(LG_Transport ** transport);
void (*destroy)(LG_Transport ** transport);
LG_TransportStatus (*connect)(LG_Transport * transport,
LG_TransportSession * session);
void (*disconnect)(LG_Transport * transport);
bool (*sessionValid)(LG_Transport * transport);
bool (*supportsDMA)(LG_Transport * transport); bool (*supportsDMA)(LG_Transport * transport);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no input. */
const LG_InputOps *(*getInputOps)(LG_Transport * transport,
void ** opaque);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no audio. */
const LG_AudioOps *(*getAudioOps)(LG_Transport * transport,
void ** opaque);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no
* clipboard. */
const LG_ClipboardOps *(*getClipboardOps)(LG_Transport * transport,
void ** opaque);
bool (*attachRenderer)(LG_Transport * transport, bool (*attachRenderer)(LG_Transport * transport,
const LG_RendererInterop * interop); const LG_RendererInterop * interop);
void (*detachRenderer)(LG_Transport * transport); void (*detachRenderer)(LG_Transport * transport);
@@ -274,16 +252,62 @@ typedef struct LG_TransportOps
const LG_TransportFrame * frame, LG_TransportFrameTiming * timing); const LG_TransportFrame * frame, LG_TransportFrameTiming * timing);
void (*releaseFrame)(LG_Transport * transport, LG_TransportFrame * frame); void (*releaseFrame)(LG_Transport * transport, LG_TransportFrame * frame);
/* Called by the frame consumer as it exits. A backend may release transient /* Called by the frame consumer as it exits. A backend may release transient
* stream resources; nextFrame must reacquire them when the consumer restarts. */ * stream resources; nextFrame must reacquire them when the consumer
* restarts. */
void (*stopFrame)(LG_Transport * transport); void (*stopFrame)(LG_Transport * transport);
LG_TransportStatus (*nextPointer)(LG_Transport * transport, LG_TransportStatus (*nextPointer)(LG_Transport * transport,
LG_TransportPointer * pointer); LG_TransportPointer * pointer);
void (*releasePointer)(LG_Transport * transport, void (*releasePointer)(LG_Transport * transport,
LG_TransportPointer * pointer); LG_TransportPointer * pointer);
/* Called by the pointer consumer as it exits. A backend may release transient /* Called by the pointer consumer as it exits. A backend may release
* stream resources; nextPointer must reacquire them when the consumer restarts. */ * transient stream resources; nextPointer must reacquire them when the
* consumer restarts. */
void (*stopPointer)(LG_Transport * transport); void (*stopPointer)(LG_Transport * transport);
}
LG_FrameOps;
typedef enum LG_VideoType
{
LG_VIDEO_TYPE_FRAME,
}
LG_VideoType;
typedef struct LG_VideoOps
{
const char * name;
LG_VideoType type;
const LG_FrameOps * frame;
}
LG_VideoOps;
typedef struct LG_TransportOps
{
const char * name;
void (*setup)(void);
bool (*create)(LG_Transport ** transport);
void (*destroy)(LG_Transport ** transport);
LG_TransportStatus (*connect)(LG_Transport * transport,
LG_TransportSession * session);
void (*disconnect)(LG_Transport * transport);
bool (*sessionValid)(LG_Transport * transport);
/* Queried after create. The returned operations remain valid until the
* transport is destroyed. NULL indicates that this transport has no video. */
const LG_VideoOps *(*getVideoOps)(LG_Transport * transport);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no input. */
const LG_InputOps *(*getInputOps)(LG_Transport * transport,
void ** opaque);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no audio. */
const LG_AudioOps *(*getAudioOps)(LG_Transport * transport,
void ** opaque);
/* Queried after connect. The returned operations and opaque value remain
* valid until disconnect; NULL indicates that this session has no
* clipboard. */
const LG_ClipboardOps *(*getClipboardOps)(LG_Transport * transport,
void ** opaque);
LG_TransportStatus (*sendControl)(LG_Transport * transport, LG_TransportStatus (*sendControl)(LG_Transport * transport,
const LG_TransportControl * control, LG_TransportControlToken * token); const LG_TransportControl * control, LG_TransportControlToken * token);

View File

@@ -1044,8 +1044,8 @@ static int renderThread(void * unused)
core_stopCursorThread(); core_stopCursorThread();
core_stopFrameThread(); core_stopFrameThread();
if (g_state.transport.ops && g_state.transport.ops->detachRenderer) if (g_state.videoOps && g_state.videoOps->frame->detachRenderer)
g_state.transport.ops->detachRenderer(g_state.transport.handle); g_state.videoOps->frame->detachRenderer(g_state.transport.handle);
RENDERER(deinitialize); RENDERER(deinitialize);
g_state.lgr = NULL; g_state.lgr = NULL;
@@ -1066,7 +1066,7 @@ int main_cursorThread(void * unused)
while(app_getState() == APP_STATE_RUNNING && !g_state.stopVideo) while(app_getState() == APP_STATE_RUNNING && !g_state.stopVideo)
{ {
LG_TransportPointer pointer; LG_TransportPointer pointer;
const LG_TransportStatus status = g_state.transport.ops->nextPointer( const LG_TransportStatus status = g_state.videoOps->frame->nextPointer(
g_state.transport.handle, &pointer); g_state.transport.handle, &pointer);
if (status != LG_TRANSPORT_OK) if (status != LG_TRANSPORT_OK)
{ {
@@ -1119,7 +1119,7 @@ int main_cursorThread(void * unused)
case CURSOR_TYPE_MASKED_COLOR: cursorType = LG_CURSOR_MASKED_COLOR; break; case CURSOR_TYPE_MASKED_COLOR: cursorType = LG_CURSOR_MASKED_COLOR; break;
default: default:
DEBUG_ERROR("Invalid cursor type"); DEBUG_ERROR("Invalid cursor type");
g_state.transport.ops->releasePointer( g_state.videoOps->frame->releasePointer(
g_state.transport.handle, &pointer); g_state.transport.handle, &pointer);
continue; continue;
} }
@@ -1130,7 +1130,7 @@ int main_cursorThread(void * unused)
pointer.pitch, pointer.shape)) pointer.pitch, pointer.shape))
{ {
DEBUG_ERROR("Failed to update mouse shape"); DEBUG_ERROR("Failed to update mouse shape");
g_state.transport.ops->releasePointer( g_state.videoOps->frame->releasePointer(
g_state.transport.handle, &pointer); g_state.transport.handle, &pointer);
continue; continue;
} }
@@ -1192,11 +1192,12 @@ int main_cursorThread(void * unused)
(g_params.mouseRedraw || contentChanged)))) (g_params.mouseRedraw || contentChanged))))
cursorRepaintRequest(); cursorRepaintRequest();
g_state.transport.ops->releasePointer(g_state.transport.handle, &pointer); g_state.videoOps->frame->releasePointer(
g_state.transport.handle, &pointer);
} }
if (g_state.transport.ops->stopPointer) if (g_state.videoOps->frame->stopPointer)
g_state.transport.ops->stopPointer(g_state.transport.handle); g_state.videoOps->frame->stopPointer(g_state.transport.handle);
return 0; return 0;
} }
@@ -1213,15 +1214,15 @@ int main_frameThread(void * unused)
lgWaitEvent(e_startup, TIMEOUT_INFINITE); lgWaitEvent(e_startup, TIMEOUT_INFINITE);
if (app_getState() != APP_STATE_RUNNING) if (app_getState() != APP_STATE_RUNNING)
{ {
if (g_state.transport.ops->stopFrame) if (g_state.videoOps->frame->stopFrame)
g_state.transport.ops->stopFrame(g_state.transport.handle); g_state.videoOps->frame->stopFrame(g_state.transport.handle);
return 0; return 0;
} }
while(app_getState() == APP_STATE_RUNNING && !g_state.stopVideo) while(app_getState() == APP_STATE_RUNNING && !g_state.stopVideo)
{ {
LG_TransportFrame frame; LG_TransportFrame frame;
const LG_TransportStatus status = g_state.transport.ops->nextFrame( const LG_TransportStatus status = g_state.videoOps->frame->nextFrame(
g_state.transport.handle, g_state.useDMA, &frame); g_state.transport.handle, g_state.useDMA, &frame);
if (status != LG_TRANSPORT_OK) if (status != LG_TRANSPORT_OK)
{ {
@@ -1251,7 +1252,7 @@ int main_frameThread(void * unused)
if (frame.serial == frameSerial && g_state.formatValid && if (frame.serial == frameSerial && g_state.formatValid &&
!frame.scheduleOwner) !frame.scheduleOwner)
{ {
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
continue; continue;
} }
frameSerial = frame.serial; frameSerial = frame.serial;
@@ -1261,7 +1262,7 @@ int main_frameThread(void * unused)
if (!format) if (!format)
{ {
DEBUG_ERROR("Transport returned a frame without format metadata"); DEBUG_ERROR("Transport returned a frame without format metadata");
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
app_setState(APP_STATE_SHUTDOWN); app_setState(APP_STATE_SHUTDOWN);
break; break;
} }
@@ -1343,7 +1344,8 @@ int main_frameThread(void * unused)
if (invalid) if (invalid)
{ {
DEBUG_ERROR("Unsupported frame type"); DEBUG_ERROR("Unsupported frame type");
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(
g_state.transport.handle, &frame);
app_setState(APP_STATE_SHUTDOWN); app_setState(APP_STATE_SHUTDOWN);
break; break;
} }
@@ -1365,7 +1367,8 @@ int main_frameThread(void * unused)
{ {
LG_UNLOCK(g_state.lgrLock); LG_UNLOCK(g_state.lgrLock);
DEBUG_ERROR("Renderer failed to configure format"); DEBUG_ERROR("Renderer failed to configure format");
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(
g_state.transport.handle, &frame);
app_setState(APP_STATE_SHUTDOWN); app_setState(APP_STATE_SHUTDOWN);
break; break;
} }
@@ -1418,7 +1421,7 @@ int main_frameThread(void * unused)
rendererOwnsFrame ? frame.releaseHandle : 0)) rendererOwnsFrame ? frame.releaseHandle : 0))
{ {
frameTimingCancel(frameToken); frameTimingCancel(frameToken);
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
DEBUG_ERROR("Renderer onFrame returned failure"); DEBUG_ERROR("Renderer onFrame returned failure");
app_setState(APP_STATE_SHUTDOWN); app_setState(APP_STATE_SHUTDOWN);
break; break;
@@ -1428,8 +1431,8 @@ int main_frameThread(void * unused)
* is signalled below, so sample producer timing while this lease is still * is signalled below, so sample producer timing while this lease is still
* unambiguously owned by the frame thread. */ * unambiguously owned by the frame thread. */
LG_TransportFrameTiming timing = {}; LG_TransportFrameTiming timing = {};
if (g_state.transport.ops->getFrameTiming) if (g_state.videoOps->frame->getFrameTiming)
g_state.transport.ops->getFrameTiming( g_state.videoOps->frame->getFrameTiming(
g_state.transport.handle, &frame, &timing); g_state.transport.handle, &frame, &timing);
const uint64_t queueStart = nanotime(); const uint64_t queueStart = nanotime();
@@ -1474,7 +1477,7 @@ int main_frameThread(void * unused)
frameTimingFinishFrame(frameToken, &timing); frameTimingFinishFrame(frameToken, &timing);
if (!rendererOwnsFrame) if (!rendererOwnsFrame)
g_state.transport.ops->releaseFrame(g_state.transport.handle, &frame); g_state.videoOps->frame->releaseFrame(g_state.transport.handle, &frame);
app_useSpiceDisplay(false); app_useSpiceDisplay(false);
} }
@@ -1491,8 +1494,8 @@ int main_frameThread(void * unused)
/* Renderer reset requests release for every asynchronous DMA snapshot. /* Renderer reset requests release for every asynchronous DMA snapshot.
* Drain those requests before the transport unsubscribes or reconnects. */ * Drain those requests before the transport unsubscribes or reconnects. */
if (g_state.transport.ops->stopFrame) if (g_state.videoOps->frame->stopFrame)
g_state.transport.ops->stopFrame(g_state.transport.handle); g_state.videoOps->frame->stopFrame(g_state.transport.handle);
return 0; return 0;
} }
@@ -2126,6 +2129,16 @@ static int lg_run(void)
} }
DEBUG_INFO("Using Transport: %s", g_state.transport.ops->name); DEBUG_INFO("Using Transport: %s", g_state.transport.ops->name);
g_state.videoOps =
g_state.transport.ops->getVideoOps(g_state.transport.handle);
if (!g_state.videoOps || g_state.videoOps->type != LG_VIDEO_TYPE_FRAME ||
!g_state.videoOps->frame)
{
DEBUG_ERROR("Transport does not provide a frame source");
return -1;
}
DEBUG_INFO("Using Video: %s", g_state.videoOps->name);
// setup the spice startup condition // setup the spice startup condition
if (!(e_spice = lgCreateEvent(false, 0))) if (!(e_spice = lgCreateEvent(false, 0)))
{ {
@@ -2207,7 +2220,8 @@ static int lg_run(void)
return -1; return -1;
} }
g_state.useDMA = g_state.transport.ops->supportsDMA(g_state.transport.handle); g_state.useDMA =
g_state.videoOps->frame->supportsDMA(g_state.transport.handle);
// initialize the window dimensions at init for renderers // initialize the window dimensions at init for renderers
g_state.windowW = g_params.w; g_state.windowW = g_params.w;
@@ -2305,8 +2319,8 @@ static int lg_run(void)
if (g_state.lgr->ops.getInterop && if (g_state.lgr->ops.getInterop &&
g_state.lgr->ops.getInterop(g_state.lgr, &interop)) g_state.lgr->ops.getInterop(g_state.lgr, &interop))
interopPtr = &interop; interopPtr = &interop;
if (g_state.transport.ops->attachRenderer && if (g_state.videoOps->frame->attachRenderer &&
!g_state.transport.ops->attachRenderer( !g_state.videoOps->frame->attachRenderer(
g_state.transport.handle, interopPtr)) g_state.transport.handle, interopPtr))
{ {
DEBUG_ERROR("Failed to attach the renderer to the transport"); DEBUG_ERROR("Failed to attach the renderer to the transport");

View File

@@ -124,6 +124,7 @@ struct AppState
bool useDMA; bool useDMA;
LG_TransportInstance transport; LG_TransportInstance transport;
const LG_VideoOps * videoOps;
LG_TransportFeatureFlags transportFeatures; LG_TransportFeatureFlags transportFeatures;
LGThread * cursorThread; LGThread * cursorThread;

View File

@@ -82,6 +82,7 @@ int main(void)
PLGMPMemory frameMemory = NULL; PLGMPMemory frameMemory = NULL;
PLGMPMemory pointerMemory = NULL; PLGMPMemory pointerMemory = NULL;
LG_Transport * transport = NULL; LG_Transport * transport = NULL;
const LG_FrameOps * frameOps = NULL;
debug_init(); debug_init();
@@ -155,6 +156,11 @@ int main(void)
option_set_int("lgmp", "framePollInterval", 0); option_set_int("lgmp", "framePollInterval", 0);
option_set_int("lgmp", "cursorPollInterval", 0); option_set_int("lgmp", "cursorPollInterval", 0);
CHECK(LGT_LGMP.create(&transport)); CHECK(LGT_LGMP.create(&transport));
const LG_VideoOps * videoOps = LGT_LGMP.getVideoOps(transport);
CHECK(videoOps);
CHECK(videoOps->type == LG_VIDEO_TYPE_FRAME);
CHECK(videoOps->frame);
frameOps = videoOps->frame;
CHECK(unlink(path) == 0); CHECK(unlink(path) == 0);
pathExists = false; pathExists = false;
@@ -167,8 +173,8 @@ int main(void)
LG_TransportFrame frame; LG_TransportFrame frame;
LG_TransportPointer pointer; LG_TransportPointer pointer;
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT);
CHECK(lgmpHostQueueHasSubs(frameQueue)); CHECK(lgmpHostQueueHasSubs(frameQueue));
CHECK(lgmpHostQueueHasSubs(pointerQueue)); CHECK(lgmpHostQueueHasSubs(pointerQueue));
CHECK(lgmpHostQueueNewSubs(frameQueue) == 1); CHECK(lgmpHostQueueNewSubs(frameQueue) == 1);
@@ -177,16 +183,16 @@ int main(void)
CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK); CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK);
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION, CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
pointerMemory) == LGMP_OK); pointerMemory) == LGMP_OK);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_OK); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_OK);
LG_TransportFrameTiming timing; LG_TransportFrameTiming timing;
LGT_LGMP.getFrameTiming(transport, &frame, &timing); frameOps->getFrameTiming(transport, &frame, &timing);
CHECK(timing.captureTime == wireFrame->captureTime); CHECK(timing.captureTime == wireFrame->captureTime);
CHECK(timing.postProcessTime == wireFrame->postProcessTime); CHECK(timing.postProcessTime == wireFrame->postProcessTime);
CHECK(timing.copyTime == wireFrame->copyTime); CHECK(timing.copyTime == wireFrame->copyTime);
CHECK(timing.readyTime == wireFrame->readyTime); CHECK(timing.readyTime == wireFrame->readyTime);
LGT_LGMP.releaseFrame(transport, &frame); frameOps->releaseFrame(transport, &frame);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_OK); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_OK);
LGT_LGMP.releasePointer(transport, &pointer); frameOps->releasePointer(transport, &pointer);
/* /*
* Stop with messages pending. Unsubscribing before the host timeout is the * Stop with messages pending. Unsubscribing before the host timeout is the
@@ -195,10 +201,10 @@ int main(void)
CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK); CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK);
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION, CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
pointerMemory) == LGMP_OK); pointerMemory) == LGMP_OK);
CHECK(LGT_LGMP.stopFrame); CHECK(frameOps->stopFrame);
CHECK(LGT_LGMP.stopPointer); CHECK(frameOps->stopPointer);
LGT_LGMP.stopFrame(transport); frameOps->stopFrame(transport);
LGT_LGMP.stopPointer(transport); frameOps->stopPointer(transport);
CHECK(!lgmpHostQueueHasSubs(frameQueue)); CHECK(!lgmpHostQueueHasSubs(frameQueue));
CHECK(!lgmpHostQueueHasSubs(pointerQueue)); CHECK(!lgmpHostQueueHasSubs(pointerQueue));
@@ -206,8 +212,8 @@ int main(void)
CHECK(lgmpHostQueuePending(frameQueue) == 0); CHECK(lgmpHostQueuePending(frameQueue) == 0);
CHECK(lgmpHostQueuePending(pointerQueue) == 0); CHECK(lgmpHostQueuePending(pointerQueue) == 0);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT);
CHECK(lgmpHostQueueNewSubs(frameQueue) == 1); CHECK(lgmpHostQueueNewSubs(frameQueue) == 1);
CHECK(lgmpHostQueueNewSubs(pointerQueue) == 1); CHECK(lgmpHostQueueNewSubs(pointerQueue) == 1);
@@ -215,10 +221,10 @@ int main(void)
CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK); CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK);
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION, CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
pointerMemory) == LGMP_OK); pointerMemory) == LGMP_OK);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_OK); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_OK);
LGT_LGMP.releaseFrame(transport, &frame); frameOps->releaseFrame(transport, &frame);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_OK); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_OK);
LGT_LGMP.releasePointer(transport, &pointer); frameOps->releasePointer(transport, &pointer);
/* /*
* Also recover when the host has already marked the cached handles bad. * Also recover when the host has already marked the cached handles bad.
@@ -229,15 +235,15 @@ int main(void)
CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK); CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK);
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION, CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
pointerMemory) == LGMP_OK); pointerMemory) == LGMP_OK);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_OK); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_OK);
CHECK(waitForQueuesEmpty(host, frameQueue, pointerQueue)); CHECK(waitForQueuesEmpty(host, frameQueue, pointerQueue));
CHECK(lgmpHostQueueHasSubs(frameQueue)); CHECK(lgmpHostQueueHasSubs(frameQueue));
CHECK(lgmpHostQueueHasSubs(pointerQueue)); CHECK(lgmpHostQueueHasSubs(pointerQueue));
LGT_LGMP.stopFrame(transport); frameOps->stopFrame(transport);
LGT_LGMP.stopPointer(transport); frameOps->stopPointer(transport);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_TIMEOUT);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_TIMEOUT);
CHECK(lgmpHostQueueNewSubs(frameQueue) == 1); CHECK(lgmpHostQueueNewSubs(frameQueue) == 1);
CHECK(lgmpHostQueueNewSubs(pointerQueue) == 1); CHECK(lgmpHostQueueNewSubs(pointerQueue) == 1);
@@ -245,10 +251,10 @@ int main(void)
CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK); CHECK(lgmpHostQueuePost(frameQueue, 0, frameMemory) == LGMP_OK);
CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION, CHECK(lgmpHostQueuePost(pointerQueue, CURSOR_FLAG_POSITION,
pointerMemory) == LGMP_OK); pointerMemory) == LGMP_OK);
CHECK(LGT_LGMP.nextFrame(transport, false, &frame) == LG_TRANSPORT_OK); CHECK(frameOps->nextFrame(transport, false, &frame) == LG_TRANSPORT_OK);
LGT_LGMP.releaseFrame(transport, &frame); frameOps->releaseFrame(transport, &frame);
CHECK(LGT_LGMP.nextPointer(transport, &pointer) == LG_TRANSPORT_OK); CHECK(frameOps->nextPointer(transport, &pointer) == LG_TRANSPORT_OK);
LGT_LGMP.releasePointer(transport, &pointer); frameOps->releasePointer(transport, &pointer);
result = 0; result = 0;

View File

@@ -1360,17 +1360,9 @@ static const LG_InputOps * lgmp_getInputOps(LG_Transport * this,
return lgmpInput_getOps(); return lgmpInput_getOps();
} }
const LG_TransportOps LGT_LGMP = static const LG_FrameOps lgmpFrameOps =
{ {
.name = "lgmp",
.setup = lgmp_setup,
.create = lgmp_create,
.destroy = lgmp_destroy,
.connect = lgmp_connect,
.disconnect = lgmp_disconnect,
.sessionValid = lgmp_sessionValid,
.supportsDMA = lgmp_supportsDMA, .supportsDMA = lgmp_supportsDMA,
.getInputOps = lgmp_getInputOps,
.attachRenderer = lgmp_attachRenderer, .attachRenderer = lgmp_attachRenderer,
.detachRenderer = lgmp_detachRenderer, .detachRenderer = lgmp_detachRenderer,
.nextFrame = lgmp_nextFrame, .nextFrame = lgmp_nextFrame,
@@ -1380,6 +1372,31 @@ const LG_TransportOps LGT_LGMP =
.nextPointer = lgmp_nextPointer, .nextPointer = lgmp_nextPointer,
.releasePointer = lgmp_releasePointer, .releasePointer = lgmp_releasePointer,
.stopPointer = lgmp_stopPointer, .stopPointer = lgmp_stopPointer,
.sendControl = lgmp_sendControl, };
.controlStatus = lgmp_controlStatus,
static const LG_VideoOps lgmpVideoOps =
{
.name = "LGMP",
.type = LG_VIDEO_TYPE_FRAME,
.frame = &lgmpFrameOps,
};
static const LG_VideoOps * lgmp_getVideoOps(LG_Transport * this)
{
return &lgmpVideoOps;
}
const LG_TransportOps LGT_LGMP =
{
.name = "lgmp",
.setup = lgmp_setup,
.create = lgmp_create,
.destroy = lgmp_destroy,
.connect = lgmp_connect,
.disconnect = lgmp_disconnect,
.sessionValid = lgmp_sessionValid,
.getVideoOps = lgmp_getVideoOps,
.getInputOps = lgmp_getInputOps,
.sendControl = lgmp_sendControl,
.controlStatus = lgmp_controlStatus,
}; };

View File

@@ -734,23 +734,40 @@ static const LG_InputOps * test_getInputOps(LG_Transport * this,
return NULL; return NULL;
} }
const LG_TransportOps LGT_Test = static const LG_FrameOps testFrameOps =
{ {
.name = "test",
.setup = test_setup,
.create = test_create,
.destroy = test_destroy,
.connect = test_connect,
.disconnect = test_disconnect,
.sessionValid = test_sessionValid,
.supportsDMA = test_supportsDMA, .supportsDMA = test_supportsDMA,
.getInputOps = test_getInputOps,
.attachRenderer = test_attachRenderer, .attachRenderer = test_attachRenderer,
.detachRenderer = test_detachRenderer, .detachRenderer = test_detachRenderer,
.nextFrame = test_nextFrame, .nextFrame = test_nextFrame,
.releaseFrame = test_releaseFrame, .releaseFrame = test_releaseFrame,
.nextPointer = test_nextPointer, .nextPointer = test_nextPointer,
.releasePointer = test_releasePointer, .releasePointer = test_releasePointer,
.sendControl = test_sendControl, };
.controlStatus = test_controlStatus,
static const LG_VideoOps testVideoOps =
{
.name = "test",
.type = LG_VIDEO_TYPE_FRAME,
.frame = &testFrameOps,
};
static const LG_VideoOps * test_getVideoOps(LG_Transport * this)
{
return &testVideoOps;
}
const LG_TransportOps LGT_Test =
{
.name = "test",
.setup = test_setup,
.create = test_create,
.destroy = test_destroy,
.connect = test_connect,
.disconnect = test_disconnect,
.sessionValid = test_sessionValid,
.getVideoOps = test_getVideoOps,
.getInputOps = test_getInputOps,
.sendControl = test_sendControl,
.controlStatus = test_controlStatus,
}; };