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

📄 dvr.c

📁 this ebook is for GSM if any one has interest in it you can take it
💻 C
字号:
#include <sys/ioctl.h>#include <time.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <stdio.h>#include <stdint.h>#include <stdlib.h>#include <errno.h>#include <assert.h>#include <linux/dvb/dmx.h>#include <linux/dvb/frontend.h>#include <event.h>#include "getstream.h"const char       *pidtnames[]={ "None", "PAT", "PMT", "PCR", "Video", "Audio", "Privat", "User", "Static", "Other" };struct pidcallback_s {	void		(*callback)(void *data, void *arg);	void		*arg;	uint16_t	pid;	unsigned int	type;	unsigned int	pidt;};static inline char *dvrname(int adapter) {	static char	dvrname[128];	sprintf(dvrname, "/dev/dvb/adapter%d/dvr0", adapter);	return dvrname;}static inline void dvr_input_ts(struct adapter_s *a, uint8_t *ts) {	uint16_t	pid;	GList		*pcbl;	/* TS (Transport Stream) packets start with 0x47 */	if (ts[TS_SYNC_OFF] != TS_SYNC) {		logwrite(LOG_XTREME, "dvr: Non TS Stream packet (!0x47) received on dvr0");		dump_hex(LOG_XTREME, "dvr:", ts, TS_PACKET_SIZE);		return;	}	/* Full stream callbacks - pseudo pid 0x2000 */	for(pcbl=g_list_first(a->dvr.fullcb);pcbl!=NULL;pcbl=g_list_next(pcbl)) {		struct pidcallback_s	*pcb=pcbl->data;		pcb->callback(ts, pcb->arg);	}	pid=ts_pid(ts);	a->dvr.pidtable[pid].packets++;	/* Does somebody want this pid ? */	if (!a->dvr.pidtable[pid].callback)		return;	/* FIXME This is ugly to have the same list with different users */	if (a->dvr.pidtable[pid].secuser) {		int	off=0;		while(off < TS_PACKET_SIZE) {			off=psi_reassemble(a->dvr.pidtable[pid].section, ts, off);			if (off<0)				break;			for(pcbl=g_list_first(a->dvr.pidtable[pid].callback);pcbl!=NULL;pcbl=g_list_next(pcbl)) {				struct pidcallback_s	*pcb=pcbl->data;				if (pcb->type == DVRCB_SECTION)					pcb->callback(a->dvr.pidtable[pid].section, pcb->arg);			}		}	}	for(pcbl=g_list_first(a->dvr.pidtable[pid].callback);pcbl!=NULL;pcbl=g_list_next(pcbl)) {		struct pidcallback_s	*pcb=pcbl->data;		if (pcb->type == DVRCB_TS)			pcb->callback(ts, pcb->arg);	}}void dvr_del_pcb(struct adapter_s *a, unsigned int pid, void *vpcb) {	struct pidcallback_s	*pcb=vpcb;	logwrite(LOG_DEBUG, "dvr: Del callback for PID %4d (0x%04x) type %d (%s)",			pid, pid, pcb->pidt, pidtnames[pcb->pidt]);	a->dvr.pidtable[pid].callback=g_list_remove(a->dvr.pidtable[pid].callback, pcb);	if (pcb->type == DVRCB_SECTION) {		a->dvr.pidtable[pid].secuser--;		if (!a->dvr.pidtable[pid].secuser)			psi_section_free(a->dvr.pidtable[pid].section);	}	free(pcb);	if (!a->dvr.pidtable[pid].callback)		dmx_leave_pid(a, pid);}void *dvr_add_pcb(struct adapter_s *a, unsigned int pid, unsigned int type,		unsigned int pidt, void (*callback)(void *data, void *arg), void *arg) {	struct pidcallback_s	*pcb;	logwrite(LOG_DEBUG, "dvr: Add %s callback for PID %4d (0x%04x) type %d (%s)",			((type == DVRCB_TS) ? "TS" : "Section"), pid, pid, pidt, pidtnames[pidt]);	/* FIXME - check for error of malloc */	pcb=malloc(sizeof(struct pidcallback_s));	pcb->pid=pid;	pcb->callback=callback;	pcb->arg=arg;	pcb->pidt=pidt;	pcb->type=type;	/* Joined pseudo pid 0x2000 e.g. input full */	if (pid == PID_MAX+1) {		/* FIXME: How to detect we need to join 0x2000? */		a->dvr.fullcb=g_list_append(a->dvr.fullcb, pcb);		return pcb;	}	if (type == DVRCB_SECTION) {		a->dvr.pidtable[pid].secuser++;		if (!a->dvr.pidtable[pid].section)			a->dvr.pidtable[pid].section=psi_section_new();	}	if (!a->dvr.pidtable[pid].callback)		dmx_join_pid(a, pid, DMX_PES_OTHER);	a->dvr.pidtable[pid].callback=g_list_append(a->dvr.pidtable[pid].callback, pcb);	return pcb;}/* * Read TS packet chunks from dvr0 device and fill them one after * another into dvr_input_ts */static void dvr_read(int fd, short event, void *arg) {	int			len, i;	struct adapter_s	*adapter=arg;	uint8_t			*db=adapter->dvr.buffer.ptr;	do {		len=read(fd, db, adapter->dvr.buffer.size*TS_PACKET_SIZE);		/*		 * Increase readcounter - we need to detect flexcop not delivering		 * TS packets anymore e.g. the IRQ Stop bug. A timer will then		 * try to issue a frontend tune which will hopefully reset the		 * card to deliver packets		 *		 */		adapter->dvr.stat.reads++;		/* EOF aka no more TS Packets ? */		if (len == 0)			break;		/* Read returned error ? */		if (len < 0) {			if (errno != EAGAIN)				logwrite(LOG_ERROR, "demux: read in dvr_read returned with errno %d", errno);			break;		}		/* Loop on TS packets and fill them into dvr_input_ts */		for(i=0;i<len;i+=TS_PACKET_SIZE) {			dvr_input_ts(adapter, &db[i]);		}	} while (len == adapter->dvr.buffer.size*TS_PACKET_SIZE);}static void dvr_init_stat_timer(struct adapter_s *a);#define DVR_STAT_INTERVAL	60static void dvr_stat_timer(int fd, short event, void *arg) {	struct adapter_s	*a=arg;	int			i;	unsigned long		total=0, pids=0;	for(i=0;i<PID_MAX;i++) {		if (a->dvr.pidtable[i].packets) {			pids++;			total+=a->dvr.pidtable[i].packets;		}	}	logwrite(LOG_INFO, "dvr: inputstats: %d pids %u pkt/s %u byte/s",				pids,				total/a->dvr.stat.interval,				total*TS_PACKET_SIZE/a->dvr.stat.interval);	for(i=0;i<PID_MAX;i++) {		a->dvr.pidtable[i].packets=0;	}	dvr_init_stat_timer(a);}static void dvr_init_stat_timer(struct adapter_s *a) {	struct timeval	tv;	if (!a->dvr.stat.interval)		return;	a->dvr.stat.last=time(NULL);	tv.tv_sec=a->dvr.stat.interval;	tv.tv_usec=0;	evtimer_set(&a->dvr.stat.event, dvr_stat_timer, a);	evtimer_add(&a->dvr.stat.event, &tv);}static void dvr_stuck_init(struct adapter_s *a);static void dvr_stuck_timer(int fd, short event, void *arg) {	struct adapter_s	*adapter=arg;	/*	 * Flexcop is known to randomly lockup. A workaround in the kernel	 * driver is to reset some registers known to reanimate the flexcop.	 *	 * See: http://lkml.org/lkml/2005/6/27/135	 *	 * The patch went into 2.6.13-rc3 so in case you are running an FlexCop based	 * card (SkyStar2, AirStar) you better upgrade to 2.6.13 or better.	 *	 * First try was to retune which itself is not enough. One needs to bring	 * down the number of received pids to 0 as the transition from 0 -> 1 resets	 * the board. So let dmx bounce all filters.	 *	 */	if (adapter->dvr.stat.reads == 0) {		logwrite(LOG_ERROR, "dvr: lockup of DVB card detected - trying to reanimate via bouncing filter");		fe_retune(adapter);		dmx_bounce_filter(adapter);	}	adapter->dvr.stat.reads=0;	dvr_stuck_init(adapter);}static void dvr_stuck_init(struct adapter_s *a) {	struct timeval	tv;	/* stuck-interval 0; disables the stuck check timer */	if (!a->dvr.stuckinterval)		return;	tv.tv_sec=a->dvr.stuckinterval/1000;	tv.tv_usec=a->dvr.stuckinterval%1000*1000;	evtimer_set(&a->dvr.stucktimer, dvr_stuck_timer, a);	evtimer_add(&a->dvr.stucktimer, &tv);}int dvr_init(struct adapter_s *a) {	int			dvrfd;	a->dvr.buffer.ptr=malloc(a->dvr.buffer.size*TS_PACKET_SIZE);	dvrfd=open(dvrname(a->no), O_RDONLY|O_NONBLOCK);	if (dvrfd < 0)		return 0;	event_set(&a->dvr.dvrevent, dvrfd, EV_READ|EV_PERSIST, dvr_read, a);	event_add(&a->dvr.dvrevent, NULL);	if (a->budgetmode) {		if (!dmx_join_pid(a, 0x2000, DMX_PES_OTHER)) {			logwrite(LOG_INFO, "demux: Setting budget filter failed - switching off budget mode");			a->budgetmode=0;		}	}	a->dvr.fd=dvrfd;	dvr_init_stat_timer(a);	dvr_stuck_init(a);	return 1;}

⌨️ 快捷键说明

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