TS Parser(PAT PMT EIT SDT分离)

几年前写的将TS码流中的PAT、PMT、SDT、EIT分离的代码;不多说,有兴趣的参考下;


/*******************************************************************************
TS Parse Code
data:2011.1.15
yanxi.jiang
*******************************************************************************/

#include "Stdio.h"
#include "Conio.h"
#include "io.h"
#include "string.h"
#include "TsParser.h"

/*****************************************************************************
                            PSI/SI PID DEFINE
******************************************************************************/
#define PID_PAT  0x00
#define PID_SDT  0x11
#define PID_EIT  0x12


/* SD:188 bytes HD:204 bytes */
#define TSSDLen 188
#define TSSyncByte 0x47
#define SectionMaxLen    (1024)

/*******************************************************************************/
#define TsDataLenRead  (188*5)
#define PsiMaxSectionNum (100)
#define PIDFilterNum  (10)
/*=================================Table parse define===========================*/
typedef struct Ts_Parser_Para
{
    unsigned char PrePsicc;
    unsigned char PsiCCError;
    unsigned int PsiPreTotalPayloadLenth;
    int PsiSecHandle;
    int PsiSecMaxLen;
    unsigned long TsPsiSecCount;
    unsigned char *pTsPsitSecBuffTemp;
}Parser_Para;

char *TSPath;

Parser_Para PAT_Parser,EIT_Parser,SDT_Parser,TXT_Parser,NIT_Parser,PMT_Parser;

static unsigned long PatSecNum = 0;
unsigned int PIDLIST[PIDFilterNum] = {0};
/*==============================================================================*/

void SetFilePath(char *path)
{
    TSPath = path;
}

/*******************************************************************************
input: void
output: return ts file handle on first position
         -1 means file open failed
*******************************************************************************/
int GetTsFileStartHandle(void)
{
  int TSPacketHandle = 0;

  TSPacketHandle = open(TSPath,0x01|0x8000 ,0);
  return  TSPacketHandle;
}

/*******************************************************************************
input: void
output: return ts file length  (byte)
*******************************************************************************/
unsigned long GetTsFileLen(void)
{
    FILE*fp;
    unsigned long longBytes;
    fp = fopen(TSPath,"r");/* localfile文件名 */
    fseek(fp,0,SEEK_END);
    longBytes = ftell(fp);/* longBytes就是文件的长度*/
    fclose(fp);
    return longBytes;
}


/*******************************************************************************
输入:FileHandle 句柄
返回:输入句柄位置与同步字节的Offset大小
      -1 means Get Packet SyncByte failed
Note:当函数执行后,句柄被恢复原有Value
*******************************************************************************/
int GetFirstSyncOffsetInFile(int FileHandle)
{
    unsigned char Count = 0;
    unsigned char Sync0,Sync1,Sync2;
    while(Count < TSSDLen)
    {
        read(FileHandle, &Sync0, 1);
        lseek(FileHandle, (TSSDLen-1), SEEK_CUR);
        read(FileHandle, &Sync1, 1);
        lseek(FileHandle, (TSSDLen-1), SEEK_CUR);
        read(FileHandle, &Sync2, 1);
        lseek(FileHandle, -(TSSDLen+TSSDLen+1), SEEK_CUR);

        if((Sync0 == TSSyncByte) && (Sync1 == TSSyncByte) && (Sync2 == TSSyncByte))
        {

            lseek(FileHandle, -Count, SEEK_CUR);/*恢复句柄原有Value*/
            return (Count);
        }

        Count++;
        lseek(FileHandle, 1, SEEK_CUR);

     }
    lseek(FileHandle, -Count, SEEK_CUR);/*恢复句柄原有Value*/
    return -1;
}


