gstreamer基础教程3-Dynamic pipelines

GStreamer 基础教程三: 动态管道 目标 我们可以在应用程序开始时定义整体管道,也可以在有足够信息时“动态”构建管道。 这篇教程的目标是搞清楚如下问题: 如何在链接元件时获得更精细的控制? 如何收到感兴趣事件的通知,并及时反应? 元件可能处于的哪些不同的状态? 介绍 这篇教程中的管道在设置为 “Playing” 状态之前并未完全构建好。 这没问题。如果我们不采取进一步的行动,数据将到达管道的尽头,管道将会产生一个错误消息并停止。... 阅读详情

索引:https://blog.youkuaiyun.com/knowledgebao/article/details/84621238

Goal

目标是动态创建管道,包括组件连接、消息及时获取以及组件的状态转换。

This tutorial shows the rest of the basic concepts required to use GStreamer, which allow building the pipeline "on the fly", as information becomes available, instead of having a monolithic(单一的) pipeline defined at the beginning of your application.

After this tutorial, you will have the necessary knowledge to start the Playback tutorials. The points reviewed here will be:

  • How to attain finer control when linking elements.

  • How to be notified of interesting events so you can react(反应) in time.

  • The various states in which an element can be.

Introduction

这里主要介绍衬垫(pad)的概念。source element只有source pad,sink element只有sink pad,filter element二者兼有。

As you are about to see, the pipeline in this tutorial is not completely built before it is set to the playing state. This is OK. If we did not take further action, data would reach the end of the pipeline and the pipeline would produce an error message and stop. But we are going to take further action...

In this example we are opening a file which is multiplexed (or muxed), this is, audio and video are stored together inside a container file. The elements responsible for opening such containers are called demuxers, and some examples of container formats are Matroska (MKV), Quick Time (QT, MOV), Ogg, or Advanced Systems Format (ASF, WMV, WMA).

If a container embeds multiple streams (one video and two audio tracks, for example), the demuxer will separate them and expose them through different output ports. In this way, different branches can be created in the pipeline, dealing with different types of data.

The ports through which GStreamer elements communicate with each other are called pads(衬垫) (GstPad). There exists sink pads, through which data enters an element, and source pads, through which data exits an element. It follows naturally that source elements only contain source pads, sink elements only contain sink pads, and filter elements contain both.

  

Figure 1. GStreamer elements with their pads.

A demuxer contains one sink pad, through which the muxed data arrives, and multiple source pads, one for each stream found in the container:

Figure 2. A demuxer with two source pads.

For completeness(完整), here you have a simplified pipeline containing a demuxer and two branches, one for audio and one for video. This is NOT the pipeline that will be built in this example:

Figure 3. Example pipeline with two branches.

只有数据正在到来的时候,才能知道需要创建多少个source pad,所以这里涉及动态创建source pad.

The main complexity when dealing with demuxers is that they cannot produce any information until they have received some data and have had a chance to look at the container to see what is inside. This is, demuxers start with no source pads to which other elements can link, and thus the pipeline must necessarily terminate at them.

The solution is to build the pipeline from the source down to the demuxer, and set it to run (play). When the demuxer has received enough information to know about the number and kind of streams in the container, it will start creating source pads. This is the right time for us to finish building the pipeline and attach it to the newly added demuxer pads.

For simplicity(简化), in this example, we will only link to the audio pad and ignore the video.

Dynamic Hello World

Copy this code into a text file named basic-tutorial-3.c (or find it in your GStreamer installation).

basic-tutorial-3.c

#include <gst/gst.h>

/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
  GstElement *pipeline;
  GstElement *source;
  GstElement *convert;
  GstElement *sink;
} CustomData;

