TS Parser(PAT PMT EIT SDT分离)

来源:互联网 发布:mysql安装失败怎么清理 编辑:程序博客网 时间:2024/06/05 10:16

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


/*******************************************************************************TS Parse Codedata:2011.1.15yanxi.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: voidoutput: 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: voidoutput: 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 failedNote:当函数执行后,句柄被恢复原有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开始handleOutput:该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  pBuffOutput: voidnote: 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,pPMTProNumPIDOutput: Num of Programnote: 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 PIDOutput: return PAT_Parser/SDT_Parser ... address in ppPsiParanote: 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 0