#if 0
/*******************************************************************************
input: TsPacketBuff  一个被确认的TSPacket开始handle
Output:该TSPackt的PID
*******************************************************************************/
unsigned int GetPidInTsPacket(int FileHandle)
{
    unsigned int PidDate = 0xFFFF;
    unsigned char PidHigh,PidLow;

    lseek(FileHandle, 1, SEEK_CUR);
    read(FileHandle, &PidHigh, 1);
    read(FileHandle, &PidLow, 1);

    lseek(FileHandle, -2, SEEK_CUR);

    PidDate = 0x1fff & ((PidHigh<<8)&0xff00) | (PidLow&0x00ff);
    return PidDate;
}
#else
/*******************************************************************************
input: TsPacketBuff  一个被确认的TSPacket开始地址
Output:该TSPackt的PID
*******************************************************************************/
unsigned int GetPidInTsPacket(unsigned char *TsPacketBuff)
{
    unsigned int PidDate = 0xffff;

    PidDate = 0x1fff & ((TsPacketBuff[1] << 8)&0xff00) | (TsPacketBuff[2]&0x00ff);
    return PidDate;
}
#endif


/*******************************************************************************
input: PID  pBuff
Output: void
note: parse ts packet,and collect section to buffer
*******************************************************************************/
void PsiTransportStreamParser(Parser_Para *pPsiTableTemp,unsigned char *pBuff)
{
    unsigned char transport_error_indicator = 0;
    unsigned char payload_unit_start_indicator = 0;
    unsigned char adaptation_field_control = 0,adaptation_field_Len = 0;
    unsigned char continuity_counter = 0;
    unsigned char PayloadLenth = 0;
    unsigned char PayloadStartPositionOffset = 0;

/*================================  packet flag parsing ===============================*/

    transport_error_indicator = pBuff[1]&0x80;
    payload_unit_start_indicator = (pBuff[1]&0x40)>>5;
    adaptation_field_control = (pBuff[3] >> 4)&0x03;
    adaptation_field_Len = pBuff[4];
    continuity_counter = pBuff[3]&0x0f;

    if(transport_error_indicator == 0x01)
        return;/*Check TEI bit of flag*/


/*================================  adptation field parsing ============================*/
    switch (adaptation_field_control)
    {
    case 0x00:                  /* reserved */
        goto EXIT;
    case 0x01:                  /* payload only */
        PayloadLenth = TSSDLen - 4;
        PayloadStartPositionOffset = 4;
        break;
    case 0x02:                  /* af only */
        goto EXIT;
    case 0x03:                  /* af + payload */
        PayloadLenth = TSSDLen - (adaptation_field_Len + 1) - 4;
        PayloadStartPositionOffset = 4 + (adaptation_field_Len + 1);
        break;
    }

    PayloadLenth -= 1;/*jump PSI pointer_field,one byte*/
    PayloadStartPositionOffset += 1;

/*===============================  collect psi section ================================*/
    if( (( ++(pPsiTableTemp->PrePsicc) % 0x10 ) != continuity_counter) &&
        (((pPsiTableTemp->TsPsiSecCount) > 0) || ((pPsiTableTemp->PsiPreTotalPayloadLenth) > 0)) )
            pPsiTableTemp->PsiCCError = 1;

    pPsiTableTemp->PrePsicc = continuity_counter;

    if(payload_unit_start_indicator)
    {
        if( (pPsiTableTemp->PsiPreTotalPayloadLenth > 0) && (pPsiTableTemp->PsiCCError == 0) )
        {
           lseek(pPsiTableTemp->PsiSecHandle, (pPsiTableTemp->PsiSecMaxLen)*(pPsiTableTemp->TsPsiSecCount), SEEK_SET);
           pPsiTableTemp->TsPsiSecCount++;
           write(pPsiTableTemp->PsiSecHandle,pPsiTableTemp->pTsPsitSecBuffTemp,pPsiTableTemp->PsiPreTotalPayloadLenth);
        }
        pPsiTableTemp->PsiPreTotalPayloadLenth = 0;/*last section has collected*/
        memset(pPsiTableTemp->pTsPsitSecBuffTemp,0,pPsiTableTemp->PsiSecMaxLen);
        pPsiTableTemp->PsiCCError = 0;

        memcpy(pPsiTableTemp->pTsPsitSecBuffTemp,&pBuff[PayloadStartPositionOffset],PayloadLenth);
        pPsiTableTemp->PsiPreTotalPayloadLenth += PayloadLenth;
    }
    else
    {
        if(pPsiTableTemp->PsiCCError == 1)
        {
            pPsiTableTemp->PsiPreTotalPayloadLenth = 0;
            memset(pPsiTableTemp->pTsPsitSecBuffTemp,0,pPsiTableTemp->PsiSecMaxLen);
            return;
        }
        if( (pPsiTableTemp->PsiPreTotalPayloadLenth + PayloadLenth) <= pPsiTableTemp->PsiSecMaxLen )
        {
            memcpy(&pPsiTableTemp->pTsPsitSecBuffTemp[pPsiTableTemp->PsiPreTotalPayloadLenth],&pBuff[PayloadStartPositionOffset],PayloadLenth);
            pPsiTableTemp->PsiPreTotalPayloadLenth += PayloadLenth;
        }
    }

EXIT:
    return;
}

