[libdvbpsi-devel] NIT and BAT tables bugs

Angelo Schiavone angelo.schiavone at gmail.com
Tue Jan 22 16:13:16 CET 2013


Hi, my name is Angelo Schiavone and I'm a developer working
on a dvb transport stream analyzer which uses libdvbpsi version 1.0.0
library.
First of all thanks a lot for sharing your efforts.
I've noticed that there are 2 bugs in decoding BAT and NIT
tables, according to ETSI EN 300 468 standard, which makes tables decoding
wrong.

In BAT.c file ->  "dvbpsi_bat_sections_decode" function is :

void dvbpsi_bat_sections_decode(dvbpsi_bat_t* p_bat,

                              dvbpsi_psi_section_t* p_section)

{

  uint8_t* p_byte, * p_end, * p_end2;

  while(p_section)

  {

    /* - first loop descriptors */

    p_byte = p_section->p_payload_start + 2;

    p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[0] & 0x0f) << 8)

                       | p_section->p_payload_start[1]);

    while(p_byte + 2 <= p_end)

    {

      uint8_t i_tag = p_byte[0];

      uint8_t i_length = p_byte[1];

      if(i_length + 2 <= p_end - p_byte)

        dvbpsi_bat_bouquet_descriptor_add(p_bat, i_tag, i_length, p_byte + 2);

      p_byte += 2 + i_length;

    }

    p_end = p_byte + ( ((uint16_t)(p_byte[0] & 0x0f) << 8)

                       | p_byte[1]);

    if(p_end > p_section->p_payload_end)

    {

        p_end = p_section->p_payload_end;

    }

    /* - TSs */

    for(; p_byte + 6 <= p_end;)

    {

      p_byte += 2;

      uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];

      uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];

      uint16_t i_transport_descriptors_length = ((uint16_t)(p_byte[4]
& 0x0f) << 8) | p_byte[5];

      dvbpsi_bat_ts_t* p_ts = dvbpsi_bat_ts_add(p_bat, i_ts_id,
i_orig_network_id);

      /* - TS descriptors */

      p_byte += 6;

      p_end2 = p_byte + i_transport_descriptors_length;

      if( p_end2 > p_section->p_payload_end )

      {

            p_end2 = p_section->p_payload_end;

      }

      while(p_byte + 2 <= p_end2)

      {

        uint8_t i_tag = p_byte[0];

        uint8_t i_length = p_byte[1];

        if(i_length + 2 <= p_end2 - p_byte)

          dvbpsi_bat_ts_descriptor_add(p_ts, i_tag, i_length, p_byte + 2);

        p_byte += 2 + i_length;

      }

    }

    p_section = p_section->p_next;

  }

}




while it should be:

void dvbpsi_bat_sections_decode(dvbpsi_bat_t* p_bat,

                              dvbpsi_psi_section_t* p_section)

{

  uint8_t* p_byte, * p_end, * p_end2;

  while(p_section)

  {

    /* - first loop descriptors */

    p_byte = p_section->p_payload_start + 2;

    p_end = p_byte + ( ((uint16_t)(p_section->p_payload_start[0] & 0x0f) << 8)

                       | p_section->p_payload_start[1]);

    while(p_byte + 2 <= p_end)

    {

      uint8_t i_tag = p_byte[0];

      uint8_t i_length = p_byte[1];

      if(i_length + 2 <= p_end - p_byte)

        dvbpsi_bat_bouquet_descriptor_add(p_bat, i_tag, i_length, p_byte + 2);

      p_byte += 2 + i_length;

    }

    p_end =  2 +p_byte + ( ((uint16_t)(p_byte[0] & 0x0f) << 8)

                       | p_byte[1]);

    if(p_end > p_section->p_payload_end)

    {

        p_end = p_section->p_payload_end;

    }

    p_byte += 2;

    /* - TSs */

    for(; p_byte + 6 <= p_end;)

    {

      uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];

      uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];

      uint16_t i_transport_descriptors_length = ((uint16_t)(p_byte[4]
& 0x0f) << 8) | p_byte[5];

      dvbpsi_bat_ts_t* p_ts = dvbpsi_bat_ts_add(p_bat, i_ts_id,
i_orig_network_id);

      /* - TS descriptors */

      p_byte += 6;

      p_end2 = p_byte + i_transport_descriptors_length;

      if( p_end2 > p_section->p_payload_end )

      {

            p_end2 = p_section->p_payload_end;

      }

      while(p_byte + 2 <= p_end2)

      {

        uint8_t i_tag = p_byte[0];

        uint8_t i_length = p_byte[1];

        if(i_length + 2 <= p_end2 - p_byte)

          dvbpsi_bat_ts_descriptor_add(p_ts, i_tag, i_length, p_byte + 2);

        p_byte += 2 + i_length;

      }

    }

    p_section = p_section->p_next;

  }

}