/* Handler for the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);

int main(int argc, char *argv[]) {
  CustomData data;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;
  gboolean terminate = FALSE;

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

  /* Create the elements */
  data.source = gst_element_factory_make ("uridecodebin", "source");
  data.convert = gst_element_factory_make ("audioconvert", "convert");
  data.sink = gst_element_factory_make ("autoaudiosink", "sink");

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

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

  /* Build the pipeline. Note that we are NOT linking the source at this
   * point. We will do it later. */
  gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert , data.sink, NULL);
  if (!gst_element_link (data.convert, data.sink)) {
    g_printerr ("Elements could not be linked.\n");
    gst_object_unref (data.pipeline);
    return -1;
  }

  /* Set the URI to play */
  g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

  /* Connect to the pad-added signal */
  g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);

  /* Start playing */
  ret = gst_element_set_state (data.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 (data.pipeline);
    return -1;
  }

  /* Listen to the bus */
  bus = gst_element_get_bus (data.pipeline);
  do {
    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    /* 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 */
          if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
            GstState old_state, new_state, pending_state;
            gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
            g_print ("Pipeline state changed from %s to %s:\n",
                gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
          }
          break;
        default:
          /* We should not reach here */
          g_printerr ("Unexpected message received.\n");
          break;
      }
      gst_message_unref (msg);
    }
  } while (!terminate);

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

/* This function will be called by the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {
  GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");
  GstPadLinkReturn ret;
  GstCaps *new_pad_caps = NULL;
  GstStructure *new_pad_struct = NULL;
  const gchar *new_pad_type = NULL;

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

  /* If our converter is already linked, we have nothing to do here */
  if (gst_pad_is_linked (sink_pad)) {
    g_print ("We are already linked. Ignoring.\n");
    goto exit;
  }

  /* Check the new pad's type */
  new_pad_caps = gst_pad_get_current_caps (new_pad);
  new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
  new_pad_type = gst_structure_get_name (new_pad_struct);
  if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
    g_print ("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
    goto exit;
  }

  /* Attempt the link */
  ret = gst_pad_link (new_pad, sink_pad);
  if (GST_PAD_LINK_FAILED (ret)) {
    g_print ("Type is '%s' but link failed.\n", new_pad_type);
  } else {
    g_print ("Link succeeded (type '%s').\n", new_pad_type);
  }

exit:
  /* Unreference the new pad's caps, if we got them */
  if (new_pad_caps != NULL)
    gst_caps_unref (new_pad_caps);

  /* Unreference the sink pad */
  gst_object_unref (sink_pad);
}

 

Walkthrough

封装一个结构体,为了方便将来在回调中设置。

/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
  GstElement *pipeline;
  GstElement *source;
  GstElement *convert;
  GstElement *sink;
} CustomData;

So far we have kept all the information we needed (pointers to GstElements, basically) as local variables. Since this tutorial (and most real applications) involves callbacks, we will group all our data in a structure for easier handling.

下边这个接口是设置回调,稍后介绍。

/* Handler for the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);

This is a forward reference, to be used later.

/* Create the elements */
data.source = gst_element_factory_make ("uridecodebin", "source");
data.convert = gst_element_factory_make ("audioconvert", "convert");
data.sink = gst_element_factory_make ("autoaudiosink", "sink");

uridecodebin 类型会内部初始化必要的element,从uri地址中分离出音视频。audioconvert 是一个音频转换器,使音频转化为标准音频。autoaudiosink 是一个音频接收器,播放出声音。

We create the elements as usual. uridecodebin will internally instantiate(内部实例化) all the necessary elements (sources, demuxers and decoders) to turn a URI into raw audio and/or video streams. It does half the work that playbin does. Since it contains demuxers, its source pads are not initially(开头) available and we will need to link to them on the fly.

audioconvert is useful for converting between different audio formats, making sure that this example will work on any platform, since the format produced by the audio decoder might not be the same that the audio sink expects.

The autoaudiosink is the equivalent(相当于) of autovideosink seen in the previous tutorial, for audio. It will render the audio stream to the audio card.