/*******************************************************************************
input: pPatSec: one pat section,pPMTProNumPID
Output: Num of Program
note: collect PMT PID and Pro num
*******************************************************************************/
unsigned char TsGetPmtPid(unsigned char *pPatSec,unsigned long *pPMTProNumPID)
{
    int Section_lenth = 0,point = 0;
    unsigned char i = 0;
    unsigned long temp = 0;

    temp = (pPatSec[1]&0x0F);
    temp = temp << 8;
    temp += pPatSec[2];
    Section_lenth = temp;
    Section_lenth -= 9;/*jump version number section number,CRC...*/
    point = 8;
    while(Section_lenth >=4 )
    {
        if(pPatSec[point] != 0)/*program 0 means that is network pid */
        {
            /*Program number*/
            temp = pPatSec[point];
            temp = temp << 8;
            temp += pPatSec[point+1];
            pPMTProNumPID[i] = temp << 16;
            /*Program map pid*/
            temp = pPatSec[point+2];
            temp = (temp&0x1F) << 8;
            temp += pPatSec[point+3];
            pPMTProNumPID[i] += temp;

            i++;
        }
        point += 4;
        Section_lenth -= 4;
    }

    return i;
}



void TsInitPidFilter(void)
{
    memset(PIDLIST,0xFFFF,PIDFilterNum);
}


void TsAddPidToFilter(unsigned int PID)
{
    unsigned char i;

    for(i = 0;i < PIDFilterNum; i++)
    {
        if(PIDLIST[i] == 0xFFFF)
            break;
    }
    PIDLIST[i] = PID;
}
/*******************************************************************************
input: packet PID
Output: return PAT_Parser/SDT_Parser ... address in ppPsiPara
note: check Is PID in PID Filter list
*******************************************************************************/
unsigned char TsGetFlag_PIDInFilter(Parser_Para **ppPsiPara,unsigned int PID,unsigned char PMT)
{
    unsigned char i = 0;

    while(i < PIDFilterNum)
    {
        if(PIDLIST[i] == 0xFFFF)return 0;

        if(PIDLIST[i] == PID)
            break;
        i++;
    }

    if(i < PIDFilterNum)
    {
        switch(PID)
        {
            case PID_PAT:*ppPsiPara = &PAT_Parser;break;
            case PID_SDT:*ppPsiPara = &SDT_Parser;break;
            case PID_EIT:*ppPsiPara = &EIT_Parser;break;
            default:if(PMT){*ppPsiPara = &PMT_Parser;break;}
                    else return 0;
        }
        return 1;
    }

    return 0;
}

void TsSetPatSecNumValue(unsigned long Num)
{
    PatSecNum = Num;
}

unsigned long TsGetPatSecNumValue(void)
{
    return PatSecNum;
}

