#ifndef READSTREAM_H
#define READSTREAM_H

#include <QDebug>
#include <QMutex>
#include <QObject>
#include <QQueue>
#include <QSize>
#include <QThread>

#include "avpacketqueuemanager.h"
#include "decodestream.h"
#include "ffmpeginclude.h"
#include "pushstream.h"
#include "savestream.h"

class ReadStream : public QObject {
    Q_OBJECT
public:
    explicit ReadStream(QObject *parent = nullptr);
    ~ReadStream();
    bool openFile(const QString &url);
    bool setStreamDecoder(DecodeStream *decodeStreamer);
    bool setStreamSaver(SaveStream *streamSaver);
    bool setStreamPusher(PushStream *streamPusher);  // 开启推流
    void close();

public slots:
    void startPullStream();
signals:
    // void startDecodeSignal();
    void startPullStreamSignal();
    void sendErrorMessageSignal(QString message, int type);

private:
    void initFFmpeg();  // 初始化ffmpeg库(整个程序中只需加载一次)
    bool initObject();  // 初始化对象
    // void showError(int err);  // 显示ffmpeg执行错误时的错误信息
    // qreal rationalToDouble(AVRational* rational);  //
    // 将AVRational转换为double
    void clear();  // 清空读取缓冲
    void free();   // 释放

    /**
     * @brief 重连
     * @return 重连成功或失败
     */
    bool reconnect();

    bool isValidAVPacket(AVPacket *pkt);

private:
    bool m_pushStreamFlag = false;  // 推流开始标识
    bool m_decodeStreamFlag = false;
    bool m_saveStreamFlag = false;
    QString m_pullURL;      // 拉流地址
    int MAXRECONNECT = 12;  // 最大重连次数
    qreal m_frameRate = 0;  // 视频帧率
    QSize m_size;           // 视频分辨率大小
    uchar *m_buffer = nullptr;
    bool m_start = true;
    bool m_end = false;
    int64_t m_startTime;

    AVFormatContext *m_formatContext = nullptr;  // 解封装上下文
    AVCodecContext *m_codecContext = nullptr;    // 解码器上下文
    // SwsContext* m_swsContext = nullptr;          // 图像转换上下文
    AVPacket *m_inputPacket = nullptr;  // 数据包
    int m_videoIndex = 0;               // 视频流索引
    int QUEUECAPACITY = 100;
    // QQueue<AVPacket *> m_packetsQueue;
    // QQueue<AVPacket *> m_saverQueue;
    // QQueue<AVPacket *> m_pusherQueue;

    DecodeStream *m_streamDecoder = nullptr;
    SaveStream *m_streamSaver = nullptr;
    PushStream *m_streamPusher = nullptr;

    // QMutex m_mutex;
    AVPacketQueueManager m_queueManager;
};

#endif  // READSTREAM_H