FFmpegRTP推流源码分析

更新时间:2023-05-13 15:13:28 阅读: 评论:0

melon
FFmpegRTP推流源码分析
原因:由于需要涉及到RTP的推流分析,故调试查看FFmpeg内部实现流程
solo什么意思中文⽂件类型:.264,.aac
概况:FFmpeg⾸先通过sdp⽂件的创建,然后主要通过rtpenc.c⽂件和rtpenc_h264_hevc.c针对264⽂件进⾏内部进⾏格式封装。然后通过udp.c⽂件中进⾏发送.
tallest命令⾏如下:
htscffmpeg -re -i q.264 -vcodec copy -f rtp rtp://127.0.0.1:1234
ffplay -protocol_whitelist “file,udp,rtp” -i rtp://127.0.0.1:1234
sdp⽂件创建主要实现在sdp.c⽂件中.sdp的⽣成⽂件信息⼤体如下,ffplay通过sdp信息进⾏数据拉流与解析,主要的实现⽅法为
av_sdp_create,sdp_write_header,sdp_write_media_attributes等.
SDP:
海地是哪个国家v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 57.72.101
m=video 1234 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-ts=Z2QADazZQUH6EAAAPpAADqYA8UKZYA==,aOvjyyLA; profile-level-id=64000D
FFmpeg每次获取⼀个avpacket然后调⽤av_interleaved_write_frame⽅法,该⽅法通过oformat->write_packet⽅法找到对应的rtpenc.c中rtp_write_packet⽅法,然后通过avio.c⽂件中retry_transfer_
wrapper⽅法进⾏upd发送。
接下来伪代码实现如下:⾸先打开输⼊⽂件获取输⼊⽂件的AVFormatContext信息,然后创建输出⽂件的AVForamtContext,类型为
aggravate
rtp_mpegts,然后将输⼊⽂件的steram信息赋值给输出,然后调⽤avio_open创建和初始化⼀个AVIOContext对象,⽤于数据写⼊.可以简单看出AVIOContext对象内部具有⼀个AVClass对象,可以简单理解为⼀个io管道.avio_open内部简单实现了upd的创建等,然后⾸先avformat_write_header⽅法,然后通过转换avpaket中的pts为输出时间单位。然后调⽤av_interleaved_write_frame传递packet,最后调⽤av_write_trailer.流程重点为输出AVForamtContext内部成员赋值,以及时间戳的本地和远端转换.
char *path_v = "q.264";
char *path_a = "q.aac";
char *url_v = "rtp://127.0.0.1:1234";
char *url_a = "rtp://127.0.0.1:1236";
int re = avformat_open_input(&pFormatCtxV, path_v, nullptr, nullptr);
re = avformat_find_stream_info(pFormatCtxV, nullptr);
re = avformat_alloc_output_context2(&pFormatCtxA_O, nullptr, "rtp_mpegts", nullptr);
re = avio_open(&pFormatCtxA_O->pb, url_a, AVIO_FLAG_WRITE);
re = avformat_write_header(pFormatCtxV_O, nullptr);
av_interleaved_write_frame(pFormatCtxV_O, &pkt);
爱与责任
av_write_trailer(pFormatCtxA_O);
时间戳转换代码如下:⾸先通过av_compare_ts⽅法判断当前发送更新时间视频是否⼤于⾳频,如果视频⼤于⾳频则发送⾳频,如果⼩于⾳频则
发送视频.如果发送视频则此时具有三个重要的时间戳,第⼀个streams->time_ba(表⽰AVStream的时间单位1:1200000,该单位表⽰
当前流所使⽤的基本单位),streams->r_frame_rate(以帧率为单位的时间戳单位,⼀般都是帧率表⽰600000:2002),time_ba_q为当前
即时翻译
时间为单位的时间戳(1:1000000表⽰1s.).⾸先计算每帧数据之间的间隔时间calc_duation= 1s时长/帧率 ;然后将当前时间戳计算出来
的时间转换成AVSteam的时间单位。最终都要将时间转换成对端的时间戳单位(1:900000),这样对端接收到数据后可以根据⾃⼰的时间戳
单位换算成当前的时间.
分析英文av_compare_ts(cur_pts_v, pFormatCtxV->streams[iIndex_v]->time_ba, cur_pts_a, pFormatCtxA->streams[iIndex_a]->time_ba);
AVRational time_ba = pFormatCtxV->streams[iIndex_v]->time_ba;
AVRational r_famerate = pFormatCtxV->streams[iIndex_v]->r_frame_rate;
AVRational time_ba_q = {1,AV_TIME_BASE};
int64_t calc_duation = double(AV_TIME_BASE) / av_q2d(r_famerate);
pkt.pts = av_rescale_q(iFrame_index *calc_duation, time_ba_q, time_ba);
pkt.dts = pkt.pts;
pkt.duration = av_rescale_q(calc_duation, time_ba_q, time_ba);
cur_pts_v = pkt.pts;
iFrame_index++;
pkt.pts = av_rescale_q_rnd(pkt.pts, time_ba, pFormatCtxV_O->streams[0]->time_ba, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MIN pkt.dts = av_rescale_q_rnd(pkt.dts, time_ba, pFormatCtxV_O->streams[0]->time_ba, (enum AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MIN pkt.duration = av_rescale_q(pkt.duration,time_ba, pFormatCtxV_O->streams[0]->time_ba);
发送⾳频时间戳主要有如下:AVStream对应的基本时间戳(1:2822400),然后本地时间戳(1:1000000),⾸先获取⾳频帧间隔时间=1s *
nb_sample/采样率.此时由于为aac编码,故为1024字节.然后将当前时间转成AVStream时间.最终转换成对端时间戳时间(1:90000).
AVRational time_ba = pFormatCtxA->streams[iIndex_a]->time_ba;
AVRational time_ba_q = {1,AV_TIME_BASE};
double frame_size = (double)pFormatCtxA->streams[iIndex_a]->codecpar->frame_size;
double frame_rate = (double)pFormatCtxA->streams[iIndex_a]->codecpar->sample_rate;
int64_t calc_duration = (double)(AV_TIME_BASE) *(frame_size / frame_rate);
pkt.pts = av_rescale_q(iAFrame_index *calc_duration, time_ba_q,time_ba);
pkt.dts = pkt.pts;
二级建造师再教育
pkt.duration = av_rescale_q(calc_duration, time_ba_q, time_ba);
iAFrame_index++;
cur_pts_a = pkt.pts;
pkt.pts = av_rescale_q_rnd(pkt.pts, pFormatCtxA->streams[iIndex_a]->time_ba, pFormatCtxA_O->streams[0]->time_ba, (enum AVRounding)(AV_ROUND_N pkt.dts = av_rescale_q_rnd(pkt.dts, pFormatCtxA->streams[iIndex_a]->time_ba, pFormatCtxA_O->streams[0]->time_ba, (enum AV
Rounding)(AV_ROUND_N pkt.duration = av_rescale_q(pkt.duration, pFormatCtxA->streams[iIndex_a]->time_ba, pFormatCtxA_O->streams[0]->time_ba);
av_interleaved_write_frame(pFormatCtxA_O, &pkt);
总结:ffmpeg利⽤udp实现rtp推流,重点为输出AVForamtContext的赋值以及时间戳转换.代码后续上传

本文发布于:2023-05-13 15:13:28,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/107078.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:时间   输出   单位
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图