void TsPSIParser(void)
{
    int TSPacketHandle,Offset;
    unsigned int PID;
    unsigned long TsFileLen,i;
    Parser_Para **ppPsiPara;

    TSPacketHandle = GetTsFileStartHandle();

    TsFileLen = GetTsFileLen();/*get file len*/

    if(TSPacketHandle > 0)
    {
     /******************************************Section buffer*************************************************/
        unsigned char Num = 1 + 1 + 4;
        unsigned char *pbuff = (unsigned char *)calloc(SectionMaxLen*Num,1);/*pat(1024)  sdt(1024)  eit(4096)*/
        if(pbuff == NULL)
            return;
        memset(pbuff,0,SectionMaxLen*Num);

        memset(&PAT_Parser,0x00,sizeof(Parser_Para));
        memset(&SDT_Parser,0x00,sizeof(Parser_Para));
        memset(&EIT_Parser,0x00,sizeof(Parser_Para));


        PAT_Parser.PsiSecMaxLen = SectionMaxLen;
        SDT_Parser.PsiSecMaxLen = SectionMaxLen;
        EIT_Parser.PsiSecMaxLen = SectionMaxLen*4;

        PAT_Parser.pTsPsitSecBuffTemp = (unsigned char *)pbuff;
        pbuff += PAT_Parser.PsiSecMaxLen;
        SDT_Parser.pTsPsitSecBuffTemp = (unsigned char *)pbuff;
        pbuff += SDT_Parser.PsiSecMaxLen;
        EIT_Parser.pTsPsitSecBuffTemp = (unsigned char *)pbuff;
    /******************************************Section buffer*************************************************/

        pbuff = (unsigned char *)calloc(TsDataLenRead,1);

        if(pbuff == NULL)
          return;

        PAT_Parser.PsiSecHandle = open("C:\\PatSec.dat",0x04|0x8000|0x100 ,0);
        SDT_Parser.PsiSecHandle = open("C:\\SdtSec.dat",0x04|0x8000|0x100 ,0);
        EIT_Parser.PsiSecHandle = open("C:\\EitSec.dat",0x04|0x8000|0x100 ,0);

        TsInitPidFilter();
        TsAddPidToFilter(PID_PAT);
        TsAddPidToFilter(PID_SDT);
        TsAddPidToFilter(PID_EIT);

        while(TsFileLen > TsDataLenRead)
        {
            Offset = GetFirstSyncOffsetInFile(TSPacketHandle);/*利用文件的Handle,取得 指定句柄后的第一个TSPacket Offset*/

            if(Offset < 0)
            {
                lseek(TSPacketHandle, TSSDLen, SEEK_CUR);
                TsFileLen -= TSSDLen;
            }
            else
            {
                lseek(TSPacketHandle, Offset, SEEK_CUR); /*讲句柄移动到TSPacket开始*/
                read(TSPacketHandle,pbuff,TsDataLenRead);

                 for(i = 0;i < TsDataLenRead;i += TSSDLen)
                 {
                    PID = GetPidInTsPacket(&pbuff[i]);
                    if( TsGetFlag_PIDInFilter(ppPsiPara,PID,0) )
                        PsiTransportStreamParser(*ppPsiPara,&pbuff[i]);
                 }

                TsFileLen -= TsDataLenRead;
            }

        }
        TsSetPatSecNumValue(PAT_Parser.TsPsiSecCount);
        if(PAT_Parser.pTsPsitSecBuffTemp != (void *)0)
            free(PAT_Parser.pTsPsitSecBuffTemp);
        if(SDT_Parser.pTsPsitSecBuffTemp != (void *)0)
            free(SDT_Parser.pTsPsitSecBuffTemp);
        if(EIT_Parser.pTsPsitSecBuffTemp != (void *)0)
            free(EIT_Parser.pTsPsitSecBuffTemp);

        close(PAT_Parser.PsiSecHandle);
        close(SDT_Parser.PsiSecHandle);
        close(EIT_Parser.PsiSecHandle);

        close(TSPacketHandle);

        free(pbuff);
    }
}


