⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 psi.c

📁 this ebook is for GSM if any one has interest in it you can take it
💻 C
字号:
#include <string.h>#include <stdlib.h>#include "getstream.h"#include "psi.h"/* * PSI (Program Specific Information) handling * * Reassembly of TS Packets into sections * Handling of multiple sections * Callback on change * * * */static uint32_t psi_crc(struct psisec_s *section) {	uint8_t		*crcp=&section->data[psi_len(section)-4];	return	crcp[0]<<24|crcp[1]<<16|crcp[2]<<8|crcp[3];}/* Calculate the CRC of the section */static uint32_t psi_ccrc(struct psisec_s *section) {	return crc32_be(0xffffffff, section->data, psi_len(section)-4);}/* Check if PSI has valid CRC32 - return true if it has */static int psi_crc_valid(struct psisec_s *section) {	return (psi_crc(section) == psi_ccrc(section));}static void psi_section_clear(struct psisec_s *section) {	section->valid=0;	section->len=0;}int psi_reassemble_continue(struct psisec_s *section, uint8_t *ts, int off) {	int	copylen;	uint8_t	ccexp, cc;	/*	 * Calculate the next CC counter value. As a section needs to	 * be completed before the next may begin on a PID we only	 * accept continuous packets. If we fail the CC test we zap	 * the whole section.	 *	 */	ccexp=(section->cc+1)&TS_CC_MASK;	cc=ts_cc(ts);	if (ccexp != cc) {		psi_section_clear(section);		return PSI_RC_CCFAIL;	}	/*	 * If we didnt have a hdr - complete it otherwise we dont	 * even know the length and cant tell whether the section is	 * complete.	 */	if (!section->len) {		copylen=PSI_HDR_LEN-section->valid;		memcpy(&section->data[section->valid], &ts[off], copylen);		section->valid+=copylen;		section->len=_psi_len(section->data);		off+=copylen;	}	copylen=MIN(TS_PACKET_SIZE-off, section->len-section->valid);	memcpy(&section->data[section->valid], &ts[off], copylen);	section->valid+=copylen;	return off+copylen;}/* * Copy the start of an PSI packet into our section buffer beginning * at offset and fill section->len if possible * * Return the new offset */int psi_reassemble_start(struct psisec_s *section, uint8_t *ts, int off) {	uint8_t		*payloadptr=&ts[off];	int		copylen;	psi_section_clear(section);	section->cc=ts_cc(ts);	section->pid=ts_pid(ts);	/* Copy until the end of the packet */	copylen=TS_PACKET_SIZE-off;	/*	 * If not we include the PSI header in which case we	 * can get the real length	 *	 */	if (TS_PACKET_SIZE-off > PSI_HDR_LEN) {		section->len=_psi_len(payloadptr);		copylen=MIN(section->len, TS_PACKET_SIZE-off);	}	memcpy(section->data, payloadptr, copylen);	section->valid=copylen;	return off+copylen;}/* * We get passed a static allocated psisec structure, a TS packet and an * offset into the packet where we need to start looking for sections. * * Input: *	PSI section structute *	TS packet *	Offset to start looking for PSI data * * Output: *	Fills PSI section as far as possible * * Returns: *		0	- If section is finished and no more bytes in TS *		positive- If section is finished and more bytes in TS *		negative- If section is not finished and we are done * *//* Reassemble a generic PSI (Program Specific Information) section e.g. PMT PAT CA packet */int psi_reassemble(struct psisec_s *section, uint8_t *ts, int off) {	int		noff;	int		payload;	if (off) {		payload=off;		if (ts[payload] == 0xff)			return PSI_RC_NOPAYLOAD;	} else {		if (ts_tei(ts))			return PSI_RC_TEI;		if (!ts_has_payload(ts))			return PSI_RC_NOPAYLOAD;		payload=ts_payload_start(ts);		/*		 * If "Payload Unit Start Indicator" is set the first byte		 * payload is the pointer to the first section.		 * ISO 13818-1 2.4.4.2		 */		if (ts_pusi(ts))			payload+=ts[payload]+1;		if (payload >= TS_PACKET_SIZE)			return PSI_RC_CORRUPT;	}	/* If we dont have a Payload Unit Start Indicator and we already	 * started a section on this PID (valid is non null) we continue	 * otherwise we start the reassembly ...	 *	 * This means that a packet with a	 */	if (!ts_pusi(ts)) {		if (!section->valid)			return PSI_RC_NOPAYLOAD;		noff=psi_reassemble_continue(section, ts, payload);	} else {		noff=psi_reassemble_start(section, ts, payload);	}	/*	 * We didnt finish this section in this packet so wait for the next packet	 * The section->valid check is another precaution for broken/empty	 * invalid section parts collected ...	 */	if (section->len != section->valid || section->valid < PSI_HDR_LEN)		return PSI_RC_INCOMPLETE;	if (!psi_crc_valid(section))		return PSI_RC_CRCFAIL;	return noff;}int psi_section_valid(unsigned int pid, struct psisec_s *section, int len) {	section->pid=pid;	section->len=len;	section->valid=0;	if (!psi_crc_valid(section))		return PSI_RC_CRCFAIL;	if (psi_len(section)!=len)		return PSI_RC_LENFAIL;	return PSI_RC_OK;}struct psisec_s *psi_section_new(void ) {	return calloc(1, sizeof(struct psisec_s));}void psi_section_free(struct psisec_s *section) {	free(section);}struct psisec_s *psi_section_clone(struct psisec_s *section) {	struct psisec_s *new=psi_section_new();	memcpy(new, section, sizeof(struct psisec_s));	return new;}int psi_section_fromdata(struct psisec_s *section, unsigned int pid, uint8_t *data, int len) {	psi_section_clear(section);	memcpy(&section->data, data, len);	return psi_section_valid(pid, section, len);}unsigned int psi_segment_and_send(struct psisec_s *section, unsigned int pid, uint8_t cc,			void (*callback)(void *data, void *arg), void *arg) {	uint8_t		ts[TS_PACKET_SIZE];	int		pkts=0;	int		plen=psi_len(section);	int		left=plen;	int		tspayloadoff;	int		copylen;	while(1) {		memset(&ts, 0xff, TS_PACKET_SIZE);		ts[TS_SYNC_OFF]=TS_SYNC;		ts[TS_PID_OFF1]=pid>>8;		ts[TS_PID_OFF2]=pid&0xff;		ts[TS_AFC_OFF]=0x1<<TS_AFC_SHIFT;		/* Payload only */		ts[TS_CC_OFF]|=(cc+pkts)&TS_CC_MASK;		/* Continuity Counter */		tspayloadoff=TS_PAYLOAD_OFF;		if (!pkts) {			ts[TS_PID_OFF1]|=TS_PUSI_MASK;			ts[TS_PAYLOAD_OFF]=0x0;			/* Clear PSI Pointer */			tspayloadoff++;		}		/* Either full section or as much as fits */		copylen=MIN(left, TS_PACKET_SIZE-tspayloadoff);		/* Copy PSI section into TS packet */		memcpy(&ts[tspayloadoff], &section->data[plen-left], copylen);		callback(ts, arg);		left-=copylen;		pkts++;		if (left <= 0)			break;	}	return pkts;}int psi_update_table(struct psi_s *psi, struct psisec_s *section) {	uint8_t		secnum;	uint8_t		version;	secnum=psi_section_number(section);	version=psi_version(section);	/* Check if we have this section or if the section version changed */	if (psi->section[secnum]) {		if (version == psi_version(psi->section[secnum]))			return 0;		psi_section_free(psi->section[secnum]);	}	psi->section[secnum]=psi_section_clone(section);	return 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -