基于RTMP推送实时AAC+H264流(三)

https://blog.csdn.net/scnu20142005027/article/details/60623670

推送

流程:初始化、连接服务器、发送数据 
这一部分主要用的是librtmp,由于是使用别人封装好的库,总的来说比较简单

初始化

简单地调用一下函数

rtmp = RTMP_Alloc();
RTMP_Init(rtmp);

连接服务器

四个函数分别代表:设置URL、使自己成为发送端、建立NetConnection,建立NetStream

RTMP_SetupURL(rtmp, url);
RTMP_EnableWrite(rtmp);
RTMP_Connect(rtmp, NULL);
RTMP_ConnectStream(mRTMP, 0);

发送数据

不断从队列中取出RTMP包,加上时间戳和流ID,然后往服务器发送,帧率的控制位于编码线程,所以这里不用计算时间,直接加上时间戳发送即可,而且由于这里也不好计算时间,还有就是这里的队列是阻塞队列

while (true) {RTMPPacket& packet = queue.front();packet.m_nInfoField2 = rtmp->m_stream_id;packet.m_nTimeStamp = RTMP_GetTime();RTMP_SendPacket(rtmp, &packet, 1);queue.pop();
}

主程序

主要分为:视频编码线程、音频编码线程、主线程(发送线程)

视频编码线程

根据帧率算出间隔时间,然后把视频元数据的rtmp包存下来以便多次发送,从视频源获取帧,判断是否是关键帧,如果是则先发送元数据,经过编码封装后发送数据,最后比较花费时间与间隔时间决定是否需要等待

const int interval = 1000 / fps;
int bytes;
char *buf, *frame;
RTMPPacket packet, meta;
H264RTMPPackager packager;
std::chrono::milliseconds duration;
std::pair<int, char*> result;meta = encoder.getMetadata();
buf = pool.get(1024);
packet = packager.metadata(buf, result.second, result.first);auto last = std::chrono::system_clock::now();while ((frame = source.getNextFrame()) != NULL) {result = source.encode(frame);if (H264RTMPPackager::isKeyFrame(result.second)) {queue.push(meta, true);}bytes = packager.getBodyLength(result.first);buf = pool.get(bytes);packet = packager.pack(buf, result.second, result.first)queue.push(packet);duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - last);if (duration < interval) {msleep((interval - duration).count());}last = std::chrono::system_clock::now();
}

音频编码线程

步骤与视频编码线程相似,只是这里无需等待,因为音频源是根据采样率来输出帧的,这里由于元数据只需要发送一次,所以可以不用保存下来

int bytes;
char *buf;
RTMPPacket packet;
AACRTMPPackager packager;
std::pair<int, char*> frame, result;result = encoder.getMetadata();
buf = pool.get(128);
packet = packager.metadata(buf, result.second, result.first);
queue.push(packet, true);while ((frame = source.getNextFrames()).second != NULL) {result = encoder.encode(frame.first, frame.second);if (result.first != 0) {bytes = packager.getBodyLength(result.first);buf = pool.get(bytes);packet = packager.pack(buf, result.second, result.first);queue.push(packet);}
}

主线程

创建H264流以及AAC流,然后开启视频编码线程和音频编码线程

PacketQueue queue;
MemoryPool pool;
V4L2Source v4l2(width, height);
PCMSource pcm;
YUY2Converter converter(YUY2_CVT_RGB24);
MotionDetector detector;FilteredVideoSource videoSource(v4l2);
videoSource.addFilter(&converter);
videoSource.addFilter(&detector);RTMPPublisher publisher(queue, pool);
publisher.connect(url);H264Stream videoStream(videoSource, queue, pool, fps, bitrate);
AACStream audioStream(pcm, queue, pool);std::thread videoEncodeThread(&H264Stream::run, &videoStream);
std::thread audioEncodeThread(&AACStream::run, &audioStream);publisher.run();

后记

至此,简单的推送程序就完成了,项目整体比较简单,基本上也就是在调用第三方库,但是总的来说学到的东西不少,对于以前不懂的视音频编码,也有了一些了解,而且也是第一次遇到生产者-消费者的情景,虽然这里的情景比较简单,只有一位消费者 
自己的测试环境是电脑Ubuntu和树莓派Raspbian,关于使用到的库,opencv3应该是需要编译安装,树莓派上libfaac可能也需要编译安装 
rtmp服务器用的是SRS,配置方法再网上可以很简单地搜索到

