ubuntu22.04下编译安装使用gstreamer指南_ubuntu下meson安装gstreamer-程序员宅基地

技术标签: GStreamer  github  git  ubuntu  

环境准备

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-devsudo 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 <[email protected]>");
 
	//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 <[email protected]>

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盘

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/szembed/article/details/130845218

智能推荐

arm-linux移植手记(四)基于busybox1.16.0的根文件系统制作_libcrypt.so.1 arm-程序员宅基地

文章浏览阅读8k次。参考《Mini2440_Linux移植开发实战指南.pdf》中的“使用 Busybox 构建文件系统”,还是有些问题,我自己的为主要原因。详细的文件系统的介绍与理解,自己搜索查看相关资料吧,我这里仅是记录操作步骤与遇到的问题。指南手册可以在我的资源中下载。环境介绍:busybox版本:busybox-1.16.0Linux平台:虚拟机下Fedora 11 自己原来编译的gcc在deb_libcrypt.so.1 arm

Linux命令:modprobe_modprobe -l-程序员宅基地

文章浏览阅读3k次。From:https://blog.csdn.net/good5101/article/details/39472291linux内核模块相关命令:lsmod,depmod,modprobe,modinfo,insmod,rmmod 使用说明https://www.cnblogs.com/jacklikedogs/p/4659249.htmlLinux下加载.ko驱动模块的两种方法:insm..._modprobe -l

QT修改QPushButton的背景色和文字颜色_qpushbutton 文字颜色-程序员宅基地

文章浏览阅读2.5w次,点赞21次,收藏129次。首先新建一个GUI应用打开界面文件,或者新建一个将pushbutton拖进去在属性栏找到stylesheet,点击旁边的省略号点击【添加颜色】,选择color修改文字颜色,选择background-color修改背景色。..._qpushbutton 文字颜色

HTTP和WSGI协议-程序员宅基地

文章浏览阅读425次。HTTP协议简介超文本传输协议(HyperText Transfer Protocol)是一种应用层协议。HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。在Web应用中,服务器把网页传给浏览器,实际上就是把网页的HTML代码发送给浏览器,让浏览器显示出来。而浏览器和服务器之间的传输协议是HTTP,所以:HTML是一种用..._http wsgi

js正则匹配所有大小写字母、数字、半角字符、中文_js正则匹配大写字母 数字 . - 空格 半角 并且以大写字母或者数字开头-程序员宅基地

文章浏览阅读3.3k次。需求如题。解决方法:/[a-zA-Z0-9^_\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F\u4e00-\u9fa5]+$/匹配除_的所有大小写字母、数字、半角字符、中文:/[a-zA-Z0-9^_\x21-\x2f\x3a-\x40\x5b-\x60\x7B-\x7F\u4e00-\u9fa5]+$/..._js正则匹配大写字母 数字 . - 空格 半角 并且以大写字母或者数字开头

DECA:基于单张静态图像,进行 3D 人脸建模_demo_teaser.py-程序员宅基地

文章浏览阅读2.7k次,点赞4次,收藏29次。内容概要:本文罗列了 3D 人脸建模常用的 3 大方法,以及基于静态图像进行人脸建模的 3 个方法。文末分享了一个 DECA 教程。原创:HyperAI超神经关键词:3D 人脸建模 计算机视觉 教程3D 建模是计算机视觉领域中的一个关键问题,其中 3D 人脸建模,在游戏、影视特效、VR 等领域应用广泛。但是由于人脸的复杂性、易变性, 建立逼真的 3D 人脸模型,成为众多研究者不得不面对的一大挑战。3D 人脸建模的三大常用方法通常情况下,3D 人脸建模的方法分为三种:软件建模、仪器采集与基于._demo_teaser.py

随便推点

Python 进阶特性集锦--列表推导式、装饰器、列表和字典解包_python 装饰器、集合、列表和集合-程序员宅基地

文章浏览阅读884次,点赞18次,收藏20次。Python中有很多常用的模块和语法糖,以下是其中的一些,以及配套的示例代码。_python 装饰器、集合、列表和集合

渗透学习-18- WEB 攻防-ASP 安全&MDB 下载植入&IIS 短文件名&写权限&解 析_asp mdb下载-程序员宅基地

文章浏览阅读270次。假如访问.mdb不能下载,那说明要么被设置了解析,亦或者数据库是 .asp/asa后缀的.如果是后者,那么访问数据库路径将会被asp执行,那么就想能否插入后门代码到数据库里,然后访问数据库.asp时这个后门岂不是就会被执行?于是找到可以留言的地方, 将asp后门代码编码后提交,后门便存储在数据库里,然后访问数据库路径,xxx.com/xxx/xxx.asp, 这个后门将被执行。找个脚本,可用来探测猜测网站目录、路径 比如 后台,数据库地址等等,只能探测前6位,剩下的自己去猜。为社么有些.mdb可下载?_asp mdb下载

Java 内部类原理解析_java 内部类 val$ this$ access$-程序员宅基地

文章浏览阅读1.1k次。Java 内部类在代码中是非常常见的,但是在Android系统里,常常会因为内部类的使用导致内存泄漏的问题,所以本文对内部类从原理上做一个比较详细的解析以及如何在使用内部类时该如何避免内存泄漏 内部类的种类Java的内部类分为四种:静态内部类、成员内部类、局部内部类和匿名内部类; 静态内部类静态内部类,顾名思义是一个静态的类,代码如下public class MainActivity exte_java 内部类 val$ this$ access$

20180507-A · Global Coffee Chains · ggplot2 usmap geom_map geom_point 地图 热图 美国地图 · R 语言数据可视化 案例 源码-程序员宅基地

文章浏览阅读496次。Tidy Tuesday 2018-05-07 的周数据可视化示例 TidyTuesday:Global Coffee Chains,主要利用了 ggplot2 包对数据进行可视化展示。标签:R; R语言; 数据可视化; ggplot2; 可视化脚本; Data Visualization

快手:短视频平台的崛起与未来展望_快手发展问题分析-程序员宅基地

文章浏览阅读921次,点赞20次,收藏23次。快手,作为一家全球领先的短视频平台,一直在不断创新和发展。本文将深入探讨快手的发展历程,分析公司面临的问题、重大公关危机、主要罚款项,详述业务内容、目前的研究方向和采用的技术,展望可能的应用场景和未来发展,同时提供相关链接以深入了解快手。_快手发展问题分析

matlab-线性代数 det 各阶主子式、余子式、代数余子式-程序员宅基地

文章浏览阅读1.2w次,点赞7次,收藏30次。2019独角兽企业重金招聘Python工程师标准>>> ..._计算矩阵的所有阶子式代码

推荐文章

热门文章

相关标签