使用ffmpeg实现rtmp推流

服务器用的是ngix+rtmp,配置方式见博客:
https://blog.csdn.net/goldfish3/article/details/100036059

  1. 由于我是在本机配置的ngix服务器,所以host是127.0.0.1,如果用的虚拟机,就是虚拟机的ip地址。
  2. 路径中的rtmplive是ngix配置文件里指定的,room是自己写的路径。

代码涉及一些ffmpeg的知识点,这里列一下:

1: PTS 和 DTS

h264帧中,B帧需要前面的帧和后面的帧,才能解码,因此解码时间和播放时间会不一样,比如一段帧:
按播放顺序为:I B B P
但由于B帧解码需要P帧,因此解码顺序为:I P B B
因此,解码序列和播放序列就需要使用不同的时间戳来表示~
PTS:显示时间戳,对应的数据格式为 AVFrame(解码后的帧),通过 AVCodecContext->time_base 获取。
DTS:解码时间戳,对应的数据格式为AVPacket(解码前的包),通过AVStream->time_base获取。

2: AVRational

而ffmpeg中,时间戳并不是以自然时间表示的,而是以一个个格子的形式,不同的格子代表不同的 time base。格子本身使用结构体 AVRational表示:

typedef struct AVRational{
   
    int num; //分子
    int den; //分母
} AVRational;

比如num=1,den=200,一个格子就表示 1/200 秒,PTS和DTS中的时间戳都是用 AVRational表示的。

3:推流时间同步问题

我们应该在什么时间,将包推给客户端?下面的代码中选用的是包解码的时间,也就是DTS时间,因此,如果当前要推的包还没有到解码时间,就需要等一会儿再推。真实环境下,由于网络问题等,处理会更更复杂一些。

下面代码涉及的api

AVFormatContext():c语言不是面向对象的,因此所有参数和对象需要使用一个上下文进行传递和管理,ffmpeg里就是它了。
avformat_open_input():通过路径,将视频信息读入上下文。
avformat_find_stream_info():获取流信息。
av_dump_format():获取视频封装信息,比如视频中有哪些流,流的具体情况。
avformat_network_init():网络初始化
avformat_alloc_output_context2():新建输出上下文
avformat_new_stream():新建流,并将流放入上下文
avcodec_parameters_copy():拷贝流参数
avio_open():打开流,在这里输出流是网络,应该就是作网络推流的一些准备工作和参数设置
avformat_write_header():写入头信息(也不知掉这些头信息是从哪来的)
av_read_frame():虽然叫 read frame,但是这里实际上读取的是一个包(AVPacket),也就是解码前的数据。
av_q2d():将AVRational转化为秒
av_interleaved_write_frame():将数据排序,写入

总的流程大概就是:
获取输出上下文 -> 建立输出上下文 -> 复制流参数信息到输出上下文 -> 使用输出上下文打开输出流 -> 从输入流中读取数据,使用输出流推出去。

#include <iostream>
#include "string.h"

extern "C"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值