#ifndef DECODEVEDIO_H
#define DECODEVEDIO_H

#include <QObject>
#include <QQueue>
#include <QTimer>
#include <QMutex>
#include <QWaitCondition>

// #include "threadcontroller.h"

extern "C"
{
// #include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
// #include <libswscale/swscale.h>
// #include <libavutil/imgutils.h>
}

/**
 * 使用方式:
 *      1. 初始化FFmpeg:initFFmpeg()
 *      2. 开启解码线程:startDecodeVedio()
 *      3. 获取一帧图像:getOneImage()
 *      4. 停止解码线程:stopDecodeVedio()
 *      5. 在初始化完成后,未进入第二步的之前,可以获取视频的宽高信息,也可以设置宽高信息
 *      
 */
class DecodeVedio : public QObject
{
    Q_OBJECT

public:
    explicit DecodeVedio(QThread* thread, QObject* parent = nullptr);
    ~DecodeVedio();

    // void setFileName(const QString& fileName) { m_fileName = fileName; }
    void initFFmpeg(const QString& fileName);       /* 初始化函数 */
    void unInitFFmpeg();                            /* 取消ffmpeg初始化函数 */
    bool isInitFFmpeg() { return m_initFFmpeg; }     /* 获取ffmpeg初始化状态 */
    
    void startDecodeVedio();                        /* 开始解码视频,开始前先设置视频名称 */
    void stopDecodeVedio();                         /* 停止解码视频,也是停止线程 */
    void setCurrentPos(quint64 pos);                /* 设置当前播放位置 */
    qint64 getCurrentPos();                         /* 获取当前播放位置 */
    qint64 getDuration();                           /* 获取视频时长 */
    bool isRunning() { return m_isRunning; }        /* 获取解码线程是否运行 */

    void wakeUpCondQueueNoEmpty();                  /* 唤醒队列非空条件变量 */
    QImage* getOneImage();                          /* 获取一帧图像 */
    QImage* getOneImageUntilHave();                 /* 获取一帧图像,直到有图像为止 */

    /* 获取帧数 */
    int getFrameCount();                            
    /* 获取图像宽度 */
    int getSrcVideoWidth() const {return m_srcWidth;}
    /* 获取图像高度 */
    int getSrcVideoHeight() const {return m_srcHeight;}
    /* 设置图像宽度和高度 */
    void setVideoSize(int width,int height);

signals:
    void signal_oneImage();                         /* 一帧图像信号 */
    void signal_playCompleted();                    /* 播放完成信号 */
private:
    void freeFFmpeg();                              /* 取消ffmpeg初始化函数 */
    void decodeVedio();                             /* 解码视频的工作函数,这个就是新线程 */
    void exitThread();                              /* 退出线程 */
    void pauseDecode();                             /* 暂停解码 */

private slots:
    void do_startDecodeVedio();                     /* 开启解码 */

private:
    QThread* m_thread = nullptr;                    /* 解码线程 */
    std::atomic_bool m_isRunning = false;           /* 解码线程是否运行 */
    QTimer m_startThread;                           /* 开启线程的定时器 */
    std::atomic_bool m_initFFmpeg = false;          /* ffmpeg初始化标志 */
    std::atomic_bool m_threadStopped = false;       /* 停止线程 */
    std::atomic_bool m_pauseDecode = false;         /* 暂停解码 */
    std::atomic_bool m_decodeStatus = false;        /* 解码状态,这里主要是检测是否暂停解码 */
    std::atomic_bool m_isSeek = false;              /* 是否跳转 */

    QString m_fileName;                             /* 解码的视频文件名称 */
    AVFormatContext *m_pFormatContext = nullptr;    /* 格式上下文,贯穿全局 */
    AVCodecContext *m_pCodecCtx = nullptr;          /* 解码器上下文 */
    AVPacket* m_packet = nullptr;                   /* 存储解码前的数据,一个数据包 */
    AVFrame* m_pFrame = nullptr;                    /* 存储解码后的一帧数据原始视频编码 */
    AVFrame* m_pFrameRGB = nullptr;                 /* 存储解码后的一帧数据,RGB格式 */
    struct SwsContext *m_sws_ctx = nullptr;         /* 视频转换上下文 */
    uint8_t *m_buffer = nullptr;                    /* 存储解码后的一帧数据,RGB格式 */
    int m_videoStream = -1;                         /* 记录视频流是第几个流 */

    int m_srcWidth = 0;                             /* 图片原本宽度 */
    int m_srcHeight = 0;                            /* 图片原本高度 */
    int m_width = 0;                                /* 图像宽度 */
    int m_height = 0;                               /* 图像高度 */
    int m_frameCount = 0;                           /* 帧数 */
    int m_fps;                                      /* 每秒的帧数 */
    qint64 m_duration = 0;                          /* 视频时长 */
    qint64 m_currentPos = 0;                        /* 当前播放位置 */
    qint64 m_startPos = 0;                          /* 起始位置,后续操作都需要在这各基础上操作 */

    // QImage *m_image = nullptr;
    int m_queueMaxNum = 10;                         /* 这里不是环形队列,最大设置为30帧图像 */
    QQueue<QImage*> m_queueImage;                   /* 视频帧队列 */
    QMutex m_mutexQueue;                            /* 队列互斥锁 */
    QWaitCondition m_condQueueNoFull;               /* 队列不满,可以入队 */
    QWaitCondition m_condQueueNoEmpty;              /* 队列非空,可以读取 */
};





#endif /* DECODEVEDIO_H */