/*******************************************************}

{                                                       }

{       File : transport_packet_class.h                 }

{       Created by Tsviatko Jongov                      }

{       http://tsviatko.jongov.com                      }

{                                                       }

{       Transport packet class.                         }

{                                                       }

{*******************************************************/

   

#ifndef __TRANSPORT_PACKET_CLASS_H__

#define __TRANSPORT_PACKET_CLASS_H__

   

#include "mpegtsutils.h"

   

class Ctransport_packet_class

{

public:

    unsigned long m_TSPacketLen;   //188, 192, 196, 204 or 212

    unsigned char m_Data[212];

    transport_packet m_transport_packet;

    unsigned long m_PayloadOffset;

protected:

    bool ParsePacket()

    {

        unsigned char * p;

        unsigned char * paf; //Points the start of the adaptation field

        unsigned char * pe;  //Points the start of the adaptation field extension

        unsigned int i = 0;

 

        p = &m_Data[0];

        m_transport_packet.sync_byte = *p;

        if (m_transport_packet.sync_byte != 0x47)

        {

            OutputDebugString(TEXT("tsv: Error in Ctransport_packet_class.ParsePacket - invalid packet."));

            return false;

        }

        p++;

       

        m_transport_packet.transport_error_indicator = (*p >> 7) & 0x01;

        m_transport_packet.payload_unit_start_indicator = (*p >> 6) & 0x01;

        m_transport_packet.transport_priority = (*p >> 5) & 0x01;

       

        m_transport_packet.PID = (*p & 0x1F) << 8;

        p++;

       

        m_transport_packet.PID = m_transport_packet.PID | *p;

        p++;

       

        m_transport_packet.transport_scrambling_control = (*p >> 6) & 0x03;

        m_transport_packet.adaptation_field_control = (*p >> 4) & 0x03;

        m_transport_packet.continuity_counter = (*p & 0x0F);

        p++;

 

        if (m_transport_packet.adaptation_field_control & 0x02) //Has adaptation field

        {

            paf = p;

           

            m_transport_packet.adaptation_fld.adaptation_field_length = *p;

            p++;

           

            if (m_transport_packet.adaptation_fld.adaptation_field_length > 0)

            {

                m_transport_packet.adaptation_fld.discontinuity_indicator = (*p >> 7) & 0x01;

                m_transport_packet.adaptation_fld.random_access_indicator = (*p >> 6) & 0x01;

                m_transport_packet.adaptation_fld.elementary_stream_priority_indicator = (*p >> 5) & 0x01;

                m_transport_packet.adaptation_fld.PCR_flag = (*p >> 4) & 0x01;

                m_transport_packet.adaptation_fld.OPCR_flag = (*p >> 3) & 0x01;

                m_transport_packet.adaptation_fld.splicing_point_flag = (*p >> 2) & 0x01;

                m_transport_packet.adaptation_fld.transport_private_data_flag = (*p >> 1) & 0x01;

                m_transport_packet.adaptation_fld.adaptation_field_extension_flag = *p & 0x01;

                p++;

               

                if (m_transport_packet.adaptation_fld.PCR_flag & 0x01)

                {

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->HighPart = (*p >> 7) & 0x01;

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart = (*p & 0x7F) << 25;

                    p++;

                   

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart =

                        ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart | (*p << 17);

                    p++;

                   

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart =

                        ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart | (*p << 9);

                    p++;

                   

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart =

                        ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart | (*p << 1);

                    p++;

                   

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart =

                        ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.program_clock_reference_base))->LowPart | ((*p >> 7) & 0x01);

                   

                    m_transport_packet.adaptation_fld.reserved0 = (*p & 0x7E) >> 1;

                   

                    m_transport_packet.adaptation_fld.program_clock_reference_extension = (*p & 0x01) << 8;

                    p++;

                   

                    m_transport_packet.adaptation_fld.program_clock_reference_extension =

                        m_transport_packet.adaptation_fld.program_clock_reference_extension | *p;

                    p++;

                }

            }

           

            if (m_transport_packet.adaptation_fld.OPCR_flag & 0x01)

            {

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->HighPart = (*p >> 7) & 0x01;

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart = (*p & 0x7F) << 25;

                p++;

               

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart =

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart | (*p << 17);

                p++;

               

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart =

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart | (*p << 9);

                p++;

               

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart =

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart | (*p << 1);

                p++;

               

                ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart =

                    ((LARGE_INTEGER *)(&m_transport_packet.adaptation_fld.original_program_clock_reference_base))->LowPart | ((*p >> 7) & 0x01);

               

                m_transport_packet.adaptation_fld.reserved1 = (*p & 0x7E) >> 1;

               

                m_transport_packet.adaptation_fld.original_program_clock_reference_extension = (*p & 0x01) << 8;

                p++;

               

                m_transport_packet.adaptation_fld.original_program_clock_reference_extension =

                    m_transport_packet.adaptation_fld.original_program_clock_reference_extension | *p;

                p++;

            }

           

            if (m_transport_packet.adaptation_fld.splicing_point_flag & 0x01)

            {

                m_transport_packet.adaptation_fld.splice_countdown = *p;

                p++;

            }

            