将convert和sink连接起来,这二个element已经确定,source element还没有确定,需要分离器从uri中分离出来后再进行连接。

if (!gst_element_link (data.convert, data.sink)) {
  g_printerr ("Elements could not be linked.\n");
  gst_object_unref (data.pipeline);
  return -1;
}

Here we link the converter element to the sink, but we DO NOT link them with the source, since at this point it contains no source pads. We just leave this branch (converter + sink) unlinked, until later on.

/* Set the URI to play */
g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

We set the URI of the file to play via a property, just like we did in the previous tutorial.给source element设置uri地址。

Signals

/* Connect to the pad-added signal */
g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);

我们可以对指定的element元素添加一个信号,当element有信号是,会触发我们设置的回调pad_added_handler,通知我们去处理。第二个参数pad_added是一个信号名称(表示有pad产生)。信号名称可以通过对应elemnt的文档或者通过工具gst-inspect-1.0获取。

GSignals are a crucial(重要的) point in GStreamer. They allow you to be notified (by means of a callback) when something interesting has happened. Signals are identified by a name, and each GObject has its own signals.

In this line, we are attaching to the “pad-added” signal of our source (an uridecodebin element). To do so, we use g_signal_connect() and provide the callback function to be used (pad_added_handler) and a data pointer. GStreamer does nothing with this data pointer, it just forwards it to the callback so we can share information with it. In this case, we pass a pointer to the CustomData structure we built specially for this purpose.

The signals that a GstElement generates can be found in its documentation or using the gst-inspect-1.0 tool as described in Basic tutorial 10: GStreamer tools.

We are now ready to go! Just set the pipeline to the PLAYING state and start listening to the bus for interesting messages (like ERROR or EOS), just like in the previous tutorials.

The callback

当uridecodebin类型的element分理处音视频数据的时候,就会触发pad_added_handler回调,这个回调有三个参数,第一个参数就是产生这个回调的element,第二个参数,是新增的pad,第三个参数是之前设置的上下文。

When our source element finally has enough information to start producing data, it will create source pads, and trigger the “pad-added” signal. At this point our callback will be called:

static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data) {

src is the GstElement which triggered the signal. In this example, it can only be the uridecodebin, since it is the only signal to which we have attached. The first parameter of a signal handler is always the object that has triggered it.

new_pad is the GstPad that has just been added to the src element. This is usually the pad to which we want to link.

data is the pointer we provided when attaching to the signal. In this example, we use it to pass the CustomDatapointer.

通过上下文以及gst_element_get_static_pad 函数,可以获取convert这个element的sinkpad,这里我们需要将我们source pad和sink pad连接起来,和之前介绍的element直接连接一样。可以通过函数gst_pad_is_linked判断一个pad是否已经连接。

GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");

From CustomData we extract the converter element, and then retrieve its sink pad using gst_element_get_static_pad (). This is the pad to which we want to link new_pad. In the previous tutorial we linked element against element, and let GStreamer choose the appropriate pads. Now we are going to link the pads directly.

/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pad)) {
  g_print ("We are already linked. Ignoring.\n");
  goto exit;
}

可以通过new_pad_caps = gst_pad_get_current_caps,gst_caps_get_structure,gst_structure_get_name获取pad的名称,通过名称可以过滤是否是关心的pad。
uridecodebin can create as many pads as it sees fit, and for each one, this callback will be called. These lines of code will prevent us from trying to link to a new pad once we are already linked.

/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps (new_pad, NULL);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
  g_print ("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
  goto exit;
}

Now we will check the type of data this new pad is going to output, because we are only interested in pads producing audio. We have previously created a piece of pipeline which deals with audio (an audioconvert linked with an autoaudiosink), and we will not be able to link it to a pad producing video, for example.