In NIT.c file ->  "dvbpsi_nit_sections_decode" function is :

void dvbpsi_nit_sections_decode(dvbpsi_nit_t* p_nit,

                                dvbpsi_psi_section_t* p_section)

{

    uint8_t* p_byte, * p_end, * p_end2;

    while (p_section)

    {

        /* - NIT descriptors */

        p_byte = p_section->p_payload_start + 2;

        p_end = p_byte + (   ((uint16_t)(p_section->p_payload_start[0]
& 0x0f) << 8)

                           | p_section->p_payload_start[1]);

        while (p_byte + 2 <= p_end)

        {

            uint8_t i_tag = p_byte[0];

            uint8_t i_length = p_byte[1];

            if (i_length + 2 <= p_end - p_byte)

                dvbpsi_nit_descriptor_add(p_nit, i_tag, i_length, p_byte + 2);

            p_byte += 2 + i_length;

        }

        p_end = p_byte + (   ((uint16_t)(p_byte[0] & 0x0f) << 8)

                       | p_byte[1]);

        if (p_end > p_section->p_payload_end)

        {

            p_end = p_section->p_payload_end;

        }

        p_byte += 2;

        /* - TSs */

        for (; p_byte + 6 <= p_end;)

        {

            uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];

            uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];

            uint16_t i_ts_length = ((uint16_t)(p_byte[4] & 0x0f) << 8)
| p_byte[5];

            dvbpsi_nit_ts_t* p_ts = dvbpsi_nit_ts_add(p_nit, i_ts_id,
i_orig_network_id);

            /* - TS descriptors */

            p_byte += 6;

            p_end2 = p_byte + i_ts_length;

            if ( p_end2 > p_section->p_payload_end )

            {

                p_end2 = p_section->p_payload_end;

            }

            while (p_byte + 2 <= p_end2)

            {

                uint8_t i_tag = p_byte[0];

                uint8_t i_length = p_byte[1];

                if (i_length + 2 <= p_end2 - p_byte)

                    dvbpsi_nit_ts_descriptor_add(p_ts, i_tag,
i_length, p_byte + 2);

                p_byte += 2 + i_length;

            }

        }

        p_section = p_section->p_next;

    }

}


while it should be:

void dvbpsi_nit_sections_decode(dvbpsi_nit_t* p_nit,

                                dvbpsi_psi_section_t* p_section)

{

    uint8_t* p_byte, * p_end, * p_end2;

    while (p_section)

    {

        /* - NIT descriptors */

        p_byte = p_section->p_payload_start + 2;

        p_end = p_byte + (   ((uint16_t)(p_section->p_payload_start[0]
& 0x0f) << 8)

                           | p_section->p_payload_start[1]);

        while (p_byte + 2 <= p_end)

        {

            uint8_t i_tag = p_byte[0];

            uint8_t i_length = p_byte[1];

            if (i_length + 2 <= p_end - p_byte)

                dvbpsi_nit_descriptor_add(p_nit, i_tag, i_length, p_byte + 2);

            p_byte += 2 + i_length;

        }

        p_end = 2+p_byte + (   ((uint16_t)(p_byte[0] & 0x0f) << 8)

                       | p_byte[1]);

        if (p_end > p_section->p_payload_end)

        {

            p_end = p_section->p_payload_end;

        }

        p_byte += 2;

        /* - TSs */

        for (; p_byte + 6 <= p_end;)

        {

            uint16_t i_ts_id = ((uint16_t)p_byte[0] << 8) | p_byte[1];

            uint16_t i_orig_network_id = ((uint16_t)p_byte[2] << 8) | p_byte[3];

            uint16_t i_ts_length = ((uint16_t)(p_byte[4] & 0x0f) << 8)
| p_byte[5];

            dvbpsi_nit_ts_t* p_ts = dvbpsi_nit_ts_add(p_nit, i_ts_id,
i_orig_network_id);

            /* - TS descriptors */

            p_byte += 6;

            p_end2 = p_byte + i_ts_length;

            if ( p_end2 > p_section->p_payload_end )

            {

                p_end2 = p_section->p_payload_end;

            }

            while (p_byte + 2 <= p_end2)

            {

                uint8_t i_tag = p_byte[0];

                uint8_t i_length = p_byte[1];

                if (i_length + 2 <= p_end2 - p_byte)

                    dvbpsi_nit_ts_descriptor_add(p_ts, i_tag,
i_length, p_byte + 2);

                p_byte += 2 + i_length;

            }

        }

        p_section = p_section->p_next;

    }

}


I highlighted in green the diff.

I discovered them when trying to decode a transort stream with a NIT and a
BAT with 2 TS in the loop, if the second TS in the TS loop does not contain
descriptors it wont be decoded/seen by libdvbpsi without this patch
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/libdvbpsi-devel/attachments/20130122/e3b57087/attachment-0001.html>


More information about the libdvbpsi-devel mailing list