GStreamer 01 Hello World

发布于 2023-02-13  124 次阅读


一、总述

  本章以RK3568,OV13850为例。这是gst-launch-1.0的语法:

# 实时预览
gst-launch-1.0 v4l2src device=/dev/video0 !video/x-raw, format=NV12, width=640, height=480, framerate=30/1 ! autovideosink

# 采集H.264
gst-launch-1.0 v4l2src device=/dev/video0 num-buffers=100 !video/x-raw,format=NV12, width=640,height=480 ! tee name=t ! queue !mpph264enc !queue !h264parse !qtmux !filesink location=13850_h264.mp4 t. ! queue !autovideosink

# 播放视频
gst-launch-1.0 filesrc location=13850_h264.mp4 !qtdemux !queue !h264parse !mppvideodec !autovideosink

二、代码

#include <gstreamer-1.0/gst/gst.h>

int glibDemo(int argc, char** argv)
{
    GstElement *pipeline;
    GstBus *bus;
    GstMessage *msg;

    /* Initialize GStreamer */
    gst_init (&argc, &argv);

    /* Build the pipeline */
    pipeline = gst_parse_launch(
        "filesrc location=13850_h264.mp4 !qtdemux !queue !h264parse !mppvideodec !autovideosink",
        NULL
    );

    /* Start playing */
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    /* Wait until error or EOS */
    bus = gst_element_get_bus (pipeline);
    msg = gst_bus_timed_pop_filtered (
        bus, GST_CLOCK_TIME_NONE, 
        GST_MESSAGE_ERROR | GST_MESSAGE_EOS
    );

    /* See next tutorial for proper error message handling/parsing */
    if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
        g_error ("An error occurred! Re-run with the GST_DEBUG=*:WARN environment "
        "variable set for more details.");
    }

    /* Free resources */
    gst_message_unref (msg);
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
    return 0;
}

三、解释

  下面我们回顾上述的代码,并理解发生了什么:

3.1 初始化

GstElement *pipeline;
GstBus *bus;

这永远是写GStreamer的第一条命令。除其他事项外,gst_init()有如下作用:

  1. 初始化所有内部结构。
  2. 确保所有插件可用。
  3. 执行任何可能适用于GStreamer的命令行选项。
/* Initialize GStreamer */
gst_init (&argc, &argv);

/* Build the pipeline */

3.2 管线

  GStreamer是一个旨在处理多媒体流的框架。 媒体从“source”元素(生产者)向下传播到“sink”元素(消费者),通过一系列执行各种任务的中间元素。所有互连元素的集合称为“pipeline”。

  在GStreamer中,通常手动地组装各个元素来构建管道,但是,当管道足够简单并且不需要任何高级功能时,就可以采用快捷方式:gst_parse_launch()。这种方式将直接使用与gst-launch-1.0语法相同的方式来构建管道。

/* Build the pipeline */
pipeline = gst_parse_launch(
    "filesrc location=13850_h264.mp4 !qtdemux !queue !h264parse !mppvideodec !autovideosink",
    NULL
);

上述代码和下面的命令是等效的:

gst-launch-1.0 filesrc location=13850_h264.mp4 !qtdemux !queue !h264parse !mppvideodec !autovideosink

3.3 播放

  在上面我们已经构建了一个管道,通过命令行我们可以知道,我们为管线添加了一个本地的视频文件。但此时,除非我们手动的去播放它,否则管线本身并不会播放视频。

/* Start playing */
gst_element_set_state (pipeline, GST_STATE_PLAYING);

此时gst_element_set_state()将设置管线(实例中我们唯一的元素)状态设置为“PLAYING”,此时视频才被播放。这条命令将会一直等到流结束(EOS)或者遇到错误。

3.4 清理

  在应用程序结束之前,我们需要手动的进行一些清理工作:

/* Wait until error or EOS */
bus = gst_element_get_bus (pipeline);
msg = gst_bus_timed_pop_filtered (
    bus, GST_CLOCK_TIME_NONE, 
    GST_MESSAGE_ERROR | GST_MESSAGE_EOS
);

/* See next tutorial for proper error message handling/parsing */
if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
    g_error ("An error occurred! Re-run with the GST_DEBUG=*:WARN environment "
    "variable set for more details.");
}

/* Free resources */
gst_message_unref (msg);
gst_object_unref (bus);
gst_element_set_state (pipeline, GST_STATE_NULL);
gst_object_unref (pipeline);
  • gst_bus_timed_pop_filtered()返回一条消息,该消息使用gst_message_unref释放。
  • gst_element_get_bus()返回的总线则由gst_object_unref()释放。
  • 最后这是取消管线的引用,并释放它。

四、总结

  下面我们回顾一下文章的内容。

  1. 使用gst_init()初始化GStreamer。
  2. 使用gst_parse_launch()快速构建管线。
  3. 使用gst_element_set_state()设置管线的状态以播放视频。
  4. 清理与释放。