rtph264depay插件分析笔记

1、rtp协议头

2、rtp可以基于TCP或者UDP

其中基于TCP需要加4个字节的RTP标志

3、rtph264depay定义解析函数gst_rtp_h264_depay_process,通过RFC 3984文档实现。

static void
gst_rtp_h264_depay_class_init (GstRtpH264DepayClass * klass)
{
  GObjectClass *gobject_class;
  GstElementClass *gstelement_class;
  GstRTPBaseDepayloadClass *gstrtpbasedepayload_class;
  gobject_class = (GObjectClass *) klass;
  gstelement_class = (GstElementClass *) klass;
  gstrtpbasedepayload_class = (GstRTPBaseDepayloadClass *) klass;
  gobject_class->finalize = gst_rtp_h264_depay_finalize;
  gobject_class->set_property = gst_rtp_h264_depay_set_property;
  gobject_class->get_property = gst_rtp_h264_depay_get_property;

  /**
   * GstRtpH264Depay:wait-for-keyframe:
   *
   * Wait for the next keyframe after packet loss,
   * meaningful only when outputting access units
   *
   * Since: 1.20
   */
  g_object_class_install_property (gobject_class, PROP_WAIT_FOR_KEYFRAME,
      g_param_spec_boolean ("wait-for-keyframe", "Wait for Keyframe",
          "Wait for the next keyframe after packet loss, meaningful only when "
          "outputting access units",
          DEFAULT_WAIT_FOR_KEYFRAME,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));

  /**
   * GstRtpH264Depay:request-keyframe:
   *
   * Request new keyframe when packet loss is detected
   *
   * Since: 1.20
   */
  g_object_class_install_property (gobject_class, PROP_REQUEST_KEYFRAME,
      g_param_spec_boolean ("request-keyframe", "Request Keyframe",
          "Request new keyframe when packet loss is detected",
          DEFAULT_REQUEST_KEYFRAME,
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
  gst_element_class_add_static_pad_template (gstelement_class,
      &gst_rtp_h264_depay_src_template);
  gst_element_class_add_static_pad_template (gstelement_class,
      &gst_rtp_h264_depay_sink_template);
  gst_element_class_set_static_metadata (gstelement_class,
      "RTP H264 depayloader", "Codec/Depayloader/Network/RTP",
      "Extracts H264 video from RTP packets (RFC 3984)",
      "Wim Taymans <wim.taymans@gmail.com>");
  gstelement_class->change_state = gst_rtp_h264_depay_change_state;
  gstrtpbasedepayload_class->process_rtp_packet = gst_rtp_h264_depay_process;
  gstrtpbasedepayload_class->set_caps = gst_rtp_h264_depay_setcaps;
  gstrtpbasedepayload_class->handle_event = gst_rtp_h264_depay_handle_event;
}

4、gst_rtp_h264_depay_process的具体实现

static GstBuffer *
gst_rtp_h264_depay_process (GstRTPBaseDepayload * depayload, GstRTPBuffer * rtp)
{
    GstRtpH264Depay *rtph264depay;
    GstBuffer *outbuf = NULL;
    guint8 nal_unit_type;
    rtph264depay = GST_RTP_H264_DEPAY (depayload);
    if (!rtph264depay->merge)
        rtph264depay->waiting_for_keyframe = FALSE;

    /* 是否是弃用数据 */
    if (GST_BUFFER_IS_DISCONT (rtp->buffer)) {
        gst_adapter_clear (rtph264depay->adapter);
        rtph264depay->wait_start = TRUE;
        rtph264depay->current_fu_type = 0;
        rtph264depay->last_fu_seqnum = 0;
        if (rtph264depay->merge && rtph264depay->wait_for_keyframe) {
            rtph264depay->waiting_for_keyframe = TRUE;
        }
        if (rtph264depay->request_keyframe)
        gst_pad_push_event (GST_RTP_BASE_DEPAYLOAD_SINKPAD (depayload),gst_video_event_new_upstream_force_key_unit (GST_CLOCK_TIME_NONE,TRUE, 0));
    }

    {
    gint payload_len;
    guint8 *payload;
    guint header_len;
    guint8 nal_ref_idc;
    GstMapInfo map;
    guint outsize, nalu_size;
    GstClockTime timestamp;
    gboolean marker;

    timestamp = GST_BUFFER_PTS (rtp->buffer);
    payload_len = gst_rtp_buffer_get_payload_len (rtp);
    payload = gst_rtp_buffer_get_payload (rtp);
    marker = gst_rtp_buffer_get_marker (rtp);
    GST_DEBUG_OBJECT (rtph264depay, "receiving %d bytes", payload_len);

    if (payload_len == 0)
        goto empty_packet;

    /* +---------------+
     * |0|1|2|3|4|5|6|7|
     * +-+-+-+-+-+-+-+-+
     * |F|NRI|  Type   |
     * +---------------+
     *
     * F must be 0.
     */
    nal_ref_idc = (payload[0] & 0x60) >> 5;
    nal_unit_type = payload[0] & 0x1f;

    /* at least one byte header with type */
    header_len = 1;
    GST_DEBUG_OBJECT (rtph264depay, "NRI %d, Type %d %s", nal_ref_idc, nal_unit_type, marker ? "marker" : "");

    /* If FU unit was being processed, but the current nal is of a different
     * type.  Assume that the remote payloader is buggy (didn't set the end bit
     * when the FU ended) and send out what we gathered thusfar */
    if (G_UNLIKELY (rtph264depay->current_fu_type != 0 && nal_unit_type != rtph264depay->current_fu_type))
        gst_rtp_h264_finish_fragmentation_unit (rtph264depay);

    switch (nal_unit_type) {
      case 0:
      case 30:
      case 31:
        /* undefined */
        goto undefined_type;
      case 25:
        /* STAP-B    Single-time aggregation packet     5.7.1 */
        /* 2 byte extra header for DON */
        header_len += 2;
        /* fallthrough */
      case 24:
      {
        /* strip headers */
        payload += header_len;
        payload_len -= header_len;
        rtph264depay->wait_start = FALSE;

        /* STAP-A    Single-time aggregation packet     5.7.1 */
        while (payload_len > 2) {
            gboolean last = FALSE;
          /*                      1
           *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
           * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           * |         NALU Size             |
           * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
           */
          nalu_size = (payload[0] << 8) | payload[1];

          /* don't include nalu_size */
          if (nalu_size > (payload_len - 2))
            nalu_size = payload_len - 2;

          outsize = nalu_size + sizeof (sync_bytes);
          outbuf = gst_buffer_new_and_alloc (outsize);
          gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
          if (rtph264depay->byte_stream) {
            memcpy (map.data, sync_bytes, sizeof (sync_bytes));
          } else {
            map.data[0] = map.data[1] = 0;
            map.data[2] = payload[0];
            map.data[3] = payload[1];
          }

          /* strip NALU size */
          payload += 2;
          payload_len -= 2;
          memcpy (map.data + sizeof (sync_bytes), payload, nalu_size);
          gst_buffer_unmap (outbuf, &map);
          gst_rtp_copy_video_meta (rtph264depay, outbuf, rtp->buffer);
          if (payload_len - nalu_size <= 2)
            last = TRUE;
          gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp,
              marker && last);
          payload += nalu_size;
          payload_len -= nalu_size;
        }
        break;
      }
      case 26:
        /* MTAP16    Multi-time aggregation packet      5.7.2 */
        // header_len = 5;
        /* fallthrough, not implemented */
      case 27:
        /* MTAP24    Multi-time aggregation packet      5.7.2 */
        // header_len = 6;
        goto not_implemented;
        break;
      case 28:
      case 29:
      {
        /* FU-A      Fragmentation unit                 5.8 */
        /* FU-B      Fragmentation unit                 5.8 */
        gboolean S, E;
        /* +---------------+
         * |0|1|2|3|4|5|6|7|
         * +-+-+-+-+-+-+-+-+
         * |S|E|R|  Type   |
         * +---------------+
         *
         * R is reserved and always 0
         */
        S = (payload[1] & 0x80) == 0x80;
        E = (payload[1] & 0x40) == 0x40;
        GST_DEBUG_OBJECT (rtph264depay, "S %d, E %d", S, E);

        if (rtph264depay->wait_start && !S)
          goto waiting_start;

        if (S) {
          /* NAL unit starts here */
          guint8 nal_header;

          /* If a new FU unit started, while still processing an older one.
           * Assume that the remote payloader is buggy (doesn't set the end
           * bit) and send out what we've gathered thusfar */
          if (G_UNLIKELY (rtph264depay->current_fu_type != 0))
            gst_rtp_h264_finish_fragmentation_unit (rtph264depay);
          rtph264depay->current_fu_type = nal_unit_type;
          rtph264depay->fu_timestamp = timestamp;
          rtph264depay->last_fu_seqnum = gst_rtp_buffer_get_seq (rtp);
          rtph264depay->wait_start = FALSE;
          /* reconstruct NAL header */
          nal_header = (payload[0] & 0xe0) | (payload[1] & 0x1f);

          /* strip type header, keep FU header, we'll reuse it to reconstruct
           * the NAL header. */
          payload += 1;
          payload_len -= 1;

          nalu_size = payload_len;
          outsize = nalu_size + sizeof (sync_bytes);
          outbuf = gst_buffer_new_and_alloc (outsize);

          gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
          memcpy (map.data + sizeof (sync_bytes), payload, nalu_size);
          map.data[sizeof (sync_bytes)] = nal_header;
          gst_buffer_unmap (outbuf, &map);

          gst_rtp_copy_video_meta (rtph264depay, outbuf, rtp->buffer);
          GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);

          /* and assemble in the adapter */
          gst_adapter_push (rtph264depay->adapter, outbuf);
        } else {
          if (rtph264depay->current_fu_type == 0) {
            /* previous FU packet missing start bit? */
            GST_WARNING_OBJECT (rtph264depay, "missing FU start bit on an "
                "earlier packet. Dropping.");
            gst_adapter_clear (rtph264depay->adapter);
            return NULL;
          }
          if (gst_rtp_buffer_compare_seqnum (rtph264depay->last_fu_seqnum,
                  gst_rtp_buffer_get_seq (rtp)) != 1) {
            /* jump in sequence numbers within an FU is cause for discarding */
            GST_WARNING_OBJECT (rtph264depay, "Jump in sequence numbers from "
                "%u to %u within Fragmentation Unit. Data was lost, dropping "
                "stored.", rtph264depay->last_fu_seqnum,
                gst_rtp_buffer_get_seq (rtp));
            gst_adapter_clear (rtph264depay->adapter);
            return NULL;
          }
          rtph264depay->last_fu_seqnum = gst_rtp_buffer_get_seq (rtp);

          /* strip off FU indicator and FU header bytes */
          payload += 2;
          payload_len -= 2;
          outsize = payload_len;
          outbuf = gst_buffer_new_and_alloc (outsize);
          gst_buffer_fill (outbuf, 0, payload, outsize);
          gst_rtp_copy_video_meta (rtph264depay, outbuf, rtp->buffer);
          GST_DEBUG_OBJECT (rtph264depay, "queueing %d bytes", outsize);

          /* and assemble in the adapter */
          gst_adapter_push (rtph264depay->adapter, outbuf);
        }
        outbuf = NULL;
        rtph264depay->fu_marker = marker;

        /* if NAL unit ends, flush the adapter */
        if (E)
          gst_rtp_h264_finish_fragmentation_unit (rtph264depay);
        break;
      }
      default:
      {
        rtph264depay->wait_start = FALSE;

        /* 1-23   NAL unit  Single NAL unit packet per H.264   5.6 */
        /* the entire payload is the output buffer */
        nalu_size = payload_len;
        outsize = nalu_size + sizeof (sync_bytes);
        outbuf = gst_buffer_new_and_alloc (outsize);

        gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
        if (rtph264depay->byte_stream) {
          memcpy (map.data, sync_bytes, sizeof (sync_bytes));
        } else {
          map.data[0] = map.data[1] = 0;
          map.data[2] = nalu_size >> 8;
          map.data[3] = nalu_size & 0xff;
        }
        memcpy (map.data + sizeof (sync_bytes), payload, nalu_size);
        gst_buffer_unmap (outbuf, &map);
        gst_rtp_copy_video_meta (rtph264depay, outbuf, rtp->buffer);
        gst_rtp_h264_depay_handle_nal (rtph264depay, outbuf, timestamp, marker);
        break;
      }
    }
  }
  return NULL;

  /* ERRORS */
empty_packet:
  {
    GST_DEBUG_OBJECT (rtph264depay, "empty packet");
    return NULL;
  }
undefined_type:
  {
    GST_ELEMENT_WARNING (rtph264depay, STREAM, DECODE,
        (NULL), ("Undefined packet type"));
    return NULL;
  }
waiting_start:
  {
    GST_DEBUG_OBJECT (rtph264depay, "waiting for start");
    return NULL;
  }
not_implemented:
  {
    GST_ELEMENT_ERROR (rtph264depay, STREAM, FORMAT,
        (NULL), ("NAL unit type %d not supported yet", nal_unit_type));
    return NULL;
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/496475.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RTSP应用:实现视频流的实时推送

在实现实时视频流推送的项目中&#xff0c;RTSP&#xff08;Real Time Streaming Protocol&#xff09;协议扮演着核心角色。本文将指导你通过安装FFmpeg软件&#xff0c;下载并编译live555&#xff0c;以及配置ffmpeg进行视频流推送&#xff0c;来实现一个基本的RTSP流媒体服务…

WIN使用LPD协议来共享打印机含统信UOS

打开“控制面板”&#xff0c;“程序和功能”&#xff0c;“启动或关闭Windows功能”&#xff0c;下拉找到“打印和文件服务”&#xff0c;勾选“LPD打印服务”和“LPR端口监视器”。确定之后重启电脑&#xff0c;共享主机和其它需要添加共享打印机的都开启功能和重启。 一、启…

SpringMVC设置全局异常处理器

文章目录 背景分析使用ControllerAdvice&#xff08;RestControllerAdvice&#xff09;ExceptionHandler实现全局异常全局异常处理-多个处理器匹配顺序存在一个类中存在不同的类中 对于过滤器和拦截器中的异常&#xff0c;有两种思路可以考虑 背景 在项目中我们有需求做一个全…

定时器的原理和应用

#include<reg51.h> unsigned char s[]{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; unsigned char count0,num0; void inittimer() {TMOD0x01;//0000 0001TH0(65536-50000)/256; //定时50ms50000us 2562^8 初值向右边移动8位TL0(65536-50000)%256;ET01;//开启定…

TouchGFX之Button

TouchGFX中的按钮是一种感应触控事件的控件&#xff0c;能够在按钮被按下/释放时发送回调 代码 #ifndef TOUCHGFX_ABSTRACTBUTTON_HPP #define TOUCHGFX_ABSTRACTBUTTON_HPP #include <touchgfx/Callback.hpp> #include <touchgfx/events/ClickEvent.hpp> #includ…

面试题目--3.19

1.foo()和foo()之间有什么区别&#xff1f; 代表所有的warning忽略 2.什么是csrf攻击&#xff1f;如何防范&#xff1f; csrf&#xff0c;跨站请求伪造&#xff0c;攻击方伪装用户身份发送请求从而窃取信息或者破坏系统。 基本原理&#xff1a;用户访问a网站登录并生成了coo…

opencv 十九 python下实现多线程间rtsp直播流的复用

在多线程拉流的任务场景中&#xff0c;有时需要将一个rtsp拉取多次&#xff0c;每重新打开一次rtsp视频流就要多消耗一次带宽&#xff0c;为此基于类的静态对象实现rtsp视频流的复用。 1、实现代码 import threading import cv2,time #接收摄影机串流影像&#xff0c;采用多线…

论文《Exploring to Prompt for Vision-Language Models》阅读

论文《Exploring to Prompt for Vision-Language Models》阅读 论文概况论文动机&#xff08;Intro&#xff09;MethodologyPreliminaryCoOp[CLASS]位置Context 是否跨 class 共享表示和训练 ExperimentsOverall ComparisonDomain GeneralizationContext Length (M) 和 backbon…

如何配置本地ssh连接远程Linux服务器

1.条件 本地操作系统Ubuntu远程服务器&#xff08;Linux都可以&#xff09; 本地如果是Window,其实也一样&#xff0c;但是需要先下载ssh和putty工具&#xff0c;然后操作步骤是一样的 2.生成ssh公私钥对 # 在本地重新生成SSH公私钥对非常简单&#xff0c;在你的命令行终端&a…

vscode从安装到卸载

&#x1f308;个人主页&#xff1a;Rookie Maker &#x1f3c6;&#x1f3c6;关注博主&#xff0c;随时获取更多关于IT的优质内容&#xff01;&#x1f3c6;&#x1f3c6; &#x1f600;欢迎来到小田代码世界~ &#x1f601; 喜欢的小伙伴记得一键三连哦 ૮(˶ᵔ ᵕ ᵔ˶)ა …

任务2.1 一元二次方程(顺序结构版)

在这个任务中&#xff0c;我们编写了一个Java程序来解决一元二次方程。程序接受用户输入的系数a、b、c&#xff0c;并计算出方程的根。通过计算判别式delta的值&#xff0c;我们可以确定方程有两个不相等实根、两个相等实根还是没有实数根。这个程序遵循了IPO模式&#xff0c;即…

GEC6818开机自动加载驱动与更改开发板的RTC时钟

GEC6818开机自动加载驱动与更改开发板的RTC时钟 本文主要涉及&#xff1a; 1.GEC6818开机自动加载驱动 2.更改开发板的RTC时钟 文章目录 GEC6818开机自动加载驱动与更改开发板的RTC时钟一、开机自动加载驱动或运行程序**STEP1&#xff1a;** 使用vi打开文件profile.命令如下**S…

【 MyBatis 】| 关于多表联查返回 List 集合只查到一条的 BUG

目录 一. &#x1f981; 写在前面二. &#x1f981; 探索过程2.1 开端 —— 开始写 bug2.2 发展 —— bug 完成2.3 高潮 —— bug探究2.4 结局 —— 效果展示 三. &#x1f981; 写在最后 一. &#x1f981; 写在前面 今天又是 BUG 气满满的一天&#xff0c;一个 xxxMapper.xm…

linux网络服务学习(4):SAMBA

1.什么是SAMBA SAMBA也是一种文件共享工具 &#xff08;1&#xff09;服务名&#xff1a;smb &#xff08;2&#xff09;软件名&#xff1a;samba &#xff08;3&#xff09;配置文件&#xff1a; /etc/samba/smb.conf /etc/samba/smb.conf.example &#xff08;4&#…

外包干了8天,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;19年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

位像素|海外仓系统哪个好?海外仓系统有什么功能?海外仓仓库系统排名

现在市面上还是有很多海外仓仓库管理系统的&#xff0c;他们各自都有各自的特点和优势。最近&#xff0c;很多跨境卖家朋友问我现在市场市场哪家海外仓系统比较好用&#xff0c;他们的排名分别是怎么样的&#xff1f;像行业内比较出名的位像素海外仓系统等&#xff1b; 因此&am…

使用dlv配合goland调试在wsl中运行的go程序

参考文章&#xff1a;https://marksuper.xyz/2021/06/29/dlv-goland/ 首先安装一下dlv这个工具&#xff1a; git clone GitHub - go-delve/delve: Delve is a debugger for the Go programming language. cd delve go install github.com/go-delve/delve/cmd/dlv 我们直接开始配…

帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等

帝国CMS十合一源码/字典/成语/古诗词/二十四节气/英语单词/百家姓/范文文库/词语等 功能包含: 成语大全 二十四节气 英语单词 古诗词 近反义词 词语造句 汉语字典 英文缩写 百家姓 范文文库 文件目录:1个数据库 1个系统源码 1个伪静态规则 安装方式:把1.2G的…

计算机网络:传输控制协议(Transmission Control Protocol-TCP协议

计算机网络&#xff1a;传输控制协议&#xff08;Transmission Control Protocol-TCP协议&#xff09; 本文目的前置知识点TCP协议简介主要特性通信流程1. 建立连接的过程(三次握手&#xff0c;243)1.1 为什么要三次握手&#xff0c;两次不行吗&#xff1f; 2. 释放连接的过程(…

2023全国高质量发展园区Top50榜单发布:产业升级引领新发展

[引言] 园区作为推动地方经济高质量发展的重要引擎&#xff0c;在全国范围内发挥着举足轻重的作用。为表彰在园区建设和运营方面取得卓越成就的园区&#xff0c;中国企业网和《中国周刊》联合举办了2023全国高质量发展园区Top50评选活动&#xff0c;由中国品牌峰会组委会参与评…