实战小项目之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 ...
随机推荐
- html body上有一条空白!!!
html body 上莫名其妙的就出现了一条空白,怎么搞都搞不定,弄了一下午...... 解决了!!! 格式问题/
- UVA 11990 ``Dynamic'' Inversion (序列分治)
26天以前做过的一道题,之前的做法是分治预处理,树套树在线修改,复杂度为O(nlogn+m*logn*logn),代码量较大. 本来想学习一下cdq分治的,看到论文上的凸包.斜率就暂时放一边了,只知道 ...
- Aizu 2300 Calender Colors(暴力)
状压以后,直接暴力枚举,2^20约等于1e6,而且满足bitcount = m的状态很少. #include<bits/stdc++.h> using namespace std; +; ...
- CentOS启动时自动加载内核模块
要想在CentOS中自动加载内核模块,需要在/etc/sysconfig/modules/目录中增加一个脚本,在此脚本中加载所需的模块. 下面是我所用的一个名为8021q.modules的脚本,用来在 ...
- Servlet 学习小结
一.是什么 是用java编写的服务器端程序.从狭义来讲,servlet是java语言实现的一个接口:广义的servlet是指任何实现了这个servlet接口的类.一般情况下,人们将servlet理解为 ...
- 问题005:如何配置JDK,Java运行环境?
方法一:我的电脑右击-->属性-->高级-->环境变量-->Path 方法二:set path是查询环境变灵, set path=路径
- 读取properties的简单方法,使用@Configuration
配置类代码如下 import org.springframework.beans.factory.annotation.Value; import org.springframework.contex ...
- MySQL自学笔记_联结(join)
1. 背景及原因 关系型数据库的一个基本原则是将不同细分数据放在单独的表中存储.这样做的好处是: 1).避免重复数据的出现 2).方便数据更新 3).避免创建重复数据时出错 例子: 有供应商信息和产 ...
- nginx 如何配置来获取用户真实IP
- pycharm clion rider 注册
JetBrains 公司出品的pycharm clion rider 专业版本都需要注册才能运行,这里有个免费注册方法: JetBrains授权服务器2017.10.7授权方法:激活时选择Licens ...