rtmp直播拉流客户端EasyRTMPClient设计过程中时间戳问题汇总

不羁的心 提交于 2020-01-02 00:52:17

EasyRTMPClient 简介

EasyRTMPClient是EasyDarwin流媒体团队开发、提供的一套非常稳定、易用、支持重连接的RTMPClient工具,以SDK形式提供,接口调用非常简单。该EasyRTMPClient库未使用或参考现有的任何RTMP库,完全由EasyDarwin团队自主实现,因此,EasyRTMPClient更易于维护,稳定性、可扩展性得以提升,同时,本RTMP库全平台支持(包括windows/linux 32&64,ARM各平台,android, ios)!

相关连接

EasyRTMPClient调用示例地址:https://github.com/EasyDSS/EasyRTMPClient

由EasyDarwin团队推出的 RTMP协议教程:

谈谈RTMP时间戳的形式

RTMP时间戳基本概念

RTMP消息包一共分成三种类型。一类是命令(通知)消息,一类是音频消息,一类是视频消息。在实际开发过程中,我们主要关心的是音频和视频消息包的时间戳。RTMP消息分为块头和消息头,而RTMP消息包的时间戳主要存储于消息头域中的,用三个字节以大端序来存储,如果时间戳超过0xFFFFFF时,则将消息包域的时间戳域设成0xFFFFFF,然后在消息包域和负载之间会插入四节来表示时间戳,该四字节时间戳域通常称为扩展时间戳。

RTMP时间戳的形式

按adobe公司已公开的rtmp资料来看,rtmp消息包的时间戳主要有两种形式,一种称为递增模式,一种称为差值模式。

递增模式

此时间戳格式与flv文件tag的时间戳保持一致。即音频、视频时间戳基于同一个时钟来进行递增。
如:A0 -> V0 ->A1 -> A2 -> V1 ….
基于此种模块,它们的时间戳值一定满足:V1 >= A2 >= A1 >= V0 >= A0。通常,在打音频或视频时间戳时,可直接取系统时间戳即可。

差值模式

此时间戳格式,则较前一种有很大不同,主要区别是,音频和视频时间戳不在基于同一时钟来处理。无论音频还是视频消息包,每次打的时间戳都是相较于同一类消息包的前一条消息的时间戳的差值,或者可以将该值理解成为某一帧的duration值。例如,在某个流中,视频是25帧,那么此时,视频帧消息包的时间戳每次打的值基本都是在40左右(40=1000ms / 25f, 实际情况可能距该值上浮或下降几毫秒),音频每包时间戳跟视频包同理。

EasyRTMPClient 中的处理

在实际的开发过程当中,我们通常无法预知对端的流是采用以上何种时间戳格式来进行处理的(当然,可以通过RTMP协商的时候进行约束)。为了减少上层开发的工作量,EasyRTMPClient在实际开发过程中,对上述两种时间戳都进行了兼容。输出统一的格式,与flv文件tag时间戳保持一致,即使用递增模式。

在RTMP中,音频包时间戳和视频包时间戳处理方法基本是一致的,因此,下面只贴出EasyRTMPClient对上述两种时间戳的视频处理代码为:

        if ( 0xFFFFFF != pkt->timestamp )
        {
            pkt->extendTimestamp = pkt->timestamp;
        }

        s = pkt->extendTimestamp / 1000;
        us = ( pkt->extendTimestamp % 1000 ) * 1000;
        if ( 0 == easyRtmp->preTimestamp.s && 0 == easyRtmp->preTimestamp.us )
        {
            easyRtmp->preTimestamp.s = s;
            easyRtmp->preTimestamp.us = us;
        }
        else
        {
            if ( s >= easyRtmp->preTimestamp.s && us >= easyRtmp->preTimestamp.us )
            {
                goto _WRITE_TIMESTAMP;
            }
            ms = easyRtmp->videoTimestamp.s * 1000 + easyRtmp->videoTimestamp.us / 1000;
            ms += pkt->extendTimestamp;
            s = ms / 1000;
            us = ( ms % 1000 ) * 1000;
            easyRtmp->videoTimestamp.s = s;
            easyRtmp->videoTimestamp.us = us;
        }

_WRITE_TIMESTAMP:
        easyRtmp->preTimestamp.s = s;
        easyRtmp->preTimestamp.us = us;

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

EasyRTMPClient交流群:544917793

Copyright © EasyDarwin.org 2012-2017

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!