Coverage Report

Created: 2026-05-21 08:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/contrib/contrib-build/libdvbpsi/src/dvbpsi.c
Line
Count
Source
1
/*****************************************************************************
2
 * dvbpsi.c: conversion from TS packets to PSI sections
3
 *----------------------------------------------------------------------------
4
 * Copyright (C) 2001-2012 VideoLAN
5
 * $Id$
6
 *
7
 * Authors: Arnaud de Bossoreille de Ribou <bozo@via.ecp.fr>
8
 *          Jean-Paul Saman <jpsaman@videolan.org>
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
23
 *
24
 *----------------------------------------------------------------------------
25
 *
26
 *****************************************************************************/
27
28
#include "config.h"
29
30
#include <string.h>
31
#include <stdio.h>
32
#include <stdarg.h>
33
#include <stdlib.h>
34
#include <stdbool.h>
35
36
#if defined(HAVE_INTTYPES_H)
37
#include <inttypes.h>
38
#elif defined(HAVE_STDINT_H)
39
#include <stdint.h>
40
#endif
41
42
#include <assert.h>
43
44
#include "dvbpsi.h"
45
#include "dvbpsi_private.h"
46
#include "psi.h"
47
48
/*****************************************************************************
49
 * dvbpsi_new
50
 *****************************************************************************/
51
dvbpsi_t *dvbpsi_new(dvbpsi_message_cb callback, enum dvbpsi_msg_level level)
52
93.8k
{
53
93.8k
    dvbpsi_t *p_dvbpsi = calloc(1, sizeof(dvbpsi_t));
54
93.8k
    if (p_dvbpsi == NULL)
55
0
        return NULL;
56
57
93.8k
    p_dvbpsi->p_decoder  = NULL;
58
93.8k
    p_dvbpsi->pf_message = callback;
59
93.8k
    p_dvbpsi->i_msg_level = level;
60
93.8k
    return p_dvbpsi;
61
93.8k
}
62
63
/*****************************************************************************
64
 * dvbpsi_delete
65
 *****************************************************************************/
66
void dvbpsi_delete(dvbpsi_t *p_dvbpsi)
67
93.8k
{
68
93.8k
    if (p_dvbpsi) {
69
93.8k
        assert(p_dvbpsi->p_decoder == NULL);
70
93.8k
        p_dvbpsi->pf_message = NULL;
71
93.8k
    }
72
93.8k
    free(p_dvbpsi);
73
93.8k
}
74
75
/*****************************************************************************
76
 * dvbpsi_decoder_new
77
 *****************************************************************************/
78
955k
#define DVBPSI_INVALID_CC (0xFF)
79
void *dvbpsi_decoder_new(dvbpsi_callback_gather_t pf_gather,
80
    const int i_section_max_size, const bool b_discontinuity, const size_t psi_size)
81
93.8k
{
82
93.8k
    assert(psi_size >= sizeof(dvbpsi_decoder_t));
83
84
93.8k
    dvbpsi_decoder_t *p_decoder = (dvbpsi_decoder_t *) calloc(1, psi_size);
85
93.8k
    if (p_decoder == NULL)
86
0
        return NULL;
87
88
93.8k
    memcpy(&p_decoder->i_magic[0], "psi", 3);
89
93.8k
    p_decoder->pf_gather = pf_gather;
90
93.8k
    p_decoder->p_current_section = NULL;
91
93.8k
    p_decoder->i_section_max_size = i_section_max_size;
92
93.8k
    p_decoder->b_discontinuity = b_discontinuity;
93
93.8k
    p_decoder->i_continuity_counter = DVBPSI_INVALID_CC;
94
93.8k
    p_decoder->prevpacket[0] = 0;
95
93.8k
    p_decoder->p_current_section = NULL;
96
93.8k
    p_decoder->b_current_valid = false;
97
98
93.8k
    p_decoder->i_last_section_number = 0;
99
93.8k
    p_decoder->p_sections = NULL;
100
93.8k
    p_decoder->b_complete_header = false;
101
102
93.8k
    return p_decoder;
103
93.8k
}
104
105
/*****************************************************************************
106
 * dvbpsi_decoder_reset
107
 *****************************************************************************/
