基于FFMPEG的RTP推流H264和AAC文件

本文详细介绍了如何使用FFMPEG库创建RTP推流程序,重点关注视频H264和音频AAC的时间戳处理。在Linux环境下,通过avformat_open_input打开输入文件,利用avformat_alloc_output_context2打开RTP输出流。内容包括文件和输出流的打开,视频和音频时间戳的计算,并讨论了VLC播放SDP文件时可能遇到的问题。
摘要由CSDN通过智能技术生成

在本文中主要讲如何用FFMPEG编写RTP的推流程序和打视音频时间戳上的问题
PS:文中代码基于LINUX

一. 文件的打开和输出流的打开

用avformat_open_input分别打开视音频文件,用avformat_alloc_output_context2打开输出的RTP流,注意,这里用的选项是rtp_mpegts,代表的是传输的视音频数据会打包成TS流的形式进行发送。rtp一个端口只能传输一路数据,所以我这里开了两个rtp端口,分别传输视音频数据。

avformat_open_input(&ifmt_ctx_v, in_filename_v, 0, 0);
avformat_open_input(&ifmt_ctx_a, in_filename_a, 0, 0);
avformat_alloc_output_context2(ofmt_ctx, NULL, "rtp_mpegts", NULL);
avformat_alloc_output_context2(ofmt_ctx+1, NULL, "rtp_mpegts", NULL);

二. 读取视音频数据并打上时间戳

av_compare_ts两个不同时基的时间戳,谁的比较大。
通过av_compare_ts决定要读取音频数据还是视频数据,当音频时间戳比较大的时候就读取视频数据,当视频时间戳比较大的时候就读取音频时间戳。

1. 视频时间戳
AVRational time_base = in_stream->time_base;//{ 1, 1000 };  
AVRational r_framerate1 = in_stream->r_frame_rate;
AVRational time_base_q = { 1, AV_TIME_BASE };  
//Duration between 2 frames (us)  
int64_t calc_duration = (double)(AV_TIME_BASE) / av_q2d(r_framerate1);  //内部时间戳 
pkt.pts = av_rescale_q(vframe_index*calc_duration, time_base_q, time_base);
pkt.dts = pkt.pts; 
pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base);
pkt.pos = -1;
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);  
pkt.pos = -1;  

av_q2d(a) ——————— 把AVRatioal结构a转换成double的函数
av_rescale_q(a,b,c) ——– 把a从b时基转换成c时基
上面的一大堆代码其实是在不同的时基上大时间戳后,进行转换。

首先是这段代码

AVRational time_base1=in_stream->time_base; 
AVRational time_base_q = { 1, AV_TIME_BASE }; 
double frame_size = (double)in_stream->codec->frame_size;
double sample_rate = (double)in_stream->codec->sample_rate;
//Duration between 2 frames (us)  
int64_t calc_duration=(double)(AV_TIME_BASE) * (frame_size/sample_rate);
pkt.pts = av_rescale_q(aframe_index*calc_duration, time_base_q, time_base1);
pkt.dts = pkt.pts; 
pkt.duration = av_rescale_q(calc_duration, time_base_q, time_base1);
pkt.pos = -1;

在视频文件时钟的时基上打时间戳,然后进行时间戳的转换,把时间戳转换为RTP的时基单位。

pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base, (enum AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));  
pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);  
pkt.pos = -1;  

减去那些时钟转化的步骤其实就是

pkt.pts &#
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值