gstreamer中是否有用于视频接收器的模板,就像插件元素一样?
我有一个非常简单的想法:一个init函数,渲染(显示)函数和deinit函数。而已。
答案 0 :(得分:1)
最好的"模板"是可用的源代码。从-base或-good中获取一个简单的接收器,并将其作为起点。这也是了解GStreamer的好方法,了解编写好的元素的行为方式。你想要的基类可能是gstbasesink,因为 就像gstbaseaudiosink一样,但还没有gstbasevideosink。
答案 1 :(得分:0)
我还寻找了一个基于 gstbasesink 的接收器“模板”,但没有找到。我按照上面的建议从我称为 vpphlsvideosink 的 fakesink 元素创建了一个,尽管它不是专门的视频接收器(还)。除了向 std cout 发送一个用于渲染的 'r' 字符和一个用于事件的 'e' 字符外,它什么都不做。这些是文件:
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "vpphlsvideosink.h"
static gboolean plugin_init (GstPlugin * plugin)
{
return gst_element_register(plugin, "vpphlsvideosink", GST_RANK_NONE, GST_TYPE_VPPHLSVIDEOSINK);
}//end plugin_init.
// GST_PLUGIN_DEFINE needs PACKAGE to be defined.
#ifndef PACKAGE
#define PACKAGE "vpphlsvideosink"
#endif
#ifndef VERSION
#define VERSION "1.0.0.0"
#endif
#ifndef GST_PACKAGE_NAME
#define GST_PACKAGE_NAME "GStreamer"
#endif
#ifndef GST_PACKAGE_ORIGIN
#define GST_PACKAGE_ORIGIN "http://somewhere.net/"
#endif
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
vpphlsvideosink,
"HLS Video Sink Plugin",
plugin_init,
VERSION,
"LGPL",
GST_PACKAGE_NAME,
GST_PACKAGE_ORIGIN);
#pragma once
#include <gst/gst.h>
#include <gst/base/gstbasesink.h>
G_BEGIN_DECLS
// Definition of structure storing data for this element.
typedef struct _Gstvpphlsvideosink
{
GstBaseSink element;
gboolean silent;
} Gstvpphlsvideosink;
// Standard definition defining a class for this element.
typedef struct _GstvpphlsvideosinkClass
{
GstBaseSinkClass parent_class;
} GstvpphlsvideosinkClass;
// Standard macros for defining types for this element.
#define GST_TYPE_VPPHLSVIDEOSINK (gst_vpphlsvideosink_get_type())
#define GST_VPPHLSVIDEOSINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VPPHLSVIDEOSINK,Gstvpphlsvideosink))
#define GST_VPPHLSVIDEOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VPPHLSVIDEOSINK,GstvpphlsvideosinkClass))
#define GST_IS_VPPHLSVIDEOSINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VPPHLSVIDEOSINK))
#define GST_IS_VPPHLSVIDEOSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VPPHLSVIDEOSINK))
GType gst_vpphlsvideosink_get_type(void);
G_END_DECLS
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include "vpphlsvideosink.h"
#include <iostream>
using namespace std;
GST_DEBUG_CATEGORY_STATIC (gst_vpphlsvideosink_debug);
#define GST_CAT_DEFAULT gst_vpphlsvideosink_debug
#define DEFAULT_SYNC true
#define DEFAULT_SILENT false
// Filter signals and args
enum
{
/* FILL ME */
LAST_SIGNAL
};
enum
{
PROP_0,
PROP_SILENT
};
// The capabilities of the inputs and outputs.
static GstStaticPadTemplate sinkpadtemplate = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY"));
#define gst_vpphlsvideosink_parent_class parent_class
G_DEFINE_TYPE(Gstvpphlsvideosink, gst_vpphlsvideosink, GST_TYPE_BASE_SINK);
static void gst_vpphlsvideosink_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
static void gst_vpphlsvideosink_get_property (GObject* object, guint prop_id, GValue* value, GParamSpec* pspec);
static void gst_vpphlsvideosink_finalize(GObject* obj);
static GstStateChangeReturn gst_vpphlsvideosink_change_state(GstElement* element, GstStateChange transition);
static GstFlowReturn gst_vpphlsvideosink_render(GstBaseSink* parent, GstBuffer* buffer);
static GstFlowReturn gst_vpphlsvideosink_preroll(GstBaseSink* parent, GstBuffer* buffer);
static gboolean gst_vpphlsvideosink_event(GstBaseSink* parent, GstEvent* event);
static gboolean gst_vpphlsvideosink_query(GstBaseSink* parent, GstQuery* query);
// Use this when there is at least one signal enum defined
//static guint gst_vpphlsvideosink_signals[LAST_SIGNAL] = { 0 };
// ------------- GObject virtual methods ------------------------------------------------------------------------------
// Initialize the vpphlsvideosink class
static void gst_vpphlsvideosink_class_init(GstvpphlsvideosinkClass* klass)
{
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
GstElementClass* gstelement_class = GST_ELEMENT_CLASS(klass);
GstBaseSinkClass* gstbasesink_class = GST_BASE_SINK_CLASS(klass);
gobject_class->set_property = gst_vpphlsvideosink_set_property;
gobject_class->get_property = gst_vpphlsvideosink_get_property;
gobject_class->finalize = gst_vpphlsvideosink_finalize;
g_object_class_install_property (gobject_class, PROP_SILENT,
g_param_spec_boolean ("silent", "Silent", "Produce verbose output?",
DEFAULT_SILENT,
(GParamFlags)(G_PARAM_READWRITE | GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS)));
gst_element_class_set_static_metadata(gstelement_class,
"A VPP HLS Video Sink",
"Sink/VPPHLSVIDEOSINK",
"Writes video buffers to an externally defined queue",
"Keith L Ferguson <<user@hostname.org>>");
// The one sink pad template
gst_element_class_add_static_pad_template(gstelement_class, &sinkpadtemplate);
// Set override methods
gstbasesink_class->render = GST_DEBUG_FUNCPTR(gst_vpphlsvideosink_render);
gstbasesink_class->preroll = GST_DEBUG_FUNCPTR(gst_vpphlsvideosink_preroll);
gstbasesink_class->event = GST_DEBUG_FUNCPTR(gst_vpphlsvideosink_event);
gstbasesink_class->query = GST_DEBUG_FUNCPTR(gst_vpphlsvideosink_query);
}//end gst_vpphlsvideosink_class_init.
// Initialise the new element.
static void gst_vpphlsvideosink_init (Gstvpphlsvideosink* vsink)
{
// On this sink class
vsink->silent = DEFAULT_SILENT;
// On the base class
gst_base_sink_set_sync(GST_BASE_SINK(vsink), DEFAULT_SYNC);
}//end gst_vpphlsvideosink_init.
static void gst_vpphlsvideosink_finalize(GObject* obj)
{
G_OBJECT_CLASS(parent_class)->finalize(obj);
}//end gst_vpphlsvideosink_finalize.
static void gst_vpphlsvideosink_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
{
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK (object);
switch (prop_id)
{
case PROP_SILENT:
vsink->silent = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}//end switch prop_id...
}//end gst_vpphlsvideosink_set_property.
static void gst_vpphlsvideosink_get_property (GObject* object, guint prop_id, GValue* value, GParamSpec* pspec)
{
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK (object);
switch (prop_id)
{
case PROP_SILENT:
g_value_set_boolean (value, vsink->silent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}//end switch prop_id...
}//end gst_vpphlsvideosink_get_property.
// -------------- GstBaseSink virtual methods ---------------------------------------------------------------
static GstFlowReturn gst_vpphlsvideosink_render(GstBaseSink* parent, GstBuffer* buffer)
{
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK(parent);
if (!vsink->silent)
cout << "r";
return GST_FLOW_OK;
}//end gst_vpphlsvideosink_render.
static GstFlowReturn gst_vpphlsvideosink_preroll(GstBaseSink* parent, GstBuffer* buffer)
{
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK(parent);
if (!vsink->silent)
cout << "p";
return GST_FLOW_OK;
}//end gst_vpphlsvideosink_preroll.
static gboolean gst_vpphlsvideosink_event(GstBaseSink* parent, GstEvent* event)
{
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK(parent);
if (!vsink->silent)
cout << "e";
return GST_BASE_SINK_CLASS(parent_class)->event(parent, event);
}//end gst_vpphlsvideosink_event.
static gboolean gst_vpphlsvideosink_query(GstBaseSink* parent, GstQuery* query)
{
gboolean ret;
switch (GST_QUERY_TYPE(query))
{
case GST_QUERY_SEEKING:
{
// Seeking is not supported
GstFormat fmt;
gst_query_parse_seeking(query, &fmt, NULL, NULL, NULL);
gst_query_set_seeking(query, fmt, FALSE, 0, -1);
ret = TRUE;
break;
}
default:
ret = GST_BASE_SINK_CLASS(parent_class)->query(parent, query);
break;
}//end switch query...
return ret;
}//end gst_vpphlsvideosink_query.
static GstStateChangeReturn gst_vpphlsvideosink_change_state(GstElement* element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
Gstvpphlsvideosink* vsink = GST_VPPHLSVIDEOSINK(element);
ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
}//end gst_vpphlsvideosink_change_state.