108
void dvbpsi_decoder_reset(dvbpsi_decoder_t* p_decoder, const bool b_force)
109
403k
{
110
403k
    assert(p_decoder);
111
112
    /* Force redecoding */
113
403k
    if (b_force)
114
144k
        p_decoder->b_current_valid = false;
115
116
403k
    p_decoder->i_continuity_counter = DVBPSI_INVALID_CC;
117
403k
    p_decoder->prevpacket[0] = 0;
118
119
    /* Clear the section array */
120
403k
    dvbpsi_DeletePSISections(p_decoder->p_sections);
121
403k
    p_decoder->p_sections = NULL;
122
403k
}
123
124
/*****************************************************************************
125
 * dvbpsi_decoder_psi_sections_completed
126
 *****************************************************************************/
127
bool dvbpsi_decoder_psi_sections_completed(dvbpsi_decoder_t* p_decoder)
128
259k
{
129
259k
    assert(p_decoder);
130
131
259k
    bool b_complete = false;
132
133
259k
    dvbpsi_psi_section_t *p = p_decoder->p_sections;
134
259k
    unsigned int prev_nr = 0;
135
518k
    while (p)
136
259k
    {
137
259k
        assert(prev_nr < 256);
138
259k
        if (prev_nr != p->i_number)
139
178
            break;
140
259k
        if (p_decoder->i_last_section_number == p->i_number)
141
259k
            b_complete = true;
142
259k
        p = p->p_next;
143
259k
        prev_nr++;
144
259k
    }
145
146
259k
    return b_complete;
147
259k
}
148
149
/*****************************************************************************
150
 * dvbpsi_decoder_psi_section_add
151
 *****************************************************************************/
152
bool dvbpsi_decoder_psi_section_add(dvbpsi_decoder_t *p_decoder, dvbpsi_psi_section_t *p_section)
153
261k
{
154
261k
    assert(p_decoder);
155
261k
    assert(p_section);
156
261k
    assert(p_section->p_next == NULL);
157
158
    /* Empty list */
159
261k
    if (!p_decoder->p_sections)
160
260k
    {
161
260k
        p_decoder->p_sections = p_section;
162
260k
        p_section->p_next = NULL;
163
260k
        return false;
164
260k
    }
165
166
    /* Insert in right place */
167
426
    dvbpsi_psi_section_t *p = p_decoder->p_sections;
168
426
    dvbpsi_psi_section_t *p_prev = NULL;
169
426
    bool b_overwrite = false;
170
171
429
    while (p)
172
426
    {
173
426
        if (p->i_number == p_section->i_number)
174
397
        {
175
            /* Replace */
176
397
            if (p_prev)
177
0
            {
178
0
                p_prev->p_next = p_section;
179
0
                p_section->p_next = p->p_next;
180
0
                p->p_next = NULL;
181
0
                dvbpsi_DeletePSISections(p);
182
0
                b_overwrite = true;
183
0
            }
184
397
            else
185
397
            {
186
397
                p_section->p_next = p->p_next;
187
397
                p->p_next = NULL;
188
397
                dvbpsi_DeletePSISections(p);
189
397
                p = p_section;
190
397
                p_decoder->p_sections = p;
191
397
                b_overwrite = true;
192
397
            }
193
397
            goto out;
194
397
        }
195
29
        else if (p->i_number > p_section->i_number)
196
26
        {
197
            /* Insert before p */
198
26
            if (p_prev)
199
0
            {
200
0
                p_prev->p_next = p_section;
201
0
                p_section->p_next = p;
202
0
            }
203
26
            else
204
26
            {
205
26
                p_section->p_next = p;
206
26
                p_decoder->p_sections = p_section;
207
26
            }
208
26
            goto out;
209
26
        }
210
211
3
        p_prev = p;
212
3
        p = p->p_next;
213
3
    }
214
215
    /* Add to end of list */
216
3
    if (p_prev->i_number < p_section->i_number)
217
3
    {
218
3
        p_decoder->i_last_section_number = p_section->i_last_number;
219
3
        p_prev->p_next = p_section;
220
3
        p_section->p_next = NULL;
221
3
    }
222
223
426
out:
224
426
    return b_overwrite;
225
3
}
226
227
/*****************************************************************************
228
 * dvbpsi_decoder_delete
229
 *****************************************************************************/
