mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2025-01-19 13:18:32 +00:00
a/gst: Add GStreamer helper code
Co-authored-by: Aaron Boxer <aaron.boxer@collabora.com>
This commit is contained in:
parent
2b63fd8078
commit
30573fb90f
|
@ -69,6 +69,14 @@ if(XRT_HAVE_DBUS)
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(GSTREAMER_SOURCE_FILES
|
||||||
|
gstreamer/gst_internal.h
|
||||||
|
gstreamer/gst_sink.h
|
||||||
|
gstreamer/gst_sink.c
|
||||||
|
gstreamer/gst_pipeline.h
|
||||||
|
gstreamer/gst_pipeline.c
|
||||||
|
)
|
||||||
|
|
||||||
set(TRACKING_SOURCE_FILES
|
set(TRACKING_SOURCE_FILES
|
||||||
tracking/t_data_utils.c
|
tracking/t_data_utils.c
|
||||||
tracking/t_imu_fusion.hpp
|
tracking/t_imu_fusion.hpp
|
||||||
|
@ -221,6 +229,23 @@ if(ANDROID)
|
||||||
target_link_libraries(aux_util PUBLIC ${ANDROID_LOG_LIBRARY})
|
target_link_libraries(aux_util PUBLIC ${ANDROID_LOG_LIBRARY})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# GStreamer library.
|
||||||
|
if(XRT_HAVE_GST)
|
||||||
|
add_library(aux_gstreamer STATIC ${GSTREAMER_SOURCE_FILES})
|
||||||
|
target_link_libraries(aux_gstreamer PUBLIC
|
||||||
|
aux-includes
|
||||||
|
)
|
||||||
|
target_link_libraries(aux_gstreamer PRIVATE
|
||||||
|
xrt-interfaces
|
||||||
|
aux_math
|
||||||
|
aux_os
|
||||||
|
${GST_LIBRARIES}
|
||||||
|
)
|
||||||
|
target_include_directories(aux_gstreamer PRIVATE
|
||||||
|
${GST_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Tracking library.
|
# Tracking library.
|
||||||
add_library(aux_tracking STATIC ${TRACKING_SOURCE_FILES})
|
add_library(aux_tracking STATIC ${TRACKING_SOURCE_FILES})
|
||||||
target_link_libraries(aux_tracking PUBLIC aux-includes PRIVATE aux_math)
|
target_link_libraries(aux_tracking PUBLIC aux-includes PRIVATE aux_math)
|
||||||
|
|
80
src/xrt/auxiliary/gstreamer/gst_internal.h
Normal file
80
src/xrt/auxiliary/gstreamer/gst_internal.h
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// Copyright 2019-2021, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Semi internal structs for gstreamer code.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_frame.h"
|
||||||
|
|
||||||
|
#include <gst/app/gstappsink.h>
|
||||||
|
#include <gst/app/gstappsrc.h>
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Pipeline
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* A pipeline from which you can create one or more @ref gstreamer_sink from.
|
||||||
|
*
|
||||||
|
* @implements xrt_frame_node
|
||||||
|
*/
|
||||||
|
struct gstreamer_pipeline
|
||||||
|
{
|
||||||
|
struct xrt_frame_node node;
|
||||||
|
|
||||||
|
struct xrt_frame_context *xfctx;
|
||||||
|
|
||||||
|
GstElement *pipeline;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Sink
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* An @ref xrt_frame_sink that uses appsrc.
|
||||||
|
*
|
||||||
|
* @implements xrt_frame_sink
|
||||||
|
* @implements xrt_frame_node
|
||||||
|
*/
|
||||||
|
struct gstreamer_sink
|
||||||
|
{
|
||||||
|
//! The base structure exposing the sink interface.
|
||||||
|
struct xrt_frame_sink base;
|
||||||
|
|
||||||
|
//! A sink can expose multie @ref xrt_frame_sink but only one node.
|
||||||
|
struct xrt_frame_node node;
|
||||||
|
|
||||||
|
//! Pipeline this sink is producing frames into.
|
||||||
|
struct gstreamer_pipeline *gp;
|
||||||
|
|
||||||
|
//! Offset applied to timestamps given to GStreamer.
|
||||||
|
uint64_t offset_ns;
|
||||||
|
|
||||||
|
//! Last sent timestamp, used to calculate duration.
|
||||||
|
uint64_t timestamp_ns;
|
||||||
|
|
||||||
|
//! Cached appsrc element.
|
||||||
|
GstElement *appsrc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
152
src/xrt/auxiliary/gstreamer/gst_pipeline.c
Normal file
152
src/xrt/auxiliary/gstreamer/gst_pipeline.c
Normal file
|
@ -0,0 +1,152 @@
|
||||||
|
// Copyright 2019-2021, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief An @ref xrt_frame_sink that does gst things.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @author Aaron Boxer <aaron.boxer@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
|
||||||
|
#include "gstreamer/gst_internal.h"
|
||||||
|
#include "gstreamer/gst_pipeline.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Internal pipeline functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
break_apart(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gstreamer_pipeline *gp = container_of(node, struct gstreamer_pipeline, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called when we are shutting down, after returning
|
||||||
|
* from this function you are not allowed to call any other nodes in the
|
||||||
|
* graph. But it must be safe for other nodes to call any normal
|
||||||
|
* functions on us. Once the context is done calling break_aprt on all
|
||||||
|
* objects it will call destroy on them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void)gp;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gstreamer_pipeline *gp = container_of(node, struct gstreamer_pipeline, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All of the nodes has been broken apart and none of our functions will
|
||||||
|
* be called, it's now safe to destroy and free ourselves.
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(gp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Exported functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_play(struct gstreamer_pipeline *gp)
|
||||||
|
{
|
||||||
|
U_LOG_D("Starting pipeline");
|
||||||
|
|
||||||
|
gst_element_set_state(gp->pipeline, GST_STATE_PLAYING);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_stop(struct gstreamer_pipeline *gp)
|
||||||
|
{
|
||||||
|
U_LOG_D("Stopping pipeline");
|
||||||
|
|
||||||
|
// Settle the pipeline.
|
||||||
|
U_LOG_T("Sending EOS");
|
||||||
|
gst_element_send_event(gp->pipeline, gst_event_new_eos());
|
||||||
|
|
||||||
|
// Wait for EOS message on the pipeline bus.
|
||||||
|
U_LOG_T("Waiting for EOS");
|
||||||
|
GstMessage *msg = NULL;
|
||||||
|
msg = gst_bus_timed_pop_filtered(GST_ELEMENT_BUS(gp->pipeline), GST_CLOCK_TIME_NONE,
|
||||||
|
GST_MESSAGE_EOS | GST_MESSAGE_ERROR);
|
||||||
|
//! @todo Should check if we got an error message here or an eos.
|
||||||
|
(void)msg;
|
||||||
|
|
||||||
|
// Completely stop the pipeline.
|
||||||
|
U_LOG_T("Setting to NULL");
|
||||||
|
gst_element_set_state(gp->pipeline, GST_STATE_NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_create_from_string(struct xrt_frame_context *xfctx,
|
||||||
|
const char *pipeline_string,
|
||||||
|
struct gstreamer_pipeline **out_gp)
|
||||||
|
{
|
||||||
|
gst_init(NULL, NULL);
|
||||||
|
|
||||||
|
struct gstreamer_pipeline *gp = U_TYPED_CALLOC(struct gstreamer_pipeline);
|
||||||
|
gp->node.break_apart = break_apart;
|
||||||
|
gp->node.destroy = destroy;
|
||||||
|
gp->xfctx = xfctx;
|
||||||
|
|
||||||
|
// Setup pipeline.
|
||||||
|
gp->pipeline = gst_parse_launch(pipeline_string, NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add ourselves to the context so we are destroyed.
|
||||||
|
* This is done once we know everything is completed.
|
||||||
|
*/
|
||||||
|
xrt_frame_context_add(xfctx, &gp->node);
|
||||||
|
|
||||||
|
*out_gp = gp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_create_autovideo_sink(struct xrt_frame_context *xfctx,
|
||||||
|
const char *appsrc_name,
|
||||||
|
struct gstreamer_pipeline **out_gp)
|
||||||
|
{
|
||||||
|
gst_init(NULL, NULL);
|
||||||
|
|
||||||
|
struct gstreamer_pipeline *gp = U_TYPED_CALLOC(struct gstreamer_pipeline);
|
||||||
|
gp->node.break_apart = break_apart;
|
||||||
|
gp->node.destroy = destroy;
|
||||||
|
gp->xfctx = xfctx;
|
||||||
|
|
||||||
|
// Setup pipeline.
|
||||||
|
gp->pipeline = gst_pipeline_new("pipeline");
|
||||||
|
GstElement *appsrc = gst_element_factory_make("appsrc", appsrc_name);
|
||||||
|
GstElement *conv = gst_element_factory_make("videoconvert", "conv");
|
||||||
|
GstElement *scale = gst_element_factory_make("videoscale", "scale");
|
||||||
|
GstElement *videosink = gst_element_factory_make("autovideosink", "videosink");
|
||||||
|
|
||||||
|
gst_bin_add_many(GST_BIN(gp->pipeline), //
|
||||||
|
appsrc, //
|
||||||
|
conv, //
|
||||||
|
scale, //
|
||||||
|
videosink, //
|
||||||
|
NULL);
|
||||||
|
gst_element_link_many(appsrc, //
|
||||||
|
conv, //
|
||||||
|
scale, //
|
||||||
|
videosink, //
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add ourselves to the context so we are destroyed.
|
||||||
|
* This is done once we know everything is completed.
|
||||||
|
*/
|
||||||
|
xrt_frame_context_add(xfctx, &gp->node);
|
||||||
|
|
||||||
|
*out_gp = gp;
|
||||||
|
}
|
40
src/xrt/auxiliary/gstreamer/gst_pipeline.h
Normal file
40
src/xrt/auxiliary/gstreamer/gst_pipeline.h
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2019-2021, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief Functions for creating @ref gstreamer_pipeline objects.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_frame.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
struct gstreamer_pipeline;
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_create_from_string(struct xrt_frame_context *xfctx,
|
||||||
|
const char *pipeline_string,
|
||||||
|
struct gstreamer_pipeline **out_gp);
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_create_autovideo_sink(struct xrt_frame_context *xfctx,
|
||||||
|
const char *appsrc_name,
|
||||||
|
struct gstreamer_pipeline **out_gp);
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_play(struct gstreamer_pipeline *gp);
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_pipeline_stop(struct gstreamer_pipeline *gp);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
187
src/xrt/auxiliary/gstreamer/gst_sink.c
Normal file
187
src/xrt/auxiliary/gstreamer/gst_sink.c
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
// Copyright 2019-2021, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief An @ref xrt_frame_sink that does gst things.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @author Aaron Boxer <aaron.boxer@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "util/u_misc.h"
|
||||||
|
#include "util/u_debug.h"
|
||||||
|
#include "util/u_format.h"
|
||||||
|
|
||||||
|
#include "gstreamer/gst_sink.h"
|
||||||
|
#include "gstreamer/gst_pipeline.h"
|
||||||
|
#include "gstreamer/gst_internal.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Internal sink functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
wrapped_buffer_destroy(gpointer data)
|
||||||
|
{
|
||||||
|
struct xrt_frame *xf = (struct xrt_frame *)data;
|
||||||
|
|
||||||
|
U_LOG_T("Called");
|
||||||
|
|
||||||
|
xrt_frame_reference(&xf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
push_frame(struct xrt_frame_sink *xfs, struct xrt_frame *xf)
|
||||||
|
{
|
||||||
|
struct gstreamer_sink *gs = (struct gstreamer_sink *)xfs;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
GstFlowReturn ret;
|
||||||
|
|
||||||
|
U_LOG_T(
|
||||||
|
"Called"
|
||||||
|
"\n\tformat: %s"
|
||||||
|
"\n\twidth: %u"
|
||||||
|
"\n\theight: %u",
|
||||||
|
u_format_str(xf->format), xf->width, xf->height);
|
||||||
|
|
||||||
|
/* We need to take a reference on the frame to keep it alive. */
|
||||||
|
struct xrt_frame *taken = NULL;
|
||||||
|
xrt_frame_reference(&taken, xf);
|
||||||
|
|
||||||
|
/* Wrap the frame that we now hold a reference to. */
|
||||||
|
buffer = gst_buffer_new_wrapped_full( //
|
||||||
|
0, // GstMemoryFlags flags
|
||||||
|
(gpointer)xf->data, // gpointer data
|
||||||
|
taken->size, // gsize maxsize
|
||||||
|
0, // gsize offset
|
||||||
|
taken->size, // gsize size
|
||||||
|
taken, // gpointer user_data
|
||||||
|
wrapped_buffer_destroy); // GDestroyNotify notify
|
||||||
|
|
||||||
|
//! Get the timestampe from the frame.
|
||||||
|
uint64_t xtimestamp_ns = xf->timestamp;
|
||||||
|
|
||||||
|
// Use the first frame as offset.
|
||||||
|
if (gs->offset_ns == 0) {
|
||||||
|
gs->offset_ns = xtimestamp_ns;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Need to be offset or gstreamer becomes sad.
|
||||||
|
GST_BUFFER_PTS(buffer) = xtimestamp_ns - gs->offset_ns;
|
||||||
|
|
||||||
|
// Duration is measured from last time stamp.
|
||||||
|
GST_BUFFER_DURATION(buffer) = xtimestamp_ns - gs->timestamp_ns;
|
||||||
|
gs->timestamp_ns = xtimestamp_ns;
|
||||||
|
|
||||||
|
// All done, send it to the gstreamer pipeline.
|
||||||
|
ret = gst_app_src_push_buffer((GstAppSrc *)gs->appsrc, buffer);
|
||||||
|
if (ret != GST_FLOW_OK) {
|
||||||
|
U_LOG_E("Got GST error '%i'", ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
enough_data(GstElement *appsrc, gpointer udata)
|
||||||
|
{
|
||||||
|
// Debugging code.
|
||||||
|
U_LOG_T("Called");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
break_apart(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gstreamer_sink *gs = container_of(node, struct gstreamer_sink, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function is called when we are shutting down, after returning
|
||||||
|
* from this function you are not allowed to call any other nodes in the
|
||||||
|
* graph. But it must be safe for other nodes to call any normal
|
||||||
|
* functions on us. Once the context is done calling break_aprt on all
|
||||||
|
* objects it will call destroy on them.
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void)gs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
destroy(struct xrt_frame_node *node)
|
||||||
|
{
|
||||||
|
struct gstreamer_sink *gs = container_of(node, struct gstreamer_sink, node);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All of the nodes has been broken apart and none of our functions will
|
||||||
|
* be called, it's now safe to destroy and free ourselves.
|
||||||
|
*/
|
||||||
|
|
||||||
|
free(gs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Exported functions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_sink_send_eos(struct gstreamer_sink *gs)
|
||||||
|
{
|
||||||
|
gst_element_send_event(gs->appsrc, gst_event_new_eos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_sink_create_with_pipeline(struct gstreamer_pipeline *gp,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
enum xrt_format format,
|
||||||
|
const char *appsrc_name,
|
||||||
|
struct gstreamer_sink **out_gs,
|
||||||
|
struct xrt_frame_sink **out_xfs)
|
||||||
|
{
|
||||||
|
const char *format_str = NULL;
|
||||||
|
switch (format) {
|
||||||
|
case XRT_FORMAT_R8G8B8: format_str = "RGB"; break;
|
||||||
|
case XRT_FORMAT_YUYV422: format_str = "YUY2"; break;
|
||||||
|
case XRT_FORMAT_L8: format_str = "GRAY8"; break;
|
||||||
|
default: assert(false); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gstreamer_sink *gs = U_TYPED_CALLOC(struct gstreamer_sink);
|
||||||
|
gs->base.push_frame = push_frame;
|
||||||
|
gs->node.break_apart = break_apart;
|
||||||
|
gs->node.destroy = destroy;
|
||||||
|
gs->gp = gp;
|
||||||
|
gs->appsrc = gst_bin_get_by_name(GST_BIN(gp->pipeline), appsrc_name);
|
||||||
|
|
||||||
|
|
||||||
|
GstCaps *caps = gst_caps_new_simple( //
|
||||||
|
"video/x-raw", //
|
||||||
|
"format", G_TYPE_STRING, format_str, //
|
||||||
|
"width", G_TYPE_INT, width, //
|
||||||
|
"height", G_TYPE_INT, height, //
|
||||||
|
"framerate", GST_TYPE_FRACTION, 0, 1, //
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_object_set(G_OBJECT(gs->appsrc), //
|
||||||
|
"caps", caps, //
|
||||||
|
"stream-type", GST_APP_STREAM_TYPE_STREAM, //
|
||||||
|
"format", GST_FORMAT_TIME, //
|
||||||
|
"is-live", TRUE, //
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect(G_OBJECT(gs->appsrc), "enough-data", G_CALLBACK(enough_data), gs);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add ourselves to the context so we are destroyed.
|
||||||
|
* This is done once we know everything is completed.
|
||||||
|
*/
|
||||||
|
xrt_frame_context_add(gp->xfctx, &gs->node);
|
||||||
|
|
||||||
|
*out_gs = gs;
|
||||||
|
*out_xfs = &gs->base;
|
||||||
|
}
|
37
src/xrt/auxiliary/gstreamer/gst_sink.h
Normal file
37
src/xrt/auxiliary/gstreamer/gst_sink.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
// Copyright 2019-2021, Collabora, Ltd.
|
||||||
|
// SPDX-License-Identifier: BSL-1.0
|
||||||
|
/*!
|
||||||
|
* @file
|
||||||
|
* @brief @ref xrt_frame_sink that does gst things.
|
||||||
|
* @author Jakob Bornecrantz <jakob@collabora.com>
|
||||||
|
* @ingroup aux_util
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "xrt/xrt_frame.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct gstreamer_sink;
|
||||||
|
struct gstreamer_pipeline;
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_sink_send_eos(struct gstreamer_sink *gp);
|
||||||
|
|
||||||
|
void
|
||||||
|
gstreamer_sink_create_with_pipeline(struct gstreamer_pipeline *gp,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
enum xrt_format format,
|
||||||
|
const char *appsrc_name,
|
||||||
|
struct gstreamer_sink **out_gs,
|
||||||
|
struct xrt_frame_sink **out_xfs);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
Loading…
Reference in a new issue