GStreamer Probe 探針的妙用

探針 Probe 是一種可由應(yīng)用程序安裝的回調(diào)辑舷,可將數(shù)據(jù)流的狀態(tài)及內(nèi)容回調(diào)給應(yīng)用程序灌旧,在實現(xiàn)中妙用無窮,既可以用來檢查在 GStreamer Pipeline 中流傳的 Data, Query 和 Event, 還可以用來檢查和修改在回調(diào)函數(shù)中收到的數(shù)據(jù),以及阻塞或傳遞在 pipeline 流傳的數(shù)據(jù)。

先總結(jié)一下我在 GStreamer Probe 看到的內(nèi)容夕玩,然后寫一個簡單的小程序演示一下探針的妙用你弦。

用法

應(yīng)用程序應(yīng)該能夠監(jiān)視和控制 pad 上的數(shù)據(jù)流,有以下用法:

  • 當(dāng) pad 空閑時收到通知风秤,并確保 pad 保持空閑鳖目。這對于能夠?qū)崿F(xiàn)元件的動態(tài)重新鏈接至關(guān)重要扮叨,從而不會中斷數(shù)據(jù)流缤弦。
  • 當(dāng)數(shù)據(jù) data、事件 event 或查詢 query 被發(fā)送到 pad 上就會被通知彻磁,這樣就可以在回調(diào)函數(shù)中檢查和修改數(shù)據(jù)碍沐。
  • 能夠根據(jù)回調(diào)函數(shù)返回的結(jié)果,在 pad 上丟棄衷蜓、傳遞和阻塞數(shù)據(jù)
  • 能夠在被阻塞的 pad 中由應(yīng)用線程執(zhí)行的方法丟棄累提,傳遞數(shù)據(jù)

概述

函數(shù) gst_pad_add_probe() 用于在 pad 上添加探針 probe. 它接受的參數(shù)有 probe type mask 和一個 callback 函數(shù).

    gulong  gst_pad_add_probe    (GstPad *pad,
                                  GstPadProbeType mask,
                                  GstPadProbeCallback callback,
                                  gpointer user_data,
                                  GDestroyNotify destroy_data);

此函數(shù)返回 gulong 數(shù)據(jù)類型來標(biāo)識這個探針,這個 probe_id 可以用 gst_pad_remove_probe() 來移除探針

    void    gst_pad_remove_probe (GstPad *pad, gulong id);

而 mask 掩碼參數(shù)是以下 flags 的按位或操作 "bitwise or"

typedef enum
{
  GST_PAD_PROBE_TYPE_INVALID          = 0,

  /* flags to control blocking */
  GST_PAD_PROBE_TYPE_IDLE             = (1 << 0),
  GST_PAD_PROBE_TYPE_BLOCK            = (1 << 1),

  /* flags to select datatypes */
  GST_PAD_PROBE_TYPE_BUFFER           = (1 << 4),
  GST_PAD_PROBE_TYPE_BUFFER_LIST      = (1 << 5),
  GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM = (1 << 6),
  GST_PAD_PROBE_TYPE_EVENT_UPSTREAM   = (1 << 7),
  GST_PAD_PROBE_TYPE_EVENT_FLUSH      = (1 << 8),
  GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM = (1 << 9),
  GST_PAD_PROBE_TYPE_QUERY_UPSTREAM   = (1 << 10),

  /* flags to select scheduling mode */
  GST_PAD_PROBE_TYPE_PUSH             = (1 << 12),
  GST_PAD_PROBE_TYPE_PULL             = (1 << 13),
} GstPadProbeType;

添加帶有 IDLE 或 BLOCK 標(biāo)志的探針時磁浇,探針將成為阻塞探針 (blocking probe)斋陪。否則,探針將是數(shù)據(jù)探針 (Data Probe)置吓。

數(shù)據(jù)類型和調(diào)度選擇器標(biāo)志用于選擇在回調(diào)函數(shù)中可以使用哪種類型的數(shù)據(jù)類型和調(diào)度模式无虚。

Blocking flags 必須與所觸發(fā)的 probe 完全匹配。

探測回調(diào)定義為:


GstPadProbeReturn (*GstPadProbeCallback) (GstPad *pad, GstPadProbeInfo *info,
    gpointer user_data);

probe info 結(jié)構(gòu)作為參數(shù)傳遞衍锚,其類型必須匹配于注冊回調(diào)時使用的掩碼友题。Probe info 中包含的數(shù)據(jù)項包含特定類型的數(shù)據(jù),通常是被阻止的數(shù)據(jù)項或者是 NULL(當(dāng)不存在數(shù)據(jù)項時)

探針可以返回以下任何返回值:

typedef enum
{
  GST_PAD_PROBE_DROP,
  GST_PAD_PROBE_OK,
  GST_PAD_PROBE_REMOVE,
  GST_PAD_PROBE_PASS,
  GST_PAD_PROBE_HANDLED
} GstPadProbeReturn;

  • GST_PAD_PROBE_OK 是正常的返回值戴质。 _DROP 將丟棄目前正在探測的數(shù)據(jù)度宦, GST_PAD_PROBE_REMOVE 將從探針列表中移除當(dāng)前所正在執(zhí)行的探針

  • GST_PAD_PROBE_PASS 與阻塞探針相關(guān),并將暫時取消阻塞告匠, 讓數(shù)據(jù)項通過戈抄,然后它會再次阻塞下一個數(shù)據(jù)項。

阻塞探針

阻塞探針是設(shè)置了 BLOCKIDLE 標(biāo)志的探針后专。它們將一直阻止數(shù)據(jù)流并按照以下規(guī)則觸發(fā)回調(diào):

  • 當(dāng) IDLE 標(biāo)志設(shè)置后呛凶,一旦沒有數(shù)據(jù)經(jīng)過 pad,就會調(diào)用探針的回調(diào)函數(shù)行贪。如果在探針注冊時漾稀,pad 處于空閑狀態(tài), 回調(diào)函數(shù)會立即從當(dāng)前線程調(diào)用建瘫。否則崭捍, 一旦 pad 的狀態(tài)變?yōu)榭臻e (Idle),就會在數(shù)據(jù)流線程中調(diào)用探針的回調(diào)函數(shù)啰脚。

IDLE 探針在執(zhí)行動態(tài)鏈接時很有用殷蛇,允許應(yīng)用程序等待 "unlink/link" 操作的正確執(zhí)行实夹。由于探針是阻擋探針,它還將確保 pad 保持空閑狀態(tài)粒梦,直到此探針被刪除亮航。

  • 當(dāng) BLOCK 標(biāo)志設(shè)置后,當(dāng)有新數(shù)據(jù)時到達(dá) Pad 時將調(diào)用探針的回調(diào)函數(shù)匀们,也就在 pad 即將進(jìn)入阻塞狀態(tài)之前缴淋。因此只有當(dāng) pad 上有新數(shù)據(jù)時才會調(diào)用此探針的回調(diào)。

阻塞探針由 gst_pad_remove_probe() 函數(shù)移除泄朴, 或當(dāng)探針的回調(diào)函數(shù)返回 GST_PAD_PROBE_REMOVE 時移除此探針重抖。

在這兩種情況下,如果這是 pad 上的最后一個阻塞探針祖灰,pad 就會被解鎖 (unblocked)钟沛,數(shù)據(jù)流可以繼續(xù)。

非阻塞探針

非阻塞探針或數(shù)據(jù)探針是在 Pad 中數(shù)據(jù)流動時觸發(fā)的探針局扶。它們在阻塞探針運行之后調(diào)用恨统,并且始終針對于數(shù)據(jù)。

推送數(shù)據(jù)流

推送探針在回調(diào)中設(shè)置了 GST_PAD_PROBE_TYPE_PUSH 標(biāo)志三妈。

在基于推送的調(diào)度中畜埋,首先使用數(shù)據(jù)項調(diào)用阻塞探針 (blocking probe)。然后沈跨,在對等 pad 的 chainevent 函數(shù)調(diào)用之前 調(diào)用數(shù)據(jù)探針 (data probe)

在對等的 pad 被檢查之前會調(diào)用 data probe, 它允許鏈接 pad 以阻塞探針 (BLOCK probe) 或者數(shù)據(jù)探針 (DATA probe)

在對等的 pad 的 chain 或 event 函數(shù)調(diào)用之前由捎, 對等的 pad 的阻塞探針 (BLOCK probe) 或者數(shù)據(jù)探針 (DATA probe) 會被調(diào)用。

最后饿凛,在數(shù)據(jù)發(fā)送給對等的 pad 之后 IDEL 探針被調(diào)用

推送數(shù)據(jù)流探針行為與數(shù)據(jù)緩沖和雙向事件的行為相同

                    pad                           peerpad
                     |                               |
gst_pad_push() /     |                               |
gst_pad_push_event() |                               |
-------------------->O                               |
                     O                               |
       flushing?     O                               |
       FLUSHING      O                               |
       < - - - - - - O                               |
                     O-> do BLOCK probes             |
                     O                               |
                     O-> do DATA probes              |
        no peer?     O                               |
       NOT_LINKED    O                               |
       < - - - - - - O                               |
                     O   gst_pad_chain() /           |
                     O   gst_pad_send_event()        |
                     O------------------------------>O
                     O                   flushing?   O
                     O                   FLUSHING    O
                     O< - - - - - - - - - - - - - - -O
                     O                               O-> do BLOCK probes
                     O                               O
                     O                               O-> do DATA probes
                     O                               O
                     O                               O---> chainfunc /
                     O                               O     eventfunc
                     O< - - - - - - - - - - - - - - -O
                     O                               |
                     O-> do IDLE probes              |
                     O                               |
       < - - - - - - O                               |
                     |                               |

拉取數(shù)據(jù)流