230
void dvbpsi_decoder_delete(dvbpsi_decoder_t *p_decoder)
231
93.8k
{
232
93.8k
    assert(p_decoder);
233
234
93.8k
    if (p_decoder->p_sections)
235
174
    {
236
174
        dvbpsi_DeletePSISections(p_decoder->p_sections);
237
174
        p_decoder->p_sections = NULL;
238
174
    }
239
240
93.8k
    dvbpsi_DeletePSISections(p_decoder->p_current_section);
241
93.8k
    free(p_decoder);
242
93.8k
}
243
244
/*****************************************************************************
245
 * dvbpsi_decoder_present
246
 *****************************************************************************/
247
bool dvbpsi_decoder_present(dvbpsi_t *p_dvbpsi)
248
148k
{
249
148k
    if (p_dvbpsi && p_dvbpsi->p_decoder)
250
133k
        return true;
251
14.3k
    else
252
14.3k
        return false;
253
148k
}
254
255
/*****************************************************************************
256
 * dvbpsi_packet_push
257
 *****************************************************************************
258
 * Injection of a TS packet into a PSI decoder.
259
 *****************************************************************************/
260
bool dvbpsi_packet_push(dvbpsi_t *p_dvbpsi, uint8_t* p_data)
261
458k
{
262
458k
    uint8_t i_expected_counter;           /* Expected continuity counter */
263
458k
    dvbpsi_psi_section_t* p_section;      /* Current section */
264
458k
    uint8_t* p_payload_pos;               /* Where in the TS packet */
265
458k
    uint8_t* p_new_pos = NULL;            /* Beginning of the new section,
266
                                             updated to NULL when the new
267
                                             section is handled */
268
458k
    int i_available;                      /* Byte count available in the
269
                                             packet */
270
458k
    const uint8_t *p_data_end = &p_data[188]; /* end of packet */
271
272
458k
    dvbpsi_decoder_t *p_decoder = p_dvbpsi->p_decoder;
273
458k
    assert(p_decoder);
274
275
    /* TS start code */
276
458k
    if (p_data[0] != 0x47)
277
0
    {
278
0
        dvbpsi_error(p_dvbpsi, "PSI decoder", "not a TS packet");
279
0
        return false;
280
0
    }
281
282
    /* Continuity check */
283
458k
    bool b_first = (p_decoder->i_continuity_counter == DVBPSI_INVALID_CC);
284
458k
    if (b_first)
285
256k
        p_decoder->i_continuity_counter = p_data[3] & 0xf;
286
201k
    else
287
201k
    {
288
201k
        i_expected_counter = (p_decoder->i_continuity_counter + 1) & 0xf;
289
201k
        p_decoder->i_continuity_counter = p_data[3] & 0xf;
290
291
201k
        if (i_expected_counter == ((p_decoder->i_continuity_counter + 1) & 0xf)
292
162k
            && !p_decoder->b_discontinuity)
293
123k
        {
294
123k
            if(!memcmp(p_decoder->prevpacket, p_data, 188))
295
49.1k
            {
296
49.1k
                dvbpsi_debug(p_dvbpsi, "PSI decoder",
297
49.1k
                             "TS duplicate (received %d, expected %d) for PID %d",
298
49.1k
                             p_decoder->i_continuity_counter, i_expected_counter,
299
49.1k
                             ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
300
49.1k
                return false;
301
49.1k
            }
302
74.6k
            else /* Fake duplicate */
303
74.6k
            {
304
                /* force discontinuity */
305
74.6k
                i_expected_counter = p_decoder->i_continuity_counter + 1;
306
74.6k
            }
307
123k
        }
308
309
152k
        if (i_expected_counter != p_decoder->i_continuity_counter)
310
133k
        {
311
133k
            dvbpsi_error(p_dvbpsi, "PSI decoder",
312
133k
                     "TS discontinuity (received %d, expected %d) for PID %d",
313
133k
                     p_decoder->i_continuity_counter, i_expected_counter,
314
133k
                     ((uint16_t)(p_data[1] & 0x1f) << 8) | p_data[2]);
315
133k
            p_decoder->b_discontinuity = true;
316
133k
            if (p_decoder->p_current_section)
317
48.1k
            {
318
48.1k
                dvbpsi_DeletePSISections(p_decoder->p_current_section);
319
48.1k
                p_decoder->p_current_section = NULL;
320
48.1k
            }
321
133k
        }
322
152k
    }
323
324
409k
    memcpy(p_decoder->prevpacket, p_data, 188);
325
326
    /* Return if no payload in the TS packet */
327
409k
    if (!(p_data[3] & 0x10))
328
73
        return false;
329
330
    /* Skip the adaptation_field if present */
331
409k
    if (p_data[3] & 0x20)
332
25.9k
    {
333
25.9k
        p_payload_pos = p_data + 5 + p_data[4];
334
25.9k
  if(p_payload_pos >= p_data_end)
335
1
      return false;
336
25.9k
    }
337
383k
    else
338
383k
        p_payload_pos = p_data + 4;
339
340
    /* Unit start -> skip the pointer_field and a new section begins */
341
409k
    if (p_data[1] & 0x40)
342
399k
    {
343
399k
        p_new_pos = p_payload_pos + *p_payload_pos + 1;
344
399k
        p_payload_pos += 1;
345
399k
  if(p_payload_pos >= p_data_end || p_new_pos >= p_data_end)
346
1.20k
      return false;
347
399k
    }
348
349
408k
    p_section = p_decoder->p_current_section;
350
351
    /* If the psi decoder needs a beginning of a section and a new section
352
       begins in the packet then initialize the dvbpsi_psi_section_t structure */
353
408k
    if (p_section == NULL)
354
378k
    {
355
378k
        if (p_new_pos)
356
375k
        {
357
            /* Allocation of the structure */
358
375k
            p_decoder->p_current_section
359
375k
                        = p_section
360
375k
                        = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
361
375k
            if (!p_section)
362
0
                return false;
363
            /* Update the position in the packet */
364
375k
            p_payload_pos = p_new_pos;
365
            /* New section is being handled */
366
375k
            p_new_pos = NULL;
367
            /* Just need the header to know how long is the section */
368
375k
            p_decoder->i_need = 3;
369
375k
            p_decoder->b_complete_header = false;
370
375k
        }
371
2.67k
        else
372
2.67k
        {
373
            /* No new section => return */
374
2.67k
            return false;
375
2.67k
        }
376
378k
    }
377
378
    /* Remaining bytes in the payload */
379
405k
    i_available = p_data_end - p_payload_pos;
380
381
1.36M
    while (i_available > 0)
382
968k
    {
383
968k
        if (i_available >= p_decoder->i_need)
384
890k
        {
385
            /* There are enough bytes in this packet to complete the
386
               header/section */
387
890k
            memcpy(p_section->p_payload_end, p_payload_pos, p_decoder->i_need);
388
890k
            p_payload_pos += p_decoder->i_need;
389
890k
            p_section->p_payload_end += p_decoder->i_need;
390
890k
            i_available -= p_decoder->i_need;
391
392
890k
            if (!p_decoder->b_complete_header)
393
487k
            {
394
                /* Compute p_section->i_length and update p_decoder->i_need */
395
487k
                p_section->i_length = ((uint16_t)(p_section->p_data[1] & 0xf)) << 8
396
487k
                                       | p_section->p_data[2];
397
487k
                if(p_section->i_length > 4093)
398
12.6k
                    return false;
399
475k
                p_decoder->i_need = p_section->i_length;
400
                /* Header is complete */
401
475k
                p_decoder->b_complete_header = true;
402
                /* Check that the section isn't too long */
403
475k
                if (p_decoder->i_need > p_decoder->i_section_max_size - 3)
404
22.7k
                {
405
22.7k
                    dvbpsi_error(p_dvbpsi, "PSI decoder", "PSI section too long");
406
22.7k
                    dvbpsi_DeletePSISections(p_section);
407
22.7k
                    p_decoder->p_current_section = NULL;
408
                    /* If there is a new section not being handled then go forward
409
                       in the packet */
410
22.7k
                    if (p_new_pos)
411
1
                    {
412
1
                        p_decoder->p_current_section
413
1
                                    = p_section
414
1
                                    = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
415
1
                        if (!p_section)
416
0
                            return false;
417
1
                        p_payload_pos = p_new_pos;
418
1
                        p_new_pos = NULL;
419
1
                        p_decoder->i_need = 3;
420
1
                        p_decoder->b_complete_header = false;
421
1
                        i_available = p_data_end - p_payload_pos;
422
1
                    }
423
22.7k
                    else
424
22.7k
                    {
425
22.7k
                        i_available = 0;
426
22.7k
                    }
427
22.7k
                }
428
475k
            }
429
402k
            else
430
402k
            {
431
402k
                bool b_valid_crc32 = false;
432
402k
                bool has_crc32;
433
434
                /* PSI section is complete */
435
402k
                p_section->i_table_id = p_section->p_data[0];
436
402k
                p_section->b_syntax_indicator = p_section->p_data[1] & 0x80;
437
402k
                p_section->b_private_indicator = p_section->p_data[1] & 0x40;
438
439
                /* Update the end of the payload if CRC_32 is present */
440
402k
                has_crc32 = dvbpsi_has_CRC32(p_section);
441
402k
                if (p_section->b_syntax_indicator || has_crc32)
442
287k
                    p_section->p_payload_end -= 4;
443
444
                /* Check CRC32 if present */
445
402k
                if (has_crc32)
446
287k
                    b_valid_crc32 = dvbpsi_ValidPSISection(p_section);
447
448
402k
                if (!has_crc32 || b_valid_crc32)
449
332k
                {
450
                    /* PSI section is valid */
451
332k
                    if (p_section->b_syntax_indicator)
452
217k
                    {
453
217k
                        p_section->i_extension =  (p_section->p_data[3] << 8)
454
217k
                                                 | p_section->p_data[4];
455
217k
                        p_section->i_version = (p_section->p_data[5] & 0x3e) >> 1;
456
217k
                        p_section->b_current_next = p_section->p_data[5] & 0x1;
457
217k
                        p_section->i_number = p_section->p_data[6];
458
217k
                        p_section->i_last_number = p_section->p_data[7];
459
217k
                        p_section->p_payload_start = p_section->p_data + 8;
460
217k
                    }
461
114k
                    else
462
114k
                    {
463
114k
                        p_section->i_extension = 0;
464
114k
                        p_section->i_version = 0;
465
114k
                        p_section->b_current_next = true;
466
114k
                        p_section->i_number = 0;
467
114k
                        p_section->i_last_number = 0;
468
114k
                        p_section->p_payload_start = p_section->p_data + 3;
469
114k
                    }
470
332k
                    if (p_decoder->pf_gather)
471
332k
                        p_decoder->pf_gather(p_dvbpsi, p_section);
472
332k
                    p_decoder->p_current_section = NULL;
473
332k
                }
474
69.8k
                else
475
69.8k
                {
476
69.8k
                    if (has_crc32 && !dvbpsi_ValidPSISection(p_section))
477
69.8k
                        dvbpsi_error(p_dvbpsi, "misc PSI", "Bad CRC_32 table 0x%x !!!",
478
69.8k
                                               p_section->p_data[0]);
479
0
                    else
480
0
                        dvbpsi_error(p_dvbpsi, "misc PSI", "table 0x%x", p_section->p_data[0]);
481
482
                    /* PSI section isn't valid => trash it */
483
69.8k
                    dvbpsi_DeletePSISections(p_section);
484
69.8k
                    p_decoder->p_current_section = NULL;
485
69.8k
                }
486
487
                /* A TS packet may contain any number of sections, only the first
488
                 * new one is flagged by the pointer_field. If the next payload
489
                 * byte isn't 0xff then a new section starts. */
490
402k
                if (p_new_pos == NULL && i_available && *p_payload_pos != 0xff)
491
106k
                    p_new_pos = p_payload_pos;
492
493
                /* If there is a new section not being handled then go forward
494
                   in the packet */
495
402k
                if (p_new_pos)
496
110k
                {
497
110k
                    p_decoder->p_current_section
498
110k
                              = p_section
499
110k
                              = dvbpsi_NewPSISection(p_decoder->i_section_max_size);
500
110k
                    if (!p_section)
501
0
                        return false;
502
110k
                    p_payload_pos = p_new_pos;
503
110k
                    p_new_pos = NULL;
504
110k
                    p_decoder->i_need = 3;
505
110k
                    p_decoder->b_complete_header = false;
506
110k
                    i_available = p_data_end - p_payload_pos;
507
110k
                }
508
291k
                else
509
291k
                {
510
291k
                    i_available = 0;
511
291k
                }
512
402k
            }
513
890k
        }
514
78.1k
        else
515
78.1k
        {
516
            /* There aren't enough bytes in this packet to complete the
517
               header/section */
518
78.1k
            memcpy(p_section->p_payload_end, p_payload_pos, i_available);
519
78.1k
            p_section->p_payload_end += i_available;
520
78.1k
            p_decoder->i_need -= i_available;
521
78.1k
            i_available = 0;
522
78.1k
        }
523
968k
    }
524
392k
    return true;
525
405k
}
526
#undef DVBPSI_INVALID_CC
527
528
/*****************************************************************************
529
 * Message error level:
530
 * -1 is disabled,
531
 *  0 is errors only
532
 *  1 is warning and errors
533
 *  2 is debug, warning and errors
534
 *****************************************************************************/
535
#if !defined(HAVE_ASPRINTF)
536
#   define DVBPSI_MSG_SIZE 1024
537
#endif
538
539
#define DVBPSI_MSG_FORMAT "libdvbpsi (%s): "
540
541
#ifdef HAVE_VARIADIC_MACROS
542
void dvbpsi_message(dvbpsi_t *dvbpsi, const dvbpsi_msg_level_t level, const char *fmt, ...)
543
489k
{
544
489k
    if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) &&
545
489k
        (level <= dvbpsi->i_msg_level))
