Coverage Report

Created: 2026-06-09 09:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/demux/mpeg/sections.c
Line
Count
Source
1
/*****************************************************************************
2
 * sections.c: Transport Stream sections assembler
3
 *****************************************************************************
4
 * Copyright (C) 2016 VLC authors and VideoLAN
5
 *
6
 * This program is free software; you can redistribute it and/or modify it
7
 * under the terms of the GNU Lesser General Public License as published by
8
 * the Free Software Foundation; either version 2.1 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 * GNU Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public License
17
 * along with this program; if not, write to the Free Software Foundation,
18
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19
 *****************************************************************************/
20
#ifdef HAVE_CONFIG_H
21
# include "config.h"
22
#endif
23
24
#include <vlc_common.h>
25
#include <vlc_demux.h>
26
27
#include "ts_pid.h"
28
#include "sections.h"
29
30
#ifndef _DVBPSI_DVBPSI_H_
31
 #include <dvbpsi/dvbpsi.h>
32
#endif
33
#ifndef _DVBPSI_DEMUX_H_
34
 #include <dvbpsi/demux.h>
35
#endif
36
#include <dvbpsi/psi.h>
37
#include "../../mux/mpeg/dvbpsi_compat.h" /* dvbpsi_messages */
38
39
#include "ts_decoders.h"
40
41
#include <assert.h>
42
43
struct ts_sections_processor_t
44
{
45
    uint8_t i_stream_type;
46
    uint8_t i_table_id;
47
    uint16_t i_extension_id;
48
    dvbpsi_t *p_dvbpsi;
49
    ts_section_processor_callback_t pf_callback;
50
    ts_sections_processor_t *p_next;
51
    void *p_callback_data;
52
};
53
54
static void ts_subdecoder_rawsection_Callback( dvbpsi_t *p_dvbpsi,
55
                                               const dvbpsi_psi_section_t* p_section,
56
                                               void* p_proc_cb_data )
57
176k
{
58
176k
    ts_sections_processor_t *p_proc = (ts_sections_processor_t *) p_proc_cb_data;
59
176k
    if( likely(p_proc->pf_callback) )
60
176k
    {
61
352k
        for( const dvbpsi_psi_section_t *p_sec = p_section; p_sec; p_sec = p_sec->p_next )
62
176k
        {
63
176k
            size_t i_rawlength = p_sec->p_payload_end - p_sec->p_data;
64
176k
            if ( p_sec->b_syntax_indicator )
65
67.9k
                i_rawlength += 4;
66
67
176k
            if( p_proc->i_table_id && p_section->i_table_id != p_proc->i_table_id )
68
50.5k
                continue;
69
70
125k
            if( p_proc->i_extension_id && p_section->i_extension != p_proc->i_extension_id )
71
0
                continue;
72
73
125k
            p_proc->pf_callback( (demux_t *) p_dvbpsi->p_sys,
74
125k
                                 p_sec->p_data, i_rawlength,
75
125k
                                 p_sec->p_payload_start,
76
125k
                                 p_sec->p_payload_end - p_sec->p_payload_start,
77
125k
                                 p_proc->p_callback_data );
78
125k
        }
79
176k
    }
80
176k
}
81
82
void ts_sections_processor_Add( demux_t *p_demux,
83
                                ts_sections_processor_t **pp_chain,
84
                                uint8_t i_table_id, uint16_t i_extension_id,
85
                                ts_section_processor_callback_t pf_callback,
86
                                void *p_callback_data )
87
52.8k
{
88
52.8k
    ts_sections_processor_t *p_proc = *pp_chain;
89
52.8k
    for( ; p_proc; p_proc = p_proc->p_next )
90
0
    {
91
        /* Avoid duplicates */
92
0
        if ( p_proc->i_extension_id == i_extension_id &&
93
0
             p_proc->i_table_id == i_table_id &&
94
0
             p_proc->pf_callback == pf_callback )
95
0
            return;
96
0
    }
97
98
52.8k
    p_proc = malloc( sizeof(ts_sections_processor_t) );
99
52.8k
    if( p_proc )
100
52.8k
    {
101
52.8k
        p_proc->pf_callback = pf_callback;
102
52.8k
        p_proc->i_extension_id = i_extension_id;
103
52.8k
        p_proc->i_table_id = i_table_id;
104
52.8k
        p_proc->p_dvbpsi = dvbpsi_new( &dvbpsi_messages, DVBPSI_MSG_DEBUG );
105
52.8k
        p_proc->p_dvbpsi->p_sys = p_demux;
106
52.8k
        p_proc->p_callback_data = p_callback_data;
107
108
52.8k
        if( !ts_dvbpsi_AttachRawDecoder( p_proc->p_dvbpsi,
109
52.8k
                                         ts_subdecoder_rawsection_Callback, p_proc ) )
110
0
        {
111
0
            ts_sections_processor_ChainDelete( p_proc );
112
0
            return;
113
0
        }
114
        /* Insert as head */
115
52.8k
        p_proc->p_next = *pp_chain;
116
52.8k
        *pp_chain = p_proc;
117
52.8k
    }
118
52.8k
}
119
120
void ts_sections_processor_ChainDelete( ts_sections_processor_t *p_chain )
121
52.8k
{
122
105k
    while( p_chain )
123
52.8k
    {
124
52.8k
        ts_dvbpsi_DetachRawDecoder( p_chain->p_dvbpsi );
125
52.8k
        dvbpsi_delete( p_chain->p_dvbpsi );
126
52.8k
        ts_sections_processor_t *p_next = p_chain->p_next;
127
52.8k
        free( p_chain );
128
52.8k
        p_chain = p_next;
129
52.8k
    }
130
52.8k
}
131
132
void ts_sections_processor_Reset( ts_sections_processor_t *p_chain )
133
0
{
134
0
    while( p_chain )
135
0
    {
136
0
        dvbpsi_decoder_reset( p_chain->p_dvbpsi->p_decoder, true );
137
0
        p_chain = p_chain->p_next;
138
0
    }
139
0
}
140
141
void ts_sections_processor_Push( ts_sections_processor_t *p_chain,
142
                                 const uint8_t *p_buf )
143
248k
{
144
248k
    for( ts_sections_processor_t *p_proc = p_chain;
145
497k
         p_proc; p_proc = p_proc->p_next )
146
248k
    {
147
248k
        dvbpsi_packet_push( p_chain->p_dvbpsi, (uint8_t *) p_buf );
148
248k
    }
149
248k
}