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

📄 scan.c

📁 linux TV 源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		buf += descriptor_len;		descriptors_loop_len -= descriptor_len;	}}static void parse_pat(const unsigned char *buf, int section_length,		      int transport_stream_id){	while (section_length > 0) {		struct service *s;		int service_id = (buf[0] << 8) | buf[1];		if (service_id == 0) {			buf += 4;		/*  skip nit pid entry... */			section_length -= 4;			continue;		}		/* SDT might have been parsed first... */		s = find_service(current_tp, service_id);		if (!s)			s = alloc_service(current_tp, service_id);		s->pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];		if (!s->priv && s->pmt_pid) {			s->priv = malloc(sizeof(struct section_buf));			setup_filter(s->priv, demux_devname,				     s->pmt_pid, 0x02, 1, 0, 5);			add_filter (s->priv);		}		buf += 4;		section_length -= 4;	};}static void parse_pmt (const unsigned char *buf, int section_length, int service_id){	int program_info_len;	struct service *s;        char msg_buf[14 * AUDIO_CHAN_MAX + 1];        char *tmp;        int i;	s = find_service (current_tp, service_id);	if (!s) {		error("PMT for serivce_id 0x%04x was not in PAT\n", service_id);		return;	}	s->pcr_pid = ((buf[0] & 0x1f) << 8) | buf[1];	program_info_len = ((buf[2] & 0x0f) << 8) | buf[3];	buf += program_info_len + 4;	section_length -= program_info_len + 4;	while (section_length > 0) {		int ES_info_len = ((buf[3] & 0x0f) << 8) | buf[4];		int elementary_pid = ((buf[1] & 0x1f) << 8) | buf[2];		switch (buf[0]) {		case 0x01:		case 0x02:			moreverbose("  VIDEO     : PID 0x%04x\n", elementary_pid);			if (s->video_pid == 0)				s->video_pid = elementary_pid;			break;		case 0x03:		case 0x04:			moreverbose("  AUDIO     : PID 0x%04x\n", elementary_pid);			if (s->audio_num < AUDIO_CHAN_MAX) {				s->audio_pid[s->audio_num] = elementary_pid;				parse_descriptors (PMT, buf + 5, ES_info_len, s);				s->audio_num++;			}			else				warning("more than %i audio channels, truncating\n",				     AUDIO_CHAN_MAX);			break;		case 0x06:			if (find_descriptor(0x56, buf + 5, ES_info_len, NULL, NULL)) {				moreverbose("  TELETEXT  : PID 0x%04x\n", elementary_pid);				s->teletext_pid = elementary_pid;				break;			}			else if (find_descriptor(0x59, buf + 5, ES_info_len, NULL, NULL)) {				/* Note: The subtitling descriptor can also signal				 * teletext subtitling, but then the teletext descriptor				 * will also be present; so we can be quite confident				 * that we catch DVB subtitling streams only here, w/o				 * parsing the descriptor. */				moreverbose("  SUBTITLING: PID 0x%04x\n", elementary_pid);				s->subtitling_pid = elementary_pid;				break;			}			else if (find_descriptor(0x6a, buf + 5, ES_info_len, NULL, NULL)) {				moreverbose("  AC3       : PID 0x%04x\n", elementary_pid);				s->ac3_pid = elementary_pid;				break;			}			/* fall through */		default:			moreverbose("  OTHER     : PID 0x%04x TYPE 0x%02x\n", elementary_pid, buf[0]);		};		buf += ES_info_len + 5;		section_length -= ES_info_len + 5;	};        tmp = msg_buf;        tmp += sprintf(tmp, "0x%04x (%.4s)", s->audio_pid[0], s->audio_lang[0]);	if (s->audio_num > AUDIO_CHAN_MAX) {		warning("more than %i audio channels: %i, truncating to %i\n",		      AUDIO_CHAN_MAX, s->audio_num, AUDIO_CHAN_MAX);		s->audio_num = AUDIO_CHAN_MAX;	}        for (i=1; i<s->audio_num; i++)                tmp += sprintf(tmp, ", 0x%04x (%.4s)", s->audio_pid[i], s->audio_lang[i]);        debug("0x%04x 0x%04x: %s -- %s, pmt_pid 0x%04x, vpid 0x%04x, apid %s\n",	    s->transport_stream_id,	    s->service_id,	    s->provider_name, s->service_name,	    s->pmt_pid, s->video_pid, msg_buf);}static void parse_nit (const unsigned char *buf, int section_length, int network_id){	int descriptors_loop_len = ((buf[0] & 0x0f) << 8) | buf[1];	if (section_length < descriptors_loop_len + 4)	{		warning("section too short: network_id == 0x%04x, section_length == %i, "		     "descriptors_loop_len == %i\n",		     network_id, section_length, descriptors_loop_len);		return;	}	parse_descriptors (NIT, buf + 2, descriptors_loop_len, NULL);	section_length -= descriptors_loop_len + 4;	buf += descriptors_loop_len + 4;	while (section_length > 6) {		int transport_stream_id = (buf[0] << 8) | buf[1];		struct transponder *t, tn;		descriptors_loop_len = ((buf[4] & 0x0f) << 8) | buf[5];		if (section_length < descriptors_loop_len + 4 ||		    !transport_stream_id)		{			warning("section too short: transport_stream_id == 0x%04x, "			     "section_length == %i, descriptors_loop_len == %i\n",			     transport_stream_id, section_length,			     descriptors_loop_len);			break;		}		debug("transport_stream_id 0x%04x\n", transport_stream_id);		memset(&tn, 0, sizeof(tn));		tn.type = -1;		tn.network_id = network_id;		tn.transport_stream_id = transport_stream_id;		parse_descriptors (NIT, buf + 6, descriptors_loop_len, &tn);		if (tn.type == fe_info.type) {			/* only add if develivery_descriptor matches FE type */			t = find_transponder(tn.param.frequency);			if (!t)				t = alloc_transponder(tn.param.frequency);			copy_transponder(t, &tn);		}		section_length -= descriptors_loop_len + 6;		buf += descriptors_loop_len + 6;	};}static void parse_sdt (const unsigned char *buf, int section_length,		int transport_stream_id){	buf += 3;	       /*  skip original network id + reserved field */	while (section_length > 4) {		int service_id = (buf[0] << 8) | buf[1];		int descriptors_loop_len = ((buf[3] & 0x0f) << 8) | buf[4];		struct service *s;		if (section_length < descriptors_loop_len ||		    !transport_stream_id ||		    !descriptors_loop_len)		{			warning("section too short: service_id == 0x%02x, section_length == %i"			     "descriptors_loop_len == %i\n",			     service_id, section_length,			     descriptors_loop_len);			break;		}		s = find_service(current_tp, service_id);		if (!s)			/* maybe PAT has not yet been parsed... */			s = alloc_service(current_tp, service_id);		s->running = (buf[3] >> 5) & 0x7;		s->scrambled = (buf[3] >> 4) & 1;		parse_descriptors (SDT, buf + 5, descriptors_loop_len, s);		section_length -= descriptors_loop_len + 5;		buf += descriptors_loop_len + 5;	};}static int get_bit (uint8_t *bitfield, int bit){	return (bitfield[bit/8] >> (bit % 8)) & 1;}static void set_bit (uint8_t *bitfield, int bit){	bitfield[bit/8] |= 1 << (bit % 8);}/** *   returns 0 when more sections are expected *	   1 when all sections are read on this pid *	   -1 on invalid table id */static int parse_section (struct section_buf *s){	const unsigned char *buf = s->buf;	int table_id;	int section_length;	int table_id_ext;	int section_version_number;	int section_number;	int last_section_number;	int i;	table_id = buf[0];	if (s->table_id != table_id)		return -1;	section_length = (((buf[1] & 0x0f) << 8) | buf[2]) - 11;	table_id_ext = (buf[3] << 8) | buf[4];	section_version_number = (buf[5] >> 1) & 0x1f;	section_number = buf[6];	last_section_number = buf[7];	if (s->segmented && s->table_id_ext != -1 && s->table_id_ext != table_id_ext) {		/* find or allocate actual section_buf matching table_id_ext */		while (s->next_seg) {			s = s->next_seg;			if (s->table_id_ext == table_id_ext)				break;		}		if (s->table_id_ext != table_id_ext) {			assert(s->next_seg == NULL);			s->next_seg = calloc(1, sizeof(struct section_buf));			s->next_seg->segmented = s->segmented;			s->next_seg->run_once = s->run_once;			s->next_seg->timeout = s->timeout;			s = s->next_seg;			s->table_id = table_id;			s->table_id_ext = table_id_ext;			s->section_version_number = section_version_number;		}	}	if (s->section_version_number != section_version_number ||			s->table_id_ext != table_id_ext) {		struct section_buf *next_seg = s->next_seg;		if (s->section_version_number != -1 && s->table_id_ext != -1)			debug("section version_number or table_id_ext changed "				"%d -> %d / %04x -> %04x\n",				s->section_version_number, section_version_number,				s->table_id_ext, table_id_ext);		s->table_id_ext = table_id_ext;		s->section_version_number = section_version_number;		s->sectionfilter_done = 0;		memset (s->section_done, 0, sizeof(s->section_done));		s->next_seg = next_seg;	}	buf += 8;	if (!get_bit(s->section_done, section_number)) {		set_bit (s->section_done, section_number);		debug("pid 0x%02x tid 0x%02x table_id_ext 0x%04x, "		    "%i/%i (version %i)\n",		    s->pid, table_id, table_id_ext, section_number,		    last_section_number, section_version_number);		switch (table_id) {		case 0x00:			verbose("PAT\n");			parse_pat (buf, section_length, table_id_ext);			break;		case 0x02:			verbose("PMT 0x%04x for service 0x%04x\n", s->pid, table_id_ext);			parse_pmt (buf, section_length, table_id_ext);			break;		case 0x41:			verbose("////////////////////////////////////////////// NIT other\n");		case 0x40:			verbose("NIT (%s TS)\n", table_id == 0x40 ? "actual":"other");			parse_nit (buf, section_length, table_id_ext);			break;		case 0x42:		case 0x46:			verbose("SDT (%s TS)\n", table_id == 0x42 ? "actual":"other");			parse_sdt (buf, section_length, table_id_ext);			break;		default:			;		};		for (i = 0; i <= last_section_number; i++)			if (get_bit (s->section_done, i) == 0)				break;		if (i > last_section_number)			s->sectionfilter_done = 1;	}	if (s->segmented) {		/* always wait for timeout; this is because we don't now how		 * many segments there are		 */		return 0;	}	else if (s->sectionfilter_done)		return 1;	return 0;}static int read_sections (struct section_buf *s){	int section_length, count;	if (s->sectionfilter_done && !s->segmented)		return 1;	/* the section filter API guarantess that we get one full section	 * per read(), provided that the buffer is large enough (it is)	 */	if (((count = read (s->fd, s->buf, sizeof(s->buf))) < 0) && errno == EOVERFLOW)		count = read (s->fd, s->buf, sizeof(s->buf));	if (count < 0) {		errorn("read_sections: read error");		return -1;	}	if (count < 4)		return -1;	section_length = ((s->buf[1] & 0x0f) << 8) | s->buf[2];	if (count != section_length + 3)		return -1;	if (parse_section(s) == 1)		return 1;	return 0;}static LIST_HEAD(running_filters);static LIST_HEAD(waiting_filters);static int n_running;#define MAX_RUNNING 32static struct pollfd poll_fds[MAX_RUNNING];static struct section_buf* poll_section_bufs[MAX_RUNNING];static void setup_filter (struct section_buf* s, const char *dmx_devname,			  int pid, int tid, int run_once, int segmented, int timeout){	memset (s, 0, sizeof(struct section_buf));	s->fd = -1;	s->dmx_devname = dmx_devname;	s->pid = pid;	s->table_id = tid;	s->run_once = run_once;	s->segmented = segmented;	if (long_timeout)		s->timeout = 5 * timeout;	else		s->timeout = timeout;	s->table_id_ext = -1;	s->section_version_number = -1;	INIT_LIST_HEAD (&s->list);}static void update_poll_fds(void){	struct list_head *p;	struct section_buf* s;	int i;	memset(poll_section_bufs, 0, sizeof(poll_section_bufs));	for (i = 0; i < MAX_RUNNING; i++)		poll_fds[i].fd = -1;	i = 0;	list_for_each (p, &running_filters) {		if (i >= MAX_RUNNING)			fatal("too many poll_fds\n");		s = list_entry (p, struct section_buf, list);		if (s->fd == -1)			fatal("s->fd == -1 on running_filters\n");		verbosedebug("poll fd %d\n", s->fd);		poll_fds[i].fd = s->fd;		poll_fds[i].events = POLLIN;		poll_fds[i].revents = 0;		poll_section_bufs[i] = s;		i++;	}	if (i != n_running)		fatal("n_running is hosed\n");}static int start_filter (struct section_buf* s){	struct dmx_sct_filter_params f;	if (n_running >= MAX_RUNNING)		goto err0;	if ((s->fd = open (s->dmx_devname, O_RDWR | O_NONBLOCK)) < 0)		goto err0;	verbosedebug("start filter pid 0x%04x table_id 0x%02x\n", s->pid, s->table_id);	memset(&f, 0, sizeof(f));	f.pid = (uint16_t) s->pid;	if (s->table_id < 0x100 && s->table_id > 0) {		f.filter.filter[0] = (uint8_t) s->table_id;		f.filter.mask[0]   = 0xff;	}	f.timeout = 0;	f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;	if (ioctl(s->fd, DMX_SET_FILTER, &f) == -1) {		errorn ("ioctl DMX_SET_FILTER failed");		goto err1;	}	s->sectionfilter_done = 0;	time(&s->start_time);	list_del_init (&s->list);  /* might be in waiting filter list */	list_add (&s->list, &running_filters);	n_running++;	update_poll_fds();	return 0;err1:	ioctl (s->fd, DMX_STOP);	close (s->fd);err0:	return -1;}static void stop_filter (struct section_buf *s){	verbosedebug("stop filter pid 0x%04x\n", s->pid);	ioctl (s->fd, DMX_STOP);	close (s->fd);	s->fd = -1;	list_del (&s->list);	s->running_time += time(NULL) - s->start_time;	n_running--;	update_poll_fds();}static void add_filter (struct section_buf *s){	verbosedebug("add filter pid 0x%04x\n", s->pid);	if (start_filter (s))		list_add_tail (&s->list, &waiting_filters);}static void remove_filter (struct section_buf *s){	verbosedebug("remove filter pid 0x%04x\n", s->pid);	stop_filter (s);	while (!list_empty(&waiting_filters)) {		struct list_head *next = waiting_filters.next;		s = list_entry (next, struct section_buf, list);		if (start_filter (s))			break;	};}static void read_filters (void){	struct section_buf *s;	int i, n, done;	n = poll(poll_fds, n_running, 1000);	if (n == -1)		errorn("poll");	for (i = 0; i < n_running; i++) {		s = poll_section_bufs[i];		if (!s)			fatal("poll_section_bufs[%d] is NULL\n", i);		if (poll_fds[i].revents)			done = read_sections (s) == 1;		else			done = 0; /* timeout */		if (done || time(NULL) > s->start_time + s->timeout) {			if (s->run_once) {				if (done)					verbosedebug("filter done pid 0x%04x\n", s->pid);				else					warning("filter timeout pid 0x%04x\n", s->pid);				remove_filter (s);			}		}	}}static int mem_is_zero (const void *mem, int size){	const char *p = mem;	while (size) {		if (*p != 0x00)			return 0;		p++;	}	return 1;}#define SWITCHFREQ 11700000#define LOF_HI     10600000#define LOF_LO      9750000static int switch_pos = 0;static int __tune_to_transponder (int frontend_fd, struct transponder *t){	struct dvb_frontend_parameters p;	fe_status_t s;	int i;	current_tp = t;	if (mem_is_zero (&t->param, sizeof(struct dvb_frontend_parameters)))		return -1;	memcpy (&p, &t->param, sizeof(struct dvb_frontend_parameters));	if (verbosity >= 1) {		dprintf(1, ">>> tune to: ");		dump_dvb_parameters (stderr, t);		if (t->last_tuning_failed)			dprintf(1, " (tuning failed)");		dprintf(1, "\n");	}	if (t->type == FE_QPSK) {

⌨️ 快捷键说明

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