예제 #1
0
/** @brief Reads the program map table
 *
 * It's used to get the differents "useful" pids of the channel
 * @param pmt the pmt packet
 * @param channel the associated channel
 */
int autoconf_read_pmt(mumudvb_ts_packet_t *pmt, mumudvb_channel_t *channel, char *card_base_path, int tuner, uint8_t *asked_pid, uint8_t *number_chan_asked_pid,fds_t *fds)
{
	int section_len, descr_section_len, i,j;
	int pid;
	int pid_type;
	int found=0;
	pmt_t *header;
	pmt_info_t *descr_header;

	int program_info_length;
	int channel_update;

	//For channel update
	int temp_pids[MAX_PIDS];
	int temp_pids_type[MAX_PIDS];
	char temp_pids_language[MAX_PIDS][4];
	//For channel update
	int temp_num_pids=0;

	pid_type=0;

	section_len=pmt->len_full;
	header=(pmt_t *)pmt->data_full;

	if(header->table_id!=0x02)
	{
		log_message( log_module,  MSG_INFO,"Packet PID %d for channel \"%s\" is not a PMT PID. We remove the pmt pid for this channel\n", pmt->pid, channel->name);
		channel->pmt_pid=0; /** @todo : put a threshold, */
		return 1;
	}

	//We check if this PMT belongs to the current channel. (Only works with autoconfiguration full for the moment because it stores the service_id)
	if(channel->service_id && (channel->service_id != HILO(header->program_number)) )
	{
		log_message( log_module,  MSG_DETAIL,"The PMT %d does not belongs to channel \"%s\"\n", pmt->pid, channel->name);
		return 1;
	}

	/*current_next_indicator – A 1-bit indicator, which when set to '1' indicates that the Program Association Table
  sent is currently applicable. When the bit is set to '0', it indicates that the table sent is not yet applicable
  and shall be the next table to become valid.*/
	if(header->current_next_indicator == 0)
	{
		log_message( log_module, MSG_DEBUG,"The current_next_indicator is set to 0, this PMT is not valid for the current stream\n");
		return 1;
	}


	log_message( log_module,  MSG_DEBUG,"PMT (PID %d) read for autoconfiguration of channel \"%s\"\n", pmt->pid, channel->name);

	channel_update=channel->num_pids>1?1:0;
	if(channel_update)
	{
		// Update
		log_message( log_module,  MSG_INFO,"Channel %s update\n",channel->name);
		temp_pids[0]=pmt->pid;
		temp_num_pids++;
#ifdef ENABLE_CAM_SUPPORT
		// Reset of the CA SYS saved for the chanel
		for (i=0; i<32; i++)
			channel->ca_sys_id[i]=0;
#endif
	}

	program_info_length=HILO(header->program_info_length); //program_info_length
	char language[4]="";
	int pos=0;

	//we read the different descriptors included in the pmt
	//for more information see ITU-T Rec. H.222.0 | ISO/IEC 13818 table 2-34
	for (i=program_info_length+PMT_LEN; i<=section_len-(PMT_INFO_LEN+4); i+=descr_section_len+PMT_INFO_LEN)
	{
		//we parse the part after the descriptors
		//we map the descriptor header
		descr_header=(pmt_info_t *)(pmt->data_full+i);
		//We get the length of the descriptor
		descr_section_len=HILO(descr_header->ES_info_length);        //ES_info_length

		// Default language value if not found
		snprintf(language,4,"%s","---");
		// Default, no position found
		pos=0;

		pid=HILO(descr_header->elementary_PID);
		//Depending of the stream type we'll take or not this pid
		switch(descr_header->stream_type)
		{
		case 0x01:
			pid_type=PID_VIDEO_MPEG1;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG1 \tpid %d\n",pid);
			break;
		case 0x02:
			pid_type=PID_VIDEO_MPEG2;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG2 \tpid %d\n",pid);
			break;
		case 0x10: /* ISO/IEC 14496-2 Visual - MPEG4 video */
			pid_type=PID_VIDEO_MPEG4_ASP;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG4-ASP \tpid %d\n",pid);
			break;
		case 0x1b: /* AVC video stream as defined in ITU-T Rec. H.264 | ISO/IEC 14496-10 Video */
			pid_type=PID_VIDEO_MPEG4_AVC;
			log_message( log_module,  MSG_DEBUG,"  Video MPEG4-AVC \tpid %d\n",pid);
			break;
		case 0x03:
			pid_type=PID_AUDIO_MPEG1;
			log_message( log_module,  MSG_DEBUG,"  Audio MPEG1 \tpid %d\n",pid);
			break;
		case 0x04:
			pid_type=PID_AUDIO_MPEG2;
			log_message( log_module,  MSG_DEBUG,"  Audio MPEG2 \tpid %d\n",pid);
			break;
		case 0x11: /* ISO/IEC 14496-3 Audio with the LATM transport syntax as defined in ISO/IEC 14496-3 */
			pid_type=PID_AUDIO_AAC_LATM;
			log_message( log_module,  MSG_DEBUG,"  Audio AAC-LATM \tpid %d\n",pid);
			break;
		case 0x0f: /* ISO/IEC 13818-7 Audio with ADTS transport syntax - usually AAC */
			pid_type=PID_AUDIO_AAC_ADTS;
			log_message( log_module,  MSG_DEBUG,"  Audio AAC-ADTS \tpid %d\n",pid);
			break;
		case 0x81: /* Audio per ATSC A/53B [2] Annex B */
			pid_type=PID_AUDIO_ATSC;
			log_message( log_module,  MSG_DEBUG,"  Audio ATSC A/53B \tpid %d\n",pid);
			break;



		case 0x06: /* Descriptor defined in EN 300 468 */
			if(descr_section_len) //If we have an accociated descriptor, we'll search inforation in it
			{
				if(pmt_find_descriptor(0x45,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  VBI Data \tpid %d\n",pid);
					pid_type=PID_EXTRA_VBIDATA;
				}else if(pmt_find_descriptor(0x46,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  VBI Teletext \tpid %d\n",pid);
					pid_type=PID_EXTRA_VBITELETEXT;
				}else if(pmt_find_descriptor(0x56,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  Teletext \tpid %d\n",pid);
					pid_type=PID_EXTRA_TELETEXT;
				}else if(pmt_find_descriptor(0x59,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){
					log_message( log_module,  MSG_DEBUG,"  Subtitling \tpid %d\n",pid);
					pid_type=PID_EXTRA_SUBTITLE;
					char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2);
					language[0]=lng[0];
					language[1]=lng[1];
					language[2]=lng[2];
					language[3]=0;
				}else if(pmt_find_descriptor(0x6a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  AC3 (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_AC3;
				}else if(pmt_find_descriptor(0x7a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  Enhanced AC3 (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_EAC3;
				}else if(pmt_find_descriptor(0x7b,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  DTS (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_DTS;
				}else if(pmt_find_descriptor(0x7c,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, NULL)){
					log_message( log_module,  MSG_DEBUG,"  AAC (audio) \tpid %d\n",pid);
					pid_type=PID_AUDIO_AAC;
				}else
				{
					log_message( log_module,  MSG_DEBUG,"Unknown descriptor see EN 300 468 v1.9.1 table 12, pid %d descriptor tags : ", pid);
					pmt_print_descriptor_tags(pmt->data_full+i+PMT_INFO_LEN,descr_section_len);
					log_message( log_module,  MSG_DEBUG,"\n");
					continue;
				}
			}
			else
			{
				log_message( log_module,  MSG_DEBUG,"PMT read : stream type 0x06 without descriptor\n");
				continue;
			}
			break;

			//Now, the list of what we drop
		case 0x05:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x05, ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private_sections \n",pid);
			continue;
			//Digital Storage Medium Command and Control (DSM-CC) cf H.222.0 | ISO/IEC 13818-1 annex B
		case 0x0a:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0A ISO/IEC 13818-6 type A (DSM-CC)\n",pid);
			continue;
		case 0x0b:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0B ISO/IEC 13818-6 type B (DSM-CC)\n",pid);
			continue;
		case 0x0c:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : 0x0C ISO/IEC 13818-6 type C (DSM-CC)\n",pid);
			continue;
		case 0x0D:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 13818-6 type D",pid);
			continue;
		case 0x0E:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 auxiliary",pid);
			continue;
		case 0x12:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets",pid);
			continue;
		case 0x13:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496_sections",pid);
			continue;
		case 0x14:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : ISO/IEC 13818-6 Synchronized Download Protocol",pid);
			continue;
		case 0x15:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in PES packets",pid);
			continue;
		case 0x16:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in metadata_sections",pid);
			continue;
		case 0x17:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Data Carousel",pid);
			continue;
		case 0x18:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Object Carousel",pid);
			continue;
		case 0x19:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol",pid);
			continue;
		case 0x1A:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP)",pid);
			continue;
		case 0x7F:
			log_message( log_module,  MSG_DEBUG, "Dropped pid %d, type : IPMP stream",pid);
			continue;
		default:
			if(descr_header->stream_type >= 0x1C && descr_header->stream_type <= 0x7E)
				log_message( log_module,  MSG_DEBUG, "Dropped pid %d, stream type : 0x%02x : ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved",pid,descr_header->stream_type);
			else if(descr_header->stream_type >= 0x80)
				log_message( log_module,  MSG_DEBUG, "Dropped pid %d, stream type : 0x%02x : User Private",pid,descr_header->stream_type);
			else
				log_message( log_module,  MSG_INFO, "!!!!Unknown stream type : 0x%02x, PID : %d cf ITU-T Rec. H.222.0 | ISO/IEC 13818\n",descr_header->stream_type,pid);
			continue;
		}

		//We keep this pid

		// We try to find a 0x0a (ISO639) descriptor to have language information about the stream
		pos=0;
		if(pmt_find_descriptor(0x0a,pmt->data_full+i+PMT_INFO_LEN,descr_section_len, &pos)){
			char * lng=(char *)(pmt->data_full+i+PMT_INFO_LEN+pos+2);
			language[0]=lng[0];
			language[1]=lng[1];
			language[2]=lng[2];
			language[3]=0;
		}
		log_message( log_module,  MSG_DEBUG,"  PID Language Code = %s\n",language);

		//For cam debugging purposes, we look if we can find a ca descriptor to display ca system ids
		if(descr_section_len)
		{
			int pos;
			int casysid;
			pos=0;
			while(pmt_find_descriptor(0x09,pmt->data_full+i+PMT_INFO_LEN,descr_section_len,&pos))
			{
				descr_ca_t *ca_descriptor;
				ca_descriptor=(descr_ca_t *)(pmt->data_full+i+PMT_INFO_LEN+pos);
				casysid=0;
				while(casysid<32 && channel->ca_sys_id[casysid] && channel->ca_sys_id[casysid]!=HILO(ca_descriptor->CA_type) )
					casysid++;
				if(casysid<32 && !channel->ca_sys_id[casysid])
				{
					channel->ca_sys_id[casysid]=HILO(ca_descriptor->CA_type);
					log_message( log_module,  MSG_DETAIL,"Ca system id 0x%04x : %s\n", HILO(ca_descriptor->CA_type), ca_sys_id_to_str(HILO(ca_descriptor->CA_type)));//we display it with the description
				}
				if(casysid==32)
					log_message( log_module,  MSG_WARN,"Too much Ca system id line %d file %s\n", __LINE__,__FILE__);
				pos+=ca_descriptor->descriptor_length+2;
			}
		}

		if(channel_update)
		{
			temp_pids[temp_num_pids]=pid;
			temp_pids_type[temp_num_pids]=pid_type;
			snprintf(temp_pids_language[temp_num_pids],4,"%s",language);
			temp_num_pids++;
			if (temp_num_pids >= MAX_PIDS)
			{
				log_message( log_module,  MSG_ERROR,
						"Too many PIDs : %d\n",
						temp_num_pids);
				temp_num_pids--;
			}
		}
		else
		{
			channel->pids[channel->num_pids]=pid;
			channel->pids_type[channel->num_pids]=pid_type;
			snprintf(channel->pids_language[channel->num_pids],4,"%s",language);
			channel->num_pids++;
		}
	}

	/**************************
	 * PCR PID
	 **************************/

	channel->pcr_pid=HILO(header->PCR_PID); //The PCR pid.
	//we check if it's not already included (ie the pcr is carried with the video)
	found=0;
	for(i=0;i<channel->num_pids;i++)
	{
		if((channel_update && temp_pids[i]==channel->pcr_pid) || (!channel_update && channel->pids[i]==channel->pcr_pid))
			found=1;
	}
	if(!found)
	{
		if(channel_update)
		{
			temp_pids[temp_num_pids]=channel->pcr_pid;
			temp_pids_type[temp_num_pids]=PID_PCR;
			snprintf(temp_pids_language[temp_num_pids],4,"%s","---");
			temp_num_pids++;
		}
		else
		{
			channel->pids[channel->num_pids]=channel->pcr_pid;
			channel->pids_type[channel->num_pids]=PID_PCR;
			snprintf(channel->pids_language[channel->num_pids],4,"%s","---");
			channel->num_pids++;
		}
	}
	log_message( log_module,  MSG_DEBUG, "PCR pid %d\n",channel->pcr_pid);

	/**************************
	 * PCR PID - END
	 **************************/
	//We store the PMT version useful to check for updates
	channel->pmt_version=header->version_number;

	/**************************
	 * Channel update
	 **************************/
	//If it's a channel update we will have to update the filters
	if(channel_update)
	{
		log_message( log_module,  MSG_DEBUG,"Channel update new number of pids %d old %d we check for changes\n", temp_num_pids, channel->num_pids);

		//We search for added pids
		for(i=0;i<temp_num_pids;i++)
		{
			found=0;
			for(j=0;j<channel->num_pids;j++)
			{
				if(channel->pids[j]==temp_pids[i])
					found=1;
			}
			if(!found)
			{
				log_message( log_module,  MSG_DETAIL, "Update : pid %d added \n",temp_pids[i]);
				//If the pid is not on the list we add it for the filters
				if(asked_pid[temp_pids[i]]==PID_NOT_ASKED)
					asked_pid[temp_pids[i]]=PID_ASKED;

				number_chan_asked_pid[temp_pids[i]]++;
				channel->pids[channel->num_pids]=temp_pids[i];
				channel->pids_type[channel->num_pids]=temp_pids_type[i];
				snprintf(channel->pids_language[channel->num_pids],4,"%s",temp_pids_language[i]);
				channel->num_pids++;

				log_message( log_module, MSG_DETAIL,"Add the new filters\n");
				// we open the file descriptors
				if (create_card_fd (card_base_path, tuner, asked_pid, fds) < 0)
				{
					log_message( log_module, MSG_ERROR,"CANNOT open the new descriptors. Some channels will probably not work\n");
					//return; //FIXME : what do we do here ?
				}
				//open the new filters
				set_filters(asked_pid, fds);

			}
		}
		//We search for suppressed pids
		for(i=0;i<channel->num_pids;i++)
		{
			found=0;
			for(j=0;j<temp_num_pids;j++)
			{
				if(channel->pids[i]==temp_pids[j])
					found=1;
			}
			if(!found)
			{
				log_message( log_module,  MSG_DETAIL, "Update : pid %d supressed \n",channel->pids[i]);

				//We check the number of channels on wich this pid is registered, if 0 it's strange we warn
				if((channel->pids[i]>MAX_MANDATORY_PID_NUMBER )&& (number_chan_asked_pid[channel->pids[i]]))
				{
					//We decrease the number of channels with this pid
					number_chan_asked_pid[channel->pids[i]]--;
					//If no channel need this pid anymore, we remove the filter (closing the file descriptor remove the filter associated)
					if(number_chan_asked_pid[channel->pids[i]]==0)
					{
						log_message( log_module,  MSG_DEBUG, "Update : pid %d does not belong to any channel anymore, we close the filter \n",channel->pids[i]);
						close(fds->fd_demuxer[channel->pids[i]]);
						fds->fd_demuxer[channel->pids[i]]=0;
						asked_pid[channel->pids[i]]=PID_NOT_ASKED;
					}
				}
				else
					log_message( log_module,  MSG_WARN, "Update : We tried to suppress pid %d in a strange way, please contact if you can reproduce\n",channel->pids[i]);
				//We remove the pid from this channel by swapping with the last one and decreasing the pid number
				channel->pids[i]=channel->pids[channel->num_pids-1];
				channel->num_pids--;
				i--; //we wan to check the pid just moved so we force the loop to reaxamine pid i

			}
		}
		log_message( log_module,  MSG_DETAIL, "        pids : \n");/**@todo Generate a strind and call log_message after, in syslog it generates one line per pid : use the toolbox unicast*/
		int ipid;
		for (ipid = 0; ipid < channel->num_pids; ipid++)
			log_message( log_module,  MSG_DETAIL, "              %d (%s) \n", channel->pids[ipid], pid_type_to_str(channel->pids_type[ipid]));

	}
	/** @todo : update generated conf file*/
	/**************************
	 * Channel update END
	 **************************/
	/*************************
	 * Language template
	 **************************/
	found =0;
	int len=MAX_NAME_LEN;
	for(i=0;i<channel->num_pids && !found;i++)
	{
		if(channel->pids_language[i][0]!='-')
		{
			log_message( log_module,  MSG_FLOOD, "Primary language for channel: %s",channel->pids_language[i]);
			mumu_string_replace(channel->name,&len,0,"%lang",channel->pids_language[i]);
			found=1; //we exit the loop
		}
	}
	//If we don't find a lang we replace by our "usual" ---
	if(!found)
		mumu_string_replace(channel->name,&len,0,"%lang",channel->pids_language[0]);
	/*************************
	 * Language template END
	 **************************/

	log_message( log_module,  MSG_DEBUG,"Number of pids after autoconf %d\n", channel->num_pids);
	return 0;
}
예제 #2
0
/** @brief Send a full XML state of the mumudvb instance
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 * @param fds the frontend device structure
 */
int
unicast_send_xml_state (int number_of_channels, mumudvb_channel_t *channels, int Socket, strength_parameters_t *strengthparams, auto_p_t *auto_p, void *cam_p_v, void *scam_vars_v)
{
#ifndef ENABLE_CAM_SUPPORT
	(void) cam_p_v; //to make compiler happy
#else
	cam_p_t *cam_p=(cam_p_t *)cam_p_v;
#endif

#ifndef ENABLE_SCAM_SUPPORT
	(void) scam_vars_v; //to make compiler happy
#else
	scam_parameters_t *scam_vars=(scam_parameters_t *)scam_vars_v;
#endif
	// Prepare the HTTP reply
	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	// Date time formatting
	time_t rawtime;
	time (&rawtime);
	char sdatetime[25];
	snprintf(sdatetime,25,"%s",ctime(&rawtime));

	// XML header
	unicast_reply_write(reply, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");

	// Starting XML content
	unicast_reply_write(reply, "<mumudvb card=\"%d\" frontend=\"%d\">\n",strengthparams->tune_p->card,strengthparams->tune_p->tuner);

	// Mumudvb information
	unicast_reply_write(reply, "\t<global_version><![CDATA[%s]]></global_version>\n",VERSION);
	unicast_reply_write(reply, "\t<global_pid>%d</global_pid>\n",getpid ());

	// Uptime
	extern long real_start_time;
	struct timeval tv;
	gettimeofday (&tv, (struct timezone *) NULL);
	unicast_reply_write(reply, "\t<global_uptime>%d</global_uptime>\n",(tv.tv_sec - real_start_time));

	// Frontend setup
	unicast_reply_write(reply, "\t<frontend_name><![CDATA[%s]]></frontend_name>\n",strengthparams->tune_p->fe_name);
	unicast_reply_write(reply, "\t<frontend_tuned>%d</frontend_tuned>\n",strengthparams->tune_p->card_tuned);
	if (strengthparams->tune_p->fe_type==FE_QPSK) // Do some test for always showing frequency in kHz
	{
		unicast_reply_write(reply, "\t<frontend_frequency>%d</frontend_frequency>\n",strengthparams->tune_p->freq);
		unicast_reply_write(reply, "\t<frontend_satnumber>%d</frontend_satnumber>\n",strengthparams->tune_p->sat_number);
	}
	else
		unicast_reply_write(reply, "\t<frontend_frequency>%d</frontend_frequency>\n",(strengthparams->tune_p->freq)/1000);
	if (strengthparams->tune_p->pol==0)
		unicast_reply_write(reply, "\t<frontend_polarization><![CDATA[-]]></frontend_polarization>\n");
	else
		unicast_reply_write(reply, "\t<frontend_polarization><![CDATA[%c]]></frontend_polarization>\n",strengthparams->tune_p->pol);
	unicast_reply_write(reply, "\t<frontend_symbolrate>%d</frontend_symbolrate>\n",strengthparams->tune_p->srate);

	// Frontend type
	char fetype[10]="Unkonwn";
	if (strengthparams->tune_p->fe_type==FE_OFDM)
#ifdef DVBT2
		if (strengthparams->tune_p->delivery_system==SYS_DVBT2)
			snprintf(fetype,10,"DVB-T2");
		else
			snprintf(fetype,10,"DVB-T");
#else
	snprintf(fetype,10,"DVB-T");
#endif
	if (strengthparams->tune_p->fe_type==FE_QAM)  snprintf(fetype,10,"DVB-C");
	if (strengthparams->tune_p->fe_type==FE_ATSC) snprintf(fetype,10,"ATSC");
	if (strengthparams->tune_p->fe_type==FE_QPSK)
	{
#if DVB_API_VERSION >= 5
		if (strengthparams->tune_p->delivery_system==SYS_DVBS2)
			snprintf(fetype,10,"DVB-S2");
#ifdef DVBT2
		else if (strengthparams->tune_p->delivery_system==SYS_DVBT2)
			snprintf(fetype,10,"DVB-T2");
#endif
		else
			snprintf(fetype,10,"DVB-S");
#else
		snprintf(fetype,10,"DVB-S");
#endif
	}
	unicast_reply_write(reply, "\t<frontend_system><![CDATA[%s]]></frontend_system>\n",fetype);

	// Frontend status
	char SCVYL[6]="-----";
	if (strengthparams->festatus & FE_HAS_SIGNAL)  SCVYL[0]=83; // S
	if (strengthparams->festatus & FE_HAS_CARRIER) SCVYL[1]=67; // C
	if (strengthparams->festatus & FE_HAS_VITERBI) SCVYL[2]=86; // V
	if (strengthparams->festatus & FE_HAS_SYNC)    SCVYL[3]=89; // Y
	if (strengthparams->festatus & FE_HAS_LOCK)    SCVYL[4]=76; // L
	SCVYL[5]=0;
	unicast_reply_write(reply, "\t<frontend_status><![CDATA[%s]]></frontend_status>\n",SCVYL);

	// Frontend signal
	unicast_reply_write(reply, "\t<frontend_ber>%d</frontend_ber>\n",strengthparams->ber);
	unicast_reply_write(reply, "\t<frontend_signal>%d</frontend_signal>\n",strengthparams->strength);
	unicast_reply_write(reply, "\t<frontend_snr>%d</frontend_snr>\n",strengthparams->snr);
	unicast_reply_write(reply, "\t<frontend_ub>%d</frontend_ub>\n",strengthparams->ub);
	unicast_reply_write(reply, "\t<ts_discontinuities>%d</ts_discontinuities>\n",strengthparams->ts_discontinuities);


	// Autoconfiguration state
	if (auto_p->autoconfiguration!=0)
		unicast_reply_write(reply, "\t<autoconf_end>%d</autoconf_end>\n",0);
	else
		unicast_reply_write(reply, "\t<autoconf_end>%d</autoconf_end>\n",1);

	// CAM information
#ifdef ENABLE_CAM_SUPPORT
	unicast_reply_write(reply, "\t<cam_support>%d</cam_support>\n",cam_p->cam_support);
	unicast_reply_write(reply, "\t<cam_number>%d</cam_number>\n",cam_p->cam_number);
	unicast_reply_write(reply, "\t<cam_menustring><![CDATA[%s]]></cam_menustring>\n",cam_p->cam_menu_string.string);
	unicast_reply_write(reply, "\t<cam_initialized>%d</cam_initialized>\n",cam_p->ca_resource_connected);
#else
	unicast_reply_write(reply, "\t<cam_support>%d</cam_support>\n",0);
	unicast_reply_write(reply, "\t<cam_number>%d</cam_number>\n",0);
	unicast_reply_write(reply, "\t<cam_menustring><![CDATA[No CAM support]]></cam_menustring>\n");
	unicast_reply_write(reply, "\t<cam_initialized>%d</cam_initialized>\n",0);
#endif

	// SCAM information
#ifdef ENABLE_SCAM_SUPPORT
	unicast_reply_write(reply, "\t<scam_support>%d</scam_support>\n",scam_vars->scam_support);
	if (scam_vars->scam_support) {
		unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",scam_vars->ring_buffer_default_size);
		unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",scam_vars->decsa_default_delay);
		unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",scam_vars->send_default_delay);
	}
	else {
		unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",0);
		unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",0);
		unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",0);
	}
#else
	unicast_reply_write(reply, "\t<scam_support>%d</scam_support>\n",0);
	unicast_reply_write(reply, "\t<ring_buffer_default_size>%u</ring_buffer_default_size>\n",0);
	unicast_reply_write(reply, "\t<decsa_default_delay>%u</decsa_default_delay>\n",0);
	unicast_reply_write(reply, "\t<send_default_delay>%u</send_default_delay>\n",0);
#endif

	// Channels list
	int curr_channel;
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
	{
		unicast_reply_write(reply, "\t<channel number=\"%d\" is_up=\"%d\">\n",curr_channel+1,channels[curr_channel].streamed_channel);
		unicast_reply_write(reply, "\t\t<lcn>%d</lcn>\n",channels[curr_channel].logical_channel_number);
		unicast_reply_write(reply, "\t\t<name><![CDATA[%s]]></name>\n",channels[curr_channel].name);
		unicast_reply_write(reply, "\t\t<service_type type=\"%d\"><![CDATA[%s]]></service_type>\n",channels[curr_channel].channel_type,service_type_to_str(channels[curr_channel].channel_type));
		if (channels[curr_channel].portOut==0)
			unicast_reply_write(reply, "\t\t<ip_multicast><![CDATA[0.0.0.0]]></ip_multicast>\n");
		else
			unicast_reply_write(reply, "\t\t<ip_multicast><![CDATA[%s]]></ip_multicast>\n",channels[curr_channel].ip4Out);
		unicast_reply_write(reply, "\t\t<port_multicast>%d</port_multicast>\n",channels[curr_channel].portOut);
		unicast_reply_write(reply, "\t\t<traffic>%.0f</traffic>\n",channels[curr_channel].traffic);
		unicast_reply_write(reply, "\t\t<ratio_scrambled>%d</ratio_scrambled>\n",channels[curr_channel].ratio_scrambled);
		unicast_reply_write(reply, "\t\t<service_id>%d</service_id>\n",channels[curr_channel].service_id);
		unicast_reply_write(reply, "\t\t<pmt_pid>%d</pmt_pid>\n",channels[curr_channel].pmt_pid);
		unicast_reply_write(reply, "\t\t<pmt_version>%d</pmt_version>\n",channels[curr_channel].pmt_version);
		unicast_reply_write(reply, "\t\t<pcr_pid>%d</pcr_pid>\n",channels[curr_channel].pcr_pid);
		unicast_reply_write(reply, "\t\t<unicast_port>%d</unicast_port>\n",channels[curr_channel].unicast_port);
		// SCAM information
#ifdef ENABLE_SCAM_SUPPORT
		if (scam_vars->scam_support) {
			unicast_reply_write(reply, "\t\t<scam descrambled=\"%d\">\n",channels[curr_channel].scam_support);
			if (channels[curr_channel].scam_support) {
				unsigned int ring_buffer_num_packets = 0;

				if (channels[curr_channel].ring_buf) {
					pthread_mutex_lock(&channels[curr_channel].ring_buf->lock);
					ring_buffer_num_packets = channels[curr_channel].ring_buf->to_descramble + channels[curr_channel].ring_buf->to_send;
					pthread_mutex_unlock(&channels[curr_channel].ring_buf->lock);
				}

				unicast_reply_write(reply, "\t\t\t<ring_buffer_size>%u</ring_buffer_size>\n",channels[curr_channel].ring_buffer_size);
				unicast_reply_write(reply, "\t\t\t<decsa_delay>%u</decsa_delay>\n",channels[curr_channel].decsa_delay);
				unicast_reply_write(reply, "\t\t\t<send_delay>%u</send_delay>\n",channels[curr_channel].send_delay);
				unicast_reply_write(reply, "\t\t\t<num_packets>%u</num_packets>\n",ring_buffer_num_packets);
			}
			unicast_reply_write(reply, "\t\t</scam>\n");
		}
#endif
		unicast_reply_write(reply, "\t\t<ca_sys>\n");
		for(int i=0;i<32;i++)
			if(channels[curr_channel].ca_sys_id[i]!=0)
				unicast_reply_write(reply, "\t\t\t<ca num=\"%d\"><![CDATA[%s]]></ca>\n",channels[curr_channel].ca_sys_id[i],ca_sys_id_to_str(channels[curr_channel].ca_sys_id[i]));
		unicast_reply_write(reply, "\t\t</ca_sys>\n");
		unicast_reply_write(reply, "\t\t<pids>\n");
		for(int i=0;i<channels[curr_channel].num_pids;i++)
			unicast_reply_write(reply, "\t\t\t<pid number=\"%d\" language=\"%s\" scrambled=\"%d\"><![CDATA[%s]]></pid>\n", channels[curr_channel].pids[i], channels[curr_channel].pids_language[i], channels[curr_channel].pids_scrambled[i], pid_type_to_str(channels[curr_channel].pids_type[i]));
		unicast_reply_write(reply, "\t\t</pids>\n");
		unicast_reply_write(reply, "\t</channel>\n");
	}

	// Ending XML content
	unicast_reply_write(reply, "</mumudvb>\n");

	unicast_reply_send(reply, Socket, 200, "application/xml; charset=UTF-8");

	// End of HTTP reply
	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
예제 #3
0
/** @brief Send a basic JSON file containig the list of streamed channels
 *
 * @param number_of_channels the number of channels
 * @param channels the channels array
 * @param Socket the socket on wich the information have to be sent
 */
int unicast_send_streamed_channels_list_js (int number_of_channels, mumudvb_channel_t *channels, int Socket)
{
	int curr_channel;
	unicast_client_t *unicast_client=NULL;
	int clients=0;

	struct unicast_reply* reply = unicast_reply_init();
	if (NULL == reply) {
		log_message( log_module, MSG_INFO,"Error when creating the HTTP reply\n");
		return -1;
	}

	unicast_reply_write(reply, "[");
	for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
	{
		clients=0;
		unicast_client=channels[curr_channel].clients;
		while(unicast_client!=NULL)
		{
			unicast_client=unicast_client->chan_next;
			clients++;
		}
		unicast_reply_write(reply, "{\"number\":%d, \"lcn\":%d, \"name\":\"%s\", \"sap_group\":\"%s\", \"ip_multicast\":\"%s\", \"port_multicast\":%d, \"num_clients\":%d, \"scrambling_ratio\":%d, \"is_up\":%d, \"pcr_pid\":%d, \"pmt_version\":%d, ",
				curr_channel+1,
				channels[curr_channel].logical_channel_number,
				channels[curr_channel].name,
				channels[curr_channel].sap_group,
				channels[curr_channel].ip4Out,
				channels[curr_channel].portOut,
				clients,
				channels[curr_channel].ratio_scrambled,
				channels[curr_channel].streamed_channel,
				channels[curr_channel].pcr_pid,
				channels[curr_channel].pmt_version );

		unicast_reply_write(reply, "\"unicast_port\":%d, \"service_id\":%d, \"service_type\":\"%s\", \"pids_num\":%d, \n",
				channels[curr_channel].unicast_port,
				channels[curr_channel].service_id,
				service_type_to_str(channels[curr_channel].channel_type),
				channels[curr_channel].num_pids);
		unicast_reply_write(reply, "\"pids\":[");
		for(int i=0;i<channels[curr_channel].num_pids;i++)
			unicast_reply_write(reply, "{\"number\":%d, \"type\":\"%s\", \"language\":\"%s\"},\n",
					channels[curr_channel].pids[i],
					pid_type_to_str(channels[curr_channel].pids_type[i]),
					channels[curr_channel].pids_language[i]);
		reply->used_body -= 2; // dirty hack to erase the last comma
		unicast_reply_write(reply, "]");
		unicast_reply_write(reply, "},\n");

	}
	reply->used_body -= 2; // dirty hack to erase the last comma
	unicast_reply_write(reply, "]\n");

	unicast_reply_send(reply, Socket, 200, "application/json");

	if (0 != unicast_reply_free(reply)) {
		log_message( log_module, MSG_INFO,"Error when releasing the HTTP reply after sendinf it\n");
		return -1;
	}
	return 0;
}
예제 #4
0
파일: log.c 프로젝트: mehulsbhatt/MuMuDVB
/**
 * @brief Display the list of the streamed channels
 *
 * @param number_of_channels the number of channels
 * @param channels : the channels array
 */
void log_streamed_channels(char *log_module,int number_of_channels, mumudvb_channel_t *channels, int multicast_ipv4,int multicast_ipv6, int unicast, int unicast_master_port, char *unicastipOut)
{
  int curr_channel;
  int curr_pid;

  log_message( log_module,  MSG_INFO, "Diffusion %d channel%s\n", number_of_channels,
	       (number_of_channels <= 1 ? "" : "s"));
  for (curr_channel = 0; curr_channel < number_of_channels; curr_channel++)
  {
    log_message( log_module,  MSG_INFO, "Channel number : %3d, name : \"%s\"  service id %d \n", curr_channel, channels[curr_channel].name, channels[curr_channel].service_id);
    if(multicast_ipv4)
      {
	log_message( log_module,  MSG_INFO, "\tMulticast4 ip : %s:%d\n", channels[curr_channel].ip4Out, channels[curr_channel].portOut);
      }
    if(multicast_ipv6)
      {
	log_message( log_module,  MSG_INFO, "\tMulticast6 ip : [%s]:%d\n", channels[curr_channel].ip6Out, channels[curr_channel].portOut);
      }
    if(unicast)
    {
      log_message( log_module,  MSG_INFO, "\tUnicast : Channel accessible via the master connection, %s:%d\n",unicastipOut, unicast_master_port);
      if(channels[curr_channel].unicast_port)
        log_message( log_module,  MSG_INFO, "\tUnicast : Channel accessible directly via %s:%d\n",unicastipOut, channels[curr_channel].unicast_port);
    }
    mumu_string_t string=EMPTY_STRING;
    char lang[5];
    if((Interrupted=mumu_string_append(&string, "        pids : ")))return;
    for (curr_pid = 0; curr_pid < channels[curr_channel].num_pids; curr_pid++)
    {
      strncpy(lang+1,channels[curr_channel].pids_language[curr_pid],4);
      lang[0]=(lang[1]=='-') ? '\0': ' ';
      if((Interrupted=mumu_string_append(&string, "%d (%s%s), ", channels[curr_channel].pids[curr_pid], pid_type_to_str(channels[curr_channel].pids_type[curr_pid]), lang)))
        return;
    }
    log_message( log_module, MSG_DETAIL,"%s\n",string.string);
    mumu_free_string(&string);
  }
}