#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);
}

bool DecodeStream::init(AVPacketQueueManager *queueManager) {
    m_queueManager = queueManager;
    return initUDPDecoder();
}

// 视频解码线程任务
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("视频解码结束!", 1);
}

void DecodeStream::close() {
    // QMutexLocker locker(&m_mutex);
    m_start = false;
    qDebug() << "decode Stream close!" << m_start;
}

AVCodecContext *DecodeStream::getCodecContext() {
    return m_codecContext;
}

AVCodecParserContext *DecodeStream::getParserContext() {
    return m_parser;
}

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;
}

bool DecodeStream::initUDPDecoder() {
    // 通过解码器ID获取视频解码器（新版本返回值必须使用const）
    const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_H264);
    if (!codec) {
        printf("Cannot find valid decode codec.\n");
        return false;
    }

    m_parser = av_parser_init(codec->id);
    if (!m_parser) {
        fprintf(stderr, "Parser not found\n");
        return false;
    }

    // 分配AVCodecContext并将其字段设置为默认值。
    m_codecContext = avcodec_alloc_context3(codec);
    if (!m_codecContext) {
#if PRINT_LOG
        qWarning() << "创建视频解码器上下文失败！";
#endif
        free();
        return false;
    }
    // AVCodecParserContext *avcodecParserContext =
    //     av_parser_init(AV_CODEC_ID_H264);

    // 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;

    // m_codecContext->pix_fmt = AV_PIX_FMT_YUV420P;
    // 初始化解码器上下文，如果之前avcodec_alloc_context3传入了解码器，这里设置NULL就可以
    int 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() << "DecodeStream: Invalid AVPacket: packet pointer is null.";
        return false;
    }
    // 检查数据指针和大小
    if (pkt->data == nullptr || pkt->size <= 0) {
        qDebug() << "DecodeStream: 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() << "DecodeStream: Invalid AVPacket: pts or dts is "
                    "AV_NOPTS_VALUE.\n";
        return false;
    }

    // 检查流索引（如果是多流）
    if (pkt->stream_index < 0) {
        qDebug()
            << "DecodeStream: Invalid AVPacket: stream_index is invalid.\n";
        return false;
    }

    // 检查是否是有效的关键帧（可选）
    if (pkt->flags & AV_PKT_FLAG_KEY) {
        // 是关键帧
        // qDebug() << "This is a keyframe.\n";
    }

    return true;
}
