Example #1
0
/*****************************************************************************
 * dvbpsi_GenNITSections
 *****************************************************************************
 * Generate NIT sections based on the dvbpsi_nit_t structure.
 *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenNITSections(dvbpsi_nit_t* p_nit,
                                            uint8_t i_table_id)
{
  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_nit->p_first_descriptor;
  dvbpsi_nit_ts_t* p_ts = p_nit->p_first_ts;
  uint16_t i_network_descriptors_length, i_transport_stream_loop_length;
  uint8_t * p_transport_stream_loop_length;

  p_current->i_table_id = i_table_id;
  p_current->b_syntax_indicator = 1;
  p_current->b_private_indicator = 0;
  p_current->i_length = 13;                     /* including CRC_32 */
  p_current->i_extension = p_nit->i_network_id;
  p_current->i_version = p_nit->i_version;
  p_current->b_current_next = p_nit->b_current_next;
  p_current->i_number = 0;
  p_current->p_payload_end += 10;
  p_current->p_payload_start = p_current->p_data + 8;

  /* NIT 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)
    {
      /* network_descriptors_length */
      i_network_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
      p_current->p_data[8] = (i_network_descriptors_length >> 8) | 0xf0;
      p_current->p_data[9] = i_network_descriptors_length;

      /* transport_stream_loop_length */
      p_current->p_payload_end[0] = 0;
      p_current->p_payload_end[1] = 0;
      p_current->p_payload_end += 2;

      p_prev = p_current;
      p_current = dvbpsi_NewPSISection(1024);
      p_prev->p_next = p_current;

      p_current->i_table_id = i_table_id;
      p_current->b_syntax_indicator = 1;
      p_current->b_private_indicator = 0;
      p_current->i_length = 13;                 /* including CRC_32 */
      p_current->i_extension = p_nit->i_network_id;
      p_current->i_version = p_nit->i_version;
      p_current->b_current_next = p_nit->b_current_next;
      p_current->i_number = p_prev->i_number + 1;
      p_current->p_payload_end += 10;
      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;
  }
Example #2
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;
}
Example #3
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;
}
Example #4
0
/*****************************************************************************
 * dvbpsi_packet_push
 *****************************************************************************
 * Injection of a TS packet into a PSI decoder.
 *****************************************************************************/
