1 /*****************************************************************************
2  * sis.c: SIS decoder/generator
3  *----------------------------------------------------------------------------
4  * Copyright (C) 2010-2011 VideoLAN
5  * $Id:$
6  *
7  * Authors: Jean-Paul Saman <jpsaman@videolan.org>
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  *----------------------------------------------------------------------------
24  *
25  *****************************************************************************/
26 
27 #include "config.h"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stdbool.h>
32 #include <string.h>
33 
34 #if defined(HAVE_INTTYPES_H)
35 #include <inttypes.h>
36 #elif defined(HAVE_STDINT_H)
37 #include <stdint.h>
38 #endif
39 
40 #include <assert.h>
41 
42 #include "../dvbpsi.h"
43 #include "../dvbpsi_private.h"
44 #include "../psi.h"
45 #include "../descriptor.h"
46 #include "../demux.h"
47 
48 #include "sis.h"
49 #include "sis_private.h"
50 
51 /*****************************************************************************
52  * dvbpsi_sis_attach
53  *****************************************************************************
54  * Initialize a SIS subtable decoder.
55  *****************************************************************************/
dvbpsi_sis_attach(dvbpsi_t * p_dvbpsi,uint8_t i_table_id,uint16_t i_extension,dvbpsi_sis_callback pf_callback,void * p_cb_data)56 bool dvbpsi_sis_attach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension,
57                       dvbpsi_sis_callback pf_callback, void* p_cb_data)
58 {
59     assert(p_dvbpsi);
60     assert(p_dvbpsi->p_decoder);
61 
62     dvbpsi_demux_t* p_demux = (dvbpsi_demux_t*)p_dvbpsi->p_decoder;
63 
64     i_extension = 0;
65 
66     if (dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension))
67     {
68         dvbpsi_error(p_dvbpsi, "SIS decoder",
69                          "Already a decoder for (table_id == 0x%02x,"
70                          "extension == 0x%02x)",
71                          i_table_id, i_extension);
72         return false;
73     }
74 
75     dvbpsi_sis_decoder_t*  p_sis_decoder;
76     p_sis_decoder = (dvbpsi_sis_decoder_t*) dvbpsi_decoder_new(NULL,
77                                              0, true, sizeof(dvbpsi_sis_decoder_t));
78     if (p_sis_decoder == NULL)
79         return false;
80 
81     /* subtable decoder configuration */
82     dvbpsi_demux_subdec_t* p_subdec;
83     p_subdec = dvbpsi_NewDemuxSubDecoder(i_table_id, i_extension, dvbpsi_sis_detach,
84                                          dvbpsi_sis_sections_gather, DVBPSI_DECODER(p_sis_decoder));
85     if (p_subdec == NULL)
86     {
87         dvbpsi_decoder_delete(DVBPSI_DECODER(p_sis_decoder));
88         return false;
89     }
90 
91     /* Attach the subtable decoder to the demux */
92     dvbpsi_AttachDemuxSubDecoder(p_demux, p_subdec);
93 
94     /* SIS decoder information */
95     p_sis_decoder->pf_sis_callback = pf_callback;
96     p_sis_decoder->p_cb_data = p_cb_data;
97     p_sis_decoder->p_building_sis = NULL;
98 
99     return true;
100 }
101 
102 /*****************************************************************************
103  * dvbpsi_sis_detach
104  *****************************************************************************
105  * Close a SIS decoder.
106  *****************************************************************************/
dvbpsi_sis_detach(dvbpsi_t * p_dvbpsi,uint8_t i_table_id,uint16_t i_extension)107 void dvbpsi_sis_detach(dvbpsi_t *p_dvbpsi, uint8_t i_table_id, uint16_t i_extension)
108 {
109     assert(p_dvbpsi);
110     assert(p_dvbpsi->p_decoder);
111 
112     dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
113 
114     i_extension = 0;
115     dvbpsi_demux_subdec_t* p_subdec;
116     p_subdec = dvbpsi_demuxGetSubDec(p_demux, i_table_id, i_extension);
117     if (p_subdec == NULL)
118     {
119         dvbpsi_error(p_dvbpsi, "SIS Decoder",
120                          "No such SIS decoder (table_id == 0x%02x,"
121                          "extension == 0x%02x)",
122                          i_table_id, i_extension);
123         return;
124     }
125 
126     assert(p_subdec->p_decoder);
127 
128     dvbpsi_sis_decoder_t* p_sis_decoder;
129     p_sis_decoder = (dvbpsi_sis_decoder_t*)p_subdec->p_decoder;
130     if (p_sis_decoder->p_building_sis)
131         dvbpsi_sis_delete(p_sis_decoder->p_building_sis);
132     p_sis_decoder->p_building_sis = NULL;
133 
134     dvbpsi_DetachDemuxSubDecoder(p_demux, p_subdec);
135     dvbpsi_DeleteDemuxSubDecoder(p_subdec);
136 }
137 
138 /*****************************************************************************
139  * dvbpsi_sis_init
140  *****************************************************************************
141  * Initialize a pre-allocated dvbpsi_sis_t structure.
142  *****************************************************************************/
dvbpsi_sis_init(dvbpsi_sis_t * p_sis,uint8_t i_table_id,uint16_t i_extension,uint8_t i_version,bool b_current_next,uint8_t i_protocol_version)143 void dvbpsi_sis_init(dvbpsi_sis_t *p_sis, uint8_t i_table_id, uint16_t i_extension,
144                      uint8_t i_version, bool b_current_next, uint8_t i_protocol_version)
145 {
146     p_sis->i_table_id = i_table_id;
147     p_sis->i_extension = i_extension;
148 
149     p_sis->i_version = i_version;
150     p_sis->b_current_next = b_current_next;
151 
152     assert(i_protocol_version == 0);
153     p_sis->i_protocol_version = 0; /* must be 0 */
154 
155     /* encryption */
156     p_sis->b_encrypted_packet = false;
157     p_sis->i_encryption_algorithm = 0;
158 
159     p_sis->i_pts_adjustment = (uint64_t)0;
160     p_sis->cw_index = 0;
161 
162     /* splice command */
163     p_sis->i_splice_command_length = 0;
164     p_sis->i_splice_command_type = 0x00;
165 
166     /* FIXME: splice_info_section comes here */
167 
168     /* descriptors */
169     p_sis->i_descriptors_length = 0;
170     p_sis->p_first_descriptor = NULL;
171 
172     /* FIXME: alignment stuffing */
173 
174     p_sis->i_ecrc = 0;
175 }
176 
177 /*****************************************************************************
178  * dvbpsi_sis_new
179  *****************************************************************************
180  * Allocate and Initialize a new dvbpsi_sis_t structure.
181  *****************************************************************************/
dvbpsi_sis_new(uint8_t i_table_id,uint16_t i_extension,uint8_t i_version,bool b_current_next,uint8_t i_protocol_version)182 dvbpsi_sis_t* dvbpsi_sis_new(uint8_t i_table_id, uint16_t i_extension, uint8_t i_version,
183                              bool b_current_next, uint8_t i_protocol_version)
184 {
185     dvbpsi_sis_t* p_sis = (dvbpsi_sis_t*)malloc(sizeof(dvbpsi_sis_t));
186     if (p_sis != NULL)
187         dvbpsi_sis_init(p_sis, i_table_id, i_extension, i_version,
188                         b_current_next, i_protocol_version);
189     return p_sis;
190 }
191 
192 /*****************************************************************************
193  * dvbpsi_sis_empty
194  *****************************************************************************
195  * Clean a dvbpsi_sis_t structure.
196  *****************************************************************************/
dvbpsi_sis_empty(dvbpsi_sis_t * p_sis)197 void dvbpsi_sis_empty(dvbpsi_sis_t* p_sis)
198 {
199     /* FIXME: free splice_command_sections */
200 
201     dvbpsi_DeleteDescriptors(p_sis->p_first_descriptor);
202     p_sis->p_first_descriptor = NULL;
203 
204     /* FIXME: free alignment stuffing */
205 }
206 
207 /*****************************************************************************
208  * dvbpsi_sis_delete
209  *****************************************************************************
210  * Clean and Delete a dvbpsi_sis_t structure.
211  *****************************************************************************/
dvbpsi_sis_delete(dvbpsi_sis_t * p_sis)212 void dvbpsi_sis_delete(dvbpsi_sis_t *p_sis)
213 {
214     if (p_sis)
215         dvbpsi_sis_empty(p_sis);
216     free(p_sis);
217 }
218 
219 /*****************************************************************************
220  * dvbpsi_sis_descriptor_add
221  *****************************************************************************
222  * Add a descriptor in the SIS service description.
223  *****************************************************************************/
dvbpsi_sis_descriptor_add(dvbpsi_sis_t * p_sis,uint8_t i_tag,uint8_t i_length,uint8_t * p_data)224 dvbpsi_descriptor_t *dvbpsi_sis_descriptor_add(dvbpsi_sis_t *p_sis,
225                                              uint8_t i_tag, uint8_t i_length,
226                                              uint8_t *p_data)
227 {
228     dvbpsi_descriptor_t * p_descriptor;
229     p_descriptor = dvbpsi_NewDescriptor(i_tag, i_length, p_data);
230     if (p_descriptor == NULL)
231         return NULL;
232 
233     p_sis->p_first_descriptor = dvbpsi_AddDescriptor(p_sis->p_first_descriptor,
234                                                      p_descriptor);
235     assert(p_sis->p_first_descriptor);
236     if (p_sis->p_first_descriptor == NULL)
237         return NULL;
238 
239     return p_descriptor;
240 }
241 
242 /* */
dvbpsi_ReInitSIS(dvbpsi_sis_decoder_t * p_decoder,const bool b_force)243 static void dvbpsi_ReInitSIS(dvbpsi_sis_decoder_t* p_decoder, const bool b_force)
244 {
245     assert(p_decoder);
246 
247     dvbpsi_decoder_reset(DVBPSI_DECODER(p_decoder), b_force);
248 
249     /* Force redecoding */
250     if (b_force)
251     {
252         /* Free structures */
253         if (p_decoder->p_building_sis)
254             dvbpsi_sis_delete(p_decoder->p_building_sis);
255     }
256     p_decoder->p_building_sis = NULL;
257 }
258 
dvbpsi_CheckSIS(dvbpsi_t * p_dvbpsi,dvbpsi_sis_decoder_t * p_sis_decoder,dvbpsi_psi_section_t * p_section)259 static bool dvbpsi_CheckSIS(dvbpsi_t *p_dvbpsi, dvbpsi_sis_decoder_t* p_sis_decoder,
260                             dvbpsi_psi_section_t *p_section)
261 {
262     bool b_reinit = false;
263     assert(p_dvbpsi);
264     assert(p_sis_decoder);
265 
266     if (p_sis_decoder->p_building_sis->i_protocol_version != 0)
267     {
268         dvbpsi_error(p_dvbpsi, "SIS decoder",
269                      "'protocol_version' differs"
270                      " while no discontinuity has occured");
271         b_reinit = true;
272     }
273     else if (p_sis_decoder->p_building_sis->i_extension != p_section->i_extension)
274     {
275         dvbpsi_error(p_dvbpsi, "SIS decoder",
276                 "'transport_stream_id' differs"
277                 " whereas no discontinuity has occured");
278         b_reinit = true;
279     }
280     else if (p_sis_decoder->p_building_sis->i_version != p_section->i_version)
281     {
282         /* version_number */
283         dvbpsi_error(p_dvbpsi, "SIS decoder",
284                 "'version_number' differs"
285                 " whereas no discontinuity has occured");
286         b_reinit = true;
287     }
288     else if (p_sis_decoder->i_last_section_number != p_section->i_last_number)
289     {
290         /* last_section_number */
291         dvbpsi_error(p_dvbpsi, "SIS decoder",
292                 "'last_section_number' differs"
293                 " whereas no discontinuity has occured");
294         b_reinit = true;
295     }
296 
297     return b_reinit;
298 }
299 
dvbpsi_AddSectionSIS(dvbpsi_t * p_dvbpsi,dvbpsi_sis_decoder_t * p_sis_decoder,dvbpsi_psi_section_t * p_section)300 static bool dvbpsi_AddSectionSIS(dvbpsi_t *p_dvbpsi, dvbpsi_sis_decoder_t *p_sis_decoder,
301                                  dvbpsi_psi_section_t* p_section)
302 {
303     assert(p_dvbpsi);
304     assert(p_sis_decoder);
305     assert(p_section);
306 
307     /* Initialize the structures if it's the first section received */
308     if (!p_sis_decoder->p_building_sis)
309     {
310         p_sis_decoder->p_building_sis = dvbpsi_sis_new(
311                             p_section->i_table_id, p_section->i_extension,
312                             p_section->i_version, p_section->b_current_next, 0);
313         if (p_sis_decoder->p_building_sis == NULL)
314             return false;
315         p_sis_decoder->i_last_section_number = p_section->i_last_number;
316     }
317 
318     /* Add to linked list of sections */
319     if (dvbpsi_decoder_psi_section_add(DVBPSI_DECODER(p_sis_decoder), p_section))
320         dvbpsi_debug(p_dvbpsi, "SDT decoder", "overwrite section number %d",
321                      p_section->i_number);
322 
323     return true;
324 }
325 
326 /*****************************************************************************
327  * dvbpsi_sis_sections_gather
328  *****************************************************************************
329  * Callback for the subtable demultiplexor.
330  *****************************************************************************/
dvbpsi_sis_sections_gather(dvbpsi_t * p_dvbpsi,dvbpsi_decoder_t * p_decoder,dvbpsi_psi_section_t * p_section)331 void dvbpsi_sis_sections_gather(dvbpsi_t *p_dvbpsi,
332                               dvbpsi_decoder_t *p_decoder,
333                               dvbpsi_psi_section_t * p_section)
334 {
335     assert(p_dvbpsi);
336     assert(p_dvbpsi->p_decoder);
337 
338     if (!dvbpsi_CheckPSISection(p_dvbpsi, p_section, 0xFC, "SIS decoder"))
339     {
340         dvbpsi_DeletePSISections(p_section);
341         return;
342     }
343 
344     /* */
345     dvbpsi_demux_t *p_demux = (dvbpsi_demux_t *) p_dvbpsi->p_decoder;
346     dvbpsi_sis_decoder_t * p_sis_decoder = (dvbpsi_sis_decoder_t*)p_decoder;
347 
348     if (p_section->b_private_indicator)
349     {
350         /* Invalid private_syntax_indicator */
351         dvbpsi_error(p_dvbpsi, "SIS decoder",
352                      "invalid private section (private_syntax_indicator != false)");
353         dvbpsi_DeletePSISections(p_section);
354         return;
355     }
356 
357     /* TS discontinuity check */
358     if (p_demux->b_discontinuity)
359     {
360         dvbpsi_ReInitSIS(p_sis_decoder, true);
361         p_sis_decoder->b_discontinuity = false;
362         p_demux->b_discontinuity = false;
363     }
364     else
365     {
366         /* Perform a few sanity checks */
367         if (p_sis_decoder->p_building_sis)
368         {
369             if (dvbpsi_CheckSIS(p_dvbpsi, p_sis_decoder, p_section))
370                 dvbpsi_ReInitSIS(p_sis_decoder, true);
371         }
372         else
373         {
374             if(     (p_sis_decoder->b_current_valid)
375                  && (p_sis_decoder->current_sis.i_version == p_section->i_version)
376                  && (p_sis_decoder->current_sis.b_current_next == p_section->b_current_next))
377              {
378                  /* Don't decode since this version is already decoded */
379                  dvbpsi_debug(p_dvbpsi, "SIT decoder",
380                              "ignoring already decoded section %d",
381                              p_section->i_number);
382                  dvbpsi_DeletePSISections(p_section);
383                  return;
384              }
385         }
386     }
387 
388     /* Add section to SIS */
389     if (!dvbpsi_AddSectionSIS(p_dvbpsi, p_sis_decoder, p_section))
390     {
391         dvbpsi_error(p_dvbpsi, "SIS decoder", "failed decoding section %d",
392                      p_section->i_number);
393         dvbpsi_DeletePSISections(p_section);
394         return;
395     }
396 
397     /* Check if we have all the sections */
398     if (dvbpsi_decoder_psi_sections_completed(DVBPSI_DECODER(p_sis_decoder)))
399     {
400         assert(p_sis_decoder->pf_sis_callback);
401 
402         /* Save the current information */
403         p_sis_decoder->current_sis = *p_sis_decoder->p_building_sis;
404         p_sis_decoder->b_current_valid = true;
405         /* Decode the sections */
406         dvbpsi_sis_sections_decode(p_dvbpsi, p_sis_decoder->p_building_sis,
407                                    p_sis_decoder->p_sections);
408         /* signal the new SDT */
409         p_sis_decoder->pf_sis_callback(p_sis_decoder->p_cb_data,
410                                        p_sis_decoder->p_building_sis);
411         /* Delete sections and Reinitialize the structures */
412         dvbpsi_ReInitSIS(p_sis_decoder, false);
413         assert(p_sis_decoder->p_sections == NULL);
414     }
415 }
416 
417 /*****************************************************************************
418  * dvbpsi_sis_sections_decode
419  *****************************************************************************
420  * SIS decoder.
421  *****************************************************************************/
dvbpsi_sis_sections_decode(dvbpsi_t * p_dvbpsi,dvbpsi_sis_t * p_sis,dvbpsi_psi_section_t * p_section)422 void dvbpsi_sis_sections_decode(dvbpsi_t* p_dvbpsi, dvbpsi_sis_t* p_sis,
423                               dvbpsi_psi_section_t* p_section)
424 {
425     uint8_t *p_byte, *p_end;
426 
427     while (p_section)
428     {
429         for (p_byte = p_section->p_payload_start + 3;
430              p_byte < p_section->p_payload_end; )
431         {
432             p_sis->i_protocol_version = p_byte[3];
433             p_sis->b_encrypted_packet = ((p_byte[4] & 0x80) == 0x80);
434             /* NOTE: cannot handle encrypted packet */
435             assert(p_sis->b_encrypted_packet);
436             p_sis->i_encryption_algorithm = ((p_byte[4] & 0x7E) >> 1);
437             p_sis->i_pts_adjustment = ((((uint64_t)p_byte[4] & 0x01) << 32) |
438                                         ((uint64_t)p_byte[5] << 24) |
439                                         ((uint64_t)p_byte[6] << 16) |
440                                         ((uint64_t)p_byte[7] << 8)  |
441                                          (uint64_t)p_byte[8]);
442             p_sis->cw_index = p_byte[9];
443             p_sis->i_splice_command_length = ((p_byte[11] & 0x0F) << 8) | p_byte[12];
444             p_sis->i_splice_command_type = p_byte[13];
445 
446             uint32_t i_splice_command_length = p_sis->i_splice_command_length;
447             if (p_sis->i_splice_command_length == 0xfff)
448             {
449                 /* FIXME: size 0xfff of splice_command_section is undefined */
450                 assert(p_sis->i_splice_command_length != 0xfff);
451             }
452 
453             /* FIXME: handle splice_command_sections */
454             switch(p_sis->i_splice_command_type)
455             {
456                 case 0x00: /* splice_null */
457                 case 0x04: /* splice_schedule */
458                 case 0x05: /* splice_insert */
459                 case 0x06: /* time_signal */
460                 case 0x07: /* bandwidth_reservation */
461                     break;
462                 default:
463                     dvbpsi_error(p_dvbpsi, "SIS decoder", "invalid SIS Command found");
464                     break;
465             }
466 
467             /* Service descriptors */
468             uint8_t *p_desc = p_byte + 13 + i_splice_command_length;
469             p_sis->i_descriptors_length = (p_desc[0] << 8) | p_desc[1];
470 
471             p_desc += 1;
472             p_end = p_desc + p_sis->i_descriptors_length;
473             if (p_end > p_section->p_payload_end) break;
474 
475             while (p_desc + 2 <= p_end)
476             {
477                 uint8_t i_tag = p_desc[0];
478                 uint8_t i_length = p_desc[1];
479                 if ((i_length <= 254) &&
480                     (i_length + 2 <= p_end - p_desc))
481                     dvbpsi_sis_descriptor_add(p_sis, i_tag, i_length, p_desc + 2);
482                 p_desc += 2 + i_length;
483             }
484 
485             if (p_sis->b_encrypted_packet)
486             {
487                 /* FIXME: Currently ignored */
488                 /* Calculate crc32 over decoded
489                  * p_sis->i_splice_command_type till p_sis->i_ecrc,
490                  * the result should be exactly p_sis->i_ecrc and indicates
491                  * a successfull decryption.
492                  */
493                 p_desc += 4; /* E CRC 32 */
494             }
495 
496             /* point to next section */
497             p_byte = p_desc + 4 /* CRC 32 */;
498         }
499 
500         p_section = p_section->p_next;
501     }
502 }
503 
504 /*****************************************************************************
505  * dvbpsi_sis_sections_generate
506  *****************************************************************************
507  * Generate SIS sections based on the dvbpsi_sis_t structure.
508  *****************************************************************************/
dvbpsi_sis_sections_generate(dvbpsi_t * p_dvbpsi,dvbpsi_sis_t * p_sis)509 dvbpsi_psi_section_t *dvbpsi_sis_sections_generate(dvbpsi_t *p_dvbpsi, dvbpsi_sis_t* p_sis)
510 {
511     dvbpsi_psi_section_t * p_current = dvbpsi_NewPSISection(1024);
512 
513     p_current->i_table_id = 0xFC;
514     p_current->b_syntax_indicator = false;
515     p_current->b_private_indicator = false;
516     p_current->i_length = 3;                     /* header + CRC_32 */
517 
518     /* FIXME: looks weird */
519     p_current->p_payload_end += 2;               /* just after the header */
520     p_current->p_payload_start = p_current->p_data + 3;
521 
522     p_current->p_data[3] = p_sis->i_protocol_version;
523     p_current->p_data[4] = p_sis->b_encrypted_packet ? 0x80 : 0x0;
524     /* NOTE: cannot handle encrypted packet */
525     assert(p_sis->b_encrypted_packet);
526     p_current->p_data[4] |= ((p_sis->i_encryption_algorithm << 1) & 0x7E);
527 
528     p_current->p_data[4] |= ((p_sis->i_pts_adjustment & 0x00800) >> 32);
529     p_current->p_data[5] = (p_sis->i_pts_adjustment >> 24);
530     p_current->p_data[6] = (p_sis->i_pts_adjustment >> 16);
531     p_current->p_data[7] = (p_sis->i_pts_adjustment >> 8);
532     p_current->p_data[8] =  p_sis->i_pts_adjustment;
533 
534     p_current->p_data[9]  = p_sis->cw_index;
535     p_current->p_data[11] = 0x00;
536     p_current->p_data[11]|= ((p_sis->i_splice_command_length >> 8) & 0x0F);
537     p_current->p_data[12] = (uint8_t) (p_sis->i_splice_command_length & 0xFF);
538     p_current->p_data[13] = p_sis->i_splice_command_type;
539 
540     uint32_t i_desc_start = 13 + p_sis->i_splice_command_length;
541     if (p_sis->i_splice_command_length == 0xfff)
542     {
543         /* FIXME: size 0xfff of splice_command_section is undefined */
544         assert(p_sis->i_splice_command_length != 0xfff);
545     }
546 
547     /* FIXME: handle splice_command_sections */
548 
549     /* Service descriptors */
550     p_current->p_data[i_desc_start] = (p_sis->i_descriptors_length >> 8);
551     p_current->p_data[i_desc_start+1] = (uint8_t)(p_sis->i_descriptors_length & 0xFF);
552 
553     p_current->p_payload_end += (i_desc_start + 1);
554 
555     uint32_t i_desc_length = 0;
556 
557     dvbpsi_descriptor_t * p_descriptor = p_sis->p_first_descriptor;
558     while ((p_descriptor != NULL) && (p_current->i_length <= 1018))
559     {
560         i_desc_length += p_descriptor->i_length + 2;
561         p_descriptor = p_descriptor->p_next;
562 
563         /* p_payload_end is where the descriptor begins */
564         p_current->p_payload_end[0] = p_descriptor->i_tag;
565         p_current->p_payload_end[1] = p_descriptor->i_length;
566         memcpy(p_current->p_payload_end + 2, p_descriptor->p_data, p_descriptor->i_length);
567         /* Increase length by descriptor_length + 2 */
568         p_current->p_payload_end += p_descriptor->i_length + 2;
569         p_current->i_length += p_descriptor->i_length + 2;
570 
571     }
572     /* Coding error if this condition is not met */
573     assert( i_desc_length == p_sis->i_descriptors_length);
574 
575     /* Finalization */
576     dvbpsi_BuildPSISection(p_dvbpsi, p_current);
577     return p_current;
578 }
579