音视频开发(22)---基于RTMP推送实时AAC+H264流(三)相关推荐

  1. 音视频开发(21)---基于RTMP推送实时AAC+H264流(二)

    基于RTMP推送实时AAC+H264流(二) https://blog.csdn.net/scnu20142005027/article/details/57428107 编码 图像采用H264编码, ...

  2. 音视频开发(20)---基于RTMP推送实时AAC+H264流(一)

    基于RTMP推送实时AAC+H264流(一) https://blog.csdn.net/scnu20142005027/article/details/56847293 从整体来看,推流端大概是这么 ...

  3. 即时通讯音视频开发(十四):实时音视频数据传输协议介绍

    概述 随着移动互联网的快速发展以及智能终端性能的逐步提高,智能终端间进行实时音视频通讯成为移动互联网发展的一个重要方向.那么如何保证智能终端之间实时音视频数据通讯成为一个很现实的问题. 实际上,实时音 ...

  4. 深入了解音视频开发直播协议RTMP

    说起RTMP协议,相信很多人都比较陌生,这个协议相对HTTP.HTTPS.TCP等我们常见的协议而言,我们在工作中确实较少接触它,但是对现在如火如荼的直播行业,RTMP是一个重要的协议,它在实时音视频 ...

  5. 实时音视频开发理论必备:如何省流量?视频高度压缩背后的预测技术

    本文引用了"拍乐云Pano"的"深入浅出理解视频编解码技术"和"揭秘视频千倍压缩背后的技术原理之本文引用了"拍乐云Pano"的&q ...

  6. 技术福利:最全实时音视频开发要用到的开源工程汇总

    [转自] https://my.oschina.net/jb2011/blog/1619628 1.前言 实时音视频的开发学习有很多可以参考的开源项目.一个实时音视频应用共包括几个环节:采集.编码.前 ...

  7. 即时通讯音视频开发(十八):详解音频编解码的原理、演进和应用选型

    1.引言 大家好,我是刘华平,从毕业到现在我一直在从事音视频领域相关工作,也有一些自己的创业项目,曾为早期Google Android SDK多媒体架构的构建作出贡献. 就音频而言,无论是算法多样性, ...

  8. 音视频开发常用分析工具介绍

    综述 工欲善其事,必先利其器:兵马未到,粮草先行. 在音视频开发过程中,利用工具可以更方便.更直观.更快捷的分析音视频的数据,便于开发过程中分析.调试和解决问题. 现总结一些音视频开发过程中常用的分析 ...

  9. 如何测试你的即时通讯实时音视频开发方案

    真正了解过实时音视频开发的同行都知道,实时音视频开发所需的技术储备和技能要求都是比较高的,当我们历尽折腾,自已捣鼓出的方案出声出图后,离产品化还有多远呢?为了避免出现测试不充分盲目上线导致用户体验不佳 ...

最新文章

  1. 水管工游戏 (深搜)
  2. 量子计算机怎么储存,单个比特可以存储更多的信息 量子计算机时代真的要来了?...
  3. centos yum php apc,centos – PECL APC安装 – 错误:’make’失败
  4. 【Qt】QSharedMemory类详解
  5. 让我安静的写会儿代码
  6. php实现文字向左跑马灯,js实现文字跑马灯效果
  7. Connection对象 Statement对象 ResultSet对象
  8. 马云:首批助力欧洲防疫的物资今天到达比利时
  9. 使用C#和ASP.NET Core的PayPal智能按钮的客户端/服务器实现
  10. POJ 1384 Piggy-Bank 背包DP
  11. 日语+AI语音黑科技,早道开启小语种AI智能时代!
  12. dial tcp 10.96.0.1:443: i/o timeout
  13. activitymq 集群构建
  14. Inno Setup 制作安装包问题总结
  15. 饿了么ui自定义表头内容
  16. win10 专业版安装系统
  17. 海尔智慧电视如何进入工厂模式
  18. 与大学生谈学习BIM软件开发所需要的准备
  19. 服务器硬盘品牌型号认识,服务器的硬盘和主板能和FBD内存搭配的,现在主流的是什么品牌和型号啊?...
  20. 淘宝直播数据丨食品行业研究报告2021年第一季度

热门文章

  1. js html转为实体,字符串js编码转换成实体html编码的方法(防范XSS攻击)
  2. java线程本地存储_[并发并行]_[C/C++]_[使用线程本地存储Thread Local Storage(TLS)-win32和pthread比较]...
  3. html5仿qq空间,JS实现的仿QQ空间图片弹出效果代码
  4. 【重难点】【Java集合 04】ArrayDeque 的使用场景、ArrayBlockingQueue
  5. cocos2dx-js 截屏 (原生 + H5)
  6. 《团对-学生成绩管理-开发环境搭建过程》
  7. linux设备驱动归纳总结(八):1.总线、设备和驱动【转】
  8. 《Linux多线程服务端编程:使用muduo C++网络库》书摘6.6.2节
  9. 快速入门:github发布windows版
  10. CentOS7安装Java,java高级面试笔试题