ffmpeg rtsp转 rtmp

举报
风吹稻花香 发表于 2021/06/05 01:29:08 2021/06/05
【摘要】 原文:https://www.jianshu.com/p/69eede147229 #include <iostream>using namespace std;//引入头文件extern "C"{#include "libavformat/avformat.h" //引入时间#include "libavutil/time.h"}//引入库#pragma co...

原文:https://www.jianshu.com/p/69eede147229


  
  1. #include <iostream>
  2. using namespace std;
  3. //引入头文件
  4. extern "C"
  5. {
  6. #include "libavformat/avformat.h"
  7. //引入时间
  8. #include "libavutil/time.h"
  9. }
  10. //引入库
  11. #pragma comment(lib,"avformat.lib")
  12. //工具库,包括获取错误信息等
  13. #pragma comment(lib,"avutil.lib")
  14. //编解码的库
  15. #pragma comment(lib,"avcodec.lib")
  16. int avError(int errNum);
  17. static double r2d(AVRational r)
  18. {
  19. return r.num == 0 || r.den == 0 ? 0. : (double)r.num / (double)r.den;
  20. }
  21. int main() {
  22. //所有代码执行之前要调用av_register_all和avformat_network_init
  23. //初始化所有的封装和解封装 flv mp4 mp3 mov。不包含编码和解码
  24. av_register_all();
  25. //初始化网络库
  26. avformat_network_init();
  27. //使用的相对路径,执行文件在bin目录下。test.mp4放到bin目录下即可
  28. const char *inUrl = "test.flv";
  29. //输出的地址
  30. const char *outUrl = "rtmp://192.168.136.131/live/test";
  31. //
  32. // 输入流处理部分
  33. /
  34. //打开文件,解封装 avformat_open_input
  35. //AVFormatContext **ps 输入封装的上下文。包含所有的格式内容和所有的IO。如果是文件就是文件IO,网络就对应网络IO
  36. //const char *url 路径
  37. //AVInputFormt * fmt 封装器
  38. //AVDictionary ** options 参数设置
  39. AVFormatContext *ictx = NULL;
  40. //打开文件,解封文件头
  41. int ret = avformat_open_input(&ictx, inUrl, 0, NULL);
  42. if (ret < 0) {
  43. return avError(ret);
  44. }
  45. cout << "avformat_open_input success!" << endl;
  46. //获取音频视频的信息 .h264 flv 没有头信息
  47. ret = avformat_find_stream_info(ictx, 0);
  48. if (ret != 0) {
  49. return avError(ret);
  50. }
  51. //打印视频视频信息
  52. //0打印所有 inUrl 打印时候显示,
  53. av_dump_format(ictx, 0, inUrl, 0);
  54. //
  55. // 输出流处理部分
  56. /
  57. AVFormatContext * octx = NULL;
  58. //如果是输入文件 flv可以不传,可以从文件中判断。如果是流则必须传
  59. //创建输出上下文
  60. ret = avformat_alloc_output_context2(&octx, NULL, "flv", outUrl);
  61. if (ret < 0) {
  62. return avError(ret);
  63. }
  64. cout << "avformat_alloc_output_context2 success!" << endl;
  65. //配置输出流
  66. //AVIOcontext *pb //IO上下文
  67. //AVStream **streams 指针数组,存放多个输出流 视频音频字幕流
  68. //int nb_streams;
  69. //duration ,bit_rate
  70. //AVStream
  71. //AVRational time_base
  72. //AVCodecParameters *codecpar 音视频参数
  73. //AVCodecContext *codec
  74. //遍历输入的AVStream
  75. for (int i = 0; i < ictx->nb_streams; i++) {
  76. //创建一个新的流到octx中
  77. AVStream *out = avformat_new_stream(octx, ictx->streams[i]->codec->codec);
  78. if (!out) {
  79. return avError(0);
  80. }
  81. //复制配置信息 用于mp4 过时的方法
  82. //ret=avcodec_copy_context(out->codec, ictx->streams[i]->codec);
  83. ret = avcodec_parameters_copy(out->codecpar, ictx->streams[i]->codecpar);
  84. if (ret < 0) {
  85. return avError(ret);
  86. }
  87. out->codec->codec_tag = 0;
  88. }
  89. av_dump_format(octx, 0, outUrl, 1);
  90. //
  91. // 准备推流
  92. /
  93. //打开IO
  94. ret = avio_open(&octx->pb, outUrl, AVIO_FLAG_WRITE);
  95. if (ret < 0) {
  96. avError(ret);
  97. }
  98. //写入头部信息
  99. ret = avformat_write_header(octx, 0);
  100. if (ret < 0) {
  101. avError(ret);
  102. }
  103. cout << "avformat_write_header Success!" << endl;
  104. //推流每一帧数据
  105. //int64_t pts [ pts*(num/den) 第几秒显示]
  106. //int64_t dts 解码时间 [P帧(相对于上一帧的变化) I帧(关键帧,完整的数据) B帧(上一帧和下一帧的变化)] 有了B帧压缩率更高。
  107. //uint8_t *data
  108. //int size
  109. //int stream_index
  110. //int flag
  111. AVPacket avPacket;
  112. //获取当前的时间戳 微妙
  113. long long startTime = av_gettime();
  114. while (true)
  115. {
  116. ret = av_read_frame(ictx, &avPacket);
  117. if (ret < 0) {
  118. break;
  119. }
  120. cout << avPacket.pts << " " << flush;
  121. //计算转换时间戳 pts dts
  122. //获取时间基数
  123. AVRational itime = ictx->streams[avPacket.stream_index]->time_base;
  124. AVRational otime = octx->streams[avPacket.stream_index]->time_base;
  125. avPacket.pts = av_rescale_q_rnd(avPacket.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
  126. avPacket.dts = av_rescale_q_rnd(avPacket.pts, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
  127. //到这一帧时候经历了多长时间
  128. avPacket.duration = av_rescale_q_rnd(avPacket.duration, itime, otime, (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_NEAR_INF));
  129. avPacket.pos = -1;
  130. //视频帧推送速度
  131. if (ictx->streams[avPacket.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
  132. AVRational tb = ictx->streams[avPacket.stream_index]->time_base;
  133. //已经过去的时间
  134. long long now = av_gettime() - startTime;
  135. long long dts = 0;
  136. dts = avPacket.dts * (1000 * 1000 * r2d(tb));
  137. if (dts > now)
  138. av_usleep(dts - now);
  139. else {
  140. cout << "sss";
  141. }
  142. }
  143. //推送 会自动释放空间 不需要调用av_packet_unref
  144. ret = av_interleaved_write_frame(octx, &avPacket);
  145. if (ret < 0) {
  146. break;
  147. }
  148. //视频帧推送速度
  149. //if (avPacket.stream_index == 0)
  150. // av_usleep(30 * 1000);
  151. //释放空间。内部指向的视频空间和音频空间
  152. //av_packet_unref(&avPacket);
  153. }
  154. return 0;
  155. }
  156. int avError(int errNum) {
  157. char buf[1024];
  158. //获取错误信息
  159. av_strerror(errNum, buf, sizeof(buf));
  160. cout << " failed! " << buf << endl;
  161. return -1;
  162. }

 

文章来源: blog.csdn.net,作者:网奇,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/jacke121/article/details/89525349

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。