Пример #1
0
/*****************************************************************************
 * dvbpsi_GenCATSections
 *****************************************************************************
 * Generate CAT sections based on the dvbpsi_cat_t structure.
 *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenCATSections(dvbpsi_cat_t* p_cat)
{
  dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
  dvbpsi_psi_section_t* p_current = p_result;
  dvbpsi_psi_section_t* p_prev;
  dvbpsi_descriptor_t* p_descriptor = p_cat->p_first_descriptor;

  p_current->i_table_id = 0x01;
  p_current->b_syntax_indicator = 1;
  p_current->b_private_indicator = 0;
  p_current->i_length = 9;                      /* header + CRC_32 */
  p_current->i_extension = 0;                   /* Not used in the CAT */
  p_current->i_version = p_cat->i_version;
  p_current->b_current_next = p_cat->b_current_next;
  p_current->i_number = 0;
  p_current->p_payload_end += 8;                /* just after the header */
  p_current->p_payload_start = p_current->p_data + 8;

  /* CAT descriptors */
  while(p_descriptor != NULL)
  {
    /* New section if needed */
    /* written_data_length + descriptor_length + 2 > 1024 - CRC_32_length */
    if(   (p_current->p_payload_end - p_current->p_data)
                                + p_descriptor->i_length > 1018)
    {
      p_prev = p_current;
      p_current = dvbpsi_NewPSISection(1024);
      p_prev->p_next = p_current;

      p_current->i_table_id = 0x01;
      p_current->b_syntax_indicator = 1;
      p_current->b_private_indicator = 0;
      p_current->i_length = 9;                  /* header + CRC_32 */
      p_current->i_extension = 0;               /* Not used in the CAT */
      p_current->i_version = p_cat->i_version;
      p_current->b_current_next = p_cat->b_current_next;
      p_current->i_number = p_prev->i_number + 1;
      p_current->p_payload_end += 8;            /* just after the header */
      p_current->p_payload_start = p_current->p_data + 8;
    }

    /* p_payload_end is where the descriptor begins */
    p_current->p_payload_end[0] = p_descriptor->i_tag;
    p_current->p_payload_end[1] = p_descriptor->i_length;
    memcpy(p_current->p_payload_end + 2,
           p_descriptor->p_data,
           p_descriptor->i_length);

    /* Increase length by descriptor_length + 2 */
    p_current->p_payload_end += p_descriptor->i_length + 2;
    p_current->i_length += p_descriptor->i_length + 2;

    p_descriptor = p_descriptor->p_next;
  }

  /* Finalization */
  p_prev = p_result;
  while(p_prev != NULL)
  {
    p_prev->i_last_number = p_current->i_number;
    dvbpsi_BuildPSISection(p_prev);
    p_prev = p_prev->p_next;
  }

  return p_result;
}
Пример #2
0
/*****************************************************************************
 * dvbpsi_GenPATSections
 *****************************************************************************
 * Generate PAT sections based on the dvbpsi_pat_t structure. The third
 * argument is used to limit the number of program in each section (max: 253).
 *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenPATSections(dvbpsi_pat_t* p_pat,
                                            int i_max_pps)
{
  dvbpsi_psi_section_t* p_result = dvbpsi_NewPSISection(1024);
  dvbpsi_psi_section_t* p_current = p_result;
  dvbpsi_psi_section_t* p_prev;
  dvbpsi_pat_program_t* p_program = p_pat->p_first_program;
  int i_count = 0;

  /* A PAT section can carry up to 253 programs */
  if((i_max_pps <= 0) || (i_max_pps > 253))
    i_max_pps = 253;

  p_current->i_table_id = 0;
  p_current->b_syntax_indicator = 1;
  p_current->b_private_indicator = 0;
  p_current->i_length = 9;                      /* header + CRC_32 */
  p_current->i_extension = p_pat->i_ts_id;
  p_current->i_version = p_pat->i_version;
  p_current->b_current_next = p_pat->b_current_next;
  p_current->i_number = 0;
  p_current->p_payload_end += 8;                /* just after the header */
  p_current->p_payload_start = p_current->p_payload_end;

  /* PAT programs */
  while(p_program != NULL)
  {
    /* New section if needed */
    if(++i_count > i_max_pps)
    {
      p_prev = p_current;
      p_current = dvbpsi_NewPSISection(1024);
      p_prev->p_next = p_current;
      i_count = 1;

      p_current->i_table_id = 0;
      p_current->b_syntax_indicator = 1;
      p_current->b_private_indicator = 0;
      p_current->i_length = 9;                  /* header + CRC_32 */
      p_current->i_extension = p_pat->i_ts_id;
      p_current->i_version = p_pat->i_version;
      p_current->b_current_next = p_pat->b_current_next;
      p_current->i_number = p_prev->i_number + 1;
      p_current->p_payload_end += 8;            /* just after the header */
      p_current->p_payload_start = p_current->p_payload_end;
    }

    /* p_payload_end is where the program begins */
    p_current->p_payload_end[0] = p_program->i_number >> 8;
    p_current->p_payload_end[1] = p_program->i_number;
    p_current->p_payload_end[2] = (p_program->i_pid >> 8) | 0xe0;
    p_current->p_payload_end[3] = p_program->i_pid;

    /* Increase length by 4 */
    p_current->p_payload_end += 4;
    p_current->i_length += 4;

    p_program = p_program->p_next;
  }

  /* Finalization */
  p_prev = p_result;
  while(p_prev != NULL)
  {
    p_prev->i_last_number = p_current->i_number;
    dvbpsi_BuildPSISection(p_prev);
    p_prev = p_prev->p_next;
  }

  return p_result;
}
Пример #3
0
/*****************************************************************************
 * dvbpsi_tot_sections_generate
 *****************************************************************************
 * Generate TDT/TOT sections based on the dvbpsi_tot_t structure.
 *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_tot_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_tot_t* p_tot)
{
    dvbpsi_psi_section_t* p_result;
    dvbpsi_descriptor_t* p_descriptor = p_tot->p_first_descriptor;

    /* If it has descriptors, it must be a TOT, otherwise a TDT */
    p_result = dvbpsi_NewPSISection((p_descriptor != NULL) ? 4096 : 8);

    p_result->i_table_id = (p_descriptor != NULL) ? 0x73 : 0x70;
    p_result->b_syntax_indicator = false;
    p_result->b_private_indicator = false;
    p_result->i_length = 5;
    p_result->p_payload_start = p_result->p_data + 3;
    p_result->p_payload_end = p_result->p_data + 8;

    p_result->p_data[3] = (p_tot->i_utc_time >> 32) & 0xff;
    p_result->p_data[4] = (p_tot->i_utc_time >> 24) & 0xff;
    p_result->p_data[5] = (p_tot->i_utc_time >> 16) & 0xff;
    p_result->p_data[6] = (p_tot->i_utc_time >>  8) & 0xff;
    p_result->p_data[7] =  p_tot->i_utc_time        & 0xff;

    if (p_result->i_table_id == 0x73)
    {
        /* Special handling for TOT only (A TDT doesn't have descriptors!) */
        /* Reserve two bytes for descriptors_loop_length */
        p_result->p_payload_end += 2;
        p_result->i_length += 2;

        /* TOT descriptors */
        while (p_descriptor != NULL)
        {
            /* A TOT cannot have multiple sections! */
            if(   (p_result->p_payload_end - p_result->p_data)
                                        + p_descriptor->i_length > 4090)
            {
                dvbpsi_error(p_dvbpsi, "TDT/TOT generator",
                             "TOT does not fit into one section as it ought to be !!!");
                break;
            }

            /* p_payload_end is where the descriptor begins */
            p_result->p_payload_end[0] = p_descriptor->i_tag;
            p_result->p_payload_end[1] = p_descriptor->i_length;
            memcpy(p_result->p_payload_end + 2,
                   p_descriptor->p_data,
                    p_descriptor->i_length);

            /* Increase length by descriptor_length + 2 */
            p_result->p_payload_end += p_descriptor->i_length + 2;
            p_result->i_length += p_descriptor->i_length + 2;

            p_descriptor = p_descriptor->p_next;
        }

        /* descriptors_loop_length */
        p_result->p_payload_start[5] = ((p_result->i_length - 7) << 8) | 0xf0;
        p_result->p_payload_start[6] =  (p_result->i_length - 7)       & 0xff;
    }

    /* Build the PSI section including the CRC32 on the playload.
     * NOTE: The p_payload_end pointer should point to the last byte
     * of the payload without the CRC32 field.
     */
    dvbpsi_BuildPSISection(p_dvbpsi, p_result);

    if (p_result->i_table_id == 0x73)
    {
        /* A TOT has a CRC_32 although it's a private section,
           but the CRC_32 is part of the payload! */
        p_result->p_payload_end += 4;
        p_result->i_length += 4;
    }

    if (!dvbpsi_tot_section_valid(p_dvbpsi, p_result))
    {
        dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
        dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "*  Generated TDT/TOT section is invalid.   *");
        dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "* THIS IS A BUG, PLEASE REPORT TO THE LIST *");
        dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "*  ---  [email protected]  ---  *");
        dvbpsi_error(p_dvbpsi, "TDT/TOT generator", "********************************************");
    }

    return p_result;
}
Пример #4
0
/*****************************************************************************
* dvbpsi_pat_sections_generate
*****************************************************************************
* Generate PAT sections based on the dvbpsi_pat_t structure. The third
* argument is used to limit the number of program in each section (max: 253).
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_pat_sections_generate( dvbpsi_t *p_dvbpsi,
						    dvbpsi_pat_t* p_pat, int i_max_pps )
{
	dvbpsi_psi_section_t	* p_result	= dvbpsi_NewPSISection( 1024 );
	dvbpsi_psi_section_t	* p_current	= p_result;
	dvbpsi_psi_section_t	* p_prev;
	dvbpsi_pat_program_t	* p_program	= p_pat->p_first_program;
	int			i_count		= 0;

	if ( p_current == NULL )
	{
		dvbpsi_error( p_dvbpsi, "PAT encoder", "failed to allocate new PSI section" );
		return(NULL);
	}

	/* A PAT section can carry up to 253 programs */
	if ( (i_max_pps <= 0) || (i_max_pps > 253) )
		i_max_pps = 253;

	p_current->i_table_id		= 0;
	p_current->b_syntax_indicator	= true;
	p_current->b_private_indicator	= false;
	p_current->i_length		= 9;            /* header + CRC_32 */
	p_current->i_extension		= p_pat->i_ts_id;
	p_current->i_version		= p_pat->i_version;
	p_current->b_current_next	= p_pat->b_current_next;
	p_current->i_number		= 0;
	p_current->p_payload_end	+= 8;           /* just after the header */
	p_current->p_payload_start	= p_current->p_payload_end;

	/* PAT programs */
	while ( p_program != NULL )
	{
		/* New section if needed */
		if ( ++i_count > i_max_pps )
		{
			p_prev		= p_current;
			p_current	= dvbpsi_NewPSISection( 1024 );
			if ( p_current == NULL )
			{
				dvbpsi_error( p_dvbpsi, "PAT encoder", "failed to allocate new PSI section" );
				goto error;
			}
			p_prev->p_next	= p_current;
			i_count		= 1;

			p_current->i_table_id		= 0;
			p_current->b_syntax_indicator	= true;
			p_current->b_private_indicator	= false;
			p_current->i_length		= 9;    /* header + CRC_32 */
			p_current->i_extension		= p_pat->i_ts_id;
			p_current->i_version		= p_pat->i_version;
			p_current->b_current_next	= p_pat->b_current_next;
			p_current->i_number		= p_prev->i_number + 1;
			p_current->p_payload_end	+= 8;   /* just after the header */
			p_current->p_payload_start	= p_current->p_payload_end;
		}

		/* p_payload_end is where the program begins */
		p_current->p_payload_end[0]	= p_program->i_number >> 8;
		p_current->p_payload_end[1]	= p_program->i_number;
		p_current->p_payload_end[2]	= (p_program->i_pid >> 8) | 0xe0;
		p_current->p_payload_end[3]	= p_program->i_pid;

		/* Increase length by 4 */
		p_current->p_payload_end	+= 4;
		p_current->i_length		+= 4;

		p_program = p_program->p_next;
	}

	/* Finalization */
	p_prev = p_result;
	while ( p_prev != NULL )
	{
		p_prev->i_last_number = p_current->i_number;
		dvbpsi_BuildPSISection( p_dvbpsi, p_prev );
		p_prev = p_prev->p_next;
	}

	return(p_result);