拉取探針在回調(diào)中設(shè)置了 GST_PAD_PROBE_TYPE_PULL 標(biāo)志狞玛。而 gst_pad_pull_range() 調(diào)用先觸發(fā) BLOCK 探針, 并不包含數(shù)據(jù)項涧窒。它允許對等的 pad 解析成功前進(jìn)行連接此 pad, 還允許在回調(diào)函數(shù)中設(shè)置數(shù)據(jù)項

在對等的 pad 上調(diào)用阻塞探針 blocking probe 和 getrange 并有數(shù)據(jù)項傳遞之后心肪,此 pad 上的 數(shù)據(jù)探針 Data Probe 將會被調(diào)用。

當(dāng)控制權(quán)返回到 sink pad, IDLE 回調(diào)會被調(diào)用纠吴,沒有數(shù)據(jù)項就會調(diào)用 IDLE 回調(diào)硬鞍,所以如果發(fā)生錯誤時也會調(diào)用 IDLE 回調(diào)

如果有了有效的數(shù)據(jù)項, DATA 探針也會被調(diào)用

                srcpad                          sinkpad
                  |                               |
                  |                               | gst_pad_pull_range()
                  |                               O<---------------------
                  |                               O
                  |                               O  flushing?
                  |                               O  FLUSHING
                  |                               O - - - - - - - - - - >
                  |             do BLOCK probes <-O
                  |                               O   no peer?
                  |                               O  NOT_LINKED
                  |                               O - - - - - - - - - - >
                  |          gst_pad_get_range()  O
                  O<------------------------------O
                  O                               O
                  O flushing?                     O
                  O FLUSHING                      O
                  O- - - - - - - - - - - - - - - >O
do BLOCK probes <-O                               O
                  O                               O
 getrangefunc <---O                               O
                  O  flow error?                  O
                  O- - - - - - - - - - - - - - - >O
                  O                               O
 do DATA probes <-O                               O
                  O- - - - - - - - - - - - - - - >O
                  |                               O
                  |              do IDLE probes <-O
                  |                               O   flow error?
                  |                               O - - - - - - - - - - >
                  |                               O
                  |              do DATA probes <-O
                  |                               O - - - - - - - - - - >
                  |                               |

查詢 Queries

查詢探針 (Query probes) 在回調(diào)中設(shè)置了 GST_PAD_PROBE_TYPE_QUERY_* 標(biāo)志.

                    pad                           peerpad
                     |                               |
gst_pad_peer_query() |                               |
-------------------->O                               |
                     O                               |
                     O-> do BLOCK probes             |
                     O                               |
                     O-> do QUERY | PUSH probes      |
        no peer?     O                               |
          FALSE      O                               |
       < - - - - - - O                               |
                     O   gst_pad_query()             |
                     O------------------------------>O
                     O                               O-> do BLOCK probes
                     O                               O
                     O                               O-> do QUERY | PUSH probes
                     O                               O
                     O                               O---> queryfunc
                     O                    error      O
       <- - - - - - - - - - - - - - - - - - - - - - -O
                     O                               O
                     O                               O-> do QUERY | PULL probes
                     O< - - - - - - - - - - - - - - -O
                     O                               |
                     O-> do QUERY | PULL probes      |
                     O                               |
       < - - - - - - O                               |
                     |                               |

對于查詢 queries, 當(dāng)查詢到達(dá)了要回答這個查詢的對象戴已, ProbeType 設(shè)置為 PUSH
而當(dāng) query 中已經(jīng)包含了答案 , ProbeType 將設(shè)置為 PULL

用例

預(yù)滾動部分管道

    .---------.      .---------.                .----------.
    | filesrc |      | demuxer |     .-----.    | decoder1 |
    |        src -> sink      src1 ->|queue|-> sink       src
    '---------'      |         |     '-----'    '----------' X
                     |         |                .----------.
                     |         |     .-----.    | decoder2 |
                     |        src2 ->|queue|-> sink       src
                     '---------'     '-----'    '----------' X

其目的是動態(tài)創(chuàng)建管道固该,一直連到解碼器,但尚未將它們連接到接收器 sink, 并且不會丟失任何數(shù)據(jù)糖儡。

為此伐坏,解碼器的 source pad 被阻止,以便沒有 event 或 buffer 可以逃脫握联,并且我們也不會中斷數(shù)據(jù)流桦沉。

當(dāng)所有動態(tài) pad 都被創(chuàng)建(分支點不再創(chuàng)建出新的 pad每瞒,即解復(fù)用器 demuxer 或隊列 queue 已滿)并且 pad 被阻止(收到 blocked callback )時,管道將完全預(yù)滾動 (preroll)纯露。

然后應(yīng)該可以在預(yù)滾動的管道上執(zhí)行以下操作:

  • 查詢時長/位置

  • 執(zhí)行刷新搜索以預(yù)滾動到新位置

  • 連接其他元件并疏通堵塞的 pads

在一個 PLAYING 的管道中動態(tài)切換一個元件

 .----------.      .----------.      .----------.
 | element1 |      | element2 |      | element3 |
...        src -> sink       src -> sink       ...
 '----------'      '----------'      '----------'
                   .----------.
                   | element4 |
                  sink       src
                   '----------'

