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
- TS Parser(PAT PMT EIT SDT分离)
- 对PSI(PAT,PMT,CAT,NIT,SDT,EIT)的理解
- mpeg2 ts流PAT,PMT,SDT的定义
- PAT、PMT、SDT详解 MPEG2-TS流的分析
- mpeg2 ts流PAT,PMT,SDT的定义
- PAT、PMT、SDT详解
- 什么是DVB-SI?对PSI(PAT,PMT,CAT,NIT,SDT,EIT)的理解
- 什么是DVB-SI?对PSI(PAT,PMT,CAT,NIT,SDT,EIT)的理解
- ts pat pmt
- TS流PAT/PMT详解
- TS流基础:PAT、PMT
- TS Intro - PAT and PMT
- TS流PAT/PMT详解
- TS流PAT/PMT详解
- PAT,PMT和SDT三类表格的格式
- 从TS流到PAT和PMT
- 从TS流到PAT和PMT
- 从TS流到PAT和PMT
- Chrome 扩展程序开发 Chrome Extensions
- 在Octopress中加入Latex支持
- Spark:大数据的“电光石火”
- 保存点序列的方法
- JSP常见指令
- TS Parser(PAT PMT EIT SDT分离)
- sqlMap中resultMap result column配置多个参数的用法
- Android开源项目分类汇总
- Robotium 自动化测试报错:Injecting to another application requires INJECT_EVENT permission
- MATLAB基本操作(五):MATLAB中的逻辑运算及all(),any()的使用
- 机器学习课程练习(二)——向量化与手写体识别
- linux-0.11硬盘集成盘的制作方法
- svn的搭建和使用,以及svn使用注意
- .Net业务平台的数值精度陷阱与解决方法