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

{                                                       }

{       File : MPEGPSUtils.h                            }

{       Created by Tsviatko Jongov                      }

{       http://tsviatko.jongov.com                      }

{                                                       }

{       Program stream utils.                           }

{                                                       }

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

   

#ifndef __MPEGPSUTILS_H__

#define __MPEGPSUTILS_H__

   

#include <windows.h>

   

#define PACK_START_CODE              0x000001BA

#define PACK_START_CODE_SWP          0xBA010000

#define SYSTEM_HEADER_START_CODE     0x000001BB

#define SYSTEM_HEADER_START_CODE_SWP 0xBB010000

   

struct PSTD_buffer_params

{

    unsigned long stream_id;                         //  8 bits

    unsigned long reserved;                          //  2 bits  '11'

    unsigned long P_STD_buffer_bound_scale;          //  1 bit

    unsigned long P_STD_buffer_size_bound;           // 13 bits

};

   

struct system_header

{

    unsigned long system_header_start_code;          // 32 bits

    unsigned long header_length;                     // 16 bits

    unsigned long marker_bit_1;                      //  1 bit

    unsigned long rate_bound;                        // 22 bits

    unsigned long marker_bit_2;                      //  1 bit

    unsigned long audio_bound;                       //  6 bits

    unsigned long fixed_flag;                        //  1 bit

    unsigned long CSPS_flag;                         //  1 bit

    unsigned long system_audio_lock_flag;            //  1 bit

    unsigned long system_video_lock_flag;            //  1 bit

    unsigned long marker_bit_3;                      //  1 bit

    unsigned long video_bound;                       //  5 bits

    unsigned long packet_rate_restriction_flag;      //  1 bits

    unsigned long reserved_bits;                     //  7 bits

   

    unsigned long PSTD_buffer_params_count;          // custom

    PSTD_buffer_params PSTD_buffer[256];

};

   

struct pack_header

{

    unsigned long pack_start_code;                   // 32 bits

    unsigned long reserved_1;                        //  2 bits '01'

    unsigned long system_clock_reference_base_32_30; //  3 bits

    unsigned long marker_bit_1;                      //  1 bit

    unsigned long system_clock_reference_base_29_15; // 15 bits

    unsigned long marker_bit_2;                      //  1 bit

    unsigned long system_clock_reference_base_14_0;  // 15 bits

    unsigned long marker_bit_3;                      //  1 bit

    unsigned long system_clock_reference_extension;  //  9 bits

    unsigned long marker_bit_4;                      //  1 bit

    unsigned long program_mux_rate;                  // 22 bits

    unsigned long marker_bit_5;                      //  1 bit

    unsigned long marker_bit_6;                      //  1 bit

    unsigned long reserved_2;                        //  5 bits

    unsigned long pack_stuffing_length;              //  3 bits

   

    unsigned char stuffing_byte[7];                  // up to 7 bytes (x8 bits)

   

    system_header system_hdr;

};

   

bool IsPS(char * FileName)

{

    FILE * FileStream;

    unsigned char * Buffer = NULL;

    unsigned long Read;

    unsigned char * P;

    bool Found = false;

   

        if (fopen_s(&FileStream, FileName, "rb") != 0)

    {

        OutputDebugString(L"tsv: Error in IsPS - cannot open file.");

        return false;

    }

   

    Buffer = new unsigned char[3 * 1024];

    if (!Buffer)

    {

        OutputDebugString(L"tsv: Error in IsPS - cannot allocate buffer.");

        fclose(FileStream);

        return false;

    }

   

    fseek(FileStream, 0, SEEK_SET);

    Read = (unsigned long)fread(Buffer, 1, 2 * 1024, FileStream);

    if (Read <= 0)

    {

        OutputDebugString(L"tsv: Error in IsPS - file is empty.");

        fclose(FileStream);

        delete [] Buffer;

        return false;

    }

   

    P = Buffer;

    for (;;)

    {

        if ( *(DWORD *)(P) == PACK_START_CODE_SWP)

        {

            Found = true;

            break;

        }

        

        P++;

        Read--;

        if (!Read)

        {

            break;

        }

    }

   

    fclose(FileStream);

    delete [] Buffer;

    return Found;

}

   

bool ParseSystemHeader(unsigned char * Data, unsigned long Size, system_header * system_hdr)

{

    unsigned char * p = NULL;

    unsigned long i = 0;

   

    if ( (!Data) ||(Size < 12) || (!system_hdr) )

    {

        OutputDebugString(L"tsv: Error in ParseSystemHeader - system header not full.");

        return false;

    }

   

    system_hdr->system_header_start_code = (Data[0] << 24) |

                                           (Data[1] << 16) |

                                           (Data[2] << 8) |

                                           (Data[3]);                   // 32 bits

   

    system_hdr->header_length = (Data[4] << 8) | (Data[5]);             // 16 bits

   

    system_hdr->marker_bit_1 = (Data[6] >> 7) & 0x01;                   //  1 bit

   

    system_hdr->rate_bound = ((Data[6] & 0x7F) << 15) |

                              (Data[7] << 7) |

                             ((Data[8] >> 1) & 0x7F);                   // 22 bits

   

    system_hdr->marker_bit_2 = Data[8] & 0x01;                          //  1 bit

   

    system_hdr->audio_bound = (Data[9] >> 2) & 0x3F;                    //  6 bits

   

    system_hdr->fixed_flag = (Data[9] >> 1) & 0x01;                     //  1 bit

   

    system_hdr->CSPS_flag = Data[9] & 0x01;                             //  1 bit

   

    system_hdr->system_audio_lock_flag = (Data[10] >> 7) & 0x01;        //  1 bit

   

    system_hdr->system_video_lock_flag = (Data[10] >> 6) & 0x01;        //  1 bit

   

    system_hdr->marker_bit_3 = (Data[10] >> 5) & 0x01;                  //  1 bit

   

    system_hdr->video_bound = Data[10] & 0x1F;                          //  5 bits

   

    system_hdr->packet_rate_restriction_flag = (Data[11] >> 7) & 0x01;  //  1 bits

   

    system_hdr->reserved_bits = Data[11] & 0x7F;                        //  7 bits

   

    p = &Data[12];

   

    system_hdr->PSTD_buffer_params_count = 0;

    while (p[0] & 0x80)

    {

        system_hdr->PSTD_buffer_params_count++;

        system_hdr->PSTD_buffer[i].stream_id = p[0];

        p++;

       

        system_hdr->PSTD_buffer[i].reserved = (p[0] >> 6) & 0x03;

        system_hdr->PSTD_buffer[i].P_STD_buffer_bound_scale = (p[0] >> 5) & 0x01;

        system_hdr->PSTD_buffer[i].P_STD_buffer_size_bound = ((p[0] & 0xF8) << 5) | p[1];

        p += 2;

        i++;

    }

   

    return true;

}

   

bool ParsePackHeader(unsigned char * Data, unsigned long Size, pack_header * pack_hdr)

{

    if ( (!Data) || (Size < 14) || (!pack_hdr) )

    {

        OutputDebugString(L"tsv: Error in ParsePackHeader - pack not full.");

        return false;

    }

   

    pack_hdr->pack_start_code = (Data[0] << 24) |

                                (Data[1] << 16) |

                                (Data[2] <<  8) |

                                (Data[3]);

                               

    pack_hdr->reserved_1 = (Data[4] << 6) & 0x03;                             //  2 bits '01'

   

    pack_hdr->system_clock_reference_base_32_30 = (Data[4] << 3) & 0x07;      //  3 bits

   

    pack_hdr->marker_bit_1 = (Data[4] << 2) & 0x01;                           //  1 bit

   

    pack_hdr->system_clock_reference_base_29_15 = ((Data[4] & 0x03) << 13) |

                                                  ((Data[5]       ) <<  5) |

                                                  ((Data[6] >> 3) && 0x1F);   // 15 bits

   

    pack_hdr->marker_bit_2 = (Data[6] >> 2) & 0x01;                           //  1 bit

   

    pack_hdr->system_clock_reference_base_14_0 = ((Data[6] & 0x03) << 13) |

                                                 ((Data[7]       ) <<  5) |

                                                 ((Data[8] >>   3) & 0x1F);   // 15 bits

   

    pack_hdr->marker_bit_3 = ((Data[8] >> 2) & 0x01);                         //  1 bit

   

    pack_hdr->system_clock_reference_extension = ((Data[8] & 0x03) << 7) |

                                                 ((Data[9] >> 1) & 0x7F);     //  9 bits

   

    pack_hdr->marker_bit_4 = Data[9] & 0x01;                                  //  1 bit

   

    pack_hdr->program_mux_rate = (Data[10] << 14) |

                                 (Data[11] <<  6) |

                                ((Data[12] >>  2) & 0x3F);                    // 22 bits

   

    pack_hdr->marker_bit_5 = ((Data[12] >> 1) & 0x01);                        //  1 bit

   

    pack_hdr->marker_bit_6 = (Data[12] & 0x01);                               //  1 bit

   

    pack_hdr->reserved_2 = ((Data[13] >> 3) & 0x1F);                          // 5 bits

   

    pack_hdr->pack_stuffing_length = Data[13] & 0x07;                         //  3 bits

   

    if (Size < 14 + pack_hdr->pack_stuffing_length)

    {

        OutputDebugString(L"tsv: Error in ParsePackHeader - pack not full.");

        return false;

    }

   

    for (unsigned int i = 0; i < pack_hdr->pack_stuffing_length; i++)

    {

        pack_hdr->stuffing_byte[i] = Data[14 + i];                            // x8 bits

    }

    

    if (Size < 14 + pack_hdr->pack_stuffing_length + 4)

    {

        OutputDebugString(L"tsv: Error in ParsePackHeader - pack not full.");

        return false;

    }

   

    if (*(DWORD *)(&Data[14 + pack_hdr->pack_stuffing_length]) == SYSTEM_HEADER_START_CODE_SWP)

    {

        ParseSystemHeader(&Data[14 + pack_hdr->pack_stuffing_length], Size - (14 + pack_hdr->pack_stuffing_length), &pack_hdr->system_hdr);

    }

    return true;

}

   

__int64 GetSCRInt64(pack_header * pack_hdr) //27 MHz units

{

    __int64 i;

   

    i = pack_hdr->system_clock_reference_base_14_0;

    i = i | (pack_hdr->system_clock_reference_base_29_15 << 15);

    i = i | (pack_hdr->system_clock_reference_base_32_30 << 29);

   

    return (i * 300 + pack_hdr->system_clock_reference_extension);

}

 

#endif // __MPEGPSUTILS_H__