其目的是在 PLAYING 的管道中將 element4 替換為 element2

  1. 阻塞 element1 的 src pad.
  2. 在阻塞回調(diào)函數(shù)的內(nèi)部剿骨,element1 和 element2 之間沒有任何數(shù)據(jù)流動,并且在解除阻塞之前不會有任何數(shù)據(jù)流動埠褪。
  3. 將 element1 和 element2 解除連接
  4. 可選步驟:確保數(shù)據(jù)從 element2 中清除:
  • 4a) 在 element2 src pad上添加事件探針
  • 4b) 將 EOS 事件發(fā)送到 element2浓利,這可確保 element2 清除其保存的最后一位數(shù)據(jù)。
  • 4c) 等待 EOS 出現(xiàn)在探針中组橄,丟棄 EOS 事件
  • 4d) 刪除 pad 上的 EOS 事件探針荞膘。
  1. 解除 element2 和 element3 的連接
  • 5a) 現(xiàn)在可以選擇將 element2 設(shè)置為“NULL”和/或從管道中將其刪除罚随。
  1. 連接 element4 和 element3
  2. 連接 element1 和 element4
  3. 確保 element4 與其余元素處于相同的狀態(tài)玉工。 該元素至少應(yīng)該是 PAUSED 狀態(tài)
  4. 解除 element1 src pad 的阻塞

相同的流程可用于替換“PAUSED”管道中的元素。 當(dāng)然淘菩,在 “PAUSED” 管道中可能沒有數(shù)據(jù)流遵班,因此阻塞可能不會立即發(fā)生。

示例

1. 探查 pad 上的收到的 event, query 和 data

#include <gst/gst.h>
#include <string>
#include <iostream>
#include <sstream>
#include <iomanip>

static std::string bytes_to_hex(uint8_t* bytes, size_t len) {
    std::stringstream ss;

    // Ensure the output is in uppercase and has two characters for each byte
    ss << std::uppercase << std::setfill('0');
    for (size_t i = 0; i < len; ++i) {
        ss << std::setw(2) << std::hex << static_cast<int>(bytes[i]);
    }

    return ss.str();
}

static gboolean handoff_callback(GstElement *sink, GstBuffer *buffer, gpointer user_data)
{
  // This function will be called when the handoff signal is emitted
  g_print("Handoff Callback - Received buffer with size: %zu\n", gst_buffer_get_size(buffer));
  return TRUE;
}

GstPadProbeReturn cb_have_data_list(GstPad *pad, GstPadProbeInfo *info,
                                    gpointer user_data)
{

    GstBufferList *buflist = gst_pad_probe_info_get_buffer_list(info);
    if (buflist)
        g_print("cb_hava_data_list from %s\n", (char *)user_data);
    return GST_PAD_PROBE_OK;
}

GstPadProbeReturn cb_have_data(GstPad *pad, GstPadProbeInfo *info,
                                gpointer user_data)
{

    //GstBuffer *buf = gst_pad_probe_info_get_buffer(info);
    GstBuffer *buf = (GstBuffer *) info->data;
    GstMapInfo in_map_info;
    memset (&in_map_info, 0, sizeof (in_map_info));
    static uint32_t data_count = 0;

    if (buf) {
      g_print("cb_hava_data: offet=%lu from %s\n", buf->offset,
              (char *)user_data);
      if (gst_buffer_map (buf, &in_map_info, GST_MAP_READWRITE))
      {
        std::string hexstr = bytes_to_hex(in_map_info.data, in_map_info.size);
        std::cout << "cb_hava_data, count=" <<(++data_count) << ", size=" << in_map_info.size;
        if (data_count % 5 == 0) {
          std::cout << "receive data=" << hexstr << std::endl;
        }
        
      }
    }
    return GST_PAD_PROBE_OK;
}

GstPadProbeReturn cb_have_event(GstPad *pad, GstPadProbeInfo *info,
                                    gpointer user_data)
{

    GstEvent *event = gst_pad_probe_info_get_event(info);
    if (event)
      g_print("cb_hava_event: event type=%s from %s\n", GST_EVENT_TYPE_NAME(event),
              (char *)user_data);

    return GST_PAD_PROBE_OK;
}

GstPadProbeReturn cb_have_query(GstPad *pad, GstPadProbeInfo *info,
                                gpointer user_data)
{

    GstQuery *query = gst_pad_probe_info_get_query(info);

    g_print("cb_hava_query: query type=%s from %s\n", GST_QUERY_TYPE_NAME(query),
          (char *)user_data);

    return GST_PAD_PROBE_OK;
}