gst_pad_get_current_caps() retrieves the current capabilities of the pad (that is, the kind of data it currently outputs), wrapped in a GstCaps structure. All possible caps a pad can support can be queried withgst_pad_query_caps(). A pad can offer many capabilities, and hence GstCaps can contain many GstStructure, each representing a different capability. The current caps on a pad will always have a single GstStructure and represent a single media format, or if there are no current caps yet NULL will be returned.

Since, in this case, we know that the pad we want only had one capability (audio), we retrieve the first  GstStructure  with  gst_caps_get_structure().

Finally, with gst_structure_get_name() we recover the name of the structure, which contains the main description of the format (its media type, actually).

If the name is not audio/x-raw, this is not a decoded audio pad, and we are not interested in it.

Otherwise, attempt the link:可以通过gst_pad_link将两个合适的pad进行连接(当然前提是在同一个bin里)。

/* Attempt the link */
ret = gst_pad_link (new_pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
  g_print ("Type is '%s' but link failed.\n", new_pad_type);
} else {
  g_print ("Link succeeded (type '%s').\n", new_pad_type);
}

gst_pad_link() tries to link two pads. As it was the case with gst_element_link(), the link must be specified from source to sink, and both pads must be owned by elements residing in(位于0 the same bin (or pipeline).

And we are done! When a pad of the right kind appears, it will be linked to the rest of the audio-processing pipeline and execution will continue until ERROR or EOS. However, we will squeeze(榨取,获得) a bit more content from this tutorial by also introducing the concept of State.

GStreamer States

We already talked a bit about states when we said that playback does not start until you bring the pipeline to the PLAYING state. We will introduce here the rest of states and their meaning. There are 4 states in GStreamer:

| State     | Description |
|-----------|--------------------|
| `NULL`    | the NULL state or initial state of an element. |
| `READY`   | the element is ready to go to PAUSED. |
| `PAUSED`  | the element is PAUSED, it is ready to accept and process data. Sink elements however only accept one buffer and then block. |
| `PLAYING` | the element is PLAYING, the clock is running and the data is flowing. |

You can only move between adjacent(相邻的) ones, this is, you can't go from NULL to PLAYING, you have to go through the intermediate READY and PAUSED states. If you set the pipeline to PLAYING, though, GStreamer will make the intermediate(中间的) transitions for you.

case GST_MESSAGE_STATE_CHANGED:
  /* We are only interested in state-changed messages from the pipeline */
  if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
    GstState old_state, new_state, pending_state;
    gst_message_parse_state_changed (msg, &old_state, &new_state, &pending_state);
    g_print ("Pipeline state changed from %s to %s:\n",
        gst_element_state_get_name (old_state), gst_element_state_get_name (new_state));
  }
  break;

We added this piece of code that listens to bus messages regarding state changes and prints them on screen to help you understand the transitions. Every element puts messages on the bus regarding its current state, so we filter them out and only listen to messages coming from the pipeline.

Most applications only need to worry about going to PLAYING to start playback, then to PAUSED to perform a pause, and then back to NULL at program exit to free all resources.

Exercise

Dynamic pad linking has traditionally been a difficult topic for a lot of programmers. Prove that you have achieved its mastery by instantiating an autovideosink (probably with an videoconvert in front) and link it to the demuxer when the right pad appears. Hint: You are already printing on screen the type of the video pads.

You should now see (and hear) the same movie as in Basic tutorial 1: Hello world!. In that tutorial you used playbin, which is a handy element that automatically takes care of all the demuxing and pad linking for you. Most of the Playback tutorials are devoted to playbin.

Conclusion

In this tutorial, you learned:

  • How to be notified of events using GSignals
  • How to connect GstPads directly instead of their parent elements.
  • The various states of a GStreamer element.

You also combined these items to build a dynamic pipeline, which was not defined at program start, but was created as information regarding the media was available.

You can now continue with the basic tutorials and learn about performing seeks and time-related queries in Basic tutorial 4: Time management or move to the Playback tutorials, and gain more insight about the playbin element.

