基于RK3588使用GStreamer拉取RTSP流并通过MPP解码器解码并播放

1:前言

        本文使用的是瑞芯微的RK3588开发板,编译我提供的程序需要使用SDK内置的交叉编译器。

更具官方文档若需要编译单个模块或者第三⽅应⽤,需对交叉编译环境进⾏配置。⽐如RK3588,其交叉编译⼯具位于
buildroot/output/rockchip_rk3588/host/usr ⽬录下,需要将⼯具的bin/⽬录和
aarch64-buildroot-linux-gnu/bin/ ⽬录设为环境变量,在顶层⽬录执⾏⾃动配置环境变量的脚本

source envsetup.sh

然后选择对应的交叉编译器。

配置完之后查看配置好了没:

cd buildroot/output/rockchip_rk3588/host/usr/bin
./aarch64-linux-gcc --version

我的打印信息为:

aarch64-linux-gcc.br_real (Buildroot linux-5.10-gen-rkr3.3) 11.3.0

2:程序实现:

#include <gst/gst.h>

/* 回调函数 */
static void on_pad_added(GstElement *element, GstPad *pad, gpointer data);

int main(int argc, char *argv[]) {
    GstElement *pipeline, *source, *depay, *parse, *decoder, *convert, *sink;
    GstBus *bus;
    GstMessage *msg;
    GstStateChangeReturn ret;

    /* 初始化 GStreamer库 */
    gst_init(&argc, &argv);

    /* 创建各个元素 */
    source = gst_element_factory_make("rtspsrc", "source");// RTSP 源
    depay = gst_element_factory_make("rtph264depay", "depay");//H.264 RTP 解封装
    parse = gst_element_factory_make("h264parse", "parse");// H.264 解析器
    decoder = gst_element_factory_make("mppvideodec", "decoder");// MPP 视频解码器
    convert = gst_element_factory_make("videoconvert", "convert");// 视频格式转换
    sink = gst_element_factory_make("autovideosink", "sink");// 自动选择视频输出

    if (!source || !depay || !parse || !decoder || !convert || !sink) {
        g_printerr("Not all elements could be created.\n");
        return -1;
    }

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new("test-pipeline");
    if (!pipeline) {
        g_printerr("无法创建管道\n");
        gst_object_unref(source);
        gst_object_unref(depay);
        gst_object_unref(parse);
        gst_object_unref(decoder);
        gst_object_unref(convert);
        gst_object_unref(sink);
        return -1;
    }

     /* 设置源的属性 */
    g_object_set(G_OBJECT(source), "location", "rtsp://192.168.220.10/stream/main", NULL);

     /* 构建管道 */
    gst_bin_add_many(GST_BIN(pipeline), source, depay, parse, decoder, convert, sink, NULL);

     /* 手动连接元素 */
    if (gst_element_link(depay, parse) != TRUE ||
        gst_element_link(parse, decoder) != TRUE ||
        gst_element_link(decoder, convert) != TRUE ||
        gst_element_link(convert, sink) != TRUE) {
        g_printerr("Elements could not be linked.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    /* 动态连接 rtspsrc 到 rtph264depay */
    g_signal_connect(source, "pad-added", G_CALLBACK(on_pad_added), depay);

    /* 开始播放 */
    ret = gst_element_set_state(pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE) {
        g_printerr("Unable to set the pipeline to the playing state.\n");
        gst_object_unref(pipeline);
        return -1;
    }

    /* 等待错误或 EOS(End-Of-Stream)消息 */
    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) {
        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("达到流末尾.\n");
                break;
            default:
                g_printerr("收到意外的消息.\n");
                break;
        }
        gst_message_unref(msg);
    }

    /* Free resources */
    gst_object_unref(bus);
    gst_element_set_state(pipeline, GST_STATE_NULL);
    gst_object_unref(pipeline);
    return 0;
}
/* 回调函数,用于动态链接 rtspsrc 到 rtph264depay */
static void on_pad_added(GstElement *element, GstPad *pad, gpointer data) {
    GstPad *sinkpad;
    GstElement *depay = (GstElement *)data;

    g_print("Received new pad '%s' from '%s':\n", GST_PAD_NAME(pad), GST_ELEMENT_NAME(element));

    /* If our depay is already linked, we have nothing to do here */
    sinkpad = gst_element_get_static_pad(depay, "sink");
    if (sinkpad && gst_pad_is_linked(sinkpad)) {
        g_print("We are already linked. Ignoring.\n");
        gst_object_unref(sinkpad);
        return;
    }

     /* 尝试链接 */
    if (sinkpad && gst_pad_link(pad, sinkpad) != GST_PAD_LINK_OK) {
        g_print("Type of the pad does not match type of sink pad.\n");
    } else {
        g_print("Link succeeded.\n");
    }

    /* 释放 sink pad */
    if (sinkpad) {
        gst_object_unref(sinkpad);
    }
}

使用SDK的交叉编译器编译,生成可执行文件,把可执行文件拖到开发板上面就可以实现使用GStreamer拉取RTSP流并通过MPP解码器解码并播放

### RK3588 GStreamer RTSP配置与实现 #### 使用GStreamerRTSP解码播放 对于RK3588平台而言,可以利用其内置的多媒体处理平台(MPP),通过GStreamer框架来高效地完成RTSP媒体数据的接收、解码以及最终的画面呈现工作。具体来说,在构建应用程序的过程中应当采用官方所提供的SDK配套工具链来进行源代码级别的交叉编译操作,从而确保所生成的目标二进制文件能够完美适配硬件环境特性[^1]。 当一切准备就绪之后,只需简单地将此程序传输至目标设备即可投入使用。下面给出了一段Python脚本用于展示如何借助`subprocess`模块调用命令行指令启动该程: ```python import subprocess def start_rtsp_playback(): command = [ "gst-launch-1.0", "rtspsrc location=your_rtsp_url ! decodebin ! autovideosink" ] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE) while True: output = process.stdout.readline() if output == '' and process.poll() is not None: break if output: print(output.strip()) ``` 请注意替换其中的`your_rtsp_url`为实际使用RTSP地址。 #### 实现基于摄像头输入的H.264编码后的RTSP推送服务端 另一方面,如果意图创建一个以本地摄像机作为视频源,经过硬件加速压缩成H.264格式再经由网络向外提供实时串的服务,则可以通过如下所示的一组GST管道定义语句达成目的。这里特别强调的是,整个过程同样依赖于Rockchip自家优化过的组件如`v4l2src`, `mpph264enc`等来充分发挥SoC内部资源的优势[^2]: ```bash sudo ./test-launch "( v4l2src device=/dev/video-camera0 ! videoconvert ! mpph264enc ! rtph264pay name=pay0 pt=96 )" ``` 上述命令中的路径参数需依据实际情况调整,比如摄像头节点名称可能会有所不同;同时也要确认已经正确安装部署好必要的软件包和服务守护进程(即`gst-rtsp-server`),这样才能保证整个系统的稳定性和可靠性。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值