基于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解码器解码并播放

猜你喜欢

转载自blog.csdn.net/jcf5832/article/details/143255826