实战小项目之RTMP流媒体演示系统
项目简介
windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能:
- 视频下载
- 推送文件
- 推送摄像头数据或者桌面
- 基于libvlc的播放器
视频下载部分

最大的坑就是,文件名的那个数组设小了,导致数组越界,写下一个功能的时候,总是崩溃,调了一上午,内心崩溃
推送文件

推送摄像头数据或者桌面

使用videoinput作为视频采集驱动,没有使用qt的camera类,videoinput采集出来的数据是rgb(bgr,可选),直接送入label显示,也可转码、编码推流
#include "videocap.h"
VideoCap::VideoCap(){
VI=new videoInput;
runFlag=false;
stopFlag=false;
width=;
height=;
device=;
deviceNums=;
frameSize=;
buffer=NULL;
}
VideoCap::~VideoCap(){
if(!buffer)
delete[] buffer;
delete VI;
}
void VideoCap::run(){
runFlag=true;
worker();
runFlag=false;
}
int VideoCap::getDeviceNum(){
deviceNums = VI->listDevices();
return deviceNums;
}
int VideoCap::init(int width, int height, int device){
this->device=device;
VI->setUseCallback(true);
VI->setIdealFramerate(this->device,);
VI->setupDevice(device, width, height);
this->width = VI->getWidth(device);
this->height = VI->getHeight(device);
// VI->showSettingsWindow(0);//该语句可以显示视频设置窗口,可以去掉
frameSize = VI->getSize(device);
buffer=new unsigned char[frameSize];
return frameSize;
}
void VideoCap::worker(){
while(!stopFlag){
VI->getPixels(device, buffer, true, true);//不能使用videoInput内置的翻转,内存冲突,暂未解决
emit capFinish();
}
}
void VideoCap::getFrame(unsigned char *&framebuff){
if(framebuff==NULL)
return;
memcpy(framebuff,buffer,frameSize);
}
void VideoCap::doCap(){
stopFlag=false;
this->start();
}
void VideoCap::doStop(){
stopFlag=true;
while(runFlag)
msleep();
VI->stopDevice(device);
}
/*yuv格式转换为rgb格式*/
void VideoCap::YUV422toRGB24(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
unsigned int in, out = ;
unsigned int pixel_16;
unsigned char pixel_24[];
unsigned int pixel32;
int y0, u, y1, v;
for(in = ; in < width * height * ; in += ) {
pixel_16 =
yuv[in + ] << |
yuv[in + ] << |
yuv[in + ] << |
yuv[in + ];
y0 = (pixel_16 & 0x000000ff);
u = (pixel_16 & 0x0000ff00) >> ;
y1 = (pixel_16 & 0x00ff0000) >> ;
v = (pixel_16 & 0xff000000) >> ;
pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
pixel_24[] = (pixel32 & 0x000000ff);
pixel_24[] = (pixel32 & 0x0000ff00) >> ;
pixel_24[] = (pixel32 & 0x00ff0000) >> ;
rgb[out++] = pixel_24[];
rgb[out++] = pixel_24[];
rgb[out++] = pixel_24[];
pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
pixel_24[] = (pixel32 & 0x000000ff);
pixel_24[] = (pixel32 & 0x0000ff00) >> ;
pixel_24[] = (pixel32 & 0x00ff0000) >> ;
rgb[out++] = pixel_24[];
rgb[out++] = pixel_24[];
rgb[out++] = pixel_24[];
}
}
int VideoCap::convert_yuv_to_rgb_pixel(int y, int u, int v)
{
unsigned int pixel32 = ;
unsigned char *pixel = (unsigned char *)&pixel32;
int r, g, b;
r = y + (1.370705 * (v-));
g = y - (0.698001 * (v-)) - (0.337633 * (u-));
b = y + (1.732446 * (u-));
if(r > ) r = ;
if(g > ) g = ;
if(b > ) b = ;
if(r < ) r = ;
if(g < ) g = ;
if(b < ) b = ;
pixel[] = r * / ;
pixel[] = g * / ;
pixel[] = b * / ;
return pixel32;
}
基于libvlc的视频播放器
可以播放本地文件
可以播放rtmp流

