基于gstreamer的rtsp推送和转发
前段时间因为实验室项目要求,需要读取摄像头并推rtsp流,由于我们实验室不是做与之相关的工作,所以并没有什么参考资料或者学长去问,只能自己在网上瞎找,也是费了很大的劲儿才最终实现,不过也只是简单推流。
本教程系统为ubuntu16.04
一、配置gstreamer环境
安装gstreamer基础库
sudo apt-get install libgl1-mesa-dev
sudo apt-get install gstreamer1.0-libav
sudo apt-get install gstreamer1.0-plugins-bad
sudo apt-get install gstreamer1.0-plugins-base
sudo apt-get install gstreamer1.0-plugins-ugly
sudo apt-get install gstreamer1.0-plugins-good
装完之后最好在bachrc中加两句路径,不加的话有时候gstreamer不好用,读不到组件。
sudo gedit ~/.bachrc //打开bachrc文件
//在bachrc文件中加下边两句,我试过只加第二句也可以
export LD_LIBRARY_PATH=/usr/local/lib
export GST_PLUGIN_PATH=/usr/local/lib:/usr/lib/x86_64-linux-gnu/gstreamer-1.0
source ~/.bachrc //在终端输入,每次改完bachrc都要source一下
加完上边两句刚开始报错,不用管它,等一会儿就好啦
做完这些基本gstreamer就能用了,可以用下边命令试一下:
gst-launch-1.0 rtspsrc latency=20 location="rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov" ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
出现上边这个画面应该就配置好环境了
二、安装gstreamer-rtsp-server
git clone -b 1.8 https://github.com/GStreamer/gst-rtsp-server.git //下载源码
cd gst-rtsp-server //目录名可能不正确,自己注意点,就是刚刚下载的目录
./autogen.sh
sudo make
sudo make install
三、读取usb摄像头并推rtsp流
直接上源码:
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#define DEFAULT_RTSP_PORT "7551"
static char *port = (char *) DEFAULT_RTSP_PORT;
static GOptionEntry entries[] = {
{"port", 'p', 0, G_OPTION_ARG_STRING, &port,
"Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"},
{NULL}
};
int
main (int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory;
GOptionContext *optctx;
GError *error = NULL;
optctx = g_option_context_new ("<launch line> - Test RTSP Server, Launch\n\n"
"Example: \"( videotestsrc ! x264enc ! rtph264pay name=pay0 pt=96 )\"");
g_option_context_add_main_entries (optctx, entries, NULL);
g_option_context_add_group (optctx, gst_init_get_option_group ());
if (!g_option_context_parse (optctx, &argc, &argv, &error)) {
g_printerr ("Error parsing options: %s\n", error->message);
g_option_context_free (optctx);
g_clear_error (&error);
return -1;
}
g_option_context_free (optctx);
loop = g_main_loop_new (NULL, FALSE);
/* create a server instance */
server = gst_rtsp_server_new ();
g_object_set (server, "service", port, NULL);
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points (server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
factory = gst_rtsp_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory, argv[1]);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test", factory);
/* don't need the ref to the mapper anymore */
g_object_unref (mounts);
/* attach the server to the default maincontext */
gst_rtsp_server_attach (server, NULL);
/* start serving */
g_print ("stream ready at rtsp://127.0.0.1:%s/test\n", port);
g_main_loop_run (loop);
return 0;
}
编译指令:
gcc test-launch.c -o test $(pkg-config --cflags --libs gstreamer-rtsp-server-1.0 gstreamer-1.0)
源码其实就是刚刚下载编译的gst-rtsp-server文件夹下边的examples文件夹中的test-launch.c文件,我一点都没改,因为主要还是在终端执行的命令。
编译完成后,会生成一个名为test的可执行文件。在当前目录下打开终端,输入:
./test "( v4l2src device=/dev/video0 norm=255 ! video/x-raw-yuv,format='fourcc'YUY2,width=640,height=480 ! x264enc tune="zerolatency" threads=4 ! rtph264pay name=pay0 pt=96 )"
其中device=/dev/video0是你读取的摄像头编号,如果是笔记本,video0应该是笔记本自带摄像头。
再开一个终端,输入:
gst-launch-1.0 rtspsrc latency=20 location="rtsp://127.0.0.1:7551/test" ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
应该就能看到你自己了
四、转发rtsp
转发rtsp和读取usb摄像头的源码可以一模一样,因为最主要的还是在执行可执行文件时的命令,为了便于大家理解,我还是对上述源码做微小的改动:
#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#define DEFAULT_RTSP_PORT "8551"
static char *port = (char *) DEFAULT_RTSP_PORT;
static GOptionEntry entries[] = {
{"port", 'p', 0, G_OPTION_ARG_STRING, &port,
"Port to listen on (default: " DEFAULT_RTSP_PORT ")", "PORT"},
{NULL}
};
int
main (int argc, char *argv[])
{
GMainLoop *loop;
GstRTSPServer *server;
GstRTSPMountPoints *mounts;
GstRTSPMediaFactory *factory1;
GOptionContext *optctx;
GError *error = NULL;
optctx = g_option_context_new ("<launch line> - Test RTSP Server, Launch\n\n"
"Example: \"( videotestsrc ! x264enc ! rtph264pay name=pay0 pt=96 )\"");
g_option_context_add_main_entries (optctx, entries, NULL);
g_option_context_add_group (optctx, gst_init_get_option_group ());
if (!g_option_context_parse (optctx, &argc, &argv, &error)) {
g_printerr ("Error parsing options: %s\n", error->message);
g_option_context_free (optctx);
g_clear_error (&error);
return -1;
}
g_option_context_free (optctx);
loop = g_main_loop_new (NULL, FALSE);
/* create a server instance */
server = gst_rtsp_server_new ();
g_object_set (server, "service", port, NULL);
/* get the mount points for this server, every server has a default object
* that be used to map uri mount points to media factories */
mounts = gst_rtsp_server_get_mount_points (server);
/* make a media factory for a test stream. The default media factory can use
* gst-launch syntax to create pipelines.
* any launch line works as long as it contains elements named pay%d. Each
* element with pay%d names will be a stream */
*
factory1 = gst_rtsp_media_factory_new ();
gst_rtsp_media_factory_set_launch (factory1, argv[1]);
/* attach the test factory to the /test url */
gst_rtsp_mount_points_add_factory (mounts, "/test1", factory1);
/* don't need the ref to the mapper anymore */
g_object_unref (mounts);
/* attach the server to the default maincontext */
gst_rtsp_server_attach (server, NULL);
/* start serving */
g_print ("stream ready at rtsp://127.0.0.1:%s/test1\n", port);
g_main_loop_run (loop);
return 0;
}
我只是把端口号修改成8551,factory和test名字做了修改
编译指令同上,名字可以换一下:
gcc test-tra.c -o test-tra $(pkg-config --cflags --libs gstreamer-rtsp-server-1.0 gstreamer-1.0)
打开终端,执行:
./test-tra "( rtspsrc latency=20 location=rtsp://127.0.0.1:7551/test ! queue ! rtph264depay ! queue ! rtph264pay name=pay0 pt=96 )"
在执行这个命令之前要执行上边推usb摄像头的命令,但不要用gstreamer直接打开直推的码流,要用下边这个命令:
gst-launch-1.0 rtspsrc latency=20 location="rtsp://127.0.0.1:8551/test1" ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
也可以用公共的rtsp地址测试:
gst-launch-1.0 rtspsrc latency=20 location="rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov" ! rtph264depay ! h264parse ! avdec_h264 ! autovideosink
至此,基本读取usb摄像头推rtsp和转发就都实现了。