void add_pad_probe(GstPad *pad_to_probe, const char *evt_pad_name)
{
    // GST_PAD_PROBE_TYPE_BUFFER_LIST
    gulong probe_id_0 = gst_pad_add_probe(pad_to_probe,
                                          GST_PAD_PROBE_TYPE_BUFFER_LIST, cb_have_data_list,
                                          (gpointer)evt_pad_name, NULL);

    // GST_PAD_PROBE_TYPE_BUFFER
    gulong probe_id_1 = gst_pad_add_probe(pad_to_probe,
                                          GST_PAD_PROBE_TYPE_BUFFER, cb_have_data, (gpointer)evt_pad_name,
                                          NULL);

    // GST_PAD_PROBE_TYPE_EVENT_BOTH
    gulong probe_id_2 = gst_pad_add_probe(pad_to_probe,
                                          GST_PAD_PROBE_TYPE_EVENT_BOTH, cb_have_event,
                                          (gpointer)evt_pad_name, NULL);

    // GST_PAD_PROBE_TYPE_QUERY_BOTH
    gulong probe_id_3 = gst_pad_add_probe(pad_to_probe,
                                          GST_PAD_PROBE_TYPE_QUERY_BOTH, cb_have_query,
                                          (gpointer)evt_pad_name, NULL);

}

