Exemple #1
0
static int run_scan(struct arguments *args,
		    struct dvb_v5_fe_parms *parms)
{
	struct dvb_file *dvb_file = NULL, *dvb_file_new = NULL;
	struct dvb_entry *entry;
	int i, rc, count = 0, dmx_fd, shift;
	uint32_t freq, sys;

	/* This is used only when reading old formats */
	switch (parms->current_sys) {
	case SYS_DVBT:
	case SYS_DVBS:
	case SYS_DVBC_ANNEX_A:
	case SYS_ATSC:
		sys = parms->current_sys;
		break;
	case SYS_DVBC_ANNEX_C:
		sys = SYS_DVBC_ANNEX_A;
		break;
	case SYS_DVBC_ANNEX_B:
		sys = SYS_ATSC;
		break;
	case SYS_ISDBT:
		sys = SYS_DVBT;
		break;
	default:
		sys = SYS_UNDEFINED;
		break;
	}
	dvb_file = dvb_read_file_format(args->confname, sys,
				    args->input_format);
	if (!dvb_file)
		return -2;

	dmx_fd = open(args->demux_dev, O_RDWR);
	if (dmx_fd < 0) {
		perror("openening pat demux failed");
		return -3;
	}

	for (entry = dvb_file->first_entry; entry != NULL; entry = entry->next) {
		struct dvb_v5_descriptors *dvb_desc = NULL;

		/* First of all, set the delivery system */
		for (i = 0; i < entry->n_props; i++)
			if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM)
				dvb_set_compat_delivery_system(parms,
							       entry->props[i].u.data);

		/* Copy data into parms */
		for (i = 0; i < entry->n_props; i++) {
			uint32_t data = entry->props[i].u.data;

			/* Don't change the delivery system */
			if (entry->props[i].cmd == DTV_DELIVERY_SYSTEM)
				continue;

			dvb_fe_store_parm(parms, entry->props[i].cmd, data);
			if (parms->current_sys == SYS_ISDBT) {
				dvb_fe_store_parm(parms, DTV_ISDBT_PARTIAL_RECEPTION, 0);
				dvb_fe_store_parm(parms, DTV_ISDBT_SOUND_BROADCASTING, 0);
				dvb_fe_store_parm(parms, DTV_ISDBT_LAYER_ENABLED, 0x07);
				if (entry->props[i].cmd == DTV_CODE_RATE_HP) {
					dvb_fe_store_parm(parms, DTV_ISDBT_LAYERA_FEC,
							data);
					dvb_fe_store_parm(parms, DTV_ISDBT_LAYERB_FEC,
							data);
					dvb_fe_store_parm(parms, DTV_ISDBT_LAYERC_FEC,
							data);
				} else if (entry->props[i].cmd == DTV_MODULATION) {
					dvb_fe_store_parm(parms,
							DTV_ISDBT_LAYERA_MODULATION,
							data);
					dvb_fe_store_parm(parms,
							DTV_ISDBT_LAYERB_MODULATION,
							data);
					dvb_fe_store_parm(parms,
							DTV_ISDBT_LAYERC_MODULATION,
							data);
				}
			}
			if (parms->current_sys == SYS_ATSC &&
			    entry->props[i].cmd == DTV_MODULATION) {
				if (data != VSB_8 && data != VSB_16)
					dvb_fe_store_parm(parms,
							DTV_DELIVERY_SYSTEM,
							SYS_DVBC_ANNEX_B);
			}
		}

		/*
		 * If the channel file has duplicated frequencies, or some
		 * entries without any frequency at all, discard.
		 */
		freq = 0;
		for (i = 0; i < entry->n_props; i++) {
			if (entry->props[i].cmd == DTV_FREQUENCY) {
				freq = entry->props[i].u.data;
				break;
			}
		}
		if (!freq)
			continue;
		shift = estimate_freq_shift(parms);
		if (dvb_desc && !new_freq_is_needed(dvb_file->first_entry, entry,
					freq, dvb_desc->nit_table.pol, shift))
			continue;

		rc = dvb_fe_set_parms(parms);
		if (rc < 0) {
			PERROR("dvb_fe_set_parms failed");
			return -1;
		}

		/* As the DVB core emulates it, better to always use auto */
		dvb_fe_store_parm(parms, DTV_INVERSION, INVERSION_AUTO);

		dvb_fe_retrieve_parm(parms, DTV_FREQUENCY, &freq);
		count++;
		dvb_log("Scanning frequency #%d %d", count, freq);
		if (verbose)
			dvb_fe_prt_parms(parms);

		rc = check_frontend(args, parms);
		if (rc < 0)
			continue;

		dvb_desc = dvb_get_ts_tables(parms, dmx_fd,
					     parms->current_sys,
					     args->other_nit,
					     args->timeout_multiply,
					     verbose);
		if (!dvb_desc)
			continue;

