#include "decodestream.h" DecodeStream::DecodeStream(QObject *parent) : QObject{parent} {} bool DecodeStream::init(AVPacketQueueManager *queueManager, AVFormatContext *formatContext, int videoIndex) { // QMutexLocker locker(&m_mutex); // m_packetsQueue = queue; m_queueManager = queueManager; m_formatContext = formatContext; m_videoIndex = videoIndex; return initDecoder(formatContext, videoIndex); } // 视频解码线程任务 void DecodeStream::startDecode() { qDebug() << "deocdeStreamThreadID:" << QThread::currentThreadId(); m_start = initObject(); if (!m_start) { free(); return; } while (m_start) { try { AVPacket *inputPacket = m_queueManager->dequeueDecodePacket(); if (inputPacket) { AVFrame *frame = decodePacket(inputPacket); emit repaintSignal(frame); av_packet_unref(inputPacket); av_packet_free(&inputPacket); inputPacket = nullptr; } else { // QThread::usleep(1000); // av_usleep(1000); } } catch (...) { } av_usleep(1000); } free(); qDebug() << "Decoding Thread End!"; emit sendErrorMessageSignal("视频解码结束!", NotificationType::NOTIFICATION_SUCCESS); } void DecodeStream::close() { // QMutexLocker locker(&m_mutex); m_start = false; qDebug() << "decode Stream close!" << m_start; } bool DecodeStream::initObject() { // 分配AVFrame并将其字段设置为默认值。 m_frame = av_frame_alloc(); if (!m_frame) { qWarning() << "av_frame_alloc() Error!"; free(); return false; } return true; } bool DecodeStream::initDecoder(AVFormatContext *inputFormatContext, int videoIndex) { if (!inputFormatContext) return false; AVStream *videoStream = inputFormatContext->streams[videoIndex]; // 通过查询到的索引获取视频流 // 获取视频图像分辨率(AVStream中的AVCodecContext在新版本中弃用,改为使用AVCodecParameters) // m_size.setWidth(videoStream->codecpar->width); // m_size.setHeight(videoStream->codecpar->height); // m_frameRate = rationalToDouble(&videoStream->avg_frame_rate); // // 视频帧率 AVCodecParameters *videoCodecPara = videoStream->codecpar; // 通过解码器ID获取视频解码器(新版本返回值必须使用const) const AVCodec *codec = avcodec_find_decoder(videoCodecPara->codec_id); if (!codec) { printf("Cannot find valid decode codec.\n"); return false; } // 分配AVCodecContext并将其字段设置为默认值。 m_codecContext = avcodec_alloc_context3(codec); if (!m_codecContext) { #if PRINT_LOG qWarning() << "创建视频解码器上下文失败!"; #endif free(); return false; } // 使用视频流的codecpar为解码器上下文赋值 int ret = avcodec_parameters_to_context(m_codecContext, videoCodecPara); if (ret < 0) { showError(ret); free(); return false; } m_codecContext->lowres = codec->max_lowres; m_codecContext->flags2 |= AV_CODEC_FLAG2_FAST; // 允许不符合规范的加速技巧。 // m_codecContext->thread_count = 4; // 使用8线程解码 // 设置解码器容错选项,忽略丢失的帧或参数 // m_codecContext->err_recognition = AV_EF_IGNORE_ERR; // m_codecContext->flags |= AV_CODEC_FLAG2_CHUNKS; // 初始化解码器上下文,如果之前avcodec_alloc_context3传入了解码器,这里设置NULL就可以 ret = avcodec_open2(m_codecContext, codec, nullptr); if (ret < 0) { showError(ret); free(); return false; } return true; } AVFrame *DecodeStream::decodePacket(AVPacket *inputPacket) { if (!isValidAVPacket(inputPacket)) return nullptr; // 将读取到的原始数据包传入解码器 int ret = avcodec_send_packet(m_codecContext, inputPacket); if (ret >= 0) { while ((ret = avcodec_receive_frame(m_codecContext, m_frame)) >= 0) { if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { showError(ret); qWarning() << "decoding file end\n"; break; } else if (ret < 0) { showError(ret); qWarning() << "Error during decoding\n"; break; } if (!isValidAVFrame(m_frame)) { break; } m_frameTemp = m_frame; return m_frameTemp; // QThread::msleep(1); } } else { qDebug() << "avcodec_send_packet error:" << ret << "\n"; if (ret == AVERROR(EAGAIN)) { qDebug() << "AVERROR(EAGAIN)"; av_usleep(10000); } if (ret == AVERROR_EOF) { qDebug() << " AVERROR_EOF"; avcodec_flush_buffers(m_codecContext); av_usleep(10000); } showError(ret); } av_frame_unref(m_frame); return nullptr; } void DecodeStream::free() { if (m_codecContext) { avcodec_free_context(&m_codecContext); } if (m_frame) { av_frame_free(&m_frame); } } bool DecodeStream::isValidAVFrame(AVFrame *frame) { // 空指针检查 if (!frame) { return false; } // 检查像素格式是否有效 if (frame->format == AV_PIX_FMT_NONE) { return false; } // 检查数据指针是否有效 if (!frame->data[0]) { return false; } // 检查宽高是否有效 if (frame->width <= 0 || frame->height <= 0) { return false; } // 检查行大小是否有效 if (frame->linesize[0] <= 0) { return false; } // 如果需要,添加更多判断条件,例如时间戳或关键帧检查 // if (frame->pts == AV_NOPTS_VALUE) { // return false; // } return true; // 如果所有条件都通过,则认为 AVFrame 有效 } bool DecodeStream::isValidAVPacket(AVPacket *pkt) { if (pkt == nullptr) { qDebug() << "Invalid AVPacket: packet pointer is null."; return false; } // 检查数据指针和大小 if (pkt->data == nullptr || pkt->size <= 0) { qDebug() << "Invalid AVPacket: data is null or size is non-positive.\n"; return false; } // 检查时间戳 // if (pkt->pts == AV_NOPTS_VALUE || pkt->dts == AV_NOPTS_VALUE) { // qDebug() << "Invalid AVPacket: pts or dts is AV_NOPTS_VALUE.\n"; // return false; // } // 检查流索引(如果是多流) if (pkt->stream_index < 0) { qDebug() << "Invalid AVPacket: stream_index is invalid.\n"; return false; } // 检查是否是有效的关键帧(可选) if (pkt->flags & AV_PKT_FLAG_KEY) { // 是关键帧 // qDebug() << "This is a keyframe.\n"; } return true; }