gstreamer实现sink插件的代码,及无法结束的问题

简介: gstreamer实现sink插件的代码,及无法结束的问题

同事写了一个 gstreamer插件,去掉显示之后,整个流不运行。吾视之,看不出问题。猜测是插件类型不对,于是改写了一个sink插件,试之,流运行了。然后,有一个问题没有解决:


如果是播放文件,文件结束后,无法结束(即使得GstBus收到GST_MESSAGE_EOS消息)。


虽然有此严重问题,整个系统运行起来了。这个问题以后看看怎么解决。这里把代码共享出来,希望能给朋友们们带来文件。


  • 头文件
#ifndef __GH_GSTSINK_H__
#define __GH_GSTSINK_H__
#include <gst/base/gstbasesink.h>
#include <gst/video/video.h>
#define GH_GSTSINK_NAME "gh_gstsink"
/* Package and library details required for plugin_init */
#define PACKAGE         GH_GSTSINK_NAME
#define VERSION         "1.0"
#define LICENSE         "Proprietary"
#define DESCRIPTION     "wuxi sink"
#define BINARY_PACKAGE  "wuxi sink"
#define URL             "http://wuxi.com/"
G_BEGIN_DECLS
/* Standard boilerplate stuff */
typedef struct _GhGstSink GhGstSink;
typedef struct _GhGstSinkClass GhGstSinkClass;
/* Standard boilerplate stuff */
#define GST_TYPE_GHGSTSINK            (gh_gstsink_get_type())
#define GST_GHGSTSINK(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GHGSTSINK,GhGstSink))
#define GST_GHGSTSINK_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GHGSTSINK,GhGstSinkClass))
#define GST_GHGSTSINK_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_GHGSTSINK, GhGstSinkClass))
#define GST_IS_GHGSTSINK(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GHGSTSINK))
#define GST_IS_GHGSTSINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GHGSTSINK))
#define GST_GHGSTSINK_CAST(obj)       ((GhGstSink *)(obj))
struct _GhGstSink
{
  GstBaseSink base_trans;
  //when i received a eos, how to end ? 
  int isEOS;
};
// Boiler plate stuff
struct _GhGstSinkClass
{
  GstBaseSinkClass parent_class;
  //gint (*eos)(GhGstSink *sink);
  //gint (*signal_action)(GhGstSink *sink);
};
GType gh_gst_sink_get_type (void);
G_END_DECLS
#endif /* __GH_GSTSINK_H__ */
  • 代码
#include <string.h>
#include <string>
#include <fstream>
#include "gh_kit.h"
#include "gh_gstsink.h"
GST_DEBUG_CATEGORY_STATIC (gh_gstsink_debug);
#define GST_CAT_DEFAULT gh_gstsink_debug
/* Enum to identify properties */
enum
{
  PROP_0,
  PROP_UNIQUE_ID
};
/* Default values for properties */
#define DEFAULT_UNIQUE_ID     15
#define DEFAULT_PROCESSING_WIDTH  640
#define DEFAULT_PROCESSING_HEIGHT   480
#define DEFAULT_PROCESS_FULL_FRAME  TRUE
#define DEFAULT_GPU_ID      0
static GstStaticPadTemplate gh_gstsink_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("WUXI"));
static GstStaticPadTemplate gh_gstsink_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("WUXI"));
/* Define our element type. Standard GObject/GStreamer boilerplate stuff */
#define gh_gstsink_parent_class parent_class
G_DEFINE_TYPE (GhGstSink, gh_gstsink, GST_TYPE_BASE_SINK);
static void gh_gstsink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
static void gh_gstsink_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
static gboolean gh_gstsink_start (   GstBaseSink * basesink);
static gboolean gh_gstsink_stop (    GstBaseSink * basesink);
/**
GstEvent *gst_event_new_eos (void);
Create a new EOS event. The eos event can only travel downstream synchronized with the buffer flow. Elements that receive the EOS event on a pad can return GST_FLOW_EOS as a GstFlowReturn when data after the EOS event arrives.
The EOS event will travel down to the sink elements in the pipeline which will then post the GST_MESSAGE_EOS on the bus after they have finished playing any buffered data.
When all sinks have posted an EOS message, an EOS message is forwarded to the application.
The EOS event itself will not cause any state transitions of the pipeline.
Events are usually created with gst_event_new_*() which takes event-type specific parameters as arguments. To send an event application will usually use gst_element_send_event() and elements will use gst_pad_send_event() or gst_pad_push_event(). The event should be unreffed with gst_event_unref() if it has not been sent.
gst_event_type_get_flags(), GST_EVENT_IS_UPSTREAM, GST_EVENT_IS_DOWNSTREAM, and GST_EVENT_IS_SERIALIZED. 
gst_collect_pads_event
*/
//所有sinks发出了EOS消息,EOS就会转发给应用。我这里发出了,为什么还没结束?
//GST_MESSAGE_EOS
static gboolean gh_gstsink_event(GstBaseSink *sink, GstEvent *event)
{
    GstElement* element = (GstElement*)sink;
    GhGstSink*  ghsink  = (GhGstSink*) sink;
    switch(event-> type)
    {
        case GST_EVENT_EOS:
            //GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
            //parent_class->change_state(element, transition);
            GH_LOG_TEXT("GST_EVENT_EOS");
            gst_element_set_state(element, GST_STATE_NULL);
            //gst_event_new_eos();
            //gst_send_event(
            ghsink->isEOS = 1;
            gst_element_send_event(element, event);
            gst_pad_send_event ((GstPad*)element, event);
            return TRUE;
        case GST_EVENT_FLUSH_START:
        case GST_EVENT_FLUSH_STOP:
        default:
            break;
    }
    return TRUE;
}
static GstFlowReturn gh_gstsink_render(GstBaseSink *sink, GstBuffer *buffer)
{
    GhGstSink*  ghsink  = (GhGstSink*) sink;
    return ghsink->isEOS ? GST_FLOW_EOS : GST_FLOW_OK;
}
static GstStateChangeReturn gh_gstsink_change_state(GstElement* element, GstStateChange transition)
{
  GstElementClass *oclass;
  GstStateChangeReturn result = GST_STATE_CHANGE_SUCCESS;
  GhGstSink*  ghsink  = (GhGstSink*) element;
  g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_CHANGE_FAILURE);
  oclass = GST_ELEMENT_GET_CLASS (element);
  if (oclass->set_state && ghsink->isEOS)
  {
     (oclass->set_state) (element, GST_STATE_NULL);
  }
  return result;
}
/* Install properties, set sink and src pad capabilities, override the required
 * functions of the base class, These are common to all instances of the
 * element.
 */