546
489k
    {
547
489k
        va_list ap;
548
489k
        va_start(ap, fmt);
549
489k
        char *msg = NULL;
550
489k
#if defined(HAVE_ASPRINTF)
551
489k
        int err = vasprintf(&msg, fmt, ap);
552
#else
553
        msg = malloc(DVBPSI_MSG_SIZE);
554
        if (msg == NULL) {
555
            va_end(ap);
556
            return;
557
        }
558
        int err = vsnprintf(msg, DVBPSI_MSG_SIZE, DVBPSI_MSG_FORMAT fmt, ap);
559
#endif
560
489k
        va_end(ap);
561
489k
        if (err > 0) {
562
489k
            if (dvbpsi->pf_message)
563
489k
                dvbpsi->pf_message(dvbpsi, level, msg);
564
489k
        }
565
489k
        free(msg);
566
489k
    }
567
489k
}
568
#else
569
570
/* Common code for printing messages */
571
#   if defined(HAVE_ASPRINTF)
572
#       define DVBPSI_MSG_COMMON(level)                         \
573
    do {                                                        \
574
        va_list ap;                                             \
575
        va_start(ap, fmt);                                      \
576
        char *tmp = NULL;                                       \
577
        int err = vasprintf(&tmp, fmt, ap);                     \
578
        if (err < 0) {                                          \
579
            va_end(ap);                                         \
580
            return;                                             \
581
        }                                                       \
582
        char *msg = NULL;                                       \
583
        if (asprintf(&msg, DVBPSI_MSG_FORMAT "%s", src, tmp) < 0) { \
584
            va_end(ap);                                         \
585
            free(tmp);                                          \
586
            return;                                             \
587
        }                                                       \
588
        free(tmp);                                              \
589
        va_end(ap);                                             \
590
        if (err > 0) {                                          \
591
            if (dvbpsi->pf_message)                             \
592
                dvbpsi->pf_message(dvbpsi, level, msg);         \
593
        }                                                       \
594
        free(msg);                                              \
595
    } while(0);
