/*
 * Video On Demand Samples
 *
 * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * You may also obtain this software under a propriety license from Microchip.
 * Please contact Microchip for further information.
 *
 */

/*----------------------------------------------------------*/
/*! \file
 *  \brief  This file contains the CStream class.
 */
/*----------------------------------------------------------*/
#ifndef STREAM_H
#define	STREAM_H

#include "MacAddr.h"
#include "RingBuffer.h"
#include "Source.h"

#define PID_VIDEO(x)    ( 0x100 + (x) )
#define PID_AUDIO(x)    ( 0x200 + (x) )
#define PID_PMT(x)      ( 0x300 + (x) )

#define mPID_VIDEO      ( PID_VIDEO((*m_MacAddr)[5]) )
#define mPID_AUDIO      ( PID_AUDIO((*m_MacAddr)[5]) )
#define mPID_PMT        ( PID_PMT((*m_MacAddr)[5]) )

class CSource;

/*----------------------------------------------------------*/
/*! \brief Class representing a single transport stream for multiplexing.
 */
/*----------------------------------------------------------*/
class CStream : public CRingBuffer
{
    static const uint32_t NUM_PACKETS_BUFFERED = 64;        // the number has to be set that the total buffer is bigger than the buffer used by the driver. Otherwise streams might run dry or get overflows
    static uint32_t m_nInstCnt;
    uint32_t        m_nInst;
    CMacAddr       *m_MacAddr;
    CSource        *m_pCurrSource;
    CSource        *m_pNextSource;
    uint64_t        m_nBytesSent;
    uint32_t        m_nErrBufOvfl;
    uint8_t         m_TsPmt[188];

    /*----------------------------------------------------------*/
    /*! \brief switch to a new source file
     */
    /*----------------------------------------------------------*/
    void Switch();



    /*----------------------------------------------------------*/
    /*! \brief calculates a PMT packet
     */
    /*----------------------------------------------------------*/
    void CalcPmt();
    
    
    
public:
    /*----------------------------------------------------------*/
    /*! \brief constructs CStream instance
     */
    /*----------------------------------------------------------*/
    CStream();

    
    
    /*----------------------------------------------------------*/
    /*! \brief de-constructs CStream instance
     */
    /*----------------------------------------------------------*/
    ~CStream();

    
    
    /*----------------------------------------------------------*/
    /*! \brief gets the current mac address for the stream
     *  \return Pointer to the assigned MAC address
     */
    /*----------------------------------------------------------*/
    CMacAddr *GetMacAddr()
    {
        return m_MacAddr;
    };


    
    /*----------------------------------------------------------*/
    /*! \brief Statistic function: gets the amount of Bytes sent.
     *  \note Calling this method will clear this value to 0.
     */
    /*----------------------------------------------------------*/
    uint64_t GetBytesSent()
    {
        uint64_t nTmp = m_nBytesSent;
        m_nBytesSent = 0;
        return nTmp;
    };

    /*----------------------------------------------------------*/
    /*! \brief Statistic function: gets the amount of Bytes read.
     *  \note Calling this method will clear this value to 0.
     */
    /*----------------------------------------------------------*/
    uint64_t GetBytesRead();



    /*----------------------------------------------------------*/
    /*! \brief number of PCR errors since last call
     */
    /*----------------------------------------------------------*/
    uint64_t GetErrPcr();



    /*----------------------------------------------------------*/
    /*! \brief number of source buffer underflows since last call
     */
    /*----------------------------------------------------------*/
    uint64_t GetErrBufUnderflow();

    
    
    /*----------------------------------------------------------*/
    /*! \brief number of send buffer overflows since last call
     */
    /*----------------------------------------------------------*/
    uint32_t GetErrBufOverflow();


    
    /*----------------------------------------------------------*/
    /*! \brief Statistic function: gets the amount of erroneous transport streams packets.
     *  \note Calling this method will clear this value to 0.
     */
    /*----------------------------------------------------------*/
    uint64_t GetErrTs();
    
    
    /*----------------------------------------------------------*/
    /*! \brief unique ID for each stream
     */
    /*----------------------------------------------------------*/
    uint32_t GetInstId() { return m_nInst; };
    
    


    void SendPmt();
    void SendAudio(uint8_t *pTs);
    void SendVideo(uint8_t *pTs);



    /*----------------------------------------------------------*/
    /*! \brief set a new source
     *  \param pSource - pointer to source object
     */
    /*----------------------------------------------------------*/
    void SetSource(CSource *pSource) { m_pNextSource = pSource; }




    /*----------------------------------------------------------*/
    /*! \brief sets a new mac address for the stream
     *  \param pMacAddr - The new MAC address assigned to this stream.
     *  \note This method performs a deep copy of the  pMacAddr, so you are free to delete the variable at any time.
     */
    /*----------------------------------------------------------*/
    void SetMacAddr(CMacAddr *pMacAddr);



    /*----------------------------------------------------------*/
    /*! \brief set pause on/off
     *  \param bPause - true, to pause the stream. false, to play the stream.
     */
    /*----------------------------------------------------------*/
    void SetPause(bool bPause);

    
    
    /*----------------------------------------------------------*/
    /*! \brief set repeat mode
     *  \param bRepetition - if true stream will repeated for ever
     */
    /*----------------------------------------------------------*/
    void SetRepetition(bool bRepetition);



    
    /*----------------------------------------------------------*/
    /*! \brief Sets the new time position in the stream.
     *  \param nPos - The new time positon to set.
     */
    /*----------------------------------------------------------*/
    void SetPos(uint16_t nPos);


    
    /*----------------------------------------------------------*/
    /*! \brief Read from HDD to fill ring buffer
     *
     *  \return true, if something was read from file.
     */
    /*----------------------------------------------------------*/
    bool ReadHdd();



    /*----------------------------------------------------------*/
    /*! \brief gets next TS packet to be sent
     *
     * \return true, if a packet was available
     */
    /*----------------------------------------------------------*/
    bool GetTsPacket(uint8_t *pTrg);
    
    
    
    /*----------------------------------------------------------*/
    /*! \brief Trace stream properties to console
     */
    /*----------------------------------------------------------*/
    void PrintStream();
};

#endif