Remember that attached to this page you should find the complete source code of the tutorial and any accessory files needed to build it. It has been a pleasure having you here, and see you soon!

gst-launch-1.0详细说明 是GStreamer库提供的命令行工具,用于构建和运行基于GStreamer的多媒体处理管道。它接受一个管道描述作为输入,可以从各种来源中捕获音视频数据,并将其转换、编解码、过滤、传输和显示等。 阅读详情

相关推荐

Zemax光机热集成分析:从FEA数据导入到光学性能评估实战

在精密光学系统设计中,环境温度变化和机械应力是导致像质恶化的关键因素,这涉及到光、机、热多物理场的耦合分析。其核心原理在于,通过有限元分析(FEA)软件(如ANSYS)模拟热与力学载荷下的结构变形和温度分布,并将这些物理场数据精准映射到光学设计软件(如Zemax)中,以评估其对调制传递函数(MTF)、点列图等核心光学指标的影响。这项技术的工程价值在于,它使设计从静态的理想模型跃升至动态的工程现实,能够在设计阶段就预测并补偿环境扰动,从而显著提升光学系统在航空航天、车载镜头、高功率激光等严苛工况下的可靠性与稳

weixin_30565327的博客 356

GStream常用类及其类间关系

1. GstElement GstElement 是GStreamer管道(pipeline)中构建组件的抽象基类。GstElement子类的更多信息,请参考插件编写者指南。 gst_element_get_name:获取组件名称; gst_element_set_name:设置组件名称。为了提高速度,使用适当的锁定时,可以在内核中使用GST_ELEMENT_NAME。请勿在插件...

MoL的博客 1325

AI大模型开发——transformer模型超全完整版(0基础可懂)

为了更深入的了解transformer模型,我们首先从transformer的诞生聊起吧。transformer在2017年由Vaswani等人首次提出,它摒弃了之前流行的循环神经网络和卷积神经网络的架构,引入了自注意力机制( Self-Attention),显著提高了处理序列数据的能力和效率。transformer模型的这种设计使其在处理长距离依赖问题时, 相比于传统的循环神经网络和长短期记忆网络(LSTM)表现得更加出色,至此, 开启了NLP技术的新篇章。

m0_74922316的博客 2120

【无标题】

***参考:***Gstreamer应用开发手册5:构建一个应用 注意 1:gst_pad_link (pad, sinkpad);//将两个pad 进行链接 2:g_object_set (G_OBJECT (source), “location”, argv[1], NULL); //设置播放源 3:当碰见动态创建 pad 的 element 需要特殊对待。   只能上面的方法 gst_element_link (source, demuxer); gst_element_link_many (deco

aningxiaoxixi的博客 379

Android应用隐私合规自动化检测:Frida与Camille实战指南

