GStreamer---Basic tutorial 6: 媒体格式和衬垫 Capabilities

pads

Pads允许信息进出elements。Pad的Capabilities(简称为Caps)指定了Pad能够传递什么类型的信息。例如,“320x200分辨率,30FPS的RGB视频”,或是“16位音频样本,5.1通道,采样率44100Hz”,或者是mp3和h264这类的压缩格式。

Pads可以支持多种Capabilities(例如一个video sink可以支持不同格式的RGB/YUV视频)并且Capabilities的值可以是一个范围(例如一个audio sink能够支持从1hz到48000hz的采样率)。然而,真正在Pad之间传递的信息必须只有一种明确制定的类型。 通过一个称为“协商”的过程,两个连接的pad就一个公共类型达成一致,从而pad的capability固定下来(它们只有一种类型,不包含范围)。下面的例程讲向你清楚的展现这个协商的过程。

两个elements支持的Capabilities类型必须有交集它们才能连接,否则它们无法理解彼此传递的数据,这就是Capabilities的主要设计目的。
作为一个应用程序开发者,你经常需要通过连接elements来构建piepline,因此你需要了解你所使用的elements的Pad Caps,或者至少当GStreamer elements因为“协商”错误而连接失败能够知道它们具体是什么。

Pad templates

Pads从Pad Templates生成,Pad Templates指明了一个Pad所有可能的Capabilities。模版对于创建一个相似的Caps时很有用的,并且允许提前拒绝elements之间的连接:假如两个elements的Pad模版的Capabilities没有交集,就没有必要进行更深入的“协商”。

Pad模版可以视作“协商”过程的第一步,随着过程的发展,实际的Pads被实例化并且Pads的Capabilities也不断被完善固定下来(或者“协商“失败)。

Capabilities examples

SINK template: 'sink'
Availability: Always
Capabilities:
audio/x-raw
format: S16LE
rate: [ 1, 2147483647 ]
channels: [ 1, 2 ]
audio/x-raw
format: U8
rate: [ 1, 2147483647 ]
channels: [ 1, 2 ]

这是一个element的永久sink pad(暂时不讨论Availablility)。它支持2种媒体格式,都是音频的原始数据audio/x-raw-int,16位的小端序符号数和8位的无符号数。方括号表示一个范围,例如,频道channels的范围是1到2.

SRC template: 'src'
Availability: Always
Capabilities:
video/x-raw
width: [ 1, 2147483647 ]
height: [ 1, 2147483647 ]
framerate: [ 0/1, 2147483647/1 ]
format: { I420, NV12, NV21, YV12, YUY2, Y42B, Y444, YUV9, YVU9, Y41B, Y800, Y8, GREY, Y16 , UYVY, YVYU, IYU1, v308, AYUV, A420 }

video/x-raw表示这个source pad输出原始格式的视频。它支持一个很广的维数和帧率,一系列的YUV格式(用花括号列出了)。所有这些格式都显示不同的图像编码格式和子采样程度。

example

#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);
    }
}

/* Prints information about a Pad Template, including its Capabilities */
static void print_pad_templates_information(GstElementFactory* factory) {
    const GList* pads;
    GstStaticPadTemplate* padtemplate;

    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;
    }

    pads = gst_element_factory_get_static_pad_templates(factory);
    while (pads) {
        padtemplate = 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");
    }
}

/* Shows the CURRENT capabilities of the requested pad in the given element */
//显示给定元素中所请求 pad 的当前能力
static void print_pad_capabilities(GstElement* element, gchar* pad_name) {
    GstPad* pad = NULL;
    GstCaps* caps = NULL;

    /* Retrieve pad */
    //gst_element_get_static_pad()用于根据Pad name检索给定element的pad结构体
    pad = gst_element_get_static_pad(element, pad_name);
    if (!pad) {
        g_printerr("Could not retrieve pad '%s'\n", pad_name);
        return;
    }

    /* Retrieve negotiated caps (or acceptable caps if negotiation is not finished yet) */
    //获取这个pad当前的capabilities,可能是固定的也可能不是,这取决于当前“协商”过程的状态。
    //pad甚至可能还未生成capabilities,在这种情况下,我们调用gst_pad_query_caps()来获取一个当前可接受的Pad Capabilities
    caps = gst_pad_get_current_caps(pad);
    if (!caps)
        caps = gst_pad_query_caps(pad, NULL);

    /* Print and free */
    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[]) {
    GstElement* pipeline, * source, * sink;
    GstElementFactory* source_factory, * sink_factory;
    GstBus* bus;
    GstMessage* msg;
    GstStateChangeReturn ret;
    gboolean terminate = FALSE;

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

    /* Create the element factories */
    source_factory = gst_element_factory_find("audiotestsrc");
    sink_factory = gst_element_factory_find("autoaudiosink");
    if (!source_factory || !sink_factory) {
        g_printerr("Not all element factories could be created.\n");
        return -1;
    }

    /* Print information about the pad templates of these factories */
    print_pad_templates_information(source_factory);
    print_pad_templates_information(sink_factory);

    /* Ask the factories to instantiate actual elements */
    source = gst_element_factory_create(source_factory, "source");
    sink = gst_element_factory_create(sink_factory, "sink");

    /* Create the empty pipeline */
    pipeline = gst_pipeline_new("test-pipeline");

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

    /* Build the pipeline */
    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;
    }

    /* Print initial negotiated caps (in NULL state) */
    g_print("In NULL state:\n");
    print_pad_capabilities(sink, "sink");

    /* Start playing */
    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");
    }

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

        /* Parse message */
        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:
                /* We are only interested in state-changed messages from the pipeline */
                //在每次pipeline状态变化时打印autoaudiosink的sink pad

                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));
                    /* Print the current capabilities of the sink element */
                    print_pad_capabilities(sink, "sink");
                }
                break;
            default:
                /* We should not reach here because we only asked for ERRORs, EOS and STATE_CHANGED */
                g_printerr("Unexpected message received.\n");
                break;
            }
            gst_message_unref(msg);
        }
    } while (!terminate);

    /* Free resources */
    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;
}