void TsPMTParser(void)
{
    int TSPacketHandle,Offset;
    unsigned int PID,PmtNum;
    unsigned long TsFileLen,i;
    unsigned long PMTProNumPID[20];/*high 16 bits is Pro num and low 16 bits is PID*/
    Parser_Para **ppPsiPara;

    TSPacketHandle = GetTsFileStartHandle();

    TsFileLen = GetTsFileLen();/*get file len*/

    if(TSPacketHandle > 0)
    {
     /******************************************Section buffer*************************************************/
        unsigned char Num = 1;
        unsigned char *pbuff = (unsigned char *)calloc(SectionMaxLen*Num,1);
        if(pbuff == NULL)
            return;
        memset(pbuff,0,SectionMaxLen*Num);

        memset(&PMT_Parser,0x00,sizeof(Parser_Para));

        PMT_Parser.PsiSecMaxLen = SectionMaxLen;
        PMT_Parser.pTsPsitSecBuffTemp = (unsigned char *)pbuff;
    /******************************************Section buffer*************************************************/

        pbuff = (unsigned char *)calloc(TsDataLenRead,1);

        if(pbuff == NULL)
          return;
        PAT_Parser.PsiSecHandle = open("C:\\PatSec.dat",0x01|0x8000 ,0);
        PMT_Parser.PsiSecHandle = open("C:\\PmtSec.dat",0x04|0x8000|0x100 ,0);

        TsInitPidFilter();
        TsAddPidToFilter(PID_PAT);
        TsAddPidToFilter(PID_SDT);
        TsAddPidToFilter(PID_EIT);

        if(TsGetPatSecNumValue() > 0)/* Get PMT Pid in TransportStream file*/
        {
            memset(PMT_Parser.pTsPsitSecBuffTemp,0x00,SectionMaxLen);
            lseek(PAT_Parser.PsiSecHandle, 0, SEEK_SET);
            read(PAT_Parser.PsiSecHandle, PMT_Parser.pTsPsitSecBuffTemp, SectionMaxLen);
            PmtNum = TsGetPmtPid(PMT_Parser.pTsPsitSecBuffTemp,PMTProNumPID);

            for(;PmtNum > 0;PmtNum--)
            {
                lseek(TSPacketHandle, 0, SEEK_SET);
                TsFileLen = GetTsFileLen();/*get file len*/
                memset(PMT_Parser.pTsPsitSecBuffTemp,0x00,SectionMaxLen);

                TsInitPidFilter();
                TsAddPidToFilter(PMTProNumPID[PmtNum-1]&0xFFFF);
                while(TsFileLen > TsDataLenRead)
                {
                    Offset = GetFirstSyncOffsetInFile(TSPacketHandle);/*利用文件的Handle,取得 指定句柄后的第一个TSPacket Offset*/

                    if(Offset < 0)
                    {
                        lseek(TSPacketHandle, TSSDLen, SEEK_CUR);
                        TsFileLen -= TSSDLen;
                    }
                    else
                    {
                        lseek(TSPacketHandle, Offset, SEEK_CUR); /*讲句柄移动到TSPacket开始*/
                        read(TSPacketHandle,pbuff,TsDataLenRead);

                         for(i = 0;i < TsDataLenRead;i += TSSDLen)
                         {
                            PID = GetPidInTsPacket(&pbuff[i]);
                            if( TsGetFlag_PIDInFilter(ppPsiPara,PID,1) )
                                PsiTransportStreamParser(*ppPsiPara,&pbuff[i]);
                         }

                        TsFileLen -= TsDataLenRead;
                    }
                }
            }
         }

        if(PMT_Parser.pTsPsitSecBuffTemp != (void *)0)
            free(PAT_Parser.pTsPsitSecBuffTemp);

        close(PAT_Parser.PsiSecHandle);
        close(PMT_Parser.PsiSecHandle);
        close(TSPacketHandle);
        free(pbuff);
    }
}


void main(void)
{
    SetFilePath("F:\\FRA14-4.ts");
    TsPSIParser();
    TsPMTParser();
    
    getch();
    return ;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值