当前位置: 首页 > news >正文

GStreamer —— 2.6、Windows下Qt加载GStreamer库后运行 - “教程6:媒体格式和Pad功能“(附:完整源码)

运行效果

在这里插入图片描述

简介

     上一个教程演示了GUI 工具包集成(gtk)。本教程介绍媒体格式和Pad功能。Pad Capabilities 是 GStreamer 的一个基本元素,尽管大多数它们不可见,因为框架会处理它们 自然而然。这个有点理论性的教程展示了:

          • 什么是 Pad 功能。

          • 如何检索它们。

          • 何时检索它们。

          • 为什么你需要了解它们。

     如前所述,Pads 允许信息进入和离开 一个元素。Pad 的功能(或简称 Caps),那么, 指定哪些类型的信息可以通过 Pad 传输。为 示例,“分辨率为 320x200 像素和 30 帧的 RGB 视频 per second“或”16 bits per sample audio, 5.1 channels at 44100 samples” 每秒“,甚至是 MP3 或 H264 等压缩格式。Pads 可以支持多种功能(例如,视频接收器可以 支持不同类型的 RGB 或 YUV 格式的视频)和功能可以是 指定为范围 (例如,音频接收器可以支持示例 速率为每秒 1 到 48000 个样本)。但是,实际的 从 Pad 到 Pad 传输的信息必须只有一个 Well Specify 类型。通过称为协商的过程,两个链接的 Pad 就 一个通用类型,因此 Pad 的 Capabilities 变得固定(它们只有一个类型并且不包含范围)。演练 下面的示例代码应该清楚地说明了这一切。为了将两个元素链接在一起,它们必须共享一个 common subset of Capabilities (否则它们不可能 相互理解)。这是 Capabilities 的主要目标。作为应用程序开发人员,您通常会通过链接 元素一起(如果使用 all-in-all 元素,则程度较小 喜欢 )。在这种情况下,您需要知道 Pad Caps(因为它们 都熟悉地引用了)的元素,或者至少知道什么 它们是 GStreamer 拒绝将两个元素与协商联系起来的时候 错误。

GStreamer相关运行库
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0/gst
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/glib-2.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0/include

LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gstreamer-1.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gobject-2.0.lib

完整源码
#include <gst/gst.h>

/* Functions below print the Capabilities in a human-friendly format */
static gboolean print_field (GQuark field, const GValue * value, gpointer pfx)
{
    gchar *str = gst_value_serialize (value);

    g_print ("%s  %15s: %s\n", (gchar *) pfx, g_quark_to_string (field), str);
    g_free (str);
    return TRUE;
}

static void print_caps (const GstCaps * caps, const gchar * pfx)
{
    guint i;

    g_return_if_fail (caps != NULL);

    if (gst_caps_is_any (caps))
    {
        g_print ("%sANY\n", pfx);
        return;
    }
    if (gst_caps_is_empty (caps))
    {
        g_print ("%sEMPTY\n", pfx);
        return;
    }

    for (i = 0; i < gst_caps_get_size (caps); i++)
    {
        GstStructure *structure = gst_caps_get_structure (caps, i);

        g_print ("%s%s\n", pfx, gst_structure_get_name (structure));
        gst_structure_foreach (structure, print_field, (gpointer) pfx);
    }
}

/* 打印有关pod模板的信息,包括其功能 */
static void print_pad_templates_information (GstElementFactory * factory)
{
    g_print ("Pad Templates for %s:\n", gst_element_factory_get_longname (factory));
    if (!gst_element_factory_get_num_pad_templates (factory)) { g_print ("  none\n"); return; }

    GstStaticPadTemplate *padtemplate;
    const GList *pads = gst_element_factory_get_static_pad_templates (factory);
    while (pads)
    {
        padtemplate = (GstStaticPadTemplate*)pads->data;
        pads = g_list_next (pads);

        if (padtemplate->direction == GST_PAD_SRC)
            g_print ("  SRC template: '%s'\n", padtemplate->name_template);
        else if (padtemplate->direction == GST_PAD_SINK)
            g_print ("  SINK template: '%s'\n", padtemplate->name_template);
        else
            g_print ("  UNKNOWN!!! template: '%s'\n", padtemplate->name_template);

        if (padtemplate->presence == GST_PAD_ALWAYS)
            g_print ("    Availability: Always\n");
        else if (padtemplate->presence == GST_PAD_SOMETIMES)
            g_print ("    Availability: Sometimes\n");
        else if (padtemplate->presence == GST_PAD_REQUEST)
            g_print ("    Availability: On request\n");
        else
            g_print ("    Availability: UNKNOWN!!!\n");

        if (padtemplate->static_caps.string)
        {
            GstCaps *caps;
            g_print ("    Capabilities:\n");
            caps = gst_static_caps_get (&padtemplate->static_caps);
            print_caps (caps, "      ");
            gst_caps_unref (caps);

        }

        g_print ("\n");
    }
}

