1

gstreamer 中是否有用于视频接收器的模板,就像插件元素一样?

我有一个非常简单的想法:一个初始化函数、渲染(显示)函数和 deinit 函数。而已。

4

2 回答 2

1

最好的“模板”是可用的源代码。从 -base 或 -good 获取一个简单的接收器,并将其用作起点。这也是了解 GStreamer 的好方法,了解编写良好的元素的行为方式。您想要的基类可能是 gstbasesink,因为有 gstbaseaudiosink这样的东西,但(还没有)gstbasevideosink。

于 2014-08-24T17:40:19.297 回答
0

我还寻找了一个基于 gstbasesink 的接收器“模板”,但一直找不到。我按照上面的建议从我称之为 vpphlsvideosink 的 fakesink 元素创建了一个,尽管它还不是专门的视频接收器。它除了向 std cout 发送一个用于渲染的 'r' 字符和一个用于事件的 'e' 字符外,什么都不做。这些是文件:

  1. gstvpphlsvideosink.cpp
#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);

  1. vpphlsvideosink.h
#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

  1. vpphlsvideosink.cpp
#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.
于 2021-06-02T12:16:32.873 回答