static void gh_gstsink_class_init (GhGstSinkClass * klass)
{
  GObjectClass     *gobject_class;
  GstElementClass  *gstelement_class;
  GstBaseSinkClass *gstbasesink_class;
  gobject_class     = (GObjectClass *) klass;
  gstelement_class  = (GstElementClass *) klass;
  gstbasesink_class = (GstBaseSinkClass *) klass;
  /* Overide base class functions */
  gobject_class->set_property     = GST_DEBUG_FUNCPTR (gh_gstsink_set_property);
  gobject_class->get_property     = GST_DEBUG_FUNCPTR (gh_gstsink_get_property);
  gstbasesink_class->render       = GST_DEBUG_FUNCPTR (gh_gstsink_render);
  gstbasesink_class->start        = GST_DEBUG_FUNCPTR (gh_gstsink_start);
  gstbasesink_class->stop         = GST_DEBUG_FUNCPTR (gh_gstsink_stop);
  gstbasesink_class->event        = GST_DEBUG_FUNCPTR (gh_gstsink_event);
  //gstelement_class->change_state  = GST_DEBUG_FUNCPTR (gh_gstsink_change_state);
  //klass->eos                      = gh_gstsink_eos_cb;
  //guint eossignal_id = 0;
  //eossignal_id = g_signal_new ("eos", G_TYPE_FROM_CLASS(klass),
  //        G_SIGNAL_RUN_LAST,
  //        G_STRUCT_OFFSET (GhGstSinkClass, eos), NULL, NULL, NULL, G_TYPE_INT, 0, G_TYPE_NONE);
  //klass->signal_action  = gh_gstsink_callback;
  //eossignal_id = g_signal_new ("act", G_TYPE_FROM_CLASS (klass),
  //        G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
  //        G_STRUCT_OFFSET (GhGstSinkClass, act), NULL, NULL, NULL, G_TYPE_INT, 0, G_TYPE_NONE);
  /* Install properties */
  g_object_class_install_property (gobject_class, PROP_UNIQUE_ID,
      g_param_spec_uint ("unique-id",
          "Unique ID",
          "Unique ID for the element. Can be used to identify output of the element", 0, G_MAXUINT, DEFAULT_UNIQUE_ID, (GParamFlags)
          (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
  /* Set sink and src pad capabilities */
  //gst_element_class_add_pad_template (gstelement_class,
  //    gst_static_pad_template_get (&gh_gstsink_src_template));
  gst_element_class_add_pad_template (gstelement_class,
      gst_static_pad_template_get (&gh_gstsink_sink_template));
  /* Set metadata describing the element */
  gst_element_class_set_details_simple (gstelement_class,
      "GhGstSink plugin",
      "GhGstSink Plugin",
      "wuxi data sink",
      URL
      URL);
}
static void gh_gstsink_init (GhGstSink * ghsink)
{
   ghsink->isEOS = 0;
}
/* Function called when a property of the element is set. Standard boilerplate.
 */
static void gh_gstsink_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GhGstSink *ghsink = GST_GHGSTSINK (object);
  switch (prop_id)
  {
    case PROP_UNIQUE_ID:
      ghsink->unique_id = g_value_get_uint (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
/* Function called when a property of the element is requested. Standard
 * boilerplate.
 */
static void gh_gstsink_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GhGstSink *ghsink = GST_GHGSTSINK (object);
  switch (prop_id)
  {
    case PROP_UNIQUE_ID:
      g_value_set_uint (value, ghsink->unique_id);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
/**
 * Initialize all resources and start the output thread
 */
static gboolean gh_gstsink_start (GstBaseSink * basesink)
{
  GH_LOG_HERE();
  return TRUE;
}
/**
 * Stop the output thread and free up all the resources
 */
static gboolean gh_gstsink_stop (GstBaseSink * basesink)
{
  GH_LOG_HERE();
  return TRUE;
}
/**
 * Boiler plate for registering a plugin and an element.
 */
static gboolean ghsink_plugin_init (GstPlugin * plugin)
{
  GST_DEBUG_CATEGORY_INIT (gh_gstsink_debug, GH_GSTSINK_NAME, 0,
      "ghgstsink plugin");
  return gst_element_register (plugin, GH_GSTSINK_NAME, GST_RANK_PRIMARY,
      GST_TYPE_GHGSTSINK);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    ghsink,
    DESCRIPTION, ghsink_plugin_init, VERSION, LICENSE, BINARY_PACKAGE, URL)
  GST_TYPE_GHGSTSINK);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
    GST_VERSION_MINOR,
    ghsink,
    DESCRIPTION, ghsink_plugin_init, VERSION, LICENSE, BINARY_PACKAGE, URL)
目录
相关文章
|
JSON Java Linux
07-PDI(Kettle)源码编译8.2.0.0.R版本
文章目录 07-PDI(Kettle)源码编译8.2.0.0.R版本 1.安装PDI8.2.0.0.R的parent工程到本地 1.1配置Maven的settings.xml文件 1.2安装PDI源码依赖的parent工程到本地仓库
07-PDI(Kettle)源码编译8.2.0.0.R版本
|
DataX 数据格式 Java
DataX插件编写指南
DataX 是阿里巴巴集团内被广泛使用的离线数据同步工具/平台,实现包括 MySQL、Oracle、HDFS、Hive、OceanBase、HBase、OTS、ODPS 等各种异构数据源之间高效的数据同步功能。DataX采用了框架 + 插件 的模式,目前已开源,代码托管在github。
13126 1
Jmeter之插件管理 Installing Plugins的安装简介
Jmeter之Installing Plugins插件管理,已安装、可安装、可更新的插件安装管理一目了然,十分方便。。。
198 0
Jmeter之插件管理 Installing Plugins的安装简介
|
编解码
gstreamer之RTSP Server编译及注意事项
gstreamer之RTSP Server编译及注意事项
382 0
|
Java API Maven
Gradle基础|自定义插件并上传到JitPack
每一个使用 Gradle 的同学,肯定都听过或者写过插件,因为其本身并不难,但碍于现在网上的文章千篇一律,大部分都比较老,新同学一上手反而是和我一样,花了大把时间在最基础的第一步如何写一个简单demo上。再者如果大家使用 AndroidStudio BumBlebee 去创建项目,那对照网上教程差别更大,甚是花费时间,而本篇就是帮你省掉这些时间。 本篇主要概括创建插件的三种方式,并如何上传到 JitPack 中。
158 0
Gradle基础|自定义插件并上传到JitPack
|
消息中间件 数据采集 Java
Lua集成kafka第三方插件代码介绍|学习笔记
快速学习Lua集成kafka第三方插件代码介绍
105 0
Lua集成kafka第三方插件代码介绍|学习笔记
|
分布式计算 Hadoop Android开发
编写MapReduce前置插件Hadoop-Eclipse-Plugin 安装
编写MapReduce前置插件Hadoop-Eclipse-Plugin 安装
144 0
编写MapReduce前置插件Hadoop-Eclipse-Plugin 安装
|
编解码 vr&ar 计算机视觉
ffmpeg工具的简单使用
ffmpeg工具的使用
135 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
471 0
【FFmpeg】ffmpeg 命令查询一 ( 版本 | 编译配置 | 复用格式 | 编解码器 )(六)
|
Java 编译器 Maven
【Android Protobuf 序列化】Protobuf 使用 ( protobuf-gradle-plugin 插件简介 | Android Studio 中配置插件 | AS 中编译源文件 )
【Android Protobuf 序列化】Protobuf 使用 ( protobuf-gradle-plugin 插件简介 | Android Studio 中配置插件 | AS 中编译源文件 )
526 0
【Android Protobuf 序列化】Protobuf 使用 ( protobuf-gradle-plugin 插件简介 | Android Studio 中配置插件 | AS 中编译源文件 )