在移动应用安全与隐私合规领域,动态代码插桩技术已成为核心检测手段。其原理是通过运行时注入,实时监控和修改应用行为,从而绕过传统静态分析的局限。这项技术的核心价值在于能够精准捕获应用在运行时的敏感数据调用与网络传输行为,为隐私合规审计、安全测试提供直接证据。在实际应用场景中,它尤其适用于自动化检测违规收集个人信息、追踪数据流向等任务。本文聚焦于利用Frida这一动态插桩框架,结合Camille隐私合规检测工具集,构建自动化监控环境。通过注入JavaScript代码,实现对Android敏感API(如获取设备标

weixin_34254464的博客 388

STM32H743 ADC多通道采样实战:CubeMX配置+DMA传输避坑指南

本文详细介绍了STM32H743 ADC多通道采样的实战配置,包括CubeMX参数设置、DMA传输优化及常见问题解决方案。重点解析了ADC模块的核心特性、多通道采样序列配置、Cache一致性处理等关键技术,帮助开发者高效实现稳定可靠的模拟信号采集系统。

weixin_29175469的博客 612

GStreamer常用命令总结

最近开始做GStreamer相关项目了,网上搜了一下,相关资料并不多,所以一边查阅一边记录总结一下,方便后期使用。 1. 播放视频、音频操作命令 音频: gst-launch-1.0 filesrc loaction=123.mp3 ! mad ! autoaudiosink   autoaudiosink可换成pulsesink或alsasink,需要使用gst-inspect查询是否存在这些sink插件,其实autoaudiosink是个壳,最终还是选择使...

程序猿老樊的博客 3039

Ubuntu22.04下ROS2与PX4仿真环境搭建全流程解析

本文详细解析了在Ubuntu22.04系统下搭建ROS2与PX4仿真环境的全流程,包括系统准备、ROS2 Humble安装、PX4飞控环境部署、ROS2与PX4通信桥梁搭建等关键步骤。针对常见问题提供了解决方案,并分享了性能优化和开发调试技巧,帮助开发者快速构建无人机仿真开发环境。

weixin_29248653的博客 607

GStreamer——教程——基础教程3:Dynamic pipelines

正如您将要看到的,本教程中的管道在设置为播放状态之前尚未完全构建。这没关系。如果我们不采取进一步行动,数据将到达管道末端,管道将生成错误消息并停止。但我们将采取进一步行动.....在这个例子中我们将打开一个多路复用的文件,音频和视频被存储在同一个容器文件中。负责打开此类容器的element称为解复用器,容器格式的一些示例有Matroska(MKV)、Quick Time(QT、MOV)、Ogg或Advanced Systems Format(ASF、WMV、WMA)。

FREEDOM_X的专栏 1500

【Claude】媒体文件处理错误:PDF 与 Image 过大的检测与预处理方法 bug报错已解决

图片压缩是必须的:原始图片的 base64 会占用大量 TokenPDF 提取文本优于传图片:文本版 PDF 比扫描版更省 Token分块处理大文件:不要一次性处理整个大文件控制分辨率:800x800 通常足够 Claude 分析。

博客 6361

【七.三维视觉与视频分析】【1.点云处理:PointNet++/PointTransformer】

各位老铁,今天咱们要聊的可不是普通的二维图像处理,而是三维视觉领域最硬核的技术——点云处理。从最早的PointNet到如今的PointTransformer,这场技术进化堪比三维版的"像素革命"。今天咱们就深入解剖两大里程碑:PointNet++和PointTransformer,保证让你看完全文就能在点云领域横着走!想象一下,你抓了把沙子撒在空中,每粒沙子的位置都是三维坐标——这就是点云的典型形态。最后送大家一句话:点云处理就像在三维宇宙中寻找星辰的轨迹,既要望远镜的宏观视野,也要显微镜的细致入微。

商务合作|问题讨论|交流学习 请联系作者微信,加微信请务必注明来意,博客主页有联系方式 474

GStreamer开发实例 3: Dynamic pipelines

可以看到这篇教程的pipeline在设置为PLAYING状态之前都没有完成构建,这种行为是允许的。但是假如在播放之前没有完成,那么数据在到达pipeline的某个节点将上报一个错误信息并停止运行。在这个例子中我们将打开一个多路复用的文件,音频和视频被存储在同一个容器文件中。负责响应打开多路复用文件的element被叫做解复用器,可以处理MKV、QT、MOV、Ogg、WMV等格式的容器文件。

浩瀚之水的专栏 397

CLRNet车道线检测模型在Orin Nano Super开发板上的全栈部署与优化实践

本文详细介绍了将CLRNet车道线检测模型部署到NVIDIA Orin Nano Super开发板的全过程。内容包括:1) Orin开发板硬件规格分析;2) JetPack SDK环境配置与Python虚拟环境搭建;3) CLRNet模型架构解析与PyTorch实现;4) 模型转换与TensorRT加速优化方法。通过系统性的环境配置、模型转换和性能优化,为边缘计算场景下的车道线检测应用提供了完整的解决方案,实现了在Orin平台上的高效部署。

