|
@@ -70,11 +70,12 @@ void DecodeVedio::getHWDecoder()
|
|
|
strTypes.append(QString(typeName));
|
|
|
}
|
|
|
}
|
|
|
- FMTLOG_INFO_NON("支持的硬件解码器:");
|
|
|
+ FMTLOG_INFO("支持的硬件解码器:");
|
|
|
for(auto type : strTypes)
|
|
|
{
|
|
|
FMTLOG_INFO_NON(" {}",type.toStdString());
|
|
|
}
|
|
|
+ FMTLOG_INFO_NON("\n");
|
|
|
}
|
|
|
|
|
|
/* 开始解码视频 */
|
|
@@ -365,7 +366,7 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
}
|
|
|
|
|
|
ret = 0;
|
|
|
- /* 检查视频容器内部的流信息,将流存储到了pFormatContext->streams中
|
|
|
+ /* 检查视频容器内部的流信息,将所有流存储到了pFormatContext->streams中
|
|
|
* 这个会补充avformat_open_input()没有获取到的信息 */
|
|
|
ret = avformat_find_stream_info(m_pFormatContext, nullptr);
|
|
|
if(ret < 0)
|
|
@@ -382,24 +383,15 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
av_dump_format(m_pFormatContext, 0, m_fileName.toStdString().c_str(), 0);
|
|
|
|
|
|
/************ 找到视频流 ************/
|
|
|
- int i = 0;
|
|
|
- AVCodecParameters *pCodecCtxOrig = nullptr;
|
|
|
-
|
|
|
- for(i = 0;i < m_pFormatContext->nb_streams; i++)
|
|
|
- {
|
|
|
- if(m_pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
|
|
- {
|
|
|
- m_videoStream = i;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if(m_videoStream == -1)
|
|
|
+ m_videoStream = av_find_best_stream(m_pFormatContext, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0);
|
|
|
+ if(m_videoStream < 0)
|
|
|
{
|
|
|
SPDLOG_WARN("没有找到视频流");
|
|
|
return;
|
|
|
}
|
|
|
SPDLOG_INFO("找到视频流");
|
|
|
-
|
|
|
+ /* 获取视频流的编解码信息 */
|
|
|
+ AVCodecParameters *pCodecCtxOrig = nullptr;
|
|
|
pCodecCtxOrig = m_pFormatContext->streams[m_videoStream]->codecpar;
|
|
|
SPDLOG_INFO("获取视频流参数成功!");
|
|
|
/* 使用编码器指向流 */
|
|
@@ -411,8 +403,8 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
SPDLOG_WARN("没有找到解码器");
|
|
|
return;
|
|
|
}
|
|
|
- SPDLOG_TRACE("找到解码器");
|
|
|
- /* 复制上下文,先分配空间,后面记得释放空间 */
|
|
|
+ SPDLOG_INFO("找到解码器 :{}",pCodec->name);
|
|
|
+ /* 获取视频信息的上下文,先分配空间,后面记得释放空间 */
|
|
|
m_pCodecCtx = avcodec_alloc_context3(pCodec);
|
|
|
SPDLOG_TRACE("分配空间成功!");
|
|
|
/* 将视频流中的编码器参数拷贝下来,这个函数不是线程安全的 */
|
|
@@ -422,7 +414,11 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
return;
|
|
|
}
|
|
|
SPDLOG_INFO("复制上下文成功!");
|
|
|
- if(avcodec_open2(m_pCodecCtx, pCodec, nullptr) < 0)
|
|
|
+
|
|
|
+ /*************** 初始化硬件解码器 ******************/
|
|
|
+
|
|
|
+ /* 打开解码器,(初始化解码器上下文,如果调用了avcodec_alloc_context3,第二个参数可以设置为nullptr) */
|
|
|
+ if(avcodec_open2(m_pCodecCtx, nullptr, nullptr) < 0)
|
|
|
{
|
|
|
SPDLOG_ERROR("打开解码器错误");
|
|
|
return;
|
|
@@ -450,7 +446,7 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
|
|
|
int numBytes = 0;
|
|
|
/* 初始化pFrameRGB */
|
|
|
- numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
+ numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGBA, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
m_buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));
|
|
|
/* 获取视频相关信息 */
|
|
|
m_width = m_srcWidth = m_pCodecCtx->width;
|
|
@@ -458,13 +454,13 @@ void DecodeVedio::initFFmpeg(const QString& fileName)
|
|
|
m_frameCount = m_pFormatContext->streams[m_videoStream]->nb_frames;
|
|
|
|
|
|
/* 这个函数的实际作用是将buffer设置给pFrameRGB作为原始数据的内存区域 */
|
|
|
- av_image_fill_arrays(m_pFrameRGB->data, m_pFrameRGB->linesize, m_buffer, AV_PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
+ av_image_fill_arrays(m_pFrameRGB->data, m_pFrameRGB->linesize, m_buffer, AV_PIX_FMT_RGBA, m_pCodecCtx->width, m_pCodecCtx->height, 1);
|
|
|
|
|
|
/********** 创建一个SwsContext结构体,主要为了格式转化的时候使用 ***********/
|
|
|
|
|
|
/* 初始化Sws Context,这是转换规则,转换成RGB */
|
|
|
m_sws_ctx = sws_getContext( m_pCodecCtx->width, m_pCodecCtx->height, m_pCodecCtx->pix_fmt, /* 原图像大小和格式 */
|
|
|
- m_srcWidth, m_srcHeight, AV_PIX_FMT_RGB24, /* 目标图像的大小和格式 */
|
|
|
+ m_srcWidth, m_srcHeight, AV_PIX_FMT_RGBA, /* 目标图像的大小和格式 */
|
|
|
SWS_BILINEAR, /* 双线性 */
|
|
|
nullptr,
|
|
|
nullptr,
|
|
@@ -597,7 +593,8 @@ void DecodeVedio::decodeVedio()
|
|
|
// std::chrono::steady_clock::time_point t7 = std::chrono::steady_clock::now();
|
|
|
// SPDLOG_TRACE("======================================= 转换RGB耗时:{}",std::chrono::duration_cast<std::chrono::milliseconds>(t7 - t6).count());
|
|
|
/* 一帧图像入队 */
|
|
|
- auto image = new QImage(m_pFrameRGB->data[0], m_width, m_height, QImage::Format_RGB888);
|
|
|
+ // auto image = new QImage(m_pFrameRGB->data[0], m_width, m_height, QImage::Format_RGB888);
|
|
|
+ auto image = new QImage(m_pFrameRGB->data[0], m_width, m_height, QImage::Format_RGBA8888);
|
|
|
// SPDLOG_DEBUG("队列中图片个数:{} ",m_queueImage.count());
|
|
|
m_mutexQueue.lock();
|
|
|
if(m_queueImage.count() >= m_queueMaxNum)
|