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

📄 scan.c

📁 关于dvb的应用程序代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* remove control characters (FIXME: handle short/long name) */	/* FIXME: handle character set correctly (e.g. via iconv)	 * c.f. EN 300 468 annex A */	for (src = dest = (unsigned char *) s->service_name; *src; src++)		if (*src >= 0x20 && (*src < 0x80 || *src > 0x9f))			*dest++ = *src;	*dest = '\0';	if (!s->service_name[0]) {		/* zap zero length names */		free (s->service_name);		s->service_name = 0;	}	info("0x%04x 0x%04x: pmt_pid 0x%04x %s -- %s (%s%s)\n",	    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 ? ", scrambled" : "");}static int find_descriptor(uint8_t tag, const unsigned char *buf,		int descriptors_loop_len,		const unsigned char **desc, int *desc_len){	while (descriptors_loop_len > 0) {		unsigned char descriptor_tag = buf[0];		unsigned char descriptor_len = buf[1] + 2;		if (!descriptor_len) {			warning("descriptor_tag == 0x%02x, len is 0\n", descriptor_tag);			break;		}		if (tag == descriptor_tag) {			if (desc)				*desc = buf;			if (desc_len)				*desc_len = descriptor_len;			return 1;		}		buf += descriptor_len;		descriptors_loop_len -= descriptor_len;	}	return 0;}static void parse_descriptors(enum table_type t, 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) {			warning("descriptor_tag == 0x%02x, len is 0\n", descriptor_tag);			break;		}		switch (descriptor_tag) {		case 0x0a:			if (t == PMT)				parse_iso639_language_descriptor (buf, data);			break;		case 0x40:			if (t == NIT)				parse_network_name_descriptor (buf, data);			break;		case 0x43:			if (t == NIT)				parse_satellite_delivery_system_descriptor (buf, data);			break;		case 0x44:			if (t == NIT)				parse_cable_delivery_system_descriptor (buf, data);			break;		case 0x48:			if (t == SDT)				parse_service_descriptor (buf, data);			break;		case 0x53:			if (t == SDT)				parse_ca_identifier_descriptor (buf, data);			break;		case 0x5a:			if (t == NIT)				parse_terrestrial_delivery_system_descriptor (buf, data);			break;		case 0x62:			if (t == NIT)				parse_frequency_list_descriptor (buf, data);			break;		case 0x83:			/* 0x83 is in the privately defined range of descriptor tags,			 * so we parse this only if the user says so to avoid			 * problems when 0x83 is something entirely different... */			if (t == NIT && vdr_dump_channum)				parse_terrestrial_uk_channel_number (buf, data);			break;		default:			verbosedebug("skip descriptor 0x%02x\n", descriptor_tag);		};		buf += descriptor_len;		descriptors_loop_len -= descriptor_len;	}}static void parse_pat(const unsigned char *buf, int section_length,		      int transport_stream_id){	(void)transport_stream_id;	while (section_length > 0) {		struct service *s;		int service_id = (buf[0] << 8) | buf[1];		if (service_id == 0)			goto skip;	/* nit pid entry */		/* 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, s->service_id, 1, 0, 5);			add_filter (s->priv);		}skip:		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 >= 5) {		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 0x81: /* Audio per ATSC A/53B [2] Annex B */		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)		{			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){	(void)transport_stream_id;	buf += 3;	       /*  skip original network id + reserved field */	while (section_length >= 5) {		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 || !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;	};}/* ATSC PSIP VCT */static void parse_atsc_service_loc_desc(struct service *s,const unsigned char *buf){	struct ATSC_service_location_descriptor d = read_ATSC_service_location_descriptor(buf);	int i;	unsigned char *b = (unsigned char *) buf+5;	s->pcr_pid = d.PCR_PID;	for (i=0; i < d.number_elements; i++) {		struct ATSC_service_location_element e = read_ATSC_service_location_element(b);		switch (e.stream_type) {			case 0x02: /* video */				s->video_pid = e.elementary_PID;				moreverbose("  VIDEO     : PID 0x%04x\n", e.elementary_PID);				break;			case 0x81: /* ATSC audio */				if (s->audio_num < AUDIO_CHAN_MAX) {					s->audio_pid[s->audio_num] = e.elementary_PID;					s->audio_lang[s->audio_num][0] = (e.ISO_639_language_code >> 16) & 0xff;					s->audio_lang[s->audio_num][1] = (e.ISO_639_language_code >> 8)  & 0xff;					s->audio_lang[s->audio_num][2] =  e.ISO_639_language_code        & 0xff;					s->audio_num++;				}				moreverbose("  AUDIO     : PID 0x%04x lang: %s\n",e.elementary_PID,s->audio_lang[s->audio_num-1]);				break;			default:				warning("unhandled stream_type: %x\n",e.stream_type);				break;		};		b += 6;	}}static void parse_atsc_ext_chan_name_desc(struct service *s,const unsigned char *buf){	unsigned char *b = (unsigned char *) buf+2;	int i,j;	int num_str = b[0];	b++;	for (i = 0; i < num_str; i++) {		int num_seg = b[3];		b += 4; /* skip lang code */		for (j = 0; j < num_seg; j++) {			int comp_type = b[0],/* mode = b[1],*/ num_bytes = b[2];			switch (comp_type) {				case 0x00:					if (s->service_name)						free(s->service_name);					s->service_name = malloc(num_bytes * sizeof(char) + 1);					memcpy(s->service_name,&b[3],num_bytes);					s->service_name[num_bytes] = '\0';					break;				default:					warning("compressed strings are not supported yet\n");					break;			}			b += 3 + num_bytes;		}	}}static void parse_psip_descriptors(struct service *s,const unsigned char *buf,int len){	unsigned char *b = (unsigned char *) buf;	int desc_len;	while (len > 0) {		desc_len = b[1];		switch (b[0]) {			case ATSC_SERVICE_LOCATION_DESCRIPTOR_ID:				parse_atsc_service_loc_desc(s,b);				break;			case ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR_ID:				parse_atsc_ext_chan_name_desc(s,b);				break;			default:				warning("unhandled psip descriptor: %02x\n",b[0]);				break;		}		b += 2 + desc_len;		len -= 2 + desc_len;	}}static void parse_psip_vct (const unsigned char *buf, int section_length,		int table_id, int transport_stream_id){	(void)section_length;	(void)table_id;	(void)transport_stream_id;/*	int protocol_version = buf[0];*/	int num_channels_in_section = buf[1];	int i;	int pseudo_id = 0xffff;	unsigned char *b = (unsigned char *) buf + 2;	for (i = 0; i < num_channels_in_section; i++) {		struct service *s;		struct tvct_channel ch = read_tvct_channel(b);		switch (ch.service_type) {			case 0x01:				info("analog channels won't be put info channels.conf\n");				break;			case 0x02: /* ATSC TV */			case 0x03: /* ATSC Radio */				break;			case 0x04: /* ATSC Data */			default:				continue;		}		if (ch.program_number == 0)			ch.program_number = --pseudo_id;		s = find_service(current_tp, ch.program_number);		if (!s)			s = alloc_service(current_tp, ch.program_number);		if (s->service_name)			free(s->service_name);		s->service_name = malloc(7*sizeof(unsigned char));		/* TODO find a better solution to convert UTF-16 */		s->service_name[0] = ch.short_name0;		s->service_name[1] = ch.short_name1;		s->service_name[2] = ch.short_name2;		s->service_name[3] = ch.short_name3;		s->service_name[4] = ch.short_name4;		s->service_name[5] = ch.short_name5;		s->service_name[6] = ch.short_name6;		parse_psip_descriptors(s,&b[32],ch.descriptors_length);		s->channel_num = ch.major_channel_number << 10 | ch.minor_channel_number;		if (ch.hidden) {			s->running = RM_NOT_RUNNING;			info("service is not running, pseudo program_number.");		} else {			s->running = RM_RUNNING;			info("service is running.");		}		info(" Channel number: %d:%d. Name: '%s'\n",			ch.major_channel_number, ch.minor_channel_number,s->service_name);		b += 32 + ch.descriptors_length;	}}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];	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;			/* past generic table header */	section_length -= 5 + 4;	/* header + crc */	if (section_length < 0) {

⌨️ 快捷键说明

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