huanghm88的专栏 226

【GStreamer 】Basic tutorials-Basic tutorial 3: Dynamic pipelines

正如您将要看到的,本教程中的管道在设置为播放状态之前并未完全构建。这是可以的。如果我们不采取进一步的行动,数据将到达管道的末端,管道将产生错误消息并停止。但我们要采取进一步的行动……在这个例子中,我们打开一个多路复用(或多路复用)的文件,也就是说,音频和视频一起存储在一个容器文件中。负责打开此类容器的元素称为解复用器,容器格式的一些示例包括 Matroska (MKV)、Quick Time (QT、MOV)、Ogg 或高级系统格式 (ASF、WMV、WMA)。

qq_43298381的博客 776

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain&#39;s apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath(&#39;DeepLearnToolbox&#39;));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand(&#39;state&#39;,0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W&#39;); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand(&#39;state&#39;,0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = &#39;sigm&#39;;%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, &#39;Too big error&#39;);```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand(&#39;state&#39;,0)sae = saesetup([784 100]);sae.ae{1}.activation_function = &#39;sigm&#39;;sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)&#39;)% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;;nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, &#39;Too big error&#39;);```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x&#39;,28,28,60000))/255;test_x = double(reshape(test_x&#39;,28,28,10000))/255;train_y = double(train_y&#39;);test_y = double(test_y&#39;);%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you&#39;ll get around 1.2% errorrand(&#39;state&#39;,0)cnn.layers = { struct(&#39;type&#39;, &#39;i&#39;) %input layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 6, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %sub sampling layer struct(&#39;type&#39;, &#39;c&#39;, &#39;outputmaps&#39;, 12, &#39;kernelsize&#39;, 5) %convolution layer struct(&#39;type&#39;, &#39;s&#39;, &#39;scale&#39;, 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, &#39;Too big error&#39;);```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, &#39;Too big error&#39;);%% ex2 neural net with L2 weight decayrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex3 neural net with dropoutrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex4 neural net with sigmoid activation functionrand(&#39;state&#39;,0)nn = nnsetup([784 100 10]);nn.activation_function = &#39;sigm&#39;; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex5 plotting functionalityrand(&#39;state&#39;,0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = &#39;softmax&#39;; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand(&#39;state&#39;,0)nn = nnsetup([784 20 10]); nn.output = &#39;softmax&#39;; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, &#39;Too big error&#39;);```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

GStreamer笔记 -- 3.Dynamic pipelines

动态管道1. 目标2. 介绍3. 代码4. 代码解读4.1. 信号4.2. 回调函数4.3. GStream 的管道的状态 1. 目标 这个教程将展示GStreamer的基本应用,就是怎么动态的建立一个pipeline,而不是在应用的开始就搭建好pipeline。 在这个教程之后,你将获得开始 Playback tutorials教程的必要知识,这里我们将学习以下几点: 怎样在链接元素的时候实现更细致的控制 怎样即使获取感兴趣的事件,以便即使做出相应的动作 元素的各种状态 2. 介绍 正如你所见的,这个

xf1234的博客 434

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

GStreamer官方教程系列——Basic tutorial 3: Dynamic pipelines

GStreamer官方教程系列 Basic tutorial 3: Dynamic pipelines 原文:https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c 目标   本教程会展示前两个教程余下的使用GStreamer需要的基本概念,“动态”构建管道,当信息变得可用时,而不是在一开始就定义一个完整的管道。   在学习本教程之后,你就有了足够的知识储备来开始

SaberZXL520的博客 433

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

GStreamer Tutorial 中文翻译:Basic tutorial 3: Dynamic pipelines

GStreamer Tutorial 3中文翻译 文章目录GStreamer Tutorial 3中文翻译前言[Basic tutorial 3: Dynamic pipelines](https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c)目的简介动态Hello World代码走读结论 前言 由于工作原因,用的GStreamer的图像解码库,所以记录GStr

