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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

书生·浦语大模型开源体系(一)论文精读笔记

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

银河麒麟操作系统Kylin Linux 离线安装Nginx1.21.5

一、查看操作系统版本号 nkvers ############## Kylin Linux Version ################# Release: Kylin Linux Advanced Server release V10 (Lance)Kernel: 4.19.90-52.15.v2207.ky10.x86_64Build: Kylin Linux Advanced Server release V10 (SP3) /(Lance)-x86_64-Build20/…

Mysql数据备份与恢复实战

文章目录 备份类型备份内容备份工具mysqldump备份 实战案例&#xff1a;恢复误删除的表准备工作2:30完全备份完全备份后更新数据表10:00误删students表需要恢复还原的状态开始还原恢复 为什么要备份&#xff1f; 备份是为了&#xff1a;灾难恢复&#xff1a;硬件故障、软件故障…

CSP-S2020提高级T3:函数调用

题目链接 [CSP-S2020] 函数调用 题目描述 函数是各种编程语言中一项重要的概念&#xff0c;借助函数&#xff0c;我们总可以将复杂的任务分解成一个个相对简单的子任务&#xff0c;直到细化为十分简单的基础操作&#xff0c;从而使代码的组织更加严密、更加有条理。然而&…

Netty源码剖析——ChannelPipeline 调度 handler 的源码剖析(三十九)

ChannelPipeline 调度 handler 的源码剖析 源码剖析目的 当一个请求进来的时候&#xff0c;ChannelPipeline 是如何调用内部的这些 handler 的首先&#xff0c;当一个请求进来的时候&#xff0c;会第一个调用 pipeline 的 相关方法&#xff0c;如果是入站事件&#xff0c;这些方…

突破编程_前端_JS编程实例(分割窗体组件)

1 开发目标 分隔窗体组件旨在提供灵活的窗体分隔功能&#xff0c;支持横向分割与纵向分隔两种类型&#xff0c;并具备拖拽调整窗体比例的功能&#xff0c;同时提供最小比例设置&#xff0c;以防止窗体被过度缩小&#xff1a; 2 详细需求 2.1 分隔窗体类型 &#xff08;1&…

数据类型和类型检测

Data Type And Type Checking 1.编程语言中的数据类型 类型和变量 一个类型是一系列值的集合&#xff0c;这些集合可以抽象出一个相同的特点&#xff0c;并且可以相互实现计算 例如&#xff1a; 布尔类型&#xff1a;true or false整形&#xff1a;1,2,3…浮点数类型&#xf…

JUC:double-checked locking(DCL) 懒汉单例模式

文章目录 double-checked locking(DCL) 问题解决方法 volatile作用 double-checked locking(DCL) 问题 第一个if用于后续进入的线程&#xff0c;不用再获取锁来判断是否已经创建了对象。第二个if&#xff0c;为的是第一个进入的线程创建对象&#xff0c;以及防止卡在第一个if之…

提升你的CSS技能:深入理解伪类选择器和伪元素选择器!

在CSS的世界里&#xff0c;有些选择器并不像它们的名字那样直接。今天&#xff0c;我们要探索的是两种特殊的选择器&#xff1a;伪类选择器和伪元素选择器。它们虽然名字相似&#xff0c;但功能和用途却大有不同。 下面就让我们一起来了解一下它们是如何在我们的页面布局中扮演…

GoogleNet神经网络介绍

一、简介 GoogleNet&#xff0c;也称为GoogLeNet&#xff0c;是谷歌工程师设计的一种深度神经网络结构&#xff0c;它在2014年的ImageNet图像识别挑战赛中取得了冠军。该神经网络的设计特点主要体现在其深度和宽度上&#xff0c;通过引入名为Inception的核心子网络结构&#x…

vue项目视频播放ckplayer使用

ckplayer 官方网址&#xff0c;点击访问 1&#xff0c;打开网页后能看到这里&#xff0c;我现在使用的是最新 X3版手册 2&#xff0c;这个ckplayer不是npm 插件&#xff0c;要下载安装包解压到项目里面使用 安装包网址 通过gitee下载 3&#xff0c;解析安装包到项目中 publ…

护眼台灯哪个牌子最好,护眼台灯五大品牌墙裂分享

近视在儿童中愈发普遍&#xff0c;许多家长开始认识到&#xff0c;除了学业成绩之外&#xff0c;孩子的视力健康同样重要。毕竟&#xff0c;学业的落后可以逐渐弥补&#xff0c;而一旦孩子近视&#xff0c;眼镜便可能成为长期伴随。因此&#xff0c;专业的护眼台灯对于每个家庭…