struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *psip) { uint8_t * buf = (uint8_t *) psip; size_t pos = 0; size_t len = section_ext_length(&(psip->ext_head)); int idx; if (len < sizeof(struct atsc_eit_section)) return NULL; struct atsc_eit_section *eit = (struct atsc_eit_section *) psip; pos += sizeof(struct atsc_eit_section); for(idx =0; idx < eit->num_events_in_section; idx++) { if (len < (pos + sizeof(struct atsc_eit_event))) return NULL; struct atsc_eit_event *event = (struct atsc_eit_event *) (buf+pos); bswap16(buf+pos); bswap32(buf+pos+2); bswap32(buf+pos+6); pos += sizeof(struct atsc_eit_event); if (len < (pos + event->title_length)) return NULL; if (atsc_text_validate(buf+pos, event->title_length)) return NULL; pos += event->title_length; if (len < (pos + sizeof(struct atsc_eit_event_part2))) return NULL; struct atsc_eit_event_part2 *part2 = (struct atsc_eit_event_part2 *) (buf+pos); bswap16(buf+pos); pos += sizeof(struct atsc_eit_event_part2); if (len < (pos + part2->descriptors_length)) return NULL; if (verify_descriptors(buf + pos, part2->descriptors_length)) return NULL; pos += part2->descriptors_length; } if (pos != len) return NULL; return (struct atsc_eit_section *) psip; }
struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *psip) { uint8_t * buf = (uint8_t *) psip; size_t pos = sizeof(struct atsc_section_psip); size_t len = section_ext_length(&(psip->ext_head)); if (len < sizeof(struct atsc_ett_section)) return NULL; bswap32(buf + pos); pos += 4; if (atsc_text_validate(buf + pos, section_ext_length(&psip->ext_head) - sizeof(struct atsc_ett_section))) return NULL; return (struct atsc_ett_section *) psip; }
struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *psip) { uint8_t * buf = (uint8_t *) psip; size_t pos = 0; size_t len = section_ext_length(&(psip->ext_head)); int idx; if (len < sizeof(struct atsc_dccsct_section)) return NULL; struct atsc_dccsct_section *dccsct = (struct atsc_dccsct_section *) psip; pos += sizeof(struct atsc_dccsct_section); for(idx =0; idx < dccsct->updates_defined; idx++) { if (len < (pos + sizeof(struct atsc_dccsct_update))) return NULL; struct atsc_dccsct_update *update = (struct atsc_dccsct_update *) (buf+pos); pos += sizeof(struct atsc_dccsct_update); if (len < (pos + update->update_data_length)) return NULL; switch(update->update_type) { case ATSC_DCCST_UPDATE_NEW_GENRE: { int sublen = sizeof(struct atsc_dccsct_update_new_genre); if (update->update_data_length < sublen) return NULL; if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) return NULL; break; } case ATSC_DCCST_UPDATE_NEW_STATE: { int sublen = sizeof(struct atsc_dccsct_update_new_state); if (update->update_data_length < sublen) return NULL; if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) return NULL; break; } case ATSC_DCCST_UPDATE_NEW_COUNTY: { int sublen = sizeof(struct atsc_dccsct_update_new_county); if (update->update_data_length < sublen) return NULL; bswap16(buf+pos+1); if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen)) return NULL; break; } } pos += update->update_data_length; if (len < (pos + sizeof(struct atsc_dccsct_update_part2))) return NULL; struct atsc_dccsct_update_part2 *part2 = (struct atsc_dccsct_update_part2 *) buf + pos; bswap16(buf+pos); pos += sizeof(struct atsc_dccsct_update_part2); if (len < (pos + part2->descriptors_length)) return NULL; if (verify_descriptors(buf + pos, part2->descriptors_length)) return NULL; pos += part2->descriptors_length; } if (len < (pos + sizeof(struct atsc_dccsct_section_part2))) return NULL; struct atsc_dccsct_section_part2 *part2 = (struct atsc_dccsct_section_part2 *) (buf+pos); bswap16(buf+pos); pos += sizeof(struct atsc_dccsct_section_part2); if (len < (pos + part2->descriptors_length)) return NULL; if (verify_descriptors(buf + pos, part2->descriptors_length)) return NULL; pos += part2->descriptors_length; if (pos != len) return NULL; return (struct atsc_dccsct_section *) psip; }
int autoconf_parse_vct_channel(unsigned char *buf, autoconf_parameters_t *parameters) { psip_vct_channel_t *vct_channel; char unconverted_short_name[15];//2*7 + 1 (for '\0') #ifdef HAVE_ICONV char *inbuf, *dest; //Pointers for iconv conversion #endif char utf8_short_name[15]; char *channel_name=NULL; char long_name[MAX_NAME_LEN]; int mpeg2_service_type=0; vct_channel=(psip_vct_channel_t *)buf; long_name[0]='\0'; mumudvb_service_t *new_service=NULL; // *********** We get the channel short name ******************* memcpy (unconverted_short_name, vct_channel->short_name, 14*sizeof(uint8_t)); unconverted_short_name[14] = '\0'; #ifdef HAVE_ICONV //Conversion to utf8 of the short name iconv_t cd; //we open the conversion table cd = iconv_open( "UTF8", "UTF-16BE" ); log_message( log_module, MSG_DEBUG,"We use big Endian UTF16 as source for channel name, if it give weird characters please contact\n"); size_t inSize, outSize=14; inSize=14; //pointers initialisation dest=utf8_short_name; inbuf=unconverted_short_name; //conversion iconv(cd, &inbuf, &inSize, &dest, &outSize ); *dest = '\0'; iconv_close( cd ); #else log_message( log_module, MSG_DETAIL, "Iconv not present, no name encoding conversion the reseult will be probably bad\n"); memcpy (utf8_short_name, vct_channel->short_name, 14*sizeof(uint8_t)); utf8_short_name[14] = '\0'; #endif log_message( log_module, MSG_DEBUG, "\tchannel short_name : \"%s\"\n", utf8_short_name); //************ We skip "ininteresting" channels **************** if(vct_channel->modulation_mode==0x01) { log_message( log_module, MSG_DEBUG, "\tAnalog channel, we skip\n"); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } if(HILO(vct_channel->channel_tsid)!=parameters->transport_stream_id) { log_message( log_module, MSG_DEBUG,"Channel for another transponder, we skip : Channel TSID 0x%x , PAT TSID 0x%x\n", HILO(vct_channel->channel_tsid), parameters->transport_stream_id); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } if(vct_channel->hidden) { log_message( log_module, MSG_DEBUG,"This channel is supposed to be hidden, we skip. Please contact if you want to bypass\n"); return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length } //We "convert" ATSC service type to the "equivalent" MPEG2 service type switch(vct_channel->service_type) { case 0x02://ATSC_digital_television — The virtual channel carries television programming (audio, video and //optional associated data) conforming to ATSC standards mpeg2_service_type=0x01; //service_type "digital television service" (0x01) log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_digital_television\n"); break; case 0x03://ATSC_audio — The virtual channel carries audio programming (audio service and optional //associated data) conforming to ATSC standards. mpeg2_service_type=0x02;//service_type digital radio sound service (0x02) log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_audio\n",vct_channel->service_type); break; case 0x04://ATSC_data_only_service — The virtual channel carries a data service conforming to ATSC //standards, but no video of stream_type 0x02 or audio of stream_type 0x81. mpeg2_service_type=0x0c;//service_type data broadcast service log_message( log_module, MSG_DEBUG,"vct_channel->service_type ATSC_data_only_service\n",vct_channel->service_type); break; default: log_message( log_module, MSG_DEBUG,"Unknown vct_channel->service_type 0x%02x\n",vct_channel->service_type); break; } #ifdef HAVE_LIBUCSI //used to decompress the atsc_text_descriptor int descriptor_delta; uint8_t *dest8=NULL; //Pointer for libusci conversion size_t destbufsize=MAX_NAME_LEN; size_t destbufpos=0; int descriptor_len; int atsc_decode_out; int delta_multiple_string_structure; //the beginning of tmultiple string structure //We loop on the different descriptors to find the long channel name for(descriptor_delta=0;descriptor_delta<HILO(vct_channel->descriptor_length);) { descriptor_len=buf[PSIP_VCT_LEN+descriptor_delta+1]; if(buf[PSIP_VCT_LEN+descriptor_delta]==0xA0) //Extended channel name descriptor { log_message( log_module, MSG_DEBUG, "Extended channel name descriptor, we try to decode long channel name\n"); dest8=(uint8_t *)long_name; //same type size, just the sign change but we don't care //check delta_multiple_string_structure=PSIP_VCT_LEN+descriptor_delta+2;//+2 to skip descriptor tag and descriptor len if (atsc_text_validate(((uint8_t*)(buf + delta_multiple_string_structure) ), buf[PSIP_VCT_LEN+descriptor_delta+1])) { log_message( log_module, MSG_DEBUG, "Error when VALIDATING long channel name, we take the short one\n"); } else { //If we have multiple strings for the channel name we ask people to report if(buf[delta_multiple_string_structure]!=1 || buf[delta_multiple_string_structure+1+3] !=1) { log_message( log_module, MSG_WARN, "!!!!! Please report : parsing of long name : number strings : %d number segments : %d\n", buf[delta_multiple_string_structure], buf[delta_multiple_string_structure+1+3]); } //Since it's only the channel name, we don't loop over strings and segments //We decode the text using LIBUCSI atsc_decode_out=atsc_text_segment_decode((struct atsc_text_string_segment *) (buf +delta_multiple_string_structure + MULTIPLE_STRING_STRUCTURE_HEADER), &dest8, &destbufsize, &destbufpos); if(atsc_decode_out!=-1) //No errors { dest8[atsc_decode_out]='\0'; //We take the long one log_message( log_module, MSG_DEBUG, "Decoded long channel name : \"%s\"\n",dest8); channel_name=long_name; } else log_message( log_module, MSG_DEBUG, "Error when decoding long channel name, we take the short one\n"); } } //Take the short name if error if(!channel_name) channel_name=utf8_short_name; //Next descriptor descriptor_delta+=descriptor_len+2;//We add the descriptor_len +2 for descriptor tag and descriptor len } #else //We don't use libusci, we don't try to get long channel name channel_name=utf8_short_name; #endif //************** We add this channel to the list of services ***************** //we search if we already have service id new_service=autoconf_find_service_for_add(parameters->services,HILO(vct_channel->program_number)); //The service id IS the program number if(new_service) { log_message( log_module, MSG_DETAIL, "Adding new channel %s to the list of services , program number : 0x%x \n", channel_name, HILO(vct_channel->program_number)); //we store the data new_service->id=HILO(vct_channel->program_number); new_service->running_status=0; new_service->type=mpeg2_service_type; new_service->free_ca_mode=vct_channel->access_controlled; log_message( log_module, MSG_DEBUG, "access_controlled : 0x%x\n", new_service->free_ca_mode); memcpy (new_service->name, channel_name, strlen(channel_name)); new_service->name[strlen(channel_name)] = '\0'; } //**************** Work done for this channel -- goodbye ********************* return PSIP_VCT_LEN + HILO(vct_channel->descriptor_length); //We return the length }