FFmpeg 开启QSV硬解加速

您所在的位置:网站首页 腊月初十一是什么生肖 FFmpeg 开启QSV硬解加速

FFmpeg 开启QSV硬解加速

2024-01-03 18:21| 来源: 网络整理| 查看: 265

简介

       QSV 全称:Quick Sync Video Acceleratio ,是Intel媒体开发库(The Intel® Media Software Development Kit)提供了一个对数字视频的通用解决方案,该解决方案支持多种图形平台(graphics platforms),实现了通用功能,能对数字视频进行预处理、编解码、以及不同编码格式的转换。

环境配置  

       1.安装intel media sdk ,官网下载后直接双击安装即可

       2.下载mfx源码: https://github.com/lu-zero/mfx_dispatch.git,下载完成后使用msys2进行编译,分别执行以下命令

autoreconf -i ./configure --prefix=/mingw64 make -j$(nproc) install

       3.下载ffmpeg源码 :https://github.com/FFmpeg/FFmpeg.git,下载完成后使用msys2进行编译,添加--enable-libmfx选项。设置PKG_CONFIG_PATH变量(默认安装的话  export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig)具体路径时编译intel media sdk 时生成的pkgconfig/libmfx.pc 所在位置

添加以下参数:

  --enable-libmfx   --enable-encoder=h264_qsv   --enable-decoder=h264_qsv

(注意使用硬解码的时候应该关闭多路复解--disable-demuxers)

完整命令(prefix 指定安装目录,执行make install 后的结果会放在prefix目录下 工 bin 、include 、lib 、 share 4个文件夹,make - 8 指定多核编译):

./configure --enable-shared --prefix=./build --enable-libmfx --enable-encoder=h264_qsv --enable-decoder=h264_qsv --disable-demuxers make -j8 make install make clean

 

代码调用 //加入头文件,由于ffmpeg是C语言完成的,导入头文件要加入extern "C" {} extern "C" { #include "libavutil/avutil.h" #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libswscale/swscale.h" #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/time.h" } //准备ffmpeg解码 av_register_all(); // 注册支持的文件格式及对应的codec avformat_network_init(); //m_url 表示视频源,可以是rtsp地址,也可以是文件路径(文件路径不能存在中文) QByteArray byte = m_url.toLatin1(); char *m_rtsp = byte.data(); pFormatCtx = nullptr; options = NULL; firstFramePts = 0; packet = nullptr; qDebug()codec_id);//h264_qsv h264_dxva2 pCodec = avcodec_find_decoder_by_name("h264_qsv"); QFFmpegThreadMutexManager::instance()->unlock(); if (!pCodec) { qDebug()height); buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture*)pFrameRGB, buffer, AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height); qDebug()height, /* pCodecCtx->pix_fmt,*/ AV_PIX_FMT_NV12, //输入格式 pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BILINEAR, nullptr, nullptr, nullptr); packet = av_packet_alloc(); // 拉流解码 while(1) { QFFmpegThreadMutexManager::instance()->lock();//如果不加锁,多视频流时可能会导致内存崩溃 int ret = av_read_frame(pFormatCtx, packet); QFFmpegThreadMutexManager::instance()->unlock(); if(ret >= 0) { if (packet->stream_index == videoStream) { QFFmpegThreadMutexManager::instance()->lock(); int frameFinished = 0; avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); QFFmpegThreadMutexManager::instance()->unlock(); //暂时没做显卡直接显示视频帧,所以拷贝到内存后显示 if (frameFinished) { sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); QImage img((uchar *)buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32); if(!img.isNull()) { emit sigShowFrame(img); }else{ qDebug()moveToThread(pThread); pThread->start(); } FFmpegDecoder::~FFmpegDecoder() { free_player(); if(pTimer) { delete pTimer; pTimer = nullptr; } pThread->quit(); pThread->wait(); delete pThread; } void FFmpegDecoder::SetUrl(QString url) { emit signalSetUrl(url); } void FFmpegDecoder::Start() { emit signalStart(); } void FFmpegDecoder::setPlayType(player::PlayType type) { emit signalSetPlayType(type); } void FFmpegDecoder::Stop() { emit signalStop(); } void FFmpegDecoder::Pause() { emit signalPause(); } void FFmpegDecoder::Starting() { emit signalStarting(); } void FFmpegDecoder::SetSpeed(double speed) { emit signalSetSpeed(speed); } void FFmpegDecoder::NextFrame() { emit signalNextFrame(); } void FFmpegDecoder::Seek(int pts) { emit signalSeek(pts); } void FFmpegDecoder::slotSetUrl(QString url) { m_url = url; } void FFmpegDecoder::slotStartPlay() { av_register_all(); // 注册支持的文件格式及对应的codec avformat_network_init(); QByteArray byte = m_url.toLatin1(); char *m_rtsp = byte.data(); // 打开audio文件 pFormatCtx = nullptr; options = NULL; firstFramePts = 0; packet = nullptr; qDebug()codec_id); pCodec = avcodec_find_decoder_by_name("h264_qsv"); QFFmpegThreadMutexManager::instance()->unlock(); if (!pCodec) { qDebug()height); buffer = (uint8_t*)av_malloc(numBytes * sizeof(uint8_t)); avpicture_fill((AVPicture*)pFrameRGB, buffer, AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height); sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_NV12, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32, SWS_BILINEAR, nullptr, nullptr, nullptr); packet = av_packet_alloc(); av_read_play(pFormatCtx); // AVStream *stream=pFormatCtx->streams[videoStream]; // qDebug()lock(); int ret = av_read_frame(pFormatCtx, packet); QFFmpegThreadMutexManager::instance()->unlock(); if(ret >= 0) { if(isRecord) { AVPacket* pkt = av_packet_clone(packet); saveH264Stream(pkt); }else{ if(pRecord) { qDebug()stream_index == videoStream) { if(player::PLAY_FILE == playType) { int pts = packet->pts * av_q2d(pStream->time_base) * 1000; if(firstFramePts == 0) { firstFramePts = pts; } // 发送播放进度 emit signalPlayProgress(pts-firstFramePts); } //保存 QFFmpegThreadMutexManager::instance()->lock(); int frameFinished = 0; avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, packet); QFFmpegThreadMutexManager::instance()->unlock(); if (frameFinished) { sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize); QImage img((uchar *)buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32); if(!img.isNull()) { emit sigShowFrame(img); }else{ qDebug()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3