596
#   else
597
#       define DVBPSI_MSG_COMMON(level)                         \
598
    do {                                                        \
599
        va_list ap;                                             \
600
        va_start(ap, fmt);                                      \
601
        char *tmp = malloc(DVBPSI_MSG_SIZE);                    \
602
        char *msg = malloc(DVBPSI_MSG_SIZE);                    \
603
        if ((tmp == NULL) || (msg == NULL)) {                   \
604
            va_end(ap);                                         \
605
            if (tmp) free(tmp);                                 \
606
            if (msg) free(msg);                                 \
607
            return;                                             \
608
        }                                                       \
609
        if (vsnprintf(tmp, DVBPSI_MSG_SIZE, fmt, ap) < 0) {     \
610
            va_end(ap);                                         \
611
            if (tmp) free(tmp);                                 \
612
            if (msg) free(msg);                                 \
613
            return;                                             \
614
        }                                                       \
615
        va_end(ap);                                             \
616
        int err = snprintf(msg, DVBPSI_MSG_SIZE, DVBPSI_MSG_FORMAT "%s", src, tmp); \
617
        if (err > 0) {                                          \
618
            if (dvbpsi->pf_message)                             \
619
                dvbpsi->pf_message(dvbpsi, level, msg);         \
620
        }                                                       \
621
        free(tmp);                                              \
622
        free(msg);                                              \
623
    } while(0);
624
#   endif
625
626
void dvbpsi_error(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
627
{
628
    if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) &&
629
        (DVBPSI_MSG_ERROR <= dvbpsi->i_msg_level))
630
    {
631
        DVBPSI_MSG_COMMON(DVBPSI_MSG_ERROR)
632
    }
633
}
634
635
void dvbpsi_warning(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
636
{
637
    if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) &&
638
        (DVBPSI_MSG_WARN <= dvbpsi->i_msg_level))
639
    {
640
        DVBPSI_MSG_COMMON(DVBPSI_MSG_WARN)
641
    }
642
}
643
644
void dvbpsi_debug(dvbpsi_t *dvbpsi, const char *src, const char *fmt, ...)
645
{
646
    if ((dvbpsi->i_msg_level > DVBPSI_MSG_NONE) &&
647
        (DVBPSI_MSG_DEBUG <= dvbpsi->i_msg_level))
648
    {
649
        DVBPSI_MSG_COMMON(DVBPSI_MSG_DEBUG)
650
    }
651
}
652
#endif