GStreamer 代码详解:连接 IP 网络摄像机

本文介绍使用GStreamer播放RTSP视频流的示例代码,包括解析和启动管道、设置状态、获取总线消息等步骤。通过playbin元素简化了视频播放流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面是本文讨论的代码。我试了一下,扩展名必须是 *.c,改成 *.cpp 的话无法编译。这个原因我回头再研究。

#include <gst/gst.h>
int main (int argc, char *argv[])
{
  GstElement *pipeline;
  GstBus *bus;
  GstMessage *msg;

  gst_init (&argc, &argv);

  pipeline = gst_parse_launch("playbin uri=rtsp://admin:root172@192.168.60.172:554/cam/realmonitor?channel=1&subtype=0", NULL);
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  bus = gst_element_get_bus (pipeline);
  msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

  if (msg != NULL)
    gst_message_unref (msg);
  gst_object_unref (bus);
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);

  return 0;
}

上面的程序可简化为下面伪代码的形式:

	pipeline = gst_parse_launch("playbin uri= ...");
	gst_element_set_state (pipeline, ...);
	bus = gst_element_get_bus (pipeline);
	msg = gst_bus_timed_pop_filtered (bus, ...);
  • pipeline
    GStreamer 能够帮助我们建立一个视频数据流架构,这个架构由 “元素” 构成。本例子建立的这个数据流只有一个元素,实现从数据源获取数据,并在窗口显示出来。
    变量 pipeline 就是这个唯一的元素,函数 gst_parse_launch(…) 则是创建这个元素最简单的方法。

  • playbin
    我们正在构建一个由一个名为playbin的元素组成的管道。playbin是一个特殊的元素,它充当(可产生视频流的端口)和(可接收视频流的端口),是一个完整的管道。在内部,它创建并连接所有必要的元素来播放您的媒体,因此您不必担心它。
    它不允许手动管道那样的控制粒度,但是,它仍然允许足够的定制以满足广泛的应用程序。

  • bus
    数据流中的元素之间的通讯,需要一种可靠的机制 ,GStreamer 采用了总线来解决这个问题。

### 边缘计算设备上的推流与拉流实现 #### 使用 GStreamer 和 OpenCV 进行推流和拉流 对于边缘计算设备而言,采用 GStreamer 结合 OpenCV 是一种高效的方式来进行视频的推流和拉流操作。这类组合特别适合于需要处理大量图像数据的应用场景,比如视频监控、直播等。 环境配置方面,在目标机器上安装必要的依赖库可以确保后续工作的顺利开展: ```bash sudo apt-get install gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-libav python3-opencv libgstrtspserver-1.0-dev ``` 通过上述命令可完成基本组件的部署[^2]。 #### 推流过程详解 当涉及到具体的推流逻辑时,可以通过 Python 编程语言来简化流程控制。下面是一个简单的例子展示如何利用 GStreamer 插件将本地摄像头捕获的画面推送出去: ```python import cv2 import gi gi.require_version('Gst', '1.0') from gi.repository import Gst, GObject def create_pipeline(): pipeline_str = ( "v4l2src device=/dev/video0 ! videoconvert ! x264enc speed-preset=ultrafast tune=zerolatency bitrate=500 key-int-max=15 ! " "rtph264pay config-interval=1 pt=96 ! udpsink host=localhost port=5000" ) return Gst.parse_launch(pipeline_str) if __name__ == "__main__": # 初始化GStreamer GObject.threads_init() Gst.init(None) pipe = create_pipeline() # 开始播放管道 pipe.set_state(Gst.State.PLAYING) try: loop = GObject.MainLoop() loop.run() except KeyboardInterrupt: pass # 清理资源 pipe.send_event(Gst.Event.new_eos()) pipe.set_state(Gst.State.NULL) ``` 这段代码展示了怎样创建一个基于 V4L2 (Video4Linux2) 的源节点读取来自 USB 摄像头的数据,并将其编码成 H.264 流格式再经由 RTP 协议发送给指定 IP 地址的服务端口。 #### 拉流过程说明 同样地,如果想要接收远程服务器传来的 RTSP 或者其他类型的媒体流,则只需要调整相应的 GStreamer 管道定义即可。这里给出一段用于接收并显示网络摄像机传输过来画面的例子: ```python import cv2 import numpy as np import gi gi.require_version('Gst', '1.0') from gi.repository import Gst, GLib def decode_stream(sample): buf = sample.get_buffer() caps_structure = sample.get_caps().get_structure(0) height = caps_structure.get_value('height') width = caps_structure.get_value('width') arr = np.ndarray( shape=(height, width, 3), dtype=np.uint8, buffer=buf.extract_dup(0, buf.get_size())) img_bgr = cv2.cvtColor(arr, cv2.COLOR_RGB2BGR) cv2.imshow('Stream', img_bgr) cv2.waitKey(1) def main(): GSTREAMER_PIPELINE = f'rtspsrc location=rtsp://<your_rtsp_url> latency=0 ! rtph264depay ! h264parse ! avdec_h264 ! videoconvert ! appsink name=sink' cap = cv2.VideoCapture(GSTREAMER_PIPELINE, cv2.CAP_GSTREAMER) while True: ret, frame = cap.read() if not ret: break window_title = "Media Stream" cv2.namedWindow(window_title, cv2.WINDOW_AUTOSIZE) cv2.imshow(window_title, frame) keyCode = cv2.waitKey(30) & 0xFF if keyCode == ord('q') or keyCode == 27: # ESCAPE break cap.release() cv2.destroyAllWindows() if __name__ == '__main__': main() ``` 此脚本会尝试连接到特定 URL 提供的 RTSP 数据源,并持续更新窗口内的预览内容直到用户主动终止程序运行。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

许野平

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值