/* 显示给定元素中请求pod的能力 */
static void print_pad_capabilities (GstElement *element, gchar *pad_name)
{
    /* 取回pad */
    GstPad *pad = gst_element_get_static_pad (element, pad_name);
    if (!pad) { g_printerr ("Could not retrieve pad '%s'\n", pad_name); return; }

    /* 获取当前在 pad 上配置的具有最后一个 GST_EVENT_CAPS 事件的功能。(如果协商尚未完成,则检索可接受的上限) */
    GstCaps *caps = gst_pad_get_current_caps (pad);
    if (!caps){caps = gst_pad_query_caps (pad, NULL);}

    /* 打印后释放 */
    g_print ("Caps for the %s pad:\n", pad_name);
    print_caps (caps, "      ");
    gst_caps_unref (caps);
    gst_object_unref (pad);
}

int main(int argc, char *argv[])
{
    /* 初始化GStreamer */
    gst_init (&argc, &argv);

    /* 创建元素工厂 */
    GstElementFactory *source_factory = gst_element_factory_find ("audiotestsrc");
    GstElementFactory *sink_factory = gst_element_factory_find ("autoaudiosink");
    if (!source_factory || !sink_factory) { g_printerr ("Not all element factories could be created.\n"); return -1; }

    /* 打印这些工厂的pod模板信息 */
    print_pad_templates_information (source_factory);
    print_pad_templates_information (sink_factory);

    /* 要求工厂实例化实际元素 */
    GstElement *source = gst_element_factory_create (source_factory, "source");
    GstElement *sink = gst_element_factory_create (sink_factory, "sink");

    /* 创建空管道 */
    GstElement *pipeline = gst_pipeline_new ("test-pipeline");
    if (!pipeline || !source || !sink) { g_printerr ("Not all elements could be created.\n"); return -1; }

    /* 构建管道 */
    gst_bin_add_many (GST_BIN (pipeline), source, sink, NULL);
    if (gst_element_link (source, sink) != TRUE) { g_printerr ("Elements could not be linked.\n"); gst_object_unref (pipeline); return -1; }

    /* 打印初始能力(处于NULL状态) */
    g_print ("In NULL state:\n");
    print_pad_capabilities (sink, (gchar *)"sink");

    /* 开始播放 */
    GstStateChangeReturn 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 (check the bus for error messages).\n"); }

    gboolean terminate = FALSE;
    GstMessage *msg;
    /* 等待错误、EOS或状态更改 */
    GstBus *bus = gst_element_get_bus (pipeline);
    do
    {
        // 等待获取符合条件的消息
        msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS | GST_MESSAGE_STATE_CHANGED));

        /* 解析消息 */
        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);
                terminate = TRUE; break;
            case GST_MESSAGE_EOS:
                g_print ("End-Of-Stream reached.\n");
                terminate = TRUE; break;
            case GST_MESSAGE_STATE_CHANGED:
                /* 我们只对来自管道的状态更改消息感兴趣 */
                if (GST_MESSAGE_SRC (msg) == GST_OBJECT (pipeline))
                {
                    GstState old_state, new_state, pending_state;
                    gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
                    g_print ("\nPipeline state changed from %s to %s:\n", gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
                    /* 打印sink元素的当前功能 */
                    print_pad_capabilities (sink, (gchar *)("sink"));
                }
                break;
            default:
                /* 通常不会运行到这里 */
                g_printerr ("Unexpected message received.\n"); break;
            }
            gst_message_unref (msg);
        }
    } while (!terminate);

    /* 释放资源 */
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
    gst_object_unref (source_factory);
    gst_object_unref (sink_factory);
    return 0;
}

关注

笔者 - jxd

相关文章:

  • 基于Spring Boot的多级缓存架构实现
  • C++学习(十四)(使用库)
  • JVM详解
  • C# 开发工具Visual Studio下载和安装
  • vue3中子组件获取父组件的name,父组件不做修改动作
  • JavaScript中的主要知识点
  • Windows 图形显示驱动开发-WDDM 3.2-GPU-P 设备上的实时迁移(一)
  • 【vscode】一键编译运行c/c++程序
  • 深度解析 slabtop:实时监控内核缓存的利器
  • 短分享-Flink图构建
  • python里调用外部控制台应用程序的方法~
  • 【人工智能学习之局部极小值与鞍点】
  • 测试用例详解
  • BetaFlight源码解读01
  • MacOS Big Sur 11 新机安装brew wget python3.12 exo
  • MySQL 中,SELECT ... FOR UPDATE
  • 游戏引擎学习第140天
  • 【C++】Class(1)
  • 虚拟机 | Ubuntu图形化系统: open-vm-tools安装失败以及实现文件拖放
  • 数据可视化大屏产品设计方案(附Axure源文件预览)
  • 美国前总统拜登确诊前列腺癌
  • 推开“房间”的门:一部“生命存在的舞台” 史
  • 浙江理工大学传播系原系主任刘曦逝世,年仅44岁
  • 昔日千亿房企祥生集团约2.03亿元债权被拍卖,起拍价8000万元
  • 跨越三十年友情,61岁余隆和60岁齐默尔曼在上海再度合作
  • 李公明︱一周书记:当前科学观中的盲点、危机与……人类命运