Qt FFmpeg 音视频播放器
使用FFmpeg庫實現 本地和rtp 音視頻播放器,使用qt繪制視頻。
本demo環境為 qt5.12 vs2019-32位 .pro的qt工程
FFmpeg版本位3.4.8 vs2092-32位
本demo一共分為四部分
1:FFmpeg接口類,封裝了一些FFmpeg的api,方便提供調用
2:thread類, 線程類,讀取視頻,解碼,發送數據
3:UI類 使用qt的QOpenGLWidget類來繪制圖像
4:audio播放類。 使用qt的QAudioOutput來播放解碼后的音頻數據
本文福利, 免費領取C++音視頻學習資料包、技術視頻,內容包括(音視頻開發,面試題,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓見下面↓↓文章底部點擊免費領取↓↓
初始化ffmpeg
avcodec_register_all();//注冊所有解碼器av_register_all();//注冊所有格式avformat_network_init();//初始化網絡流格式,使用RTSP網絡流時必須先執行m_avFormatContext = avformat_alloc_context();m_yuvFrame = av_frame_alloc();m_pcmFrame = av_frame_alloc();打開視頻流或者rtp,流獲取視頻信息
//打開視頻流int result=avformat_open_input(&m_avFormatContext, url.toStdString().c_str(),nullptr,nullptr);if (result<0){qDebug()<<"avformat_open_input error ---"<<result;return false;}//獲取視頻流信息result=avformat_find_stream_info(m_avFormatContext,nullptr);if (result<0){qDebug()<<"avformat_find_stream_info error ---"<<result;return false;}初始化音頻相關,需要獲取音頻流的索引,初始化解碼器上下文,音頻重采樣上下文
//獲取音頻流索引for (uint i = 0; i < m_avFormatContext->nb_streams; i++){if (AVMEDIA_TYPE_AUDIO == m_avFormatContext->streams[i]->codec->codec_type){m_audioCodecContext = m_avFormatContext->streams[i]->codec;m_audioStreamIndex = i;break;}}if (-1 == m_audioStreamIndex){ return false;}if(nullptr == m_audioCodecContext){ return false;}//初始化一個視音頻編解碼器的AVCodecContextAVCodec *codec = avcodec_find_decoder(m_audioCodecContext->codec_id);//查找解碼器if (avcodec_open2(m_audioCodecContext, codec, nullptr) < 0){qDebug()<<"avcodec_open2 error---";return false;}m_sampleRate = m_audioCodecContext->sample_rate;//樣本率m_channel = m_audioCodecContext->channels;//通道數switch (m_audioCodecContext->sample_fmt)//樣本大小{case AV_SAMPLE_FMT_S16:this->m_sampleSize = 16;break;case AV_SAMPLE_FMT_S32:this->m_sampleSize = 32;default:break;}if (nullptr == m_audioSwrContext){m_audioSwrContext = swr_alloc();//初始化swr_alloc_set_opts(m_audioSwrContext,m_audioCodecContext->channel_layout,AV_SAMPLE_FMT_S16,m_audioCodecContext->sample_rate,m_audioCodecContext->channels,m_audioCodecContext->sample_fmt,m_audioCodecContext->sample_rate,0,0);swr_init(m_audioSwrContext);}初始化視頻相關,獲取視頻流的索引,初始化解碼器上下文。
//獲取視頻流索引for (uint i = 0; i < m_avFormatContext->nb_streams; i++){if (AVMEDIA_TYPE_VIDEO == m_avFormatContext->streams[i]->codec->codec_type){m_videoStreamIndex = i;m_videoCodecContext = m_avFormatContext->streams[i]->codec;break;}}if(-1 == m_videoStreamIndex){qDebug()<<"videoStreamIndex init error---";return false;}if (m_videoCodecContext == nullptr){qDebug()<<"videoCodecContext init error---";return false;}//獲取視頻流解碼器AVCodec *pAVCodec = avcodec_find_decoder(m_videoCodecContext->codec_id);//打開對應解碼器int result=avcodec_open2(m_videoCodecContext,pAVCodec,nullptr);if (result<0){qDebug()<<"avcodec_open2 video open error";return false;}m_videoSwsContext = sws_getContext(m_videoCodecContext->width,m_videoCodecContext->height,m_videoCodecContext->pix_fmt,m_videoCodecContext->width,m_videoCodecContext->height,AV_PIX_FMT_BGRA,SWS_BICUBIC,0,0,0);avpicture_alloc(&pAVPicture,AV_PIX_FMT_BGRA,m_videoCodecContext->width,m_videoCodecContext->height);接下來就是線程run里面的讀取數據,解碼,發送數據的操作
void VideoThread::run() {char audioOut[10000] = {0};while(m_isRun){int free = AudioPlayer::Get()->GetFree();if (free < 10000){msleep(1);continue;}AVPacket pkt = m_ffmpeg->getPacket();if (pkt.size <= 0){msleep(10);continue;}if (pkt.stream_index == m_ffmpeg->m_audioStreamIndex){m_ffmpeg->decode(&pkt);//解碼int len = m_ffmpeg->getPCM(audioOut);//獲取一幀音頻的pcmAudioPlayer::Get()->Write(audioOut, len); }else{if(m_ffmpeg->decode(&pkt)){m_ffmpeg->getRBG();}}av_packet_unref(&pkt);} }AudioPlayer::Get()->Write(audioOut, len); 此部分是音頻播放
m_ffmpeg->getRBG(); 此部分是獲取rgb數據幀, 并且綁定信號跟槽函數到QTopenglWidget繪制
UI繪制上:
在槽函數中接受數據,并且updata刷新
void OpenglWidget::paintEvent(QPaintEvent *e) {QPainter painter;painter.begin(this);painter.drawImage(QPoint(0, 0), m_image);painter.end(); }void OpenglWidget::showImage(const QImage &image) {if(image.width() > image.height())m_image = image.scaledToWidth(width(),Qt::SmoothTransformation);elsem_image = image.scaledToHeight(height(),Qt::SmoothTransformation);update(); }繪制是按照視頻原有的比例來繪制, 如果大分辨率切成小分辨率則需要刷新一下背景
如果你對音視頻開發感興趣,覺得文章對您有幫助,別忘了點贊、收藏哦!或者對本文的一些闡述有自己的看法,有任何問題,歡迎在下方評論區討論!
本文福利, 免費領取C++音視頻學習資料包、技術視頻,內容包括(音視頻開發,面試題,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)↓↓↓↓↓↓見下面↓↓文章底部點擊免費領取↓↓
總結
以上是生活随笔為你收集整理的Qt FFmpeg 音视频播放器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: compare用法java,Java经典
- 下一篇: js有关时间换算的一些方法