		for (i = 0; i < dvb_desc->sdt_table.service_table_len; i++) {
			struct service_table *service_table = &dvb_desc->sdt_table.service_table[i];

			entry->vchannel = dvb_vchannel(dvb_desc, i);
			printf("Service #%d (%d)", i,
				service_table->service_id);
			if (service_table->service_name)
				printf(" %s", service_table->service_name);
			if (entry->vchannel)
				printf(" channel %s", entry->vchannel);
			printf("\n");
		}

		store_dvb_channel(&dvb_file_new, parms, dvb_desc,
				  args->get_detected, args->get_nit);

		if (!args->dont_add_new_freqs)
			add_other_freq_entries(dvb_file, parms, dvb_desc);

		dvb_free_ts_tables(dvb_desc);
	}

	if (dvb_file_new)
		write_file_format(args->output, dvb_file_new,
				  parms->current_sys, args->output_format);

	dvb_file_free(dvb_file);
	if (dvb_file_new)
		dvb_file_free(dvb_file_new);

	close(dmx_fd);
	return 0;
}
Exemple #2
0
int store_dvb_channel(struct dvb_file **dvb_file,
		      struct dvb_v5_fe_parms *parms,
		      struct dvb_descriptors *dvb_desc,
		      int get_detected, int get_nit)
{
	struct dvb_entry *entry;
	int i, j, has_detected = 1;

	if (!*dvb_file) {
		*dvb_file = calloc(sizeof(*dvb_file), 1);
		if (!*dvb_file) {
			perror("Allocating memory for dvb_file");
			return -1;
		}
	}

	/* Go to the last entry */
	entry = (*dvb_file)->first_entry;
	while (entry && entry->next)
		entry = entry->next;

	for (i = 0; i < dvb_desc->sdt_table.service_table_len; i++) {
		struct service_table *service_table = &dvb_desc->sdt_table.service_table[i];
		struct pat_table *pat_table = &dvb_desc->pat_table;
		struct pid_table *pid_table = NULL;

		if (!entry) {
			(*dvb_file)->first_entry = calloc(sizeof(*entry), 1);
			entry = (*dvb_file)->first_entry;
		} else {
			entry->next = calloc(sizeof(*entry), 1);
			entry = entry->next;
		}
		if (!entry) {
			fprintf(stderr, "Not enough memory\n");
			return -1;
		}
		entry->sat_number = -1;

		if (service_table->service_name) {
			entry->channel = calloc(strlen(service_table->service_name) + 1, 1);
			strcpy(entry->channel, service_table->service_name);
		} else {
			asprintf(&entry->channel, "#%d",
				 service_table->service_id);
		}
		entry->service_id = service_table->service_id;

		entry->vchannel = dvb_vchannel(dvb_desc, i);

		entry->pol = parms->pol;
		entry->sat_number = parms->sat_number;
		entry->freq_bpf = parms->freq_bpf;
		entry->diseqc_wait = parms->diseqc_wait;
		if (parms->lnb)
			entry->lnb = strdup(parms->lnb->alias);

		for (j = 0; j < pat_table->pid_table_len; j++) {
			pid_table = &pat_table->pid_table[j];
			if (service_table->service_id == pid_table->service_id)
				break;
		}
		if (j == pat_table->pid_table_len) {
			fprintf(stderr, "Service ID %d not found on PMT!\n",
			      service_table->service_id);
			has_detected = 0;
		} else has_detected = 1;

		/*
		 * Video/audio/other pid's can only be filled if the service
		 * was found.
		 */
		if (has_detected) {
			entry->video_pid = calloc(sizeof(*entry[i].video_pid),
						pid_table->video_pid_len);
			for (j = 0; j < pid_table->video_pid_len; j++)
				entry->video_pid[j] = pid_table->video_pid[j];
			entry->video_pid_len = pid_table->video_pid_len;

			entry->audio_pid = calloc(sizeof(*entry[i].audio_pid),
						pid_table->audio_pid_len);
			for (j = 0; j < pid_table->audio_pid_len; j++)
				entry->audio_pid[j] = pid_table->audio_pid[j];
			entry->audio_pid_len = pid_table->audio_pid_len;

			entry->other_el_pid = calloc(sizeof(*entry->other_el_pid),
						pid_table->other_el_pid_len);
			memcpy(entry->other_el_pid, pid_table->other_el_pid,
			pid_table->other_el_pid_len * sizeof(*entry->other_el_pid));
			entry->other_el_pid_len = pid_table->other_el_pid_len;
			qsort(entry->other_el_pid, entry->other_el_pid_len,
			sizeof(*entry->other_el_pid), sort_other_el_pid);
		}

		/* Copy data from parms */
		if (get_detected) {
			int rc;
			do {
				rc = dvb_fe_get_parms(parms);
				if (rc == EAGAIN)
					usleep(100000);
			} while (rc == EAGAIN);
		}
		for (j = 0; j < parms->n_props; j++) {
			entry->props[j].cmd = parms->dvb_prop[j].cmd;
			entry->props[j].u.data = parms->dvb_prop[j].u.data;
		}
		entry->n_props = parms->n_props;

		if (get_nit)
			handle_std_specific_parms(entry, dvb_desc);
	}

	return 0;
}