http://www.niftyadmin.cn/n/1223306.html

相关文章

nvme装系统不能自引导_不得不知的最好用的装系统方式

UltraISO软碟通UltraISO软碟通是光盘映像文件制作/编辑/转换工具&#xff0c;可以编辑ISO文件,从ISO中提取文件和目录&#xff0c;从CD-ROM制作光盘映像或者将硬盘上的文件制作成ISO文件。使用方法很简单&#xff1a;首先准备好windows原版文件&#xff0c;然后打开UltraISO软碟…

实战DeviceIoControl 之三:制作磁盘镜像文件

本文转自:[url]http://blog.csdn.net/bhw98/archive/2003/05/27/19662.aspx[/url]Q DOS命令DISKCOPY给我很深的印象&#xff0c;现在也有许多“克隆”软件&#xff0c;可以对磁盘进行全盘复制。我想&#xff0c;要制作磁盘镜像文件&#xff0c;DeviceIoControl应该很有用武之地…

raid读写速度对比_「安防行业」RAID介绍

RAID是“Redundant Array of Independent Disk”的缩写&#xff0c;中文意思是独立冗余磁盘阵列&#xff0c;是指一种由多块硬盘驱动器按照一定的要求构成的冗余阵列&#xff0c;在操作系统中&#xff0c;这多块磁盘驱动器将作为一个独立的大型存储设备而出现。RAID按照不同的需…

GStreamer---Basic tutorial 7: Multithreading and Pad Availability

GStreamer自动处理多线程&#xff0c;但是在某些情况下&#xff0c;用户可能需要手动解耦线程。这篇教程将展示如何解耦线程以及完善关于Pad Availability的描述。更准确来说&#xff0c;这篇文档解释了&#xff1a; 如何为pipeline的某些部分创建新的线程。什么是Pad Availab…

23号的23个经典时刻 乔丹职业生涯完全大盘点

1998年总决赛第6场的最后一击&#xff0c;已经成为篮球历史里永恒最伟大的画面1.最后一击98年总决赛第6场 公牛客场对爵士乔丹从卡尔马龙手里断下皮球&#xff0c;在全场比赛还剩5.2秒时投中最后一击&#xff0c;使得整个三角洲中心鸦雀无声——芝加哥公牛队也捧得了他们在8年内…

宽带和流量是分开的吗_你所不知道的流量卡套路

最近《隐秘的角落》火遍全网&#xff0c;国际巨星章子怡更是发微博大赞可以抗衡英美剧。最近更流传金句&#xff1a;“一起爬山吗&#xff1f;”“我还有机会吗&#xff1f;”小编本想凑凑热闹去看一集&#xff0c;却深深地被精彩的故事情节、演员精湛的演技还有应景的BGM给吸引…

No EGL Display nvbufsurftransform: Could not get EGL display connection

No EGL Display nvbufsurftransform: Could not get EGL display connection unset DISPLAY rm ${HOME}/.cache/gstreamer-1.0/registry.*

关注程序员健康之——用脑过度多吃松子

http://www.cnblogs.com/shihao毫无疑问&#xff0c;我们程序员每天用脑是绝对过量的。虽然食疗只是辅助措施&#xff0c;但有句话说:不管什么事只要你坚持了就一定会有效果&#xff01;松子又名松子仁、海松子等&#xff0c;不仅是美味的食物&#xff0c;更是食疗佳品&#xf…