实战小项目之RTMP流媒体演示系统
Posted 悠悠南山下
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战小项目之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=0; height=0; device=0; deviceNums=0; frameSize=0; 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,60); 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(10); VI->stopDevice(device); } /*yuv格式转换为rgb格式*/ void VideoCap::YUV422toRGB24(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height) { unsigned int in, out = 0; unsigned int pixel_16; unsigned char pixel_24[3]; unsigned int pixel32; int y0, u, y1, v; for(in = 0; in < width * height * 2; in += 4) { pixel_16 = yuv[in + 3] << 24 | yuv[in + 2] << 16 | yuv[in + 1] << 8 | yuv[in + 0]; y0 = (pixel_16 & 0x000000ff); u = (pixel_16 & 0x0000ff00) >> 8; y1 = (pixel_16 & 0x00ff0000) >> 16; v = (pixel_16 & 0xff000000) >> 24; pixel32 = convert_yuv_to_rgb_pixel(y0, u, v); pixel_24[0] = (pixel32 & 0x000000ff); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; rgb[out++] = pixel_24[0]; rgb[out++] = pixel_24[1]; rgb[out++] = pixel_24[2]; pixel32 = convert_yuv_to_rgb_pixel(y1, u, v); pixel_24[0] = (pixel32 & 0x000000ff); pixel_24[1] = (pixel32 & 0x0000ff00) >> 8; pixel_24[2] = (pixel32 & 0x00ff0000) >> 16; rgb[out++] = pixel_24[0]; rgb[out++] = pixel_24[1]; rgb[out++] = pixel_24[2]; } } int VideoCap::convert_yuv_to_rgb_pixel(int y, int u, int v) { unsigned int pixel32 = 0; unsigned char *pixel = (unsigned char *)&pixel32; int r, g, b; r = y + (1.370705 * (v-128)); g = y - (0.698001 * (v-128)) - (0.337633 * (u-128)); b = y + (1.732446 * (u-128)); if(r > 255) r = 255; if(g > 255) g = 255; if(b > 255) b = 255; if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0; pixel[0] = r * 220 / 256; pixel[1] = g * 220 / 256; pixel[2] = b * 220 / 256; return pixel32; }
基于libvlc的视频播放器
可以播放本地文件
可以播放rtmp流
#include "vlcplayer.h" #include <QDebug> VLCPlayer::VLCPlayer(){ } VLCPlayer::~VLCPlayer(){ } void VLCPlayer::init(uint32_t winId){ instance =libvlc_new(0,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(2000); } } void VLCPlayer::pause(bool stat){ if(stat){ libvlc_media_player_set_pause(player,1); }else{ libvlc_media_player_set_pause(player,0); } } 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流媒体演示系统的主要内容,如果未能解决你的问题,请参考以下文章
Android App实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)