Qt播放rtsp视频流

1.通过vlc实现rtsp视频流播放

核心代码:

if (libvlc_NothingSpecial != libvlc_state) {
        qDebug()<<"Media is playing now"<<endl;
        return;
    }
    libvlc_inst = libvlc_new(NULL,NULL);
//      libvlc_new(sizeof (vlc_args) / sizeof (vlc_args[0]),vlc_args);

    if(NULL == libvlc_inst){
        qDebug()<<"error: libvlc_new error" <<endl;
        return;
    }
    // 网络路径 libvlc_media_new_location
    if (QFile::exists(libvlc_url)) {
        libvlc_m = libvlc_media_new_path(libvlc_inst,libvlc_url.toStdString().c_str());
    }
    else {
        libvlc_m = libvlc_media_new_location(libvlc_inst,libvlc_url.toStdString().c_str());
    }

    if(NULL == libvlc_m){
        qDebug()<<"error:libvlc_media_new_location"<<endl;
        return;
    }
    libvlc_mp = libvlc_media_player_new_from_media(libvlc_m);

    if (libvlc_mainWindow) {
        libvlc_WId = libvlc_mainWindow->winId();
        libvlc_media_player_set_hwnd(libvlc_mp,(void*)libvlc_WId);
        libvlc_video_set_mouse_input(libvlc_mp, false);
        libvlc_video_set_key_input(libvlc_mp, false);
    }
    Sleep(3);

    libvlc_media_player_play(libvlc_mp);
    libvlc_state = libvlc_media_player_get_state(libvlc_mp);

2.通过ffmpeg实现rtsp视频流播放

QFFmpeg::QFFmpeg(QObject *parent) :
    QObject(parent) {
    m_is_init_succeed = true;
    m_is_play = true;
    m_is_play_by_timer = true;
    video_stream_index = -1;
    av_register_all();//注册库中所有可用的文件格式和解码器
    avformat_network_init();//初始化网络流格式,使用RTSP网络流时必须先执行
    pAVFormatContext = avformat_alloc_context();//申请一个AVFormatContext结构的内存,并进行简单初始化
    pAVFrame = av_frame_alloc();
    m_timer = new QTimer();
    m_check_get_image_index = 0;
    m_is_get_image = false;
    m_timer->setInterval(1000);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(OnTimerOut()));
}

QFFmpeg::~QFFmpeg() {
    if (m_timer) {
        delete m_timer;
        m_timer = nullptr;
    }
    Free();
}

bool QFFmpeg::Init() {
    if (m_timer && m_timer->isActive()) {
        m_timer->stop();
    }
    m_timer->start();
    //打开视频流
    int result = avformat_open_input(&pAVFormatContext, m_url.toStdString().c_str(), nullptr, nullptr);
    if (result < 0) {
#ifdef _DEBUG
        qDebug() << "avformat_open_input : Open video stream failed!";
#endif
        m_is_init_succeed = false;
        return false;
    }
    //获取视频流信息
    result = avformat_find_stream_info(pAVFormatContext, nullptr);
    if (result < 0) {
#ifdef _DEBUG
        qDebug() << "avformat_find_stream_info : Get video stream info failed!";
#endif
        m_is_init_succeed = false;
        return false;
    }

    //获取视频流索引
    video_stream_index = -1;
    for (uint i = 0; i < pAVFormatContext->nb_streams; i++) {
        if (pAVFormatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            break;
        }
    }

    if (video_stream_index == -1) {
#ifdef _DEBUG
        qDebug() << "Get video stream index failed!";
#endif
        avformat_close_input(&pAVFormatContext);
        m_is_init_succeed = false;
        return false;
    }

    m_is_init_succeed = true;

    //获取视频流的分辨率大小
    pAVCodecContext = pAVFormatContext->streams[video_stream_index]->codec;
    videoWidth = pAVCodecContext->width;
    videoHeight = pAVCodecContext->height;
    avpicture_alloc(&pAVPicture, AV_PIX_FMT_RGB24, videoWidth, videoHeight);

    // 获取视频流解码器 (真正的编解码器,其中有编解码需要调用的函数)
    AVCodec *pAVCodec = avcodec_find_decoder(pAVCodecContext->codec_id);
    if (!pAVCodec) {
        avcodec_close(pAVCodecContext);
        avformat_close_input(&pAVFormatContext);
    }
    pSwsContext = sws_getContext(videoWidth,videoHeight,AV_PIX_FMT_YUV420P,videoWidth,videoHeight,AV_PIX_FMT_RGB24,SWS_BICUBIC,0,0,0);

    //打开对应解码器
    result = avcodec_open2(pAVCodecContext, pAVCodec, nullptr);
    if (result < 0) {
#ifdef _DEBUG
        qDebug() << "avcodec_open2 : Open AVCodec decoder failed!";
#endif
        avcodec_close(pAVCodecContext);
        avformat_close_input(&pAVFormatContext);
        return false;
    }    

#ifdef _DEBUG
    qDebug() << "Init video stream Ok!";
#endif
    return true;
}

void QFFmpeg::Play()
{
    //一帧一帧读取视频
    while (true) {
//        Sleep(300);
        if (!m_is_play || !m_is_init_succeed || !m_is_play_by_timer) {
            continue;
        }
        if (av_read_frame(pAVFormatContext, &pAVPacket) >= 0) {
            if(pAVPacket.stream_index==video_stream_index){
                int frameFinished=0;
                avcodec_decode_video2(pAVCodecContext, pAVFrame, &frameFinished, &pAVPacket);
//                qDebug() << "start decode "<<QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss") << " is finish:" << frameFinished;
                if (frameFinished){
                    mutex.lock();                    
                    sws_scale(pSwsContext,(const uint8_t* const *)pAVFrame->data,pAVFrame->linesize,0,videoHeight,pAVPicture.data,pAVPicture.linesize);
                    //发送获取一帧图像信号
                    QImage image(pAVPicture.data[0], videoWidth, videoHeight, QImage::Format_RGB888);
                    qDebug() << "emit One Image ";
                    emit SetImage(image);
                    m_is_get_image = true;
                    mutex.unlock();
                }
            }
        }
        av_free_packet(&pAVPacket);//释放资源,否则内存会一直上升
    }
}

欢迎留言或交流。 QQ:1123601333 WX:clauszheng

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值