/** @brief Parse the service descriptor * It's used to get the channel name * @param buf the buffer containing the descriptor * @param service the associated service */ void parse_service_descriptor(unsigned char *buf, mumudvb_service_t *service) { /* Service descriptor : descriptor_tag 8 descriptor_length 8 service_type 8 service_provider_name_length 8 for (i=0;i<N;I++){ char 8 } service_name_length 8 for (i=0;i<N;I++){ Char 8 } */ int len; int encoding_control_char; buf += 2; if(service) service->type=*buf; //We show the service type display_service_type(*buf, MSG_DEBUG,log_module); buf ++; //we skip the service_type len = *buf; //provider name len //we jump the provider_name + the provider_name_len buf += len + 1; //Channel name len len = *buf; buf++; //we jump the channel_name_len char *name; char tempbuf[MAX_NAME_LEN]; if(service) name=service->name; else name=tempbuf; //We store the channel name with the raw encoding memcpy (name, buf, len); name[len] = '\0'; encoding_control_char=convert_en300468_string(name,MAX_NAME_LEN); if(encoding_control_char==-1) return; log_message( log_module, MSG_DEBUG, "service_name : \"%s\" (name encoding : %s)\n", name,encodings_en300468[encoding_control_char]); }
/** @brief Convert the chained list of services into channels * * This function is called when We've got all the services, we now fill the channels structure * After that we go in AUTOCONF_MODE_PIDS to get audio and video pids * @param parameters The autoconf parameters * @param channels Chained list of channels * @param port The mulicast port * @param card The card number for the ip address * @param unicast_vars The unicast parameters * @param fds The file descriptors (for filters and unicast) */ int autoconf_services_to_channels(autoconf_parameters_t parameters, mumudvb_channel_t *channels, int port, int card, int tuner, unicast_parameters_t *unicast_vars, multicast_parameters_t *multicast_vars, int server_id) { mumudvb_service_t *actual_service; int channel_number=0; int found_in_service_id_list; int unicast_port_per_channel; char tempstring[256]; actual_service=parameters.services; unicast_port_per_channel=strlen(parameters.autoconf_unicast_port)?1:0; do { if(parameters.autoconf_scrambled && actual_service->free_ca_mode) log_message( log_module, MSG_DETAIL,"Service scrambled. Name \"%s\"\n", actual_service->name); //If there is a service_id list we look if we find it (option autoconf_sid_list) if(parameters.num_service_id) { int actual_service_id; found_in_service_id_list=0; for(actual_service_id=0;actual_service_id<parameters.num_service_id && !found_in_service_id_list;actual_service_id++) { if(parameters.service_id_list[actual_service_id]==actual_service->id) { found_in_service_id_list=1; log_message( log_module, MSG_DEBUG,"Service found in the service_id list. Name \"%s\"\n", actual_service->name); } } } else //No ts id list so it is found found_in_service_id_list=1; if(!parameters.autoconf_scrambled && actual_service->free_ca_mode) log_message( log_module, MSG_DETAIL,"Service scrambled, no CAM support and no autoconf_scrambled, we skip. Name \"%s\"\n", actual_service->name); else if(!actual_service->pmt_pid) log_message( log_module, MSG_DETAIL,"Service without a PMT pid, we skip. Name \"%s\"\n", actual_service->name); else if(!found_in_service_id_list) log_message( log_module, MSG_DETAIL,"Service NOT in the service_id list, we skip. Name \"%s\", id %d\n", actual_service->name, actual_service->id); else //service is ok, we make it a channel { //Cf EN 300 468 v1.9.1 Table 81 if((actual_service->type==0x01|| actual_service->type==0x11|| actual_service->type==0x16|| actual_service->type==0x19)|| ((actual_service->type==0x02|| actual_service->type==0x0a)&¶meters.autoconf_radios)) { log_message( log_module, MSG_DETAIL,"We convert a new service into a channel, sid %d pmt_pid %d name \"%s\" \n", actual_service->id, actual_service->pmt_pid, actual_service->name); display_service_type(actual_service->type, MSG_DETAIL, log_module); channels[channel_number].channel_type=actual_service->type; channels[channel_number].num_packet = 0; channels[channel_number].num_scrambled_packets = 0; channels[channel_number].scrambled_channel = 0; channels[channel_number].streamed_channel = 1; channels[channel_number].nb_bytes=0; channels[channel_number].pids[0]=actual_service->pmt_pid; channels[channel_number].pids_type[0]=PID_PMT; channels[channel_number].num_pids=1; snprintf(channels[channel_number].pids_language[0],4,"%s","---"); if(strlen(parameters.name_template)) { strcpy(channels[channel_number].name,parameters.name_template); int len=MAX_NAME_LEN; char number[10]; mumu_string_replace(channels[channel_number].name,&len,0,"%name",actual_service->name); sprintf(number,"%d",channel_number+1); mumu_string_replace(channels[channel_number].name,&len,0,"%number",number); //put LCN here } else strcpy(channels[channel_number].name,actual_service->name); if(multicast_vars->multicast) { char number[10]; char ip[80]; int len=80; if(strlen(parameters.autoconf_multicast_port)) { strcpy(tempstring,parameters.autoconf_multicast_port); sprintf(number,"%d",channel_number); mumu_string_replace(tempstring,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(tempstring,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(tempstring,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(tempstring,&len,0,"%server",number); channels[channel_number].portOut=string_comput(tempstring); } else { channels[channel_number].portOut=port;//do here the job for evaluating the string } if(multicast_vars->multicast_ipv4) { strcpy(ip,parameters.autoconf_ip4); sprintf(number,"%d",channel_number); mumu_string_replace(ip,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(ip,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(ip,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(ip,&len,0,"%server",number); strcpy(channels[channel_number].ip4Out,ip); log_message( log_module, MSG_DEBUG,"Channel IPv4 : \"%s\" port : %d\n",channels[channel_number].ip4Out,channels[channel_number].portOut); } if(multicast_vars->multicast_ipv6) { strcpy(ip,parameters.autoconf_ip6); sprintf(number,"%d",channel_number); mumu_string_replace(ip,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(ip,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(ip,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(ip,&len,0,"%server",number); strcpy(channels[channel_number].ip6Out,ip); log_message( log_module, MSG_DEBUG,"Channel IPv6 : \"%s\" port : %d\n",channels[channel_number].ip6Out,channels[channel_number].portOut); } } //This is a scrambled channel, we will have to ask the cam for descrambling it if(parameters.autoconf_scrambled && actual_service->free_ca_mode) channels[channel_number].need_cam_ask=CAM_NEED_ASK; //We store the PMT and the service id in the channel channels[channel_number].pmt_pid=actual_service->pmt_pid; channels[channel_number].service_id=actual_service->id; init_rtp_header(&channels[channel_number]); //We init the rtp header in all cases if(channels[channel_number].pmt_packet==NULL) { channels[channel_number].pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(channels[channel_number].pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); Interrupted=ERROR_MEMORY<<8; return -1; } memset (channels[channel_number].pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&channels[channel_number].pmt_packet->packetmutex,NULL); } #ifdef ENABLE_CAM_SUPPORT //We allocate the packet for storing the PMT for CAM purposes if(channels[channel_number].cam_pmt_packet==NULL) { channels[channel_number].cam_pmt_packet=malloc(sizeof(mumudvb_ts_packet_t)); if(channels[channel_number].cam_pmt_packet==NULL) { log_message( log_module, MSG_ERROR,"Problem with malloc : %s file : %s line %d\n",strerror(errno),__FILE__,__LINE__); Interrupted=ERROR_MEMORY<<8; return -1; } memset (channels[channel_number].cam_pmt_packet, 0, sizeof( mumudvb_ts_packet_t));//we clear it pthread_mutex_init(&channels[channel_number].cam_pmt_packet->packetmutex,NULL); } #endif //We update the unicast port, the connection will be created in autoconf_finish_full if(unicast_port_per_channel && unicast_vars->unicast) { strcpy(tempstring,parameters.autoconf_unicast_port); int len;len=256; char number[10]; sprintf(number,"%d",channel_number); mumu_string_replace(tempstring,&len,0,"%number",number); sprintf(number,"%d",card); mumu_string_replace(tempstring,&len,0,"%card",number); sprintf(number,"%d",tuner); mumu_string_replace(tempstring,&len,0,"%tuner",number); sprintf(number,"%d",server_id); mumu_string_replace(tempstring,&len,0,"%server",number); channels[channel_number].unicast_port=string_comput(tempstring); log_message( log_module, MSG_DEBUG,"Channel (direct) unicast port %d\n",channels[channel_number].unicast_port); } #ifdef ENABLE_TRANSCODING //We copy the common transcode options to the new channel transcode_copy_options(&global_transcode_opt,&channels[channel_number].transcode_options); transcode_options_apply_templates(&channels[channel_number].transcode_options,card,tuner,server_id,channel_number); #endif channel_number++; } else if(actual_service->type==0x02||actual_service->type==0x0a) //service_type digital radio sound service log_message( log_module, MSG_DETAIL,"Service type digital radio sound service, no autoconfigure. (if you want add autoconf_radios=1 to your configuration file) Name \"%s\"\n",actual_service->name); else if(actual_service->type!=0) //0 is an empty service { //We show the service type log_message( log_module, MSG_DETAIL,"No autoconfigure due to service type : %s. Name \"%s\"\n",service_type_to_str(actual_service->type),actual_service->name); } } actual_service=actual_service->next; } while(actual_service && channel_number<MAX_CHANNELS); if(channel_number==MAX_CHANNELS) log_message( log_module, MSG_WARN,"Warning : We reached the maximum channel number, we drop other possible channels !\n"); return channel_number; }