wuchangwen0216的博客 397

GStreamer 基础教程学习 3 - 动态管道 (Basic tutorial 3: Dynamic pipelines)

https://gstreamer.freedesktop.org/documentation/tutorials/basic/dynamic-pipelines.html?gi-language=c 本节进一步扩展了上一节的管道, 在运行过程中(on the fly)创建管道,而不是在运行前创建一个指定的管道。 可以想象,将一个没有完全创建的管道设置为播放状态,那么在什么都不做的情况下,数据...

gsymichael的专栏 521

Gstreamer官方教程汇总基本教程3---Dynamic pipelines

https://my.oschina.net/u/735973/blog/202365 摘要: 将gstreamer的官方教程做了一下整理,分享给需要的人们。 Goal 本教程介绍剩下的的使用GStreamer的所需的基本概念,它允许随时地建立管道,作为信息变得可用,而不必在你的应用程序的开头定义一个全局的管道。 本教程后,您将具备必要的知识,开始 Playback

STN_LCD的专栏 1134

gstreamer笔记

gstreamer官方教程、gstreamer中文教程、gstreamer插件文档 常用插件:Platform-specific elements、Handy elements 本文内容全部来自于上面这些教程,仅作为个人学习记录。 pipeline pipeline是gst从输入到输出的一条处理管线,pipeline由element组成,element必须加入pipeline,并按次序首尾相接才能工作。pipeline构建好以后有各种state,包括NULL,READY,PAUSE,PLAYING,

qq_41263444的博客 2318

gstreamer之gst_pad_link/gst_element_link源码剖析

(1)如果GST_PAD_PEER (srcpad)/GST_PAD_PEER (sinkpad)已经存在了,则GST_PAD_LINK_WAS_LINKED,说明pad already linked.a)GST_PAD_LINK_CHECK_CAPS是默认值,通过gst_pad_query_caps查询srcpad和sinkpad的caps。(2)prepare pad link实现函数gst_pad_link_prepare。相关的回调函数类型。2.函数gst_pad_link_prepare。

我的博客 1097

GStreamer 简明教程(三):动态调整 Pipeline

本章来了解 GStreamer 动态调整 Pipeline 的流程,这章代码略长,略微有些复杂,各位看官稍稍耐心些。在src参数表示触发信号的 GstElement,在本例中通常为 uridecodebin,因为它是唯一附加了该信号的元素。信号处理函数的第一个参数始终是触发信号的对象。new_pad参数表示刚刚添加到src元素的 GstPad。通常,我们希望连接的就是这个 pad。第一次,添加的 pad 负责输出视频数据第二次,添加的 pad 负责输出音频数据data。

记录学习的过程 2225

GStreamer学习笔记(四)——基础教程3:动态pipeline

正如你即将看到的,本教程中的pipeline在设置为播放状态之前并没有完全构建。这没问题。如果我们不采取进一步的行动,数据将到达pipeline的末端,pipeline将产生错误消息并停止。但我们将采取进一步行动……在这个例子中,我们正在打开一个多路复用(或muxed)的文件,也就是说,音频和视频一起存储在容器文件中。

bestworker的博客 2209

【GStreamer 】1-扫盲介绍

GStreamer是一个非常强大和通用的用于开发流媒体应用程序的框架。GStreamer框架的许多优点都来自于它的模块化:GStreamer可以无缝地合并新的插件模块,但是由于模块化和强大的功能往往以更大的复杂度为代价,开发新的应用程序并不总是简单。

cau_weiyuhu的博客 4091

GStreamer教程-基础教程3:动态管道

这是第三个GStreamer的基础教程,讲解如何动态构建管道。

tangyzh的博客 1405
上一篇: gstreamer基础教程2-GStreamer concepts
下一篇: gstreamer基础教程4-Time management
knowledgebao
博客等级 码龄15年 401粉丝 198原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值