#ifndef QGSTREAMERPLAYER_H
#define QGSTREAMERPLAYER_H

#include <QObject>

#include <gst/gst.h>
#include <gst/app/app.h>

#include <QList>

#include <QElapsedTimer>

class QVideoWidget;
class QRTSPThread;
class QGstreamerPlayer;

typedef struct _CustomDataSink
{
    GstElement* m_pQueue;
    GstElement* m_pConvert;
    GstElement* m_pRate;
    GstElement* m_pSink;
    GstElement* m_pEncoder;
    GstElement* m_pParser;
    GstElement* m_pMuxer;
    GstElement* m_pQueueFileData;
    GstPad* m_pTeePad;
    gboolean removing;

    GstElement* m_pCaps;

    _CustomDataSink()
    {
        m_pQueue = NULL;
        m_pQueueFileData = NULL;
        m_pConvert = NULL;
        m_pSink = NULL;
        m_pTeePad = NULL;
        m_pEncoder = NULL;
        m_pParser = NULL;
        m_pRate = NULL;
        m_pMuxer = NULL;
        m_pCaps = NULL;
        removing = false;
    }
}CustomDataSink;

/* Structure to contain all our information, so we can pass it around */
typedef struct _GST_CustomData {
    _GST_CustomData()
    {
        pPlayer = NULL;
        pWidget = NULL;
        playbin2 = NULL;
        pipeline = NULL;
        source = NULL;
        OptionSrc = NULL;
        convert = NULL;
        sink = NULL;
        bin = NULL;

        queue_src = NULL;
        queue_sink = NULL;
        pThread = NULL;

        m_pSink = NULL;
        m_pSinks = NULL;

        m_pCaps = NULL;
        caps_videosrc = NULL;
        caps_vidconv1 = NULL;

        videoBalance = NULL;

        vidconv1 = NULL;
        vidconv2 = NULL;

        m_bVideoLink = false;

        vidrate1 = NULL;
        vidscale1 = NULL;
        vidClockDisplay = NULL;
        caps_vidrate1 = NULL;
        caps_vidscale1 = NULL;

        appsink_callbacks = NULL;
    }

  QGstreamerPlayer* pPlayer;
  QVideoWidget* pWidget;
  GstElement *playbin2;  /* Our one and only element */
  gboolean playing;      /* Are we in the PLAYING state? */
  gboolean terminate;    /* Should we terminate execution? */
  gboolean seek_enabled; /* Is seeking enabled for this media? */
  gboolean seek_done;    /* Have we performed the seek already? */
  gint64 duration;       /* How long does this media last, in nanoseconds */
  gdouble rate;      /* Current playback rate (can be negative) */

  GstElement* pipeline;
  GstElement* source;
  GstElement* videoBalance;
  GstCaps* OptionSrc;
  GstElement* convert;
  GstElement* sink;
  GstElement* bin;

  GstElement* vidconv1;
  GstElement* vidconv2;

  GstElement* vidrate1;
  GstElement* vidscale1;
  GstElement* vidClockDisplay;

  GstBus* bus;

  GstElement* queue_src;
  GstElement* queue_sink;
  QRTSPThread* pThread;

  GstElement* tee;

  GList* m_pSinks;

  CustomDataSink* m_pSink;

  QString m_strFilename;

  GstElement* m_pCaps;

  GstElement* caps_videosrc;
  GstElement* caps_vidconv1;
  GstElement* caps_vidrate1;
  GstElement* caps_vidscale1;

  bool m_bError;

  bool m_bShow;

  bool m_bVideoLink;

  bool m_bEncoding;

  GstAppSinkCallbacks* appsink_callbacks;

  QElapsedTimer m_TimerStart;
} GST_CustomData, *PGST_CustomData;



class QGstreamerPlayer : public QObject
{
    Q_OBJECT
public:
    explicit QGstreamerPlayer(QObject *parent = 0);
    virtual ~QGstreamerPlayer();

    virtual void OpenMovieFile(QString strFile);

    virtual int OpenCamera4(QString strPatameter);

    virtual void CreatePipeLineJetson();
    virtual void CreatePipeLinePC();

    static void app_sink_eos(GstAppSink *sink, gpointer user_data);
    static GstFlowReturn app_sink_new_sample(GstAppSink *sink, gpointer user_data);
    static GstFlowReturn app_sink_new_preroll(GstAppSink *sink, gpointer user_data);
    static void pad_added_handler (GstElement *src, GstPad *new_pad, GST_CustomData *data);

    void SetThread(QRTSPThread* pThread);
    void SetVideoWidget(QVideoWidget* pWidget);

    void Seek(gint64 nPos);

    void Pause();

    void StopRTSP();
    void StartRTSP();

    void exitRTSP();

    void Resume();

    bool IsSeeking();

    QList<gint64> m_ListSeeking;

    gint64 GetSeekPos();

    void SetFrameWidth(int nWidth);
    void SetFrameHeight(int nHeight);
    int GetFrameWidth();
    int GetFrameHeight();

    virtual void SaveFile(QString strFilename);
    virtual void SaveEnd();

    bool IsWorkingRTSP();

    void CaptureImage();

    bool IsPipeStart();

    void ChangeHue(float fValue);
    void ChangeSaturation(float fValue);

    void Alram();

    void SetCaptureMode(int nMode);
    int GetCaptuerMode();

    qint64 GetVideoLinkTime();

    bool IsVideoLink();

    bool IsError();

protected:

    GError* m_pError;
    bool m_bWorkingRTSP;
    bool m_bError;

signals:
    void SendFinished();

    void ExitCapture();
    void ErrorCapture();



public slots:

protected:
    int m_nTestCount;
    bool m_bPipeStart;
    bool m_bCaptureImage;
    bool m_bSeeking;
    GST_CustomData m_DataGST;
    GstMessage* m_pMsgGST;

    bool m_bTerminate;
    QVideoWidget* m_pVideoWidget;

    gint64 m_nSeekPos;

    int m_nFrameWidth;
    int m_nFrameHeight;

    int m_nCaptureMode;
};

#endif // QGSTREAMERPLAYER_H
