环境准备
ubuntu发行版22.04,该发行版内置Gstreamer1.20.1,gstreamer源码最新版本为1.20.3,差距不大
下载gstreamer源码
安装git
sudo apt install -y git
fuqiang@fuqiang-VivoBook:~/Workspace/gstreamer$ git --version
git version 2.34.1
下载gstreamer
git clone https://gitlab.freedesktop.org/gstreamer/gstreamer.git
git checkout --track -b 1.20 origin/1.20 --->1.20是目前最新版本的稳定分支,最新的小版本号为1.20.3
准备编译环境
安装meson
gstreamer1.60以后(不包含1.60),使用meson+ninja来构建
sudo apt install -y meson
fuqiang@fuqiang-VivoBook:~/Workspace/gstreamer$ meson --version
0.61.2
安装glib
gstreamer是基于glib-gobject来实现的
sudo apt install -y libglib2.0-dev
安装libsoup
sudo apt install -y libsoup2.4-dev
安装libunwind
1.下载包,http://download.savannah.nongnu.org/releases/libunwind/
2. ./configure
3.make
4.sudo make install
安装libdw
sudo apt install -y libdw-dev
安装g-ir-scanner
系统中搜索g-ir-scanner,然后将其copy到/usr/lib/下,给予执行权限
安装gobject-introspection-1.0
sudo apt-get install -y libgirepository1.0-dev
安装gtk+-3.0
sudo apt-get install -y libgtk-3-dev
安装hotdoc
sudo apt-get install -y libjson-glib-dev
sudo apt install -y cmake python3-pip
sudo pip3 install hotdoc
安装xgettext
系统中搜索xgettext,复制到/usr/bin/下,并给予执行权限
安装alsa
sudo apt-get install -y libasound2-dev
安装cdda_paranoia
sudo apt install -y cdparanoia
还不行将cdparanoia先注释掉
安装libvisual-0.4
sudo apt install libvisual-0.4-dev
安装xv
打开终端输入 sudo snap install xv --edge
,如果不能正常安装则按照提示输入 sudo snap install xv --edge --devmode
即可安装成功
安装SDL2
sudo apt-get install -y libsdl2-2.0 libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-gfx-dev
安装qt5
sudo apt-get install -y clang qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools qtcreator
sudo apt-get install -y qt5*
安装bz2
sudo apt install -y libbz2-dev
安装nasm/yasm
sudo apt install -y nasm yasm
安装gettext
sudo apt-get install -y gettext
编译安装
创建out目录
cd gstreamer
mkdir out
编译
meson out
cd out
ninja
sudo ninja install
特殊编译
meson --reconfigure -Dauto_features=enabled -Dgst-plugins-base:opus=disabled -Dgst-plugins-base:ogg=disabled out
异常处理
异常1
subprojects/gstreamer/gst/parse/meson.build:7:0: ERROR: Program 'flex win_flex' not found or not executable
解决方案:
sudo apt install -y flex
异常2
subprojects/gstreamer/gst/parse/meson.build:34:0: ERROR: Program 'bison win_bison' not found or not executable
解决方案:
sudo apt install -y bison
异常3
fuqiang@fuqiang-VivoBook:~/Workspace/gstreamer/gstreamer/out$ninja
ninja: error: 'subprojects/gst-plugins-bad/gst-libs/gst/transcoder/transcoder-enumtypes.h', needed by 'subprojects/gst-devtools/validate/tools/gst-validate-transcoding-1.0.p/gst-validate-transcoding.c.o', missing and no known rule to make it
解决方案:
meson --reconfigure
异常4
fuqiang@ubuntu:~/workspace/gstreamer$ meson out
The Meson build system
Source dir: /home/fuqiang/workspace/gstreamer
Build dir: /home/fuqiang/workspace/gstreamer/out
Build type: native build
meson.build:81:15: ERROR: lexer
['gstreamer', {'build-hotdoc': true}],
解决方案:更新meson版本,ubuntu18.04会出现这个问题,原因是其meson版本过低,使用pip3来安装meson
sudo pip3 install meson
如果版本还是低的话,可能/usr/bin有原始的meson,/usr/local/bin中是新安装的meson,将/usr/local/bin下面的copy到/usr/bin下面即可
异常5
msgfmt: command not found
解决方案:
sudo apt-get -y install gettext
测试命令
基本虚拟测试
gst-launch-1.0 videotestsrc ! autovideosink
gst-launch-1.0 -v videotestsrc pattern=ball name=left ! autovideosink
gst-launch-1.0 audiotestsrc ! autoaudiosink
黑洞fakesink
gst-launch-1.0 videotestsrc ! fakesink
音频播放
gst-launch-1.0 filesrc location='/home/fuqiang/音乐/audio.mp3' ! decodebin ! audioconvert ! audioresample ! autoaudiosink
视频播放
gst-launch-1.0 filesrc location='/home/fuqiang/视频/1080P.mov' ! decodebin ! autovideosink
分离MP4的音视频并分别播放
gst-launch-1.0 filesrc location='/home/fuqiang/视频/1080P.mov' ! qtdemux name=demux demux.audio_0 ! queue ! decodebin ! audioconvert ! audioresample ! autoaudiosink demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
gst-launch-1.0 filesrc location='/home/fuqiang/视频/1080P.mov' ! qtdemux name=demux demux.video_0 ! queue ! decodebin ! videoconvert ! videoscale ! autovideosink
视频播放并设置videobox
gst-launch-1.0 filesrc location='/home/fuqiang/视频/1080P.mov' ! qtdemux name=demux demux.video_0 ! decodebin ! videoscale ! video/x-raw,width=100,height=100 ! videobox border-alpha=0 top=-70 bottom=-70 right=-220 ! videoconvert ! autovideosink
摄像头采集播放(编码输出文件)
gst-launch-1.0 v4l2src ! videoconvert ! autovideosink
gst-launch-1.0 v4l2src ! videoconvert ! x264enc ! filesink location='/home/fuqiang/视频/xx.mp4'
gst-launch-1.0 v4l2src ! video/x-raw,width=1280,height=720 ! videoconvert ! openh264enc ! h264parse ! flvmux ! filesink location=aaa.flv
采集音频到文件
gst-launch-1.0 alsasrc ! audioresample ! audioconvert ! wavenc ! filesink location=/home/fuqiang/Videos/xx.wav
mp3转码ogg
gst-launch-1.0 filesrc location='/home/fuqiang/音乐/audio.mp3' ! decodebin ! audioconvert ! vorbisenc ! oggmux ! filesink location='/home/fuqiang/音乐/audio.ogg'
timeoverlay
gst-launch-1.0 videotestsrc ! timeoverlay ! xvimagesink
实现简单插件
实现框架
添加目录结构如下:
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer/subprojects/gst-plugins-bad/gst/myfilter$ tree
.
├── meson.build
├── myfilter.c
└── myfilter.h
实现meson.build:
myfilter_sources = [
'myfilter.c',
]
gstmyfilter = library('gstmyfilter',
myfilter_sources,
c_args : gst_plugins_bad_args,
include_directories : [configinc],
dependencies : [gstbase_dep, gsttag_dep],
install : true,
install_dir : plugins_install_dir,
)
pkgconfig.generate(gstmyfilter, install_dir : plugins_pkgconfig_install_dir)
plugins += [gstmyfilter]
添加编译相关配置:
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer/subprojects/gst-plugins-bad$ git diff
diff --git a/subprojects/gst-plugins-bad/gst/meson.build b/subprojects/gst-plugins-bad/gst/meson.build
index 9cf62db983..063fff3aef 100644
--- a/subprojects/gst-plugins-bad/gst/meson.build
+++ b/subprojects/gst-plugins-bad/gst/meson.build
@@ -12,7 +12,7 @@ foreach plugin : ['accurip', 'adpcmdec', 'adpcmenc', 'aiff', 'asfmux',
'segmentclip', 'siren', 'smooth', 'speed', 'subenc', 'switchbin',
'timecode', 'transcode', 'videofilters',
'videoframe_audiolevel', 'videoparsers', 'videosignal',
- 'vmnc', 'y4m']
+ 'vmnc', 'y4m', 'myfilter']
if not get_option(plugin).disabled()
subdir(plugin)
endif
diff --git a/subprojects/gst-plugins-bad/meson_options.txt b/subprojects/gst-plugins-bad/meson_options.txt
index b347dcb27b..320e4182c1 100644
--- a/subprojects/gst-plugins-bad/meson_options.txt
+++ b/subprojects/gst-plugins-bad/meson_options.txt
@@ -134,6 +134,7 @@ option('onnx', type : 'feature', value : 'auto', description : 'ONNX neural netw
option('openal', type : 'feature', value : 'auto', description : 'OpenAL plugin')
option('openexr', type : 'feature', value : 'auto', description : 'OpenEXR plugin')
option('openh264', type : 'feature', value : 'auto', description : 'H.264 video codec plugin')
+option('myfilter', type : 'feature', value : 'auto', description : 'test filter')
option('openjpeg', type : 'feature', value : 'auto', description : 'JPEG2000 image codec plugin')
option('openmpt', type : 'feature', value : 'auto', description : 'OpenMPT module music library plugin')
option('openni2', type : 'feature', value : 'auto', description : 'OpenNI2 library plugin')
实现h头文件
#pragma once //指示编译器只编译1次
#include <gst/gst.h>
#define VERSION "1.0"
#define PACKAGE "myfilter"
G_BEGIN_DECLS
//property id
enum{
PROP_0, //id = 0
PROP_SILENT, //1
//PROP_A, //2
//PROP_B //3
PROP_CNT //4
};
//instance struct, every instance has one
typedef struct _GstMyFilter
{
GstElement element; //父类
//pads
GstPad* srcpad; //src pad //发送端口
GstPad* sinkpad; //sink pad //接收端口
gboolean silent;
}GstMyFilter;
//class struct, all instance shared content
typedef struct _GstMyFilterClass
{
GstElementClass parent_class; //父类
}GstMyFilterClass;
/* Standard macros for defining types for this element. */
#define GST_TYPE_MY_FILTER (gst_my_filter_get_type())
#define GST_MY_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MY_FILTER,GstMyFilter))
#define GST_MY_FILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MY_FILTER,GstMyFilterClass))
#define GST_IS_MY_FILTER(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MY_FILTER))
#define GST_IS_MY_FILTER_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MY_FILTER))
/* Standard function returning type information. */
GType gst_my_filter_get_type(void);
G_END_DECLS
//GST_ELEMENT_REGISTER_DECLARE (my_filter)
实现c文件
#include "myfilter.h"
#include <gst/gstelement.h>
#include <gst/audio/audio-format.h>
#include <gst/gstpad.h>
#include <gst/gstplugin.h>
#include <gst/gstconfig.h>
#include <gobject/gparam.h>
G_DEFINE_TYPE(GstMyFilter, gst_my_filter, GST_TYPE_ELEMENT);
//GST_ELEMENT_REGISTER_DEFINE(my_filter, "my-filter", GST_RANK_NONE, GST_TYPE_MY_FILTER);
//pad模板准备,描述pad,之后会在_class_init中注册 sink_factory 和 src_factory,然后在_init中创建实例
//sink pad
static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE(
"sink", //short name of pad
GST_PAD_SINK, //pad direction - sink - input
GST_PAD_ALWAYS, //existence - always
GST_STATIC_CAPS("ANY") //support data type - any
);
static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE(
"src", //short name of pad
GST_PAD_SRC, //pad direction - src - output
GST_PAD_ALWAYS, //existence - always
GST_STATIC_CAPS("ANY") //support data type - any
);
static GstStaticPadTemplate sink_factory_1 = GST_STATIC_PAD_TEMPLATE(/sink_factory
"sink_%u",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS(
"audio/x-raw, "
"format = (string) " GST_AUDIO_NE(S16) ", "
"channels = (int) { 1, 2 }, "
"rate = (int) [ 8000, 96000 ]"
)
);
// ================ inner function start ================
// ================ inner function start ================
// ================ inner function start ================
static GstBuffer *gst_my_filter_process_data(GstMyFilter* filter,GstBuffer* buf)
{
//申请新内存
//处理buf
//获得新数据写入新内存
//返回
return NULL;
}
static gboolean gst_my_filter_stop_processing(GstMyFilter* filter)
{
//让当前element停止工作
return TRUE;
}
static gboolean gst_my_filter_allocate_memory(GstMyFilter* filter)
{
//申请必要的内存
//加载必要的run-time lib
return TRUE;
}
static gboolean gst_my_filter_free_memory(GstMyFilter* filter)
{
//释放内存
//卸载run-time lib
return TRUE;
}
// ================ inner function end ================
// ================ inner function end ================
// ================ inner function end ================
//(!!!) sink pad 常规数据处理函数
static GstFlowReturn gst_my_filter_chain(GstPad* pad/*pad reveive buffer*/ , GstObject *parent, GstBuffer *buf/*to be precessed*/)
{
GstMyFilter *filter = GST_MY_FILTER(parent); //可以理解为获取this指针
GstBuffer *outbuf;
outbuf = gst_my_filter_process_data(filter, buf);
gst_buffer_unref(buf);
if (!outbuf) {
/* something went wrong - signal an error */
GST_ELEMENT_ERROR(GST_ELEMENT(filter), STREAM, FAILED, (NULL), (NULL));
return GST_FLOW_ERROR;
}
return gst_pad_push(filter->srcpad, outbuf);
}
//(!!!) sink pad event数据处理
static gboolean gst_my_filter_event(GstPad* pad/*pad reveive event*/, GstObject *parent, GstEvent *event/*to be preocessed*/)
{
gboolean ret;
GstMyFilter *filter = GST_MY_FILTER(parent); //可以理解为获取this指针
switch (GST_EVENT_TYPE(event)) {
case GST_EVENT_CAPS:
ret = gst_pad_push_event(filter->srcpad, event); /* push the event downstream */
break;
case GST_EVENT_EOS:
gst_my_filter_stop_processing(filter);
ret = gst_pad_event_default(pad, parent, event); //目前只有GST_EVENT_CAPS有默认动作
break;
default:
ret = gst_pad_event_default(pad, parent, event); //目前只有GST_EVENT_CAPS有默认动作
break;
}
return ret;
}
//(!!!) query 对象处理
static gboolean gst_my_filter_src_query(GstPad* pad, GstObject* parent, GstQuery* query)
{
gboolean ret;
GstMyFilter *filter = GST_MY_FILTER(parent);
switch (GST_QUERY_TYPE(query)) {
case GST_QUERY_POSITION:
/* we should report the current position */
break;
case GST_QUERY_DURATION:
/* we should report the duration here */
break;
case GST_QUERY_CAPS:
/* we should report the supported caps here */
break;
default:
/* just call the default handler */
ret = gst_pad_query_default(pad, parent, query); //默认handler
break;
}
return ret;
}
//(!!!) state changed 处理函数
static GstStateChangeReturn gst_my_filter_change_state(GstElement *element, GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstMyFilter *filter = GST_MY_FILTER(element);
/*
Note that upwards (NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING) and downwards (PLAYING=>PAUSED, PAUSED=>READY, READY=>NULL) state changes
are handled in two separate blocks with the downwards state change handled only after we have chained up to the parent class's state change function.
This is necessary in order to safely handle concurrent access by multiple threads.
*/
//process upwards state change
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!gst_my_filter_allocate_memory(filter)) //申请资源
return GST_STATE_CHANGE_FAILURE;
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
//dosomething
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
//dosomething
break;
default:
break;
}
//唤起parent class 的 state change 处理函数
//ret = GST_ELEMENT_CLASS(parent_class)->change_state(element, transition);
ret = GST_ELEMENT_CLASS(GST_ELEMENT_GET_CLASS(element))->change_state(element, transition);
if (ret == GST_STATE_CHANGE_FAILURE)
return ret;
//process downwards state change
switch (transition) {
case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
//dosomething
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
//dosomething
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_my_filter_free_memory(filter);
break;
default:
break;
}
return ret;
}
//(!!!) property 读写处理函数
static void gst_my_filter_set_property(GObject* object, guint prop_id, const GValue * value, GParamSpec *pspec)
{
GstMyFilter* filter = GST_MY_FILTER(object);
switch (prop_id) {
case PROP_SILENT:
filter->silent = g_value_get_boolean(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
static void gst_my_filter_get_property(GObject* object, guint prop_id, GValue * value, GParamSpec *pspec)
{
GstMyFilter *filter = GST_MY_FILTER(object);
switch (prop_id) {
case PROP_SILENT:
g_value_set_boolean(value, filter->silent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
//类初始化函数(类构造函数)
static void gst_my_filter_class_init(GstMyFilterClass *klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS(klass); //for others
GObjectClass *object_class = G_OBJECT_CLASS(klass); //for property setter and getter,因为用到的是glib的功能,所以转为gobjectclass
//meta data
gst_element_class_set_static_metadata(element_class,
"obentul example plugin",
"Example/FirstExample",
"Shows the basic structure of a plugin",
"fuqiang <569463227@qq.com>");
//register state change funcution
element_class->change_state = gst_my_filter_change_state;
//register property setter and getter
object_class->set_property = gst_my_filter_set_property;
object_class->get_property = gst_my_filter_get_property;
//[todo]reigster properties
//silent
//g_object_class_install_property(
// object_class,
// PROP_SILENT,
// g_param_spec_boolean("property-name: silent", "description", "test propery,no specific function", FALSE, (GParamFlags)(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))
//);
//register pads
gst_element_class_add_pad_template(element_class,
gst_static_pad_template_get(&src_factory));
gst_element_class_add_pad_template(element_class,
gst_static_pad_template_get(&sink_factory));
}
//实例初始化函数(实例构造函数)
static void gst_my_filter_init(GstMyFilter *filter)
{
//instantiates and assigns pads
filter->srcpad = gst_pad_new_from_static_template(&src_factory,"src_%u"); //%u是不是代表可以有多个?
filter->sinkpad = gst_pad_new_from_static_template(&sink_factory, "sink_%u");
//add pads to element
gst_element_add_pad(GST_ELEMENT(filter),filter->srcpad);
gst_element_add_pad(GST_ELEMENT(filter), filter->sinkpad);
//set chain function for sink pad
gst_pad_set_chain_function(filter->sinkpad, gst_my_filter_chain);
//set event function
gst_pad_set_event_function(filter->sinkpad, gst_my_filter_event);
//set query function
gst_pad_set_query_function(filter->srcpad, gst_my_filter_src_query);
//所有属性当前暂不可用
filter->silent = FALSE;
}
//插件加载时被调用的函数
gboolean plugin_init(GstPlugin* myfilter)
{
return gst_element_register(myfilter, "myfilter", GST_RANK_MARGINAL, GST_TYPE_MY_FILTER);
}
//插件描述信息
GST_PLUGIN_DEFINE(
GST_VERSION_MAJOR,
GST_VERSION_MINOR,
myfilter,
"My filter plugin",
plugin_init,
VERSION,
"LGPL",
"GStreamer template Plug-ins",
"http://gstreamer.net/"
)
构建编译安装
meson --reconfigure -Dgst-plugins-bad:myfilter=enabled out
cd out
ninja
sudo ninja install
查看插件情况
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer/subprojects/gst-plugins-bad/gst/myfilter$ gst-inspect-1.0 myfilter
Factory Details:
Rank marginal (64)
Long-name obentul example plugin
Klass Example/FirstExample
Description Shows the basic structure of a plugin
Author obentul <ykun089@163.com>
Plugin Details:
Name myfilter
Description My filter plugin
Filename /usr/local/lib/x86_64-linux-gnu/gstreamer-1.0/libgstmyfilter.so
Version 1.0
License LGPL
Source module myfilter
Binary package GStreamer template Plug-ins
Origin URL http://gstreamer.net/
GObject
+----GInitiallyUnowned
+----GstObject
+----GstElement
+----GstMyFilter
Pad Templates:
SINK template: 'sink'
Availability: Always
Capabilities:
ANY
SRC template: 'src'
Availability: Always
Capabilities:
ANY
Element has no clocking capabilities.
Element has no URI handling capabilities.
Pads:
SRC: 'src_%u'
Pad Template: 'src'
SINK: 'sink_%u'
Pad Template: 'sink'
Element Properties:
name : The name of the object
flags: 可读, 可写, 0x2000
String. Default: "myfilter0"
parent : The parent of the object
flags: 可读, 可写, 0x2000
Object of type "GstObject
目前该插件没有做什么事情,无法正常使用
gst-launch-1.0 videotestsrc ! autovideosink //可以正常播放
gst-launch-1.0 videotestsrc ! myfilter ! autovideosink //无法正常播放
下面,我们将插件打通,让数据透传过去
代码调试手段
添加打印
#define GST_ERROR(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_ERROR, NULL, __VA_ARGS__)
#define GST_WARNING(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_WARNING, NULL, __VA_ARGS__)
#define GST_INFO(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_INFO, NULL, __VA_ARGS__)
#define GST_DEBUG(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_DEBUG, NULL, __VA_ARGS__)
#define GST_LOG(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_LOG, NULL, __VA_ARGS__)
#define GST_FIXME(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_FIXME, NULL, __VA_ARGS__)
#define GST_TRACE(...) GST_CAT_LEVEL_LOG (GST_CAT_DEFAULT, GST_LEVEL_TRACE, NULL, __VA_ARGS__)
gdb
确保core文件大小限制解除
fuqiang@fuqiang-VivoBook:/usr/lib/x86_64-linux-gnu$ ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
...
fuqiang@fuqiang-VivoBook:/usr/lib/x86_64-linux-gnu$ ulimit -c unlimited
fuqiang@fuqiang-VivoBook:/usr/lib/x86_64-linux-gnu$ ulimit -a
real-time non-blocking time (microseconds, -R) unlimited
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
...
确认core文件的位置
sudo service apport stop
cat /proc/sys/kernel/core_pattern
echo core > /proc/sys/kernel/core_pattern
制造崩溃
static void
gst_mydecoder_init (Gstmydecoder * filter)
{
GST_ERROR("gst_mydecoder_init");
char *str = NULL;
str[0] = 0;
filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
执行
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer$ gst-launch-1.0 --gst-debug=3 videotestsrc ! mydecoder ! autovideosink
(gst-launch-1.0:911980): GStreamer-CRITICAL **: 18:18:11.516: gst_debug_log_valist: assertion 'category != NULL' failed
0:00:00.016936571 911980 0x558ab0cca100 ERROR mydecoder gstmydecoder.c:123:gst_mydecoder_class_init: gst_mydecoder_class_init
0:00:00.016957593 911980 0x558ab0cca100 ERROR mydecoder gstmydecoder.c:158:gst_mydecoder_init: gst_mydecoder_init
Caught SIGSEGV
Spinning. Please run 'gdb gst-launch-1.0 911980' to continue debugging, Ctrl-C to quit, or Ctrl-\ to dump core
执行CTRL-\后生成core dump文件
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer$ ls -al
总用量 4380
drwxrwxr-x 13 fuqiang fuqiang 4096 7月 20 18:18 .
drwxrwxr-x 6 fuqiang fuqiang 4096 7月 19 14:58 ..
drwxrwxr-x 8 fuqiang fuqiang 4096 7月 18 08:57 ci
-rw------- 1 fuqiang fuqiang 4599808 7月 20 18:18 core.911980
drwxrwxr-x 5 fuqiang fuqiang 4096 7月 16 20:51 data
-rw-rw-r-- 1 fuqiang fuqiang 131 7月 18 08:57 .editorconfig
drwxrwxr-x 8 fuqiang fuqiang 4096 7月 20 16:44 .git
-rw-rw-r-- 1 fuqiang fuqiang 1064 7月 16 20:51 .gitignore
drwxrwxr-x 3 fuqiang fuqiang 4096 7月 16 20:51 .gitlab
...
gdb调试
fuqiang@fuqiang-VivoBook:~/workspace/gstreamer$ gdb gst-launch-1.0 core.911980
GNU gdb (Ubuntu 12.0.90-0ubuntu1) 12.0.90
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from gst-launch-1.0...
[New LWP 911980]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `gst-launch-1.0 --gst-debug=3 videotestsrc ! mydecoder ! autovideosink'.
Program terminated with signal SIGQUIT, Quit.
#0 0x00007fdda845b7fa in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=0x7ffeed177940, rem=0x7ffeed177930)
at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:78
78 ../sysdeps/unix/sysv/linux/clock_nanosleep.c: 没有那个文件或目录.
(gdb)
bt调出堆栈后可以查看问题所在
gst_mydecoder_init (filter=<optimized out>) at ../subprojects/gst-plugins-bad/gst/mydecoder/gstmydecoder.c:160
注意问题:
sudo service apport stop ,需要通过该命令关闭系统的服务
core的大小为0:1.ulimit修改 2.core必须生成在本地分区,不能在挂载分区,比如u盘