zoukankan      html  css  js  c++  java
  • 实战小项目之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

  • 相关阅读:
    栈——有效括号问题
    链表——判断是否有环,如果有,找到入口节点并返回(转自leetcode,个人留存)
    链表—判断是否有环
    链表—判断是否有环
    链表成对反转
    反转链表
    __attribute__机制
    linux write()
    错题本本-20180919
    C++ 11特性
  • 原文地址:https://www.cnblogs.com/tla001/p/6323268.html
Copyright © 2011-2022 走看看