int main(int argc, char *argv[])
{

  GstElement *pipeline, *source, *sink;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;

  gst_init(&argc, &argv);

  /* Create the elements */
  source = gst_element_factory_make("audiotestsrc", "source");
  sink = gst_element_factory_make("fakesink", "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;
  }

  /* Modify the source's properties */
  g_object_set(source, "num-buffers", 10, NULL);
  g_object_set(source, "wave", 5, NULL);

  // Connect the handoff signal to the callback function
  g_signal_connect(sink, "handoff", G_CALLBACK(handoff_callback), NULL);

  GstPad* audioSinkPad = gst_element_get_static_pad(sink, "sink");
  add_pad_probe(audioSinkPad, "fakesink");

  /* 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.\n");
    gst_object_unref(pipeline);
    return -1;
  }

  /* Wait until error or EOS */
  bus = gst_element_get_bus(pipeline);
  msg = gst_bus_timed_pop_filtered(bus, GST_CLOCK_TIME_NONE,
                                 (GstMessageType)(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);
      break;
    case GST_MESSAGE_EOS:
      g_print("End-Of-Stream reached.\n");
      break;
    default:
      /* We should not reach here because we only asked for ERRORs and EOS */
      g_printerr("Unexpected message received.\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;
}


執(zhí)行結(jié)果如下

../bin/gst-fakesink
cb_hava_event: event type=stream-start from fakesink
cb_hava_query: query type=caps from fakesink
cb_hava_query: query type=caps from fakesink
cb_hava_event: event type=caps from fakesink
cb_hava_query: query type=accept-caps from fakesink
cb_hava_query: query type=accept-caps from fakesink
cb_hava_query: query type=allocation from fakesink
cb_hava_event: event type=segment from fakesink
cb_hava_event: event type=tag from fakesink
cb_hava_data: offet=0 from fakesink
cb_hava_data, count=1, size=2048cb_hava_query: query type=latency from fakesink
cb_hava_query: query type=latency from fakesink
cb_hava_event: event type=latency from fakesink
cb_hava_data: offet=1024 from fakesink
cb_hava_data, count=2, size=2048cb_hava_data: offet=2048 from fakesink
cb_hava_data, count=3, size=2048cb_hava_data: offet=3072 from fakesink
cb_hava_data, count=4, size=2048cb_hava_data: offet=4096 from fakesink
cb_hava_data, count=5, size=2048receive data=6436810BACB8DA15DBDBA62FF7BB9A1D9D4481D1AA9C154BC0DB4FBB235F6FDD4742E2D256EA17AB2E5642BFF34591F6CB9F8E0EDA61DB5D0C0185BC529F31B6C2DA23E9D9D42CF9BF3AFAF6CDAC29DC8A0EE05F3CD572E29F9D1C01CF2DC81C4CE8563371101A3915291852C66126D8BAFF73EAACFAC323142516DFCB65F89F922CE100692AABFCE019EA4F010156CD54A82DBBD2466FCBC3A5E1B75FC2B8C409E200FC419EFBBA4256321BBFAB8E1B6F22D82E85FB1BFE38A8C122B16253D876BCC9D2CA3E595C445D89FC89EF55FD3FFBEF06D438E017CAC2702842F865EE120D53029F3FAB53A8415C463E28E9DF7BEEC5D984ADACC74D56711EAA0F5A0F4B2A633C6CF02D4621242814B7A07216E8BA8EF666D2069AA42C2B0397305D0B65DD7EFE67CC5C55A03E07B6D79A74EBAFA4FD2D7E37435EF8DCC13ED1596EE7F4F04CEB410F352D4C1569E7039C99504147AE034A12A9D767B19CFEE69B2BC788F75266360AC13857B53C037DA11EB37DA19FD8FB5F1DFD48A34F1F1F2C305B133BE94CD72447B6BBCA620D1E3FF536C91B545FDE5E661F3BD628DE919DFAFA0F25CE5618393513C64698A78D06173B59366ABD30546BC44228BDE0BEDB8127A5609B17FA1BC62C79FAB1BAC402573EF6228931F902D2D2B59BAB65AB5DA80788B96EDEB2AA292A474CD9C268C505A3C01520B72AFFE1CDFE2DF032AAFA8907DC49993FBAD755A1FFCA8D4EED6143E129F09AA89C0E434EC214D435B99A9B1670A3C8CB933743E92E053FE06A9F8B5F91FDE2C984FBA25440C021B3380B83325762CD222CCB17E5173CE837279AC9DECA1893B080BA0EB9C621B062C0F3CA5905D99D48865D14D01A14B637DDC111CC463A8C3399E5F99FC6C33D304A280262AAE640BF9D235D1F89136912ADA7444741ADA850FC52D1C7A000484122AE04B5C3B1F661480D78C54407D1D7A6EB5831D9D4AF04C5C1D819B86160E6460190B12BE629FD1F028F495A3084B1541BA801AF1E1AF9C7ED4A01905AAF0217D017C4F7D866E09FF22DF9D00128C56240A81FFC16FD112BD3EB2521C4A09E63421DBE0D3BE0F9C59C475BCA45339E7B06792AE74F01355300F0FB4F4B3C193CFB76C21563C7473018981E1E608526A6A1FB2ADE9C01F3A363C91840CA98F847DCBC22C51CC50CCF4634AB1E56C04058B9311190A9AFC421A9D69E722CF6CFAB2F5CE32702E30CE6392AE3500F95C09ABD19A19EA55E27DD14F31C2DBF7201AE249CEFF3D331B1BCBBB3B2ECED292B2A0AA138DB4C55A1D34AA0AB9F2B2FAD33C0981ACC5F40DE4EB47FCB2DC474B4094C5BD5462A1462201EEBB67855F7D5B3AD061434DF493922D4BD01055F190EA752F6CBD1AAE53C6DE7289AF2FF4BA73CEE5B3BBCC430C50B134AA03C4AAE4E0BEEF29FB89F16575F068C128058A9CFC7CF29AA2153631C3BA9CBC69464F0AE731EE7ACE0F987C3322F8EA245354F1DBB0A5764CBA29B1748E6EB484B553848033C16DFDFD211D435E1ED10172EA44153B2D9AF6F415550AABA033210FBC79F26C4F04F76CDC9B9E0530244D1EB6C355F0238B853D3051AB7B7873C542D0C048A5E4FEF95D2514601E452BFB3D8D006EF04EFE0DC1373B6DFFCABA5B40CCA06305A86325A206CED6A534631BFB1FA4B7DCC7832493821ABFD9C0C1233AEAAA9EDF7A4401E06D1517B5A423E9C9A22A7943324DBD1D4A4245DE03CD937DE14370DA41F543E01F9184FC782483BF311AD53D09CBBAC9934C72CD2CD40AA9A28C62C2FB0C5BCF3B5F1C40219DB09ECAFC707AC6406B43EF749F829714FFBAB3028F9CC625FE730AB126F2CEF636D0FA29F3EB2B333CB2345B2873A611B66EFA508B225FA4B00BB19BA2CAF512D3EE2CB5AEA5C022D12C851EB88D991B227E20CB4379EEE5DF4BC2D100D1263A3B6A2450746141EBEE6FA801BB4CB9FAEB7FC5A5DAB23EC21D7FD779F4FEDA64541B28EC2C65DFEB96BC90E33EBDAFCE2EE0E8065A52595CE293522CD13C68EED18B884B18FC5EDEA5F5C975F085758A1C522CE31833C3B1B8019842314E3B3B6D80AD0F52D33A02252E1D82DDAD09C0116EA992298FBB5A34B4638576CBB56BCAC4DA558169FBC51E3AEEAE6EF24CA9B3531B9DA67A79C23B0BD3CA459271950801011E168C5A2E674C6973BBDECE6FCF310A9C7C24A8E4AD9117F16E119FA4CD1D23AE21CA5DFCC7D36EC2494AC9A4C319F4FD2EAEB4EFA27F570C156FAA355DCD231DF0D2F5DDE1131A8A70B54CE58BC515AC0ECE7A1E53B407D5700B337DD9EC3314A8353FD2B82AD34566C24095B2AD4C39A29D8F1BF58528C1E242204C685B6EE3CD73F85A2D7E48013C4098013342FB12E0DCCAAA228233CA828E5ED247BE58EA53706D8255B19A4A5B4C2AEA5E7EC9B538FA59AC9EDDEFEB91959F46026AACDF232A70A25293E855A549B6F074DC36331D603E059E230F8581E55C317635546ECE336F2DED65ACF3D0138F44C07FF114B75A741EBE555DA4954EDBF9E869A9C1931A971BFCE0165F1369F4E461D2CA6FA32DC232887B26AAD8FDB96369A566EFF621FC34B9840FE0DE73D77A332F0144832C179CE90D237BBEBEAF03533E2E4F15846824A2DD2BEEBD3D0F9DFE0FDC2282F2C59C5A50B8915E003F322B2E8D101E40141B6C44775FAF2FC20D8E9FB89B04BA90901F63222DD3FBBC4ACC8F45EB06EC34B371000245FA604EB21A3246B58BBB1D9FE144EFC50FAE4BF56CCC2DBA4EF5783AD534CBFCAD01268FAE0AF0AE8305B8CE7BFBA49FB40A077C0AD1FE665150E7AC64CD4C7F63560941F24EE420899DAA3548A34EA02E15C8CBA955349D26FCE07EB2437CDB352F4890B43DD3EE098150BEC2807126295F06461A79AD2D9BDA7CECF
cb_hava_data: offet=5120 from fakesink
cb_hava_data, count=6, size=2048cb_hava_data: offet=6144 from fakesink
cb_hava_data, count=7, size=2048cb_hava_data: offet=7168 from fakesink
cb_hava_data, count=8, size=2048cb_hava_data: offet=8192 from fakesink
cb_hava_data, count=9, size=2048cb_hava_data: offet=9216 from fakesink
cb_hava_data, count=10, size=2048receive data=E52F5ED3E9F2FEE91EFD2ED5719BC101D2CD2C031007C1F506ADB335F83DE902FA0936B32E2ED4215552BDF5835977EBB1FFB42B1A5E6BAE5CD9A7B5AA102038B7FB8458C74847595C36FC0AA05A2BE9C7E36CCB1E5F37D991E55FB2764CAE9DBFD0862292AAA8ADB25306F9BA37AEA4D113BAD15DD3642CB25B5AF2131522F8D2EC05417A402FFED3DF6AC002A09C333BD2162D7C5EE4D1D3EF0635E72724E3250A9532BE33C0A3C82843AF531D150B84AC91CE4BDDD8178111993F62574D3EEC51DD4DE800EF3EDB3D04BB9BA1754F255D24BEFF2942DC1D44630CB525264186AAC243CAD462D7AB9BD63E264ECFF01E0AD8A55BE776FED8287AE750B89EBFE21FC333700930EB7ACD282D1E0AAA37C105BDF1180EDBD699A9C0AFC74F184CA414E005DD9913BB7C104D63430DD642EF0D55D388456CE797C290CA0D190B47A2BC8621FF3BCF5C2B23E74E3EE5C10ADBED779D2F55B01D176419C4FCE20702C70098AAB900D52061FE9321C75B74384CFE7DC32C35D7B21E61D050683D7FC84ABD330C3C25195ACCB920F88A49C69CEF528AE2B2D780A47EE56736655A7354114A9F07F0EAD39DA75A8B1A763CED29593A7333DC3CC6F7DC38613C97F6660E33AA15FE6AB3BEBCDF3126ED3AB88FF83B120A3C5D552EB69EA11A494AB830EE3AE8D2A02C9AE04985FFFCE933C11644C81EF709FC4491BE24E7C01DB0142BADBB61BA31985C4FDBF365A15C78EB2F0AD5059B1100FE02C3F5C6975FBF28F03CAAB712E9A2F679E770EEDFD4FE1718D672AF7DD240C384A83FBA53537824AEE099FB415A1CB4710C94C9FED370C3E50FC9CF964A38EA5E21D2DACBBC7C3161C6E44F9A1CAFA4AA9F0AA110BD3AB90AB55766BDEC17FCEF2DED427F2A775CF3F34BE6D8FC29EB295EC50C2A410B50E83FADEE1DC1CD3B55367764FDF23FE02EFDE8B5D1A0F1E57B48B8F008A8490580F0A7F6F51D06A99C63D90B6BF1E1340F48CA63ADE0FAF869B0CD28B924BE3AC549BB28AE1231F8C52FEAD0DDCE24B4A9197EABBF2947B4A5FD9300D904ED6066B881CEC4FDC29955A6F4BC645BB7BE583B09A52536B9336A1CE5F9F450741A6613FF47344A9262AF1216A012F176D010602AAA200291D893461CC492044CC32A25EA9C9E227D17E7BC3FC49A04754FDCA3C2E2764E35A636E56FBD38C2D20A60EDBFC29F53B3253BBA654FD74089FF960D02C1E5A4AAB6FA3CF1B2AECC10A731667EE86022E0B410552137CA5CF5EA00A5D9E828AC481CBC17562637E6530E9B9F2C0D0354B9C3D81E43AE5EFCB1F1601666F00BA985A1C7B528125BAAADA13728C1C34543F2BEDEA62FBFE7A0DB49DCAD0DE562C11DEFC6C0C8C9D65E2E04C11F80509CAA8B545FB357EE14E33CD418EEF149E639740B03D0E5A8D90279A3FBE4D60F33D06B159EC203FE1E0E1F45E0C81E6441EC5D04A3ACE2E84EAC06C25F1D78A6835336561F21C0E2B39B0247285D7E1FE5AD3CB355130504B7BA51192943B107A86210471F3F5ED1E6CD8BADBA4ED44FF642E9F5F1A2652621A0DF53A9FF2601E1F27AA3A0A40357744123EAC64A68C5FE0AEEACBFA3DEA691D4E23045B59C514D09BAA1CA40FCB3CEBEB61D90A4B8494EC1692A000F825CECBF5214133592200625F4643AF6170927C6C8A9255102245AF5B33EFC53AE43FCFD67AC77F17CD16727BE44C4A6A5C9A6FDB76274E474FAF25EB2D94F46FB4D0EDE2A478BAD0352CD3C1ABFD2407306F25CF8C2ECF271372D5560F3283078E03F3BA0B81F06A53F543F27E981E9AB1CBB4D91542A654C3C9B9BDB525FB74C1112BCCCA363EE54E37D595F3EC1EE07C08414BAD31EB808EF7CCD9306E44645BDA042A6BE25E6ED142027633B673DC52DBA4761C81A371D4E3053B63306C8FF55870BD82E7BC26625C0E6794B28CC0E17953A0C2C922B7A186B050FF9ED508624E8B0909E8830D25AECD884E6C5F3955CF25BB144EDE651E2F417A41D1B10720C4254AF339653202AC6F5CEB25CA0A4A72106CCB7D7EAAF38D2E12D64E103FA3F39E987C9EC4EA64E1EFFCDD6A0E777F30E63F2014541C10CE9285C205D01DE44ED1EE42B2DF5D6DA75B556B312E0A60954B38DF301513AD4481FFDA5E61628EA8AA9432BE99E794792DF23D79AF45EA2F1CAED23E433553F54F2CB511448C9CB13FBBFAE40F58FE8954A05FA073341BC18EE7B5AFCC781B357EB50B0DCCEBBFC5E10ADB63147F9F94C109ACBE0DAB951970F0363AD0F1A66F446E0A69BB410F83CAEDE3F505712EE7E2683BAC8DF74B398C6A4BE649C2CF52411CB01E6FDDF4B455AA00112E2081CC95D1E11505806B8CD9CAF20E856455E3BD0D165C35D2D26B1E68E43C328B308EAC567A17F1373393914604A98F023565834ACF94ACE9340C263FD5A83279C0D2902C05B95F514DCC0CD2456B89CE1BA090550C52933C32BC35700581962FBFF260B9903CB399F3B12D4942E0B1792C9CA58CEE7A45C020478D21A1D14E2D3DD9E1F259C67A61211EF175B03325F64B0C7E969BFBECA546193D6AA40AF628D5BECE7A7C927CD1B0C115364D54F2DA2B9A6A8F1BDBFA051C51054A60569247EB3D9AA97633534C9473CE35C3A33C9B3A9C241F2E7EFFD40FFC93325C7B8E75F9C9916E8E381C6D948000629B590BFA6B2A8E5BA3F58BB5F1E28038408BE495C5E70D553DDA29FBAAB2012D4249ABCF0F4F7BF51D774DD6D376124A3CEE0C6200ADBB62AE17EE487358BE9BAF537CB3A04C15B6CC1655F39356CD1ECF08D9DEDC27C58A318F44BC5366936A4CC27EBF4B5E0BFCCC97B1A38666CE849123546A2E2DF451FE70EE029EB790C7D5DE3EB53DB521910F4B5D3AE0F03F585BD05AE1C3B8544783BABCCDA241BE7E951511A
cb_hava_event: event type=eos from fakesink
End-Of-Stream reached.

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末潮改,一起剝皮案震驚了整個濱河市狭郑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌汇在,老刑警劉巖翰萨,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糕殉,居然都是意外死亡亩鬼,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門阿蝶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來雳锋,“玉大人,你說我怎么就攤上這事羡洁$韫” “怎么了筑煮?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長真仲。 經(jīng)常有香客問我,道長袒餐,這世上最難降的妖魔是什么飞蛹? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任谤狡,我火速辦了婚禮,結(jié)果婚禮上卧檐,老公的妹妹穿的比我還像新娘墓懂。我一直安慰自己,他們只是感情好霉囚,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布捕仔。 她就那樣靜靜地躺著,像睡著了一般盈罐。 火紅的嫁衣襯著肌膚如雪榜跌。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天盅粪,我揣著相機(jī)與錄音钓葫,去河邊找鬼。 笑死票顾,一個胖子當(dāng)著我的面吹牛础浮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播奠骄,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼豆同,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了含鳞?” 一聲冷哼從身側(cè)響起影锈,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蝉绷,沒想到半個月后鸭廷,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡潜必,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年靴姿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蛇更,靈堂內(nèi)的尸體忽然破棺而出维雇,到底是詐尸還是另有隱情吱型,我是刑警寧澤津滞,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布触徐,位于F島的核電站,受9級特大地震影響疟丙,放射性物質(zhì)發(fā)生泄漏享郊。R本人自食惡果不足惜炊琉,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一温自、第九天 我趴在偏房一處隱蔽的房頂上張望皇钞。 院中可真熱鬧夹界,春花似錦可柿、人聲如沸复斥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奖唯。三九已至糜值,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間病往,已是汗流浹背荣恐。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工叠穆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留硼被,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像仔掸,于是被迫代替她去往敵國和親起暮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容