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

📄 scan.c

📁 linux dvb的文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/** *  Simple MPEG parser to achieve network/service information.  * *  refered standards: * *    ETSI EN 300 468 *    ETSI TR 101 211 *    ETSI ETR 211 *    ITU-T H.222.0 */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/ioctl.h>#include <unistd.h>#include <fcntl.h>#include <time.h>#include <errno.h>#include <linux/dvb/frontend.h>#include <linux/dvb/dmx.h>#include "list.h"#include "diseqc.h"#include "dump.h"#include "scan.h"struct list_entry {	int id1;	int id2;};struct list {	char *name;	struct list_entry *entry;	int count;	int entry_size;};struct network {	int dummy;	int network_id;	char *network_name;};enum polarisation {	POLARISATION_HORIZONTAL     = 0x00,	POLARISATION_VERTICAL       = 0x01,	POLARISATION_CIRCULAR_LEFT  = 0x02,	POLARISATION_CIRCULAR_RIGHT = 0x03};struct transponder {	int network_id;	int transport_stream_id;	fe_type_t type;	struct dvb_frontend_parameters param;	enum polarisation polarisation : 2;	   /*  only for DVB-S */	int scan_done		  : 1;	int last_tuning_failed	  : 1;};enum service_type {	ST_TV       = 0x01,	ST_RADIO    = 0x02,	ST_TELETEXT = 0x03,	ST_MHP      = 0x10};enum running_mode {	RM_NOT_RUNNING = 0x01,	RM_STARTS_SOON = 0x02,	RM_PAUSING     = 0x03,	RM_RUNNING     = 0x04};struct service {	int transport_stream_id;	int service_id;	char *provider_name;	char *service_name;	uint16_t pmt_pid;	uint16_t pcr_pid;	uint16_t video_pid;	uint16_t audio_pid;	int private_pid_count     : 8;	enum service_type type    : 8;	enum running_mode running : 3;	int scrambled	     : 1;	void *priv;};staticstruct list network_list = {	"network_list",	NULL,	0,	sizeof(struct network)};staticstruct list transponder_list = {	"transponder_list",	NULL,	0,	sizeof(struct transponder)};static struct list service_list = {	"service_list",	NULL,	0,	sizeof(struct service)};static void* find_entry_by_id (struct list *list, int id1, int id2){	int i;	long entry = (long) list->entry;	for (i=0; i<list->count; i++, entry += list->entry_size) {		struct list_entry *e = (struct list_entry*) entry;		if (e->id1 == id1 && (e->id2 == id2 || id2 == -1))			return e;		if (e->id2 == id2 && id1 == -1)			return e;		if (e->id1 == id1 && e->id2 == -1) {			e->id2 = id2;			return e;		}		if (e->id1 == -1 && e->id2 == id2) {			e->id1 = id1;			return e;		}	}	return NULL;}static void* find_or_alloc_entry_by_id (struct list *list, int id1, int id2){	struct list_entry *e = find_entry_by_id (list, id1, id2);	long addr;	if (!e) {		list->entry = realloc (list->entry,				       (list->count+1) * list->entry_size);		addr = (long) list->entry + list->count * list->entry_size;		e = (struct list_entry*) addr;		memset (e, 0, list->entry_size);		e->id1 = id1;		e->id2 = id2;		list->count++;	}		return e;}staticvoid* find_nth_entry (struct list *list, unsigned int n){	if (n >= list->count)		return NULL;	return (void*) ((long) list->entry + n * list->entry_size);}staticvoid parse_network_name_descriptor (const unsigned char *buf, struct network *n){	unsigned char len = buf [1];	n->network_name = malloc (len + 1);	memcpy (n->network_name, buf + 2, len);	n->network_name[len] = '\0';	MSG("(%s)", n->network_name);}staticlong bcd32_to_cpu (const int b0, const int b1, const int b2, const int b3){	return ((b0 >> 4) & 0x0f) * 10000000 + (b0 & 0x0f) * 1000000 +	       ((b1 >> 4) & 0x0f) * 100000   + (b1 & 0x0f) * 10000 +	       ((b2 >> 4) & 0x0f) * 1000     + (b2 & 0x0f) * 100 +	       ((b3 >> 4) & 0x0f) * 10       + (b3 & 0x0f);}static const fe_code_rate_t fec_tab [8] = {	FEC_AUTO, FEC_1_2, FEC_2_3, FEC_3_4,	FEC_5_6, FEC_7_8, FEC_NONE, FEC_NONE};static const fe_modulation_t qam_tab [6] = {	QAM_AUTO, QAM_16, QAM_32, QAM_64, QAM_128, QAM_256};staticvoid parse_cable_delivery_system_descriptor (const unsigned char *buf,					     struct transponder *t){	t->type = FE_QAM;	t->param.frequency = bcd32_to_cpu (buf[2], buf[3], buf[4], buf[5]);	t->param.frequency *= 100;	t->param.u.qam.fec_inner = fec_tab[buf[12] & 0x07];	t->param.u.qam.symbol_rate = 10 * bcd32_to_cpu (buf[9],							buf[10],							buf[11],							buf[12] & 0xf0);	if ((buf[8] & 0x0f) > 5)		t->param.u.qam.modulation = QAM_AUTO;	else		t->param.u.qam.modulation = qam_tab[buf[8] & 0x0f];	fprintf (stderr, "%#06x/%#06x ", t->network_id, t->transport_stream_id);	dump_dvb_parameters (stderr, t->type, &t->param);	if (t->scan_done)		fprintf (stderr, " (done)");	if (t->last_tuning_failed)		fprintf (stderr, " (tuning failed)");	fprintf (stderr, "\n");}staticvoid parse_satellite_delivery_system_descriptor (const unsigned char *buf,						 struct transponder *t){	t->type = FE_QPSK;	t->param.frequency = 10 * bcd32_to_cpu (buf[2], buf[3], buf[4], buf[5]);	t->param.u.qpsk.fec_inner = fec_tab[buf[12] & 0x07];	t->param.u.qpsk.symbol_rate = 10 * bcd32_to_cpu (buf[9],							 buf[10],							 buf[11],							 buf[12] & 0xf0);	t->polarisation = (buf[8] >> 5) & 0x03;	dump_dvb_parameters (stderr, t->type, &t->param);	if (t->scan_done)		fprintf (stderr, " (done)");	if (t->last_tuning_failed)		fprintf (stderr, " (tuning failed)");	fprintf (stderr, "\n");}staticvoid parse_terrestrial_delivery_system_descriptor (const unsigned char *buf,						   struct transponder *t){	static const fe_modulation_t m_tab [] = { QPSK, QAM_16, QAM_64, QAM_AUTO };	static const fe_code_rate_t ofec_tab [8] = { FEC_1_2, FEC_2_3, FEC_3_4,					       FEC_5_6, FEC_7_8 };	struct dvb_ofdm_parameters *o = &t->param.u.ofdm;		t->type = FE_OFDM;	t->param.frequency = (buf[2] << 24) | (buf[3] << 16);	t->param.frequency |= (buf[4] << 8) | buf[5];	t->param.frequency *= 10;	o->bandwidth = BANDWIDTH_8_MHZ + ((buf[6] >> 5) & 0x3);	o->constellation = m_tab[(buf[7] >> 6) & 0x3];	o->hierarchy_information = HIERARCHY_NONE + ((buf[7] >> 3) & 0x3);	if ((buf[7] & 0x7) > 4)		o->code_rate_HP = FEC_AUTO;	else		o->code_rate_HP = ofec_tab [buf[7] & 0x7];	if (((buf[8] >> 5) & 0x7) > 4)		o->code_rate_HP = FEC_AUTO;	else		o->code_rate_HP = ofec_tab [(buf[8] >> 5) & 0x7];	o->guard_interval = GUARD_INTERVAL_1_32 + ((buf[8] >> 3) & 0x3);	o->transmission_mode = (buf[8] & 0x2) ?			       TRANSMISSION_MODE_8K :			       TRANSMISSION_MODE_2K;	dump_dvb_parameters (stderr, t->type, &t->param);	if (t->scan_done)		fprintf (stderr, " (done)");	if (t->last_tuning_failed)		fprintf (stderr, " (tuning failed)");	fprintf (stderr, "\n");}staticvoid parse_service_descriptor (const unsigned char *buf, struct service *s){	unsigned char len;	unsigned char *src, *dest;	s->type = buf[2];	buf += 3;	len = *buf;	buf++;	if (s->provider_name)		free (s->provider_name);	s->provider_name = malloc (len + 1);	memcpy (s->provider_name, buf, len);	s->provider_name[len] = '\0';	if (s->service_name)		free (s->service_name);	buf += len;	len = *buf;	buf++;	/* FIXME: handle character set correctly (e.g. via iconv)	 * c.f. EN 300 468 annex A */	if (len && *buf < 0x20) {		buf++;		len--;	}	s->service_name = malloc (len + 1);	memcpy (s->service_name, buf, len);	s->service_name[len] = '\0';	/* remove control characters (FIXME: handle short/long name) */	for (src = dest = s->service_name; *src; src++)		if (*src >= 0x20 && (*src < 0x80 || *src > 0x9f))			*dest++ = *src;	*dest = '\0';	MSG("0x%04x 0x%04x: pmt_pid 0x%04x %s -- %s (%s, %sscrambled)",	    s->transport_stream_id,	    s->service_id,	    s->pmt_pid,	    s->provider_name, s->service_name,	    s->running == RM_NOT_RUNNING ? "not running" :	    s->running == RM_STARTS_SOON ? "starts soon" :	    s->running == RM_PAUSING     ? "pausing" :	    s->running == RM_RUNNING     ? "running" : "???",	    s->scrambled ? "" : "not ");}staticvoid parse_descriptors (const unsigned char *buf, int descriptors_loop_len,			void *data){	while (descriptors_loop_len > 0) {		unsigned char descriptor_tag = buf[0];		unsigned char descriptor_len = buf[1] + 2;		if (!descriptor_len) {			WARN("descriptor_tag == 0x%02x, descriptor_len == %i",			     descriptor_tag, descriptor_len);			break;		}		switch (descriptor_tag) {		case 0x40:			parse_network_name_descriptor (buf, data);			break;		case 0x43:			parse_satellite_delivery_system_descriptor (buf, data);			break;		case 0x44:			parse_cable_delivery_system_descriptor (buf, data);			break;		case 0x48:			parse_service_descriptor (buf, data);			break;		case 0x5a:			parse_terrestrial_delivery_system_descriptor (buf, data);			break;		default:			/*WARN("skip descriptor 0x%02x", descriptor_tag)*/;		};		buf += descriptor_len;		descriptors_loop_len -= descriptor_len;	}}staticvoid 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;		}		s = find_or_alloc_entry_by_id (&service_list,					       transport_stream_id,					       service_id);		s->pmt_pid = ((buf[2] & 0x1f) << 8) | buf[3];		buf += 4;		section_length -= 4;	};}staticvoid parse_pmt (const unsigned char *buf, int section_length, int service_id){	int program_info_len;	struct service *s;	s = find_or_alloc_entry_by_id (&service_list,				       -1,				       service_id);	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:			s->video_pid = elementary_pid;			break;		case 0x03:		case 0x04:			s->audio_pid = elementary_pid;			break;		default:			s->private_pid_count++;		};		buf += ES_info_len + 5;		section_length -= ES_info_len + 5;	};	MSG("0x%04x 0x%04x: %s -- %s, pmt_pid 0x%04x, vpid 0x%04x, apid 0x%04x",	    s->transport_stream_id,	    s->service_id,	    s->provider_name, s->service_name,	    s->pmt_pid, s->video_pid, s->audio_pid);}staticvoid parse_nit (const unsigned char *buf, int section_length, int network_id){	int descriptors_loop_len = ((buf[0] & 0x0f) << 8) | buf[1];	struct network *n;	if (section_length < descriptors_loop_len + 4 || !descriptors_loop_len)	{		WARN("network_id == 0x%02x, section_length == %i"		     "descriptors_loop_len == %i",		     network_id, section_length, descriptors_loop_len);		return;	}	n = find_or_alloc_entry_by_id (&network_list, 0, network_id);	parse_descriptors (buf + 2, descriptors_loop_len, n);	section_length -= descriptors_loop_len + 4;	buf += descriptors_loop_len + 4;	while (section_length > 4) {		int transport_stream_id = (buf[0] << 8) | buf[1];		struct transponder *t;		descriptors_loop_len = ((buf[4] & 0x0f) << 8) | buf[5];		if (section_length < descriptors_loop_len + 4 ||		    !transport_stream_id ||		    !descriptors_loop_len)		{			WARN("transport_stream_id == 0x%02x, "			     "section_length == %i, descriptors_loop_len == %i",			     transport_stream_id, section_length,			     descriptors_loop_len);			break;		}		t = find_or_alloc_entry_by_id (&transponder_list,					       network_id,					       transport_stream_id);		parse_descriptors (buf + 6, descriptors_loop_len, t);		section_length -= descriptors_loop_len + 6;		buf += descriptors_loop_len + 6;	};}staticvoid 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)		{			WARN("service_id == 0x%02x, section_length == %i"			     "descriptors_loop_len == %i",			     service_id, section_length,			     descriptors_loop_len);			break;		}		s = find_or_alloc_entry_by_id (&service_list,					       transport_stream_id,					       service_id);		s->running = (buf[3] >> 5) & 0x7;		s->scrambled = (buf[3] >> 4) & 1;		parse_descriptors (buf + 5, descriptors_loop_len, s);		section_length -= descriptors_loop_len + 5;		buf += descriptors_loop_len + 5;	};}struct section_buf {	struct list_head list_head;	const char *dmx_devname;	int run_once;	int fd;	int pid;	int table_id [3];	int id [3];	int section_version_number [3];	int start_section_number [3];	uint8_t section_done [3][32];	int sectionfilter_done [3];	unsigned char buf [1024];	int bytes_in_buf;	time_t timeout;	time_t start_time;	time_t running_time;};static

⌨️ 快捷键说明

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