bool dvbpsi_packet_push(dvbpsi_t *p_dvbpsi, uint8_t* p_data)
{
    uint8_t i_expected_counter;           /* Expected continuity counter */
    dvbpsi_psi_section_t* p_section;      /* Current section */
    uint8_t* p_payload_pos;               /* Where in the TS packet */
    uint8_t* p_new_pos = NULL;            /* Beginning of the new section,
                                             updated to NULL when the new
                                             section is handled */
    int i_available;                      /* Byte count available in the
                                             packet */

    dvbpsi_decoder_t *p_decoder = p_dvbpsi->p_decoder;
    assert(p_decoder);

    /* TS start code */
    if (p_data[0] != 0x47)
    {
        dvbpsi_error(p_dvbpsi, "PSI decoder", "not a TS packet");
        return false;
    }

    /* Continuity check */
    bool b_first = (p_decoder->i_continuity_counter == DVBPSI_INVALID_CC);
    if (b_first)
        p_decoder->i_continuity_counter = p_data[3] & 0xf;
    else
    {
        i_expected_counter = (p_decoder->i_continuity_counter + 1) & 0xf;
        p_decoder->i_continuity_counter = p_data[3] & 0xf;

        if (i_expected_counter == ((p_decoder->i_continuity_counter + 1) & 0xf)
            && !p_decoder->b_discontinuity)
        {
            dvbpsi_error(p_dvbpsi, "PSI decoder",
                     "TS duplicate (received %d, expected %d) for PID %d",
                     p_decoder->i_continuity_counter, i_expected_counter,
                     ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
            return false;
        }

        if (i_expected_counter != p_decoder->i_continuity_counter)
        {
            dvbpsi_error(p_dvbpsi, "PSI decoder",
                     "TS discontinuity (received %d, expected %d) for PID %d",
                     p_decoder->i_continuity_counter, i_expected_counter,
                     ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
            p_decoder->b_discontinuity = true;
            if (p_decoder->p_current_section)
            {
                dvbpsi_DeletePSISections(p_decoder->p_current_section);
                p_decoder->p_current_section = NULL;
            }
        }
    }

    /* Return if no payload in the TS packet */
    if (!(p_data[3] & 0x10))
        return false;

    /* Skip the adaptation_field if present */
    if (p_data[3] & 0x20)
        p_payload_pos = p_data + 5 + p_data[4];
    else
        p_payload_pos = p_data + 4;

    /* Unit start -> skip the pointer_field and a new section begins */
    if (p_data[1] & 0x40)
    {
        p_new_pos = p_payload_pos + *p_payload_pos + 1;
        p_payload_pos += 1;
    }

    p_section = p_decoder->p_current_section;

    /* If the psi decoder needs a beginning of a section and a new section
       begins in the packet then initialize the dvbpsi_psi_section_t structure */
    if (p_section == NULL)
    {
        if (p_new_pos)
        {
            /* Allocation of the structure */
            p_decoder->p_current_section
                        = p_section
                        = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
            if (!p_section)
                return false;
            /* Update the position in the packet */
            p_payload_pos = p_new_pos;
            /* New section is being handled */
            p_new_pos = NULL;
            /* Just need the header to know how long is the section */
            p_decoder->i_need = 3;
            p_decoder->b_complete_header = false;
        }
        else
        {
            /* No new section => return */
            return false;
        }
    }

    /* Remaining bytes in the payload */
    i_available = 188 + p_data - p_payload_pos;

    while (i_available > 0)
    {
        if (i_available >= p_decoder->i_need)
        {
            /* There are enough bytes in this packet to complete the
               header/section */
            memcpy(p_section->p_payload_end, p_payload_pos, p_decoder->i_need);
            p_payload_pos += p_decoder->i_need;
            p_section->p_payload_end += p_decoder->i_need;
            i_available -= p_decoder->i_need;

            if (!p_decoder->b_complete_header)
            {
                /* Header is complete */
                p_decoder->b_complete_header = true;
                /* Compute p_section->i_length and update p_decoder->i_need */
                p_decoder->i_need = p_section->i_length
                                  = ((uint16_t)(p_section->p_data[1] & 0xf)) << 8
                                       | p_section->p_data[2];
                /* Check that the section isn't too long */
                if (p_decoder->i_need > p_decoder->i_section_max_size - 3)
                {
                    dvbpsi_error(p_dvbpsi, "PSI decoder", "PSI section too long");
                    dvbpsi_DeletePSISections(p_section);
                    p_decoder->p_current_section = NULL;
                    /* If there is a new section not being handled then go forward
                       in the packet */
                    if (p_new_pos)
                    {
                        p_decoder->p_current_section
                                    = p_section
                                    = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
                        if (!p_section)
                            return false;
                        p_payload_pos = p_new_pos;
                        p_new_pos = NULL;
                        p_decoder->i_need = 3;
                        p_decoder->b_complete_header = false;
                        i_available = 188 + p_data - p_payload_pos;
                    }
                    else
                    {
                        i_available = 0;
                    }
                }
            }
            else
            {
                bool b_valid_crc32 = false;
                bool has_crc32;

                /* PSI section is complete */
                p_section->i_table_id = p_section->p_data[0];
                p_section->b_syntax_indicator = p_section->p_data[1] & 0x80;
                p_section->b_private_indicator = p_section->p_data[1] & 0x40;

                /* Update the end of the payload if CRC_32 is present */
                has_crc32 = dvbpsi_has_CRC32(p_section);
                if (p_section->b_syntax_indicator || has_crc32)
                    p_section->p_payload_end -= 4;

                /* Check CRC32 if present */
                if (has_crc32)
                    b_valid_crc32 = dvbpsi_ValidPSISection(p_section);

                if (!has_crc32 || b_valid_crc32)
                {
                    /* PSI section is valid */
                    if (p_section->b_syntax_indicator)
                    {
                        p_section->i_extension =  (p_section->p_data[3] << 8)
                                                 | p_section->p_data[4];
                        p_section->i_version = (p_section->p_data[5] & 0x3e) >> 1;
                        p_section->b_current_next = p_section->p_data[5] & 0x1;
                        p_section->i_number = p_section->p_data[6];
                        p_section->i_last_number = p_section->p_data[7];
                        p_section->p_payload_start = p_section->p_data + 8;
                    }
                    else
                    {
                        p_section->i_extension = 0;
                        p_section->i_version = 0;
                        p_section->b_current_next = true;
                        p_section->i_number = 0;
                        p_section->i_last_number = 0;
                        p_section->p_payload_start = p_section->p_data + 3;
                    }
                    if (p_decoder->pf_gather)
                        p_decoder->pf_gather(p_dvbpsi, p_section);
                    p_decoder->p_current_section = NULL;
                }
                else
                {
                    if (has_crc32 && !dvbpsi_ValidPSISection(p_section))
Example #5
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);
}
Example #6
0
/*****************************************************************************
* dvbpsi_pmt_sections_generate
*****************************************************************************
* Generate PMT sections based on the dvbpsi_pmt_t structure.
*****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_pmt_sections_generate( dvbpsi_t *p_dvbpsi, dvbpsi_pmt_t* p_pmt )
{
	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_pmt->p_first_descriptor;
	dvbpsi_pmt_es_t		* p_es		= p_pmt->p_first_es;
	uint16_t		i_info_length;

	

	p_current->i_table_id		= 0x02;
	p_current->b_syntax_indicator	= true;
	p_current->b_private_indicator	= false;
	p_current->i_length		= 13;           /* header + CRC_32 */
	p_current->i_extension		= p_pmt->i_program_number;
	p_current->i_version		= p_pmt->i_version;
	p_current->b_current_next	= p_pmt->b_current_next;
	p_current->i_number		= 0;
	p_current->p_payload_end	+= 12;          /* just after the header */
	p_current->p_payload_start	= p_current->p_data + 8;

	/* PCR_PID */
	p_current->p_data[8]	= (p_pmt->i_pcr_pid >> 8) | 0xe0;
	p_current->p_data[9]	= p_pmt->i_pcr_pid;

	/* PMT 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 )
		{
			/* program_info_length */
			i_info_length		= (p_current->p_payload_end - p_current->p_data) - 12;
			p_current->p_data[10]	= (i_info_length >> 8) | 0xf0;
			p_current->p_data[11]	= i_info_length;

			p_prev		= p_current;
			p_current	= dvbpsi_NewPSISection( 1024 );
			p_prev->p_next	= p_current;

			p_current->i_table_id		= 0x02;
			p_current->b_syntax_indicator	= true;
			p_current->b_private_indicator	= false;
			p_current->i_length		= 13;   /* header + CRC_32 */
			p_current->i_extension		= p_pmt->i_program_number;
			p_current->i_version		= p_pmt->i_version;
			p_current->b_current_next	= p_pmt->b_current_next;
			p_current->i_number		= p_prev->i_number + 1;
			p_current->p_payload_end	+= 12;  /* just after the header */
			p_current->p_payload_start	= p_current->p_data + 8;

			/* PCR_PID */
			p_current->p_data[8]	= (p_pmt->i_pcr_pid >> 8) | 0xe0;
			p_current->p_data[9]	= p_pmt->i_pcr_pid;
		}

		/* 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;
	}
Example #7
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;
}
Example #8
0
/*****************************************************************************
 * dvbpsi_GenBATSections
 *****************************************************************************
 * Generate BAT sections based on the dvbpsi_bat_t structure.
 * similar to dvbpsi_GenNITSections
 *****************************************************************************/
dvbpsi_psi_section_t* dvbpsi_GenBATSections(dvbpsi_t *p_dvbpsi, dvbpsi_bat_t* p_bat)
{
    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_bat->p_first_descriptor;
    dvbpsi_bat_ts_t* p_ts = p_bat->p_first_ts;
    uint16_t i_bouquet_descriptors_length, i_transport_stream_loop_length;
    uint8_t * p_transport_stream_loop_length;

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

    p_current->i_table_id = 0x4a;
    p_current->b_syntax_indicator = true;
    p_current->b_private_indicator = true;
    p_current->i_length = 13;                     /* including CRC_32 */
    p_current->i_extension = p_bat->i_bouquet_id;
    p_current->i_version = p_bat->i_version;
    p_current->b_current_next = p_bat->b_current_next;
    p_current->i_number = 0;
    p_current->p_payload_end += 10;
    p_current->p_payload_start = p_current->p_data + 8;

    /* first loop 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)
        {
            /* bouquet_descriptors_length */
            i_bouquet_descriptors_length = (p_current->p_payload_end - p_current->p_payload_start) - 2;
            p_current->p_data[8] = (i_bouquet_descriptors_length >> 8) | 0xf0;
            p_current->p_data[9] = i_bouquet_descriptors_length;

            /* transport_stream_loop_length */
            p_current->p_payload_end[0] = 0;
            p_current->p_payload_end[1] = 0;
            p_current->p_payload_end += 2;

            p_prev = p_current;
            p_current = dvbpsi_NewPSISection(1024);
            if (p_current ==  NULL)
            {
                dvbpsi_error(p_dvbpsi, "BAT encoder", "failed to allocate new PSI section");
                goto error;
            }
            p_prev->p_next = p_current;

            p_current->i_table_id = 0x4a;
            p_current->b_syntax_indicator = true;
            p_current->b_private_indicator = true;
            p_current->i_length = 13;                 /* including CRC_32 */
            p_current->i_extension = p_bat->i_bouquet_id;
            p_current->i_version = p_bat->i_version;
            p_current->b_current_next = p_bat->b_current_next;
            p_current->i_number = p_prev->i_number + 1;
            p_current->p_payload_end += 10;
            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;
    }
Example #9
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;
}