gstreamer采集usb摄像头,并推流udp/srt
【代码】gstreamer采集usb摄像头,并推流udp。
·
代码实现
#include <stdio.h>
#include <gst/gst.h>
int main(int argc, char* argv[])
{
GstElement* pipeline;
GstElement* v4l2;
GstElement* v_cvert;
GstElement* x264;
GstElement* h264parse;
GstElement* tsmux;
GstElement* mysink;
GstElement* udpsink;
GstElement* srtsink;
GstBus* bus;
GstMessage* msg;
g_print("this is for u!\n");
gst_init(&argc, &argv);
pipeline = gst_pipeline_new("test_pipeline");
v4l2 = gst_element_factory_make ("v4l2src", "sourceq");
v_cvert = gst_element_factory_make ("videoconvert", "v_cvertq");
x264 = gst_element_factory_make ("x264enc", "x264encq");
h264parse = gst_element_factory_make ("h264parse", "h264parseq");
tsmux = gst_element_factory_make ("mpegtsmux", "mpegtsmuxq");
mysink = gst_element_factory_make ("filesink", "filesinkq");
// 创建 udpsink 元素
udpsink = gst_element_factory_make("udpsink", "udpsink");
srtsink = gst_element_factory_make("srtsink", "srtsink");
// srt://127.0.0.1:8088?mode=listener
GstElement *capsfilter1 = gst_element_factory_make("capsfilter", "capsfilter1");
GstElement *capsfilter2 = gst_element_factory_make("capsfilter", "capsfilter2");
if (!pipeline || !v4l2 || !capsfilter1 ||!v_cvert ||!capsfilter1 || !x264 || !h264parse || !tsmux || !mysink || !srtsink) {
g_printerr ("Not all elements could be created.\n");
return -1;
}
g_object_set(udpsink, "host", "127.0.0.1", "port", 6015, NULL);
g_object_set(mysink, "location", "./test.ts", NULL);
g_object_set(srtsink, "uri", "srt://127.0.0.1:8088?mode=listener", NULL);
//这个函数返回值为void
gst_bin_add_many(GST_BIN(pipeline), v4l2, capsfilter1, v_cvert, capsfilter2, x264, h264parse, tsmux, srtsink, NULL);
//这个函数返回值为gboolean
gst_element_link_many(v4l2, capsfilter1, v_cvert, capsfilter2, x264, h264parse, tsmux, srtsink, NULL);
g_object_set(x264, "bitrate", 5000, "key-int-max", 15, "speed-preset", 2, "tune", 0x00000004, NULL);
GstStateChangeReturn ret_state = gst_element_set_state(pipeline, GST_STATE_PLAYING);
if(ret_state == GST_STATE_CHANGE_FAILURE)
{
g_printerr("Unable to set the pipeline to the playing state.\n");
gst_object_unref(pipeline);
return -1;
}
g_object_set(v4l2, "device", "/dev/video0", NULL);
// 配置第一个 capsfilter (YUY2)
GstCaps *src_caps = gst_caps_new_simple("video/x-raw",
"width", G_TYPE_INT, 1280,
"height", G_TYPE_INT, 720,
"framerate", GST_TYPE_FRACTION, 30, 1,
"format", G_TYPE_STRING, "YUY2",
NULL); //这种方法,如何分辨率不支持,不会自动降低配置,但会报错:sourceq: streaming stopped
//gst_element_link_filtered()这种方法,不会报错,也不会推流成功
g_object_set(G_OBJECT(capsfilter1), "caps", src_caps, NULL);
gst_caps_unref(src_caps);
// 配置第二个 capsfilter (I420)
GstCaps *convert_caps = gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, "I420",
NULL);//I420
g_object_set(G_OBJECT(capsfilter2), "caps", convert_caps, NULL);
gst_caps_unref(convert_caps);
bus = gst_element_get_bus(pipeline);
GstMessageType msg_types = (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE, msg_types);
if(msg != NULL)
{
GError* err;
gchar* debug_info;
switch(GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_ERROR:
gst_message_parse_error(msg, &err, &debug_info);
g_printerr("Error received from element %s: %s\n",
GST_OBJECT_NAME(msg->src), err->message);
g_printerr("Debugging information %s\n",
debug_info ? debug_info : "none");
g_clear_error(&err);
g_free(debug_info);
break;
case GST_MESSAGE_EOS:
g_print("End-Of-Stream reached.\n");
break;
default:
g_printerr("Unexpected message received.\n");
break;
}
gst_message_unref(msg);
}
gst_object_unref(bus);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
// tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15
}
/*
ffmpeg -video_size 640x480 -framerate 30 -pixel_format yuyv422 -i /dev/video0 -pix_fmt yuv420p -c:v h264 -g 15 -b:v 500000 -tune zerolatency -preset superfast -f mpegts udp://127.0.0.1:6015
以上ffmpeg与下面的gst方法延时相同都是1s左右
指定对摄像头采集参数,指定对编码器的输入参数,videoconvert是实际去作参数各种参数转换的element
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1,format=YUY2 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! filesink location=test.ts
让v4l2src和x264enc自动协商,有出错的风险
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! filesink location=test.ts
gcc Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
ffplay -fflags nobuffer 'udp://127.0.0.1:6015'
等价于
gcc Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
// 它会去找gstreamer-1.0.pc,在这个文件可以看到它其实只添加了一个库也就是 /lib/x86_64-linux-gnu/libgstreamer-1.0
pkg-config --cflags gstreamer-1.0
-pthread -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
pkg-config --libs gstreamer-1.0
-lgstreamer-1.0 -lgobject-2.0 -lglib-2.0
ldd CCap
linux-vdso.so.1 (0x00007ffe12536000)
libgstreamer-1.0.so.0 => /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 (0x000077706e928000)
libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x000077706e8c8000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x000077706e78e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000077706e400000)
libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x000077706e787000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000077706e69e000)
libffi.so.8 => /lib/x86_64-linux-gnu/libffi.so.8 (0x000077706e691000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x000077706e38a000)
/lib64/ld-linux-x86-64.so.2 (0x000077706ea92000)
或者:
gcc -v Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
*/
// gst-inspect-1.0 version 1.25.90
// srt
// gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1,format=YUY2 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! srtsink uri=srt://127.0.0.1:8088?mode=listener
// ffplay -fflags nobuffer srt://127.0.0.1:8088?mode=caller
// ffplay -f alsa sysdefault:CARD=U0x46d0x825
//audio
// gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1,format=YUY2 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux name=mux ! srtsink uri=srt://127.0.0.1:8088?mode=listener alsasrc device=sysdefault:CARD=U0x46d0x825 ! audio/x-raw,rate=44100,channels=2 ! audioconvert ! audioresample ! avenc_aac bitrate=128000 ! aacparse ! mux.
对应的makefile
# 使用动态获取 pkg-config 配置的版本(推荐)
# --------------------------------------------------
#CC = gcc
#CFLAGS = $(shell pkg-config --cflags gstreamer-1.0)
#LDLIBS = $(shell pkg-config --libs gstreamer-1.0)
#TARGET = CCap
#SRC = Capture-udp-2.c
# 静态配置版本(基于您提供的参数)
# --------------------------------------------------
CC = g++
CFLAGS = -pthread -I/usr/include/gstreamer-1.0 \
-I/usr/include/glib-2.0 \
-I/usr/lib/x86_64-linux-gnu/glib-2.0/include
LDLIBS = -lgstreamer-1.0 -lgobject-2.0 -lglib-2.0
TARGET = CCap
SRC = Capture-udp-2.cpp
all: $(TARGET)
$(TARGET): $(SRC)
$(CC) $(CFLAGS) $< -o $@ $(LDLIBS)
clean:
rm -f $(TARGET)
.PHONY: all clean
对应的CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(CCap)
# 设置C标准(如果需要)
set(CMAKE_C_STANDARD 11)
# 手动指定包含路径
include_directories(
/usr/include/gstreamer-1.0
/usr/include/glib-2.0
/usr/lib/x86_64-linux-gnu/glib-2.0/include
)
# 添加-pthread编译选项
# add_compile_options(-pthread)
# 创建可执行文件
add_executable(CCap Capture-udp-2.cpp)
# 手动链接库
target_link_libraries(CCap
pthread
gstreamer-1.0
gobject-2.0
glib-2.0
)
补充与命令实现:
/*
ffmpeg -video_size 640x480 -framerate 30 -pixel_format yuyv422 -i /dev/video0 -pix_fmt yuv420p -c:v h264 -g 15 -b:v 500000 -tune zerolatency -preset superfast -f mpegts udp://127.0.0.1:6015
以上ffmpeg与下面的gst方法延时相同都是1s左右
gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1,format=YUY2 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! filesink location=test.ts
video/x-raw,width=640,height=480,framerate=30/1,format=YUY2:指定摄像头的采集格式
videoconvert是实际去作参数各种参数转换的element
video/x-raw,format=I420:指定编码器的格式
bitrate=500:指定编码为500kbps
h264parse:解析编码好的264流,进行调整,使它符合标准的h264结构
mpegtsmux:复用器,流封装为ts流
//下面让v4l2src和x264enc自动协商,有出错的风险
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! filesink location=test.ts
gcc Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
ffplay -fflags nobuffer 'udp://127.0.0.1:6015'
等价于
gcc Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
// 它会去找gstreamer-1.0.pc,在这个文件可以看到它其实只添加了一个库也就是 /lib/x86_64-linux-gnu/libgstreamer-1.0
pkg-config --cflags gstreamer-1.0
-pthread -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include
pkg-config --libs gstreamer-1.0
-lgstreamer-1.0 -lgobject-2.0 -lglib-2.0
ldd CCap
linux-vdso.so.1 (0x00007ffe12536000)
libgstreamer-1.0.so.0 => /lib/x86_64-linux-gnu/libgstreamer-1.0.so.0 (0x000077706e928000)
libgobject-2.0.so.0 => /lib/x86_64-linux-gnu/libgobject-2.0.so.0 (0x000077706e8c8000)
libglib-2.0.so.0 => /lib/x86_64-linux-gnu/libglib-2.0.so.0 (0x000077706e78e000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000077706e400000)
libgmodule-2.0.so.0 => /lib/x86_64-linux-gnu/libgmodule-2.0.so.0 (0x000077706e787000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000077706e69e000)
libffi.so.8 => /lib/x86_64-linux-gnu/libffi.so.8 (0x000077706e691000)
libpcre.so.3 => /lib/x86_64-linux-gnu/libpcre.so.3 (0x000077706e38a000)
/lib64/ld-linux-x86-64.so.2 (0x000077706ea92000)
或者:
gcc -v Capture-udp-2.c -o CCap `pkg-config --cflags --libs gstreamer-1.0`
*/
再补充:
//推流本地usb摄像头,264编码,udp推流
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=2000 speed-preset=ultrafast ! h264parse ! rtph264pay ! udpsink host=127.0.0.1 port=6015
播放上个推流地址,注意上个使用的是rtp封装264,如果是补充1中的mpegtsmux,那么下面的播放将会报错,Received invalid RTP payload, dropping导致无法播放
gst-launch-1.0 udpsrc port=6015 address=127.0.0.1 ! application/x-rtp,media=video,encoding-name=H264,payload=96 ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink
srt:
// gst-launch-1.0 v4l2src device=/dev/video0 ! video/x-raw,width=640,height=480,framerate=30/1,format=YUY2 ! videoconvert ! video/x-raw,format=I420 ! x264enc tune=zerolatency bitrate=500 speed-preset=superfast key-int-max=15 ! h264parse ! mpegtsmux ! srtsink uri=srt://127.0.0.1:8088?mode=listener
// ffplay -fflags nobuffer srt://127.0.0.1:8088?mode=caller
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)