error:
	/* Cleanup on error */
	p_prev = p_result;
	dvbpsi_DeletePSISections( p_prev );
	return(NULL);
}
Пример #5
0
/*****************************************************************************
 * dvbpsi_sis_sections_generate
 *****************************************************************************
 * Generate SIS sections based on the dvbpsi_sis_t structure.
 *****************************************************************************/
dvbpsi_psi_section_t *dvbpsi_sis_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_sis_t* p_sis)
{
    dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024);

    p_current->i_table_id = 0xFC;
    p_current->b_syntax_indicator = false;
    p_current->b_private_indicator = false;
    p_current->i_length = 3;                     /* header + CRC_32 */

    /* FIXME: looks weird */
    p_current->p_payload_end += 2;               /* just after the header */
    p_current->p_payload_start = p_current->p_data + 3;

    p_current->p_data[3] = p_sis->i_protocol_version;
    p_current->p_data[4] = p_sis->b_encrypted_packet ? 0x80 : 0x0;
    /* NOTE: cannot handle encrypted packet */
    assert(p_sis->b_encrypted_packet);
    p_current->p_data[4] |= ((p_sis->i_encryption_algorithm << 1) & 0x7E);

    p_current->p_data[4] |= ((p_sis->i_pts_adjustment & 0x00800) >> 32);
    p_current->p_data[5] = (p_sis->i_pts_adjustment >> 24);
    p_current->p_data[6] = (p_sis->i_pts_adjustment >> 16);
    p_current->p_data[7] = (p_sis->i_pts_adjustment >> 8);
    p_current->p_data[8] =  p_sis->i_pts_adjustment;

    p_current->p_data[9]  = p_sis->cw_index;
    p_current->p_data[11] = 0x00;
    p_current->p_data[11]|= ((p_sis->i_splice_command_length >> 8) & 0x0F);
    p_current->p_data[12] = (uint8_t) (p_sis->i_splice_command_length & 0xFF);
    p_current->p_data[13] = p_sis->i_splice_command_type;

    uint32_t i_desc_start = 13 + p_sis->i_splice_command_length;
    if (p_sis->i_splice_command_length == 0xfff)
    {
        /* FIXME: size 0xfff of splice_command_section is undefined */
        assert(p_sis->i_splice_command_length != 0xfff);
    }

    /* FIXME: handle splice_command_sections */

    /* Service descriptors */
    p_current->p_data[i_desc_start] = (p_sis->i_descriptors_length >> 8);
    p_current->p_data[i_desc_start+1] = (uint8_t)(p_sis->i_descriptors_length & 0xFF);

    p_current->p_payload_end += (i_desc_start + 1);

    uint32_t i_desc_length = 0;

    dvbpsi_descriptor_t * p_descriptor = p_sis->p_first_descriptor;
    while ((p_descriptor != NULL) && (p_current->i_length <= 1018))
    {
        i_desc_length += p_descriptor->i_length + 2;
        p_descriptor = p_descriptor->p_next;

        /* p_payload_end is where the descriptor begins */
        p_current->p_payload_end[0] = p_descriptor->i_tag;
        p_current->p_payload_end[1] = p_descriptor->i_length;
        memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length);
        /* Increase length by descriptor_length + 2 */
        p_current->p_payload_end += p_descriptor->i_length + 2;
        p_current->i_length += p_descriptor->i_length + 2;

    }
    /* Coding error if this condition is not met */
    assert( i_desc_length == p_sis->i_descriptors_length);

    /* Finalization */
    dvbpsi_BuildPSISection(p_dvbpsi, p_current);
    return p_current;
}