            if (m_transport_packet.adaptation_fld.transport_private_data_flag & 0x01)

            {

                m_transport_packet.adaptation_fld.transport_private_data_length = *p;

                p++;

               

                for (i = 0; i < m_transport_packet.adaptation_fld.transport_private_data_length; i++)

                {

                    m_transport_packet.adaptation_fld.private_data_byte[i] = *p;

                    p++;

                }

            }

           

            if (m_transport_packet.adaptation_fld.adaptation_field_extension_flag & 0x01)

            {

                pe = p;

               

                m_transport_packet.adaptation_fld.adaptation_field_extension_length = *p;

                p++;

                

                m_transport_packet.adaptation_fld.ltw_flag = (*p >> 7) & 0x01;

                m_transport_packet.adaptation_fld.piecewise_rate_flag = (*p >> 6) & 0x01;

                m_transport_packet.adaptation_fld.seamless_splice_flag = (*p >> 5) & 0x01;

                m_transport_packet.adaptation_fld.reserved2 = (*p & 0x1F);

                p++;

               

                if (m_transport_packet.adaptation_fld.ltw_flag & 0x01)

                {

                    m_transport_packet.adaptation_fld.ltw_valid_flag = (*p >> 7) & 0x01;

                    m_transport_packet.adaptation_fld.ltw_offset = (*p & 0x7F) << 8;

                    p++;

                   

                    m_transport_packet.adaptation_fld.ltw_offset = m_transport_packet.adaptation_fld.ltw_offset | *p;

                    p++;

                }

               

                if (m_transport_packet.adaptation_fld.piecewise_rate_flag & 0x01)

                {

                    m_transport_packet.adaptation_fld.reserved3 = (*p >> 6) & 0x03;

                    m_transport_packet.adaptation_fld.piecewise_rate = (*p & 0x3F) << 16;

                    p++;

                   

                    m_transport_packet.adaptation_fld.piecewise_rate = m_transport_packet.adaptation_fld.piecewise_rate | (*p << 8);

                    p++;

                   

                    m_transport_packet.adaptation_fld.piecewise_rate = m_transport_packet.adaptation_fld.piecewise_rate | *p;

                    p++;

                }

               

                if (m_transport_packet.adaptation_fld.seamless_splice_flag & 0x01)

                {

                    m_transport_packet.adaptation_fld.splice_type = (*p >> 4) & 0x0F;

                    m_transport_packet.adaptation_fld.DTS_next_AU_32_30 = (*p >> 1) & 0x07;

                    m_transport_packet.adaptation_fld.marker_bit0 = *p & 0x01;

                    p++;

                   

                    m_transport_packet.adaptation_fld.DTS_next_AU_29_15 = *p << 7;

                    p++;

                   

                    m_transport_packet.adaptation_fld.DTS_next_AU_29_15 =

                        m_transport_packet.adaptation_fld.DTS_next_AU_29_15 | ((*p >> 1) & 0x7F);

                   

                    m_transport_packet.adaptation_fld.marker_bit1 = *p & 0x01;

                    p++;

                   

                    m_transport_packet.adaptation_fld.DTS_next_AU_14_0 = *p << 7;

                    p++;

                   

                    m_transport_packet.adaptation_fld.DTS_next_AU_14_0 =

                        m_transport_packet.adaptation_fld.DTS_next_AU_14_0 | ((*p >> 1) & 0x7F);

                   

                    m_transport_packet.adaptation_fld.marker_bit2 = *p & 0x01;

                    p++;

                }

               

                //Reserved...

                int reserved_length = m_transport_packet.adaptation_fld.adaptation_field_extension_length - (p - pe - 1);

                for (i = 0; i < reserved_length; i++)

                {

                    m_transport_packet.adaptation_fld.reserved4[i] = *p;

                    p++;

                }

            }

           

            //Stuffing...

            int stuffing_length = m_transport_packet.adaptation_fld.adaptation_field_length - (p - paf - 1);

            for (i = 0; i < stuffing_length; i++)

            {

                m_transport_packet.adaptation_fld.stuffing_byte[i] = *p;

                p++;

            }

        }

       

        m_PayloadOffset = (unsigned long)(p - &m_Data[0]);

       

        return true;

    }

   

public:

    Ctransport_packet_class()

    {

   

    }

   

    virtual bool SetData(void * Data, unsigned long Size)

    {

        if ( (!Data) || (Size == 0) )

        {

            OutputDebugString(TEXT("tsv: Error in Ctransport_packet_class.SetData - invalid parameters."));

            return false;

        }

       

        memcpy(&m_Data[0], Data, Size);

       

        return ParsePacket();

    }

   

    HRESULT GetPCRPosition(unsigned long * Position)

    {

        *Position = 4;

        if (m_transport_packet.adaptation_field_control & 0x02) //Has adaptation field

        {

            *Position++;

           

            if (m_transport_packet.adaptation_fld.adaptation_field_length > 0)

            {

                *Position++;

                if (m_transport_packet.adaptation_fld.PCR_flag & 0x01)

                {

                    *Position += 6;

                    return S_OK;

                }

            }

        }

       

        *Position = 0;

        return S_FALSE;

    }

};

   

#endif // __TRANSPORT_PACKET_CLASS_H__