gstreamer分析-rtp流的接收

 关于数据流的接收过程,[1]有很好的分析。这个问题,令人困惑,依然有些东西没有搞明白。gst_pad_start_task()创建任务,使得gst_base_src_loop()被循环调用。

gst_base_src_set_playing
{
    if (start)
      gst_pad_start_task (basesrc->srcpad, (GstTaskFunction) gst_base_src_loop,
          basesrc->srcpad, NULL);   
}
static void
gst_base_src_loop (GstPad * pad)
{
  ret = gst_base_src_get_range (src, position, blocksize, &buf);
}
static GstFlowReturn
gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
    GstBuffer ** buf)
{
  ret = bclass->create (src, offset, length, &res_buf);
//GstBaseClass中的函数指针klass->create = GST_DEBUG_FUNCPTR (gst_base_src_default_create);
  if (src->priv->pending_bufferlist != NULL) {
    ret = gst_pad_push_list (pad, src->priv->pending_bufferlist);
    src->priv->pending_bufferlist = NULL;
  } else {
    ret = gst_pad_push (pad, buf);//数据在pipeline中流动,调用下一个element的chainfun,推送数据。
  }
}
static GstFlowReturn
gst_base_src_default_create (GstBaseSrc * src, guint64 offset,
    guint size, GstBuffer ** buffer)
{
    ret = bclass->fill (src, offset, size, res_buf);
//这个函数在子类中被覆盖gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_push_src_fill);
}
static GstFlowReturn
gst_push_src_fill (GstBaseSrc * bsrc, guint64 offset, guint length,
    GstBuffer * ret)
{
  pclass = GST_PUSH_SRC_GET_CLASS (src);
  if (pclass->fill)//GstPushSrcClass有同名的方法,与bclass->fill不同
    fret = pclass->fill (src, ret);//这个方法再次被子类覆盖
}
//其中GstUDPSrcClass继承了GstPushSrc
//gstpushsrc_class->fill = gst_udpsrc_fill;
static GstFlowReturn
gst_udpsrc_fill (GstPushSrc * psrc, GstBuffer * outbuf)
{
//问题出现,向socket读取数据,数据流就一定到来了吗?
//g_socket_condition_timed_wait说明这个socket并不是一个阻塞的socket。那么要是没有数据该怎么处理?
  res =
      g_socket_receive_message (udpsrc->used_socket, p_saddr, ivec, 2,
      p_msgs, &n_msgs, &flags, udpsrc->cancellable, &err);
}

 udosrc怎么同rtpbin关联起来呢?gst-lpugins-good/tests/examples/client-rtpaux.c下有个例子,有个图:


example

 udosrc和rtpbin都继承了element。gst_element_link_pads将两者连起来。

rtpSrc = gst_element_factory_make ("udpsrc", NULL);
gst_element_link_pads (rtpSrc, "src", rtpBin, padName);

 rtpbin中的pad是如何接收数据呢?

static GstPad *
gst_rtp_bin_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink_%u")) {
    result = create_recv_rtp (rtpbin, templ, pad_name);
  }
}
static GstPad *
create_recv_rtp (GstRtpBin * rtpbin, GstPadTemplate * templ, const gchar * name)
{
  recv_rtp_sink = complete_session_sink (rtpbin, session, TRUE);
}
static GstPad *
complete_session_sink (GstRtpBin * rtpbin, GstRtpBinSession * session,
    gboolean bundle_demuxer_needed)
{
  session->recv_rtp_sink =
      gst_element_get_request_pad (session->session, "recv_rtp_sink");
}
static GstPad *
gst_rtp_session_request_new_pad (GstElement * element,
    GstPadTemplate * templ, const gchar * name, const GstCaps * caps)
{
  /* figure out the template */
  if (templ == gst_element_class_get_pad_template (klass, "recv_rtp_sink")) {
    if (rtpsession->recv_rtp_sink != NULL)
      goto exists;

    result = create_recv_rtp_sink (rtpsession);
  }
}
static GstPad *
create_recv_rtp_sink (GstRtpSession * rtpsession)
{
  gst_pad_set_chain_function (rtpsession->recv_rtp_sink,
      gst_rtp_session_chain_recv_rtp);
  return rtpsession->recv_rtp_sink;
}

gst_pad_push中调用的chainfun就是这个gst_rtp_session_chain_recv_rtp。
 接下来分析rtp数据流的处理,以on-feedback-rtcp这个类型的消息为例。

static GstFlowReturn
gst_rtp_session_chain_recv_rtp (GstPad * pad, GstObject * parent,
    GstBuffer * buffer)
{
  ret = rtp_session_process_rtp (priv->session, buffer, current_time,
      running_time, ntpnstime);
}
GstFlowReturn
rtp_session_process_rtp (RTPSession * sess, GstBuffer * buffer,
    GstClockTime current_time, GstClockTime running_time, guint64 ntpnstime)
{
  /* update pinfo stats */
  if (!update_packet_info (sess, &pinfo, FALSE, TRUE, FALSE, buffer,
          current_time, running_time, ntpnstime)) {
    GST_DEBUG ("invalid RTP packet received");
    RTP_SESSION_UNLOCK (sess);
    return rtp_session_process_rtcp (sess, buffer, current_time, ntpnstime);
  }
}
GstFlowReturn
rtp_session_process_rtcp (RTPSession * sess, GstBuffer * buffer,
    GstClockTime current_time, guint64 ntpnstime)
{
    switch (type) {
      case GST_RTCP_TYPE_PSFB:
        rtp_session_process_feedback (sess, &packet, &pinfo, current_time);
        break;
}
}
static void
rtp_session_process_feedback (RTPSession * sess, GstRTCPPacket * packet,
    RTPPacketInfo * pinfo, GstClockTime current_time)
{
  if (g_signal_has_handler_pending (sess,
          rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP], 0, TRUE)) {
    g_signal_emit (sess, rtp_session_signals[SIGNAL_ON_FEEDBACK_RTCP], 0,
        type, fbtype, sender_ssrc, media_ssrc, fci_buffer);
}
}
//需要查找下程序哪里注册了"on-feedback-rtcp"这个信号。
//以此为例,信号的注册是这个形式g_signal_connect (rtpsession, "on-feedback-rtcp", G_CALLBACK (callback_fun), self);
//信号发射g_signal_emit,就会调用callback_fun进行处理。
//这样的注册函数在kurento里有。
static void
kms_remb_remote_on_feedback_rtcp (GObject *rtpsession,
    guint type, guint fbtype, guint sender_ssrc, guint media_ssrc,
    GstBuffer *fci)
{
  GST_LOG_OBJECT (rtpsession, "Signal 'on-feedback-rtcp'");
  if (type == GST_RTCP_TYPE_PSFB
      && fbtype == GST_RTCP_PSFB_TYPE_AFB) {
    process_psfb_afb (rtpsession, sender_ssrc, fci);
  }
}

 前前后后一共浪费了六天时间,好奇心害死猫。以后应该研究一些数学密集型的程序,而不是逻辑密集型的程序。
 剧终。
[1]GStreamer插件架构简析

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,324评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,356评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,328评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,147评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,160评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,115评论 1 296
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,025评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,867评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,307评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,528评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,688评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,409评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,001评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,657评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,811评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,685评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,573评论 2 353

推荐阅读更多精彩内容