#ifndef CFFMPEG_DECODE_H
#define CFFMPEG_DECODE_H

#include "ffmpeginclude.h"
#include "global.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QDebug>
#include <QDir>
#include <QImage>
#include <QMutex>
#include <QPaintEvent>
#include <QPainter>
#include <QThread>
#include <QWidget>

// class Cffmpeg_decode: public QThread
class Cffmpeg_decode : public QObject {
  Q_OBJECT
public:
  // explicit Cffmpeg_decode();
  Cffmpeg_decode(QObject *parent = nullptr);
  ~Cffmpeg_decode();

  bool open_input_file();
  void stop();
  void stopPull();
  /**
   * @brief 设置拉流保存文件夹路径
   * @param fileDirPath 文件夹路径
   */
  void setSaveFileDirPath(QString fileDirPath);
  void setFlowType(QString); // 设置拉流打开方式

  void setStreamUrl(QString url);
public slots:
  void run();
  void setPlayVideo(bool bPlay);
  void setPushStream(bool bPushStream);
signals:
  void sendQImage(QImage);
  void sendConnectFail(int);
  void sendInitPushStream_Signal(AVFormatContext *inputFormatCtx);
  void sendStreamData_Signal(AVPacket *pkt, int frm_cnt, int64_t startTime,
                             int64_t firstDts);
  void sendStopPushStream_Signal();

public:
  QMutex mutex;

  bool IsstopPlay = false;
  bool bPushStreamFlag = false; // 推流标志
  bool bPlayVideoFlag = false;  // 播放视频标志

private:
  bool bOpenPushStreamFlag = false; // 推流初始化

  AVFormatContext *inputFormatCtx = NULL; //

  AVCodecContext *decoderCtx = NULL; //
  AVCodecContext *encoderCtx = NULL; //

  const AVCodec *decoder = NULL; // 解码器

  AVPacket *inputPacket = NULL; //

  AVFrame *yuvFrame = NULL;
  AVFrame *rgbFrame = NULL;

  struct SwsContext *swsCtx = NULL; // 图像转换上下文

  AVCodecParameters *videoCodecPara = nullptr;

  unsigned char *out_buffer = nullptr;

  int videoStreamIndex = -1;
  int numBytes = -1;
  int frm_cnt = 0;

  QString _url;
  QString saveFileDirPath;
  bool bRecordTime = true;

  // 推流使用
  int64_t startTime;
  int64_t firstDts;

  // 初始化 previous_pts_time 为无效值(拉流使用)
  double previous_pts_time;       // 表示没有上一帧的时间戳
  double first_frame_pts_time;    // 第一帧的 PTS 时间
  double first_frame_system_time; // 第一帧解码时的系统时间
  /******************  保存裸流使用 ******************/
  AVFormatContext *m_formatContextSave = nullptr; // 封装上下文
  QString m_strCodecName;                         // 编解码器名称
  AVStream *m_videoStreamOut = nullptr;           // 输出视频流
  bool m_writeHeader = false;                     // 是否写入文件头

  QString m_rtsp_transport; // 拉流打开方式,UDP或TCP
  bool m_bSetRtspTransport = false;

private:
  int MAXRECONNECT = 12;
  bool m_saveVideoFlag = false;
  bool m_startPullFlag = false;
  bool m_reconnectFlag = false;
  void initFFmpegContainer();
  /**
   * @brief 打开视频保存文件
   * @return
   */
  bool openSave();
  /**
   * @brief 视频保存成功,释放资源
   */
  void saveDone();

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

#endif // CFFMPEG_DECODE_H