# i2rtmp **Repository Path**: hengzz/i2rtmp ## Basic Information - **Project Name**: i2rtmp - **Description**: stream to rtmp - **Primary Language**: Unknown - **License**: BSD-3-Clause - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-03-18 - **Last Updated**: 2022-03-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # i2rtmp ## SRS Linux 系统下安装 SRS ``` bash git clone https://gitee.com/winlinvip/srs.oschina.git srs && cd srs/trunk && git remote set-url origin https://github.com/ossrs/srs.git && git pull # Remark: Recommend to use Centos7 64bits, please read wiki(CN,EN). # ——https://github.com/ossrs/srs/wiki/v3_CN_Build ./configure && make ./objs/srs -c conf/srs.conf ``` SRS docker ``` bash # Note: You can also build SRS in docker, please read docker. # ——https://github.com/ossrs/srs-docker/tree/dev#usage docker run -d -p 1935:1935 -p 1985:1985 -p 8080:8080 registry.cn-hangzhou.aliyuncs.com/ossrs/srs:3 ``` 浏览器访问 http://localhost:8080 ## FFmpeg 推流 ``` bash ffmpeg -re -stream_loop -1 -i video.mp4 -c copy -f flv rtmp://localhost:1935/live/testvideo ``` vlc 播放 rtmp://localhost:1935/live/testvideo #### development environment ``` bash apt update && apt install git vim unzip -y apt-get install build-essential -y # FFMPEG 4.3.1 # wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz tar -zxvf yasm-1.3.0.tar.gz cd yasm-1.3.0 ./configure make -j6 make install # build ffmpeg # wget http://ffmpeg.org/releases/ffmpeg-4.3.1.tar.xz xz -d ffmpeg-4.3.1.tar.xz tar xvf ffmpeg-4.3.1.tar cd ffmpeg-4.3.1 ./configure --enable-swscale --enable-swresample --enable-gpl --enable-shared make -j6 make install export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig ``` ``` bash export LD_LIBRARY_PATH=/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}} ``` ## FFmpeg中的时间戳与时间基 —— https://www.imooc.com/article/91381 在开发多媒体播放器或直播系统时,音视频的同步是非常关键且复杂的点。 - I/B/P帧 - PTS/DTS - 时间基 - ffmpeg的内部时间基 - 不同时间基的换算 #### I/B/P帧 - I帧是关键帧,它采用帧内压缩技术; - B帧是前后参考帧,它属于帧间压缩技术。也就是说在压缩成B帧前,它会参考它前面的非压缩视频帧,和后面的非压缩视频帧,记录下前后两帧都不存放的“残差值”,这样可以达到更好的压缩率; - P帧是向前参考帧,也就是说它参考的是前一个关键帧的数据。P帧也属于帧间压缩技术,相对于B帧来说,P帧的压缩率要比B帧低。 但在实时互动直播系统中,很少使用B帧。主要的原因是压缩和解码B帧时,由于要双向参考,所以它需要缓冲更多的数据,且使用的CPU也会更高。由于实时性的要求,所以一般不使用它。不过对于播放器来说,遇到带有B帧的H264数据是常有的事儿。 #### PTS/DTS PTS(Presentation TimeStamp)是渲染用的时间戳,也就是说,我们的视频帧是按照 PTS 的时间戳来展示的。 DTS(Decoding TimeStamp)解码时间戳,是用于视频解码的顺序控制。 为什么有了PTS还要有DTS呢? 这就与上面所讲的I/B/P帧有关了。如果我们的视频中没有B帧,那显示的帧的顺序与存放的帧的顺序是一样的,此时PTS与DTS的值就是一样的,也就没有存在两个时间戳的必要了。 但有了B帧之后,就不是这个样子了。举个简单的例子: ``` 第一行,实际应展示的顺序:I B B P 第二行,实际在存放的顺序:I P B B 第三行,按实际解码序展示:1 4 2 3 第四行,按实际播放序展示:1 2 3 4 ``` 对于上面这个例子,作如下说明: - 我们实际应该展示的帧的顺序是 I, B, B, P 帧,即解码后的视频帧的播放顺序。 - 但实际上,这些帧到达之后,在缓冲区里按照第二行的样子存放。为什么会这样呢?这是由于P帧参考的是I帧,B帧是双向参考帧。也就是说,如果I帧和P帧没有解码的话,B帧是无法进行解码的。基于此,为了解决这个问题就出现了PTS和DTS两个时间戳。 - 第三行是视频帧真正的解码顺序,先解I帧,然后是P帧,然后是第一个B帧,最后是第二个B帧。 - 最终的展示顺序是I帧解码后的视频帧,第一个B帧解码后的视频帧,第二个B帧解码后的视频帧,最后是P帧解码后的视频帧。 #### 时间基 有了时间戳之后,最终进行展示时还是需要将PTS时间戳转成以秒为单位的时间。这里需要向大家介绍一下 ffmpeg的时间基。 我们在执行ffmpeg/ffplay命令时,可以通过控制台看到几个参数,分别是 tbr, tbn, tbc。这几个值是什么含义呢?其实就是不同的时间基。 - tbr: 是我们通常所说的帧率。time base of rate - tbn: 视频流的时间基。 time base of stream - tbc: 视频解码的时间基。time base of codec 在ffmpeg中,不同的时间戳对应不同的时间基。对于视频的渲染我们使用的是视频流的时间基,也就是 tbn。 那我们如何理解时间基呢?**其实非常简单,就是时间刻度。我们以帧率为例,如果每秒钟的帧率是25帧,那么它的时间基(时间刻度)就是1/25。也就是说每隔1/25秒后,显示一帧。** 所以如果我们当前的时间是 100, 时间基是 1/25,那么转成秒的时间是多少呢?100*时间基(1/25),也就是100 * 1/25 = 4秒。是不是非常的简单? #### ffmpeg内部时间基 除了上面提到的几个时间基之外,ffmpeg内部还有一个时间基。即我们通过所见到的``AV_TIME_BASE``。它在ffmpeg内部定义如下: ``` cpp #define AV_TIME_BASE 1000000 ``` 它还有一种分数所表式法: ``` cpp #define AV_TIME_BASE_Q (AVRational){1, AV_TIME_BASE} ``` 在 ffmpeg中进行换算,将不同时间基的值转成按秒为单位的值计算如下: ``` cpp timestamp(秒) = pts * av_q2d(time_base) ``` 这里引入了 av_q2d 这个函数,它的定义非常简单: ``` cpp typedef struct AVRational{ int num; //numerator int den; //denominator } AVRational; static inline double av_q2d(AVRational a){ /** * Convert rational to double. * @param a rational to convert **/ return a.num / (double) a.den; } ``` 从这里我们可以看到,它与我上面所讲的公式是一样的。 #### 不同时间基的换算 在上面我们介绍了ffmpeg有好几种不同的时间基,有时候我们需要在不同的时间基之间做换算。ffmpeg为我们提供了非常方便的函数。即: ``` cpp av_rescale_q() ``` ``av_rescale_q(a,b,c)``的作用是,把时间戳从一个时基调整到另外一个时基时候用的函数。其中,a 表示要换算的值;b 表示原来的时间基;c 表示要转换的时间基。其计算公式为 ``a * b / c``。 既然公式这么简单,我们自己写就OK了,为什么ffmpeg还要单独提供一个函数呢?其实这个看似简单的方法,还要考虑数值溢出的问题。所以把这块的逻辑加上之后,就没我们看到的这么简单了。不过没关系,我们只要清楚 av_rescale_q 是做什么的,怎么用就可以了。 下面我们再给出两个算计公式: - 时间戳转秒 ``` time_in_seconds = av_q2d(AV_TIME_BASE_Q) * timestamp ``` - 秒转时间戳 ``` timestamp = AV_TIME_BASE * time_in_seconds ``` —— https://coding.imooc.com/class/279.html?mc_marking=59c321c0417e144904c49c366f94dd57&mc_channel=shouji