예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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

}