#include "vlcplayer.h"
#include <QDebug> VLCPlayer::VLCPlayer(){ }
VLCPlayer::~VLCPlayer(){ } void VLCPlayer::init(uint32_t winId){
instance =libvlc_new(,NULL);
this->winId=winId;
// qDebug()<<winId;
player =libvlc_media_player_new(instance);
libvlc_media_player_set_hwnd(player,(void *)winId);
} void VLCPlayer::playFile(string file){
libvlc_media_t *media=libvlc_media_new_path(instance,file.c_str());
// totalTime=libvlc_media_get_duration(media);
// qDebug()<<file.c_str();
if(!media)
qDebug()<<"media null";
else{
libvlc_media_player_set_media(player,media);
// player = libvlc_media_player_new_from_media (media);
libvlc_media_release(media);
// libvlc_media_player_set_xwindow(player,winId);
libvlc_media_player_play(player);
}
}
void VLCPlayer::playUrl(string url){
libvlc_media_t *media=libvlc_media_new_location(instance,url.c_str());
if(!media)
qDebug()<<"net media null";
else{
qDebug()<<"net media not null";
libvlc_media_player_set_media(player,media);
libvlc_media_release(media);
libvlc_media_player_play(player);
_sleep();
}
}
void VLCPlayer::pause(bool stat){
if(stat){
libvlc_media_player_set_pause(player,);
}else{
libvlc_media_player_set_pause(player,);
}
}
void VLCPlayer::stop(){
if(player){
libvlc_media_player_stop(player);
// libvlc_media_player_release(player);
}
}
libvlc_time_t VLCPlayer::getTotalTime(){
return libvlc_media_player_get_length(player);
// return totalTime;
}
libvlc_time_t VLCPlayer::getCurrentTime(){
return libvlc_media_player_get_time(player);
}
libvlc_state_t VLCPlayer::getPlayerStat(){
return libvlc_media_player_get_state(player);
}
void VLCPlayer::setPlayerPostion(float pos){
libvlc_media_player_set_position(player,pos);
}
void VLCPlayer::setVolume(int value){
libvlc_audio_set_volume(player,value);
}
void VLCPlayer::setSpeed(float speed){
libvlc_media_player_set_rate(player,speed);
}
完整工程
https://github.com/tla001/RtmpLive
相关链接
vlc
http://www.cnblogs.com/qq78292959/archive/2010/11/01/2077001.html
http://blog.csdn.net/leixiaohua1020/article/category/2619507
实战小项目之RTMP流媒体演示系统的更多相关文章
- Flask框架的学习与实战(二):实战小项目
昨天写了一篇flask开发环境搭建,今天继续,进行一个实战小项目-blog系统. blog系统很简单,只有一个页面,然而麻雀虽小五脏俱全.这里目的不是为了做项目而做项目,这篇文章本意是通过这次练习传达 ...
- 实战小项目BUG纪录
果然,作为程序员最可爱的女朋友就是各种BUG,解决了你的开发能力和开发效率就会上升到一个新的层次.反之,在你面对BUG的时候,如果轻易的就放弃了,你也就失去了一次自我成长的机会.学习就是这样的,我们有 ...
- 【实战小项目】python开发自动化运维工具--批量操作主机
有很多开源自动化运维工具都很好用如ansible/salt stack等,完全不用重复造轮子.只不过,很多运维同学学习Python之后,苦于没小项目训练.本篇就演示用Python写一个批量操作主机的工 ...
- Django集成celery实战小项目
上一篇已经介绍了celery的基本知识,本篇以一个小项目为例,详细说明django框架如何集成celery进行开发. 本系列文章的开发环境: window 7 + python2.7 + pychar ...
- [ABP实战开源项目]---ABP实时服务-通知系统.发布模式
简介 在ABP中,提供了通知服务.它是一个基于实时通知的基础设施.分为订阅模式和发布模式. 本次会在项目中使用发布模式来演示一个用户注册后,收到的欢迎信息. 发布模式 首先我们在领域层建立" ...
- ASP.NET Core 2.1 Web API + Identity Server 4 + Angular 6 + Angular Material 实战小项目视频
视频简介 ASP.NET Core Web API + Angular 6的教学视频 我是后端开发人员, 前端的Angular部分讲的比较差一些, 可以直接看代码!!!! 这是一个小项目的实战视频, ...
- spring boot的一个小项目小型进销存系统
项目所需的依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId&g ...
- springboot实战小项目-简要介绍、vue项目创建
因为菜,所以要好好学习! 一.项目介绍:这是一个后台管理系统,准备实现的功能: 1.登录.注册.个人信息查看.退出登录 2.根据关键字查询用户.新增用户.根据id或者其他字段排序.编辑用户信息.删除用 ...
- 实战小项目之ffmpeg推流yolo视频实时检测
之前实现了yolo图像的在线检测,这次主要完成远程视频的检测.主要包括推流--収流--检测显示三大部分 首先说一下推流,主要使用ffmpeg命令进行本地摄像头的推流,为了实现首屏秒开使用-g设置gop ...
随机推荐
- ubuntu 16.4 安装配置IK6.3.2
1. 从官网下载对应的解析版本 https://github.com/medcl/elasticsearch-analysis-ik/releases/tag/v6.3.2 2. 配置环境 安装mvn ...
- java Vamei快速教程01
作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! Java是完全面向对象的语言.Java通过虚拟机的运行机制,实现“跨平台”的理念. ...
- javascript:理解try...catch...finally
以前,我一直喜欢用console.log(do some thing)去执行输出的类型和值,想马上看到弹出的信息,就会直接在浏览器alert()一下,这些是基础知识. 稍微复杂一点点,就要用到判断语句 ...
- [VC]socket含义
两个程序之间的通信方法.Socket 是一种识别码,应用程式可用此唯一识别通信端点.用户创建 Socket 地址与Socket 的关联性后,便可创建通信协议地址与Socket 的关联性.
- 设置和重置ssh key
查看本地是否有已经生成好的ssh key $ cat ~/.ssh/id_rsa.pub 若有,先删除: $ cd ~ $ rm -rf .ssh 重新生成ssh key ssh-keygen -t ...
- js 常用工具类
/** * 存储sessionStorage */const setStore = (name, content) => { window.sessionStorage.setItem(name ...
- python模块;opencv安装
http://www.lfd.uci.edu/~gohlke/pythonlibs/ 1. 步骤1. 下载Python2.73, 安装, 并配置Python环境变量:".\Program F ...
- C#的接口基础教程之四 访问接口
对接口成员的访问 对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的.如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员.但由于接口支持多继承,在多继承中,如果 ...
- SQL数据库查询出一张表中重复的数据,按某个字段来查找。
例如表名为Course 需要查询出name重复的有那些??? 解答如下: 补充: 如:查询每个姓名出现大于2次,SQL如下 SELECT COUNT(NAME) as '出现次数', NAME FR ...
- java面向对象思想2
1.主函数是一类特殊的函数,作为程序入口,可被虚拟机调用.主函数格式是固定的.public:函数访问权限最大.static:代表函数随着类的加载已经存在.void:主函数没有具体返回值.main:不是 ...