实战小项目之RTMP流媒体演示系统

Posted 悠悠南山下

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实战小项目之RTMP流媒体演示系统相关的知识,希望对你有一定的参考价值。

项目简介

  windows下使用基于Qt对之前的RtmpApp进行封装与应用,单独功能使用线程执行,主要包括以下几个功能:

  1. 视频下载
  2. 推送文件
  3. 推送摄像头数据或者桌面
  4. 基于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(附源码和演示视频 超详细必看)

用SRS搭建WebRTC流媒体服务器实战

流媒体协议之RTMP详解20230513

STM32MP157-视频监控项目-FFmpeg-Nginx-RTMP-流媒体视频

流媒体传输协议之 RTMP

什么是RTMP 和 RTSP?它们之间有什么区别?