Coverage Report

Created: 2025-07-11 06:16

/src/vlc/modules/demux/mpeg/pes.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * pes.h: PES Packet helpers
3
 *****************************************************************************
4
 * Copyright (C) 2004-2015 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
#ifndef VLC_MPEG_PES_H
21
#define VLC_MPEG_PES_H
22
23
#include "timestamps.h"
24
25
0
#define STREAM_ID_PROGRAM_STREAM_MAP         0xBC
26
0
#define STREAM_ID_PRIVATE_STREAM_1           0xBD
27
0
#define STREAM_ID_PADDING                    0xBE
28
0
#define STREAM_ID_PRIVATE_STREAM_2           0xBF
29
#define STREAM_ID_AUDIO_STREAM_0             0xC0
30
#define STREAM_ID_VIDEO_STREAM_0             0xE0
31
0
#define STREAM_ID_ECM                        0xF0
32
0
#define STREAM_ID_EMM                        0xF1
33
0
#define STREAM_ID_DSM_CC                     0xF2
34
0
#define STREAM_ID_H222_1_TYPE_E              0xF8
35
#define STREAM_ID_METADATA_STREAM            0xFC
36
0
#define STREAM_ID_EXTENDED_STREAM_ID         0xFD
37
0
#define STREAM_ID_PROGRAM_STREAM_DIRECTORY   0xFF
38
39
/* MPEG-2 PTS/DTS */
40
static inline ts_90khz_t GetPESTimestamp( const uint8_t *p_data )
41
0
{
42
    /* prefixed by 4 bits 0010 or 0011 */
43
0
    return  ((ts_90khz_t)(p_data[ 0]&0x0e ) << 29)|
44
0
             (ts_90khz_t)(p_data[1] << 22)|
45
0
            ((ts_90khz_t)(p_data[2]&0xfe) << 14)|
46
0
             (ts_90khz_t)(p_data[3] << 7)|
47
0
             (ts_90khz_t)(p_data[4] >> 1);
48
0
}
Unexecuted instantiation: ps.c:GetPESTimestamp
Unexecuted instantiation: pva.c:GetPESTimestamp
Unexecuted instantiation: ty.c:GetPESTimestamp
49
50
static inline bool ExtractPESTimestamp( const uint8_t *p_data, uint8_t i_flags, ts_90khz_t *ret )
51
0
{
52
    /* !warn broken muxers set incorrect flags. see #17773 and #19140 */
53
    /* check marker bits, and i_flags = b 0010, 0011 or 0001 */
54
0
    if((p_data[0] & 0xC1) != 0x01 ||
55
0
       (p_data[2] & 0x01) != 0x01 ||
56
0
       (p_data[4] & 0x01) != 0x01 ||
57
0
       (p_data[0] & 0x30) == 0 || /* at least needs one bit */
58
0
       (p_data[0] >> 5) > i_flags ) /* needs flags 1x => 1x or flags 01 => 01 */
59
0
        return false;
60
61
62
0
    *ret =  GetPESTimestamp( p_data );
63
0
    return true;
64
0
}
Unexecuted instantiation: ps.c:ExtractPESTimestamp
Unexecuted instantiation: pva.c:ExtractPESTimestamp
Unexecuted instantiation: ty.c:ExtractPESTimestamp
65
66
/* PS SCR timestamp as defined in H222 2.5.3.2 */
67
static inline ts_90khz_t ExtractPackHeaderTimestamp( const uint8_t *p_data )
68
0
{
69
    /* prefixed by 2 bits 01 */
70
0
    return  ((ts_90khz_t)(p_data[0]&0x38 ) << 27)|
71
0
            ((ts_90khz_t)(p_data[0]&0x03 ) << 28)|
72
0
             (ts_90khz_t)(p_data[1] << 20)|
73
0
            ((ts_90khz_t)(p_data[2]&0xf8 ) << 12)|
74
0
            ((ts_90khz_t)(p_data[2]&0x03 ) << 13)|
75
0
             (ts_90khz_t)(p_data[3] << 5) |
76
0
             (ts_90khz_t)(p_data[4] >> 3);
77
0
}
Unexecuted instantiation: ps.c:ExtractPackHeaderTimestamp
Unexecuted instantiation: pva.c:ExtractPackHeaderTimestamp
Unexecuted instantiation: ty.c:ExtractPackHeaderTimestamp
78
79
typedef struct
80
{
81
    ts_90khz_t i_dts;
82
    ts_90khz_t i_pts;
83
    uint8_t i_stream_id;
84
    bool b_scrambling;
85
    unsigned i_size;
86
} ts_pes_header_t;
87
88
static inline void ts_pes_header_init(ts_pes_header_t *h)
89
0
{
90
0
    h->i_dts = TS_90KHZ_INVALID;
91
0
    h->i_pts = TS_90KHZ_INVALID;
92
0
    h->i_stream_id = 0;
93
0
    h->b_scrambling = false;
94
0
    h->i_size = 0;
95
0
}
Unexecuted instantiation: ps.c:ts_pes_header_init
Unexecuted instantiation: pva.c:ts_pes_header_init
Unexecuted instantiation: ty.c:ts_pes_header_init
96
97
inline
98
static int ParsePESHeader( struct vlc_logger *p_logger, const uint8_t *p_header, size_t i_header,
99
                           ts_pes_header_t *h )
100
0
{
101
0
    unsigned i_skip;
102
103
0
    if ( i_header < 9 )
104
0
        return VLC_EGENERIC;
105
106
0
    if( p_header[0] != 0 || p_header[1] != 0 || p_header[2] != 1 )
107
0
        return VLC_EGENERIC;
108
109
0
    h->i_stream_id = p_header[3];
110
111
0
    switch( p_header[3] )
112
0
    {
113
0
    case STREAM_ID_PROGRAM_STREAM_MAP:
114
0
    case STREAM_ID_PADDING:
115
0
    case STREAM_ID_PRIVATE_STREAM_2:
116
0
    case STREAM_ID_ECM:
117
0
    case STREAM_ID_EMM:
118
0
    case STREAM_ID_PROGRAM_STREAM_DIRECTORY:
119
0
    case STREAM_ID_DSM_CC:
120
0
    case STREAM_ID_H222_1_TYPE_E:
121
0
        i_skip = 6;
122
0
        h->b_scrambling = false;
123
0
        break;
124
0
    default:
125
0
        if( ( p_header[6]&0xC0 ) == 0x80 )
126
0
        {
127
            /* mpeg2 PES */
128
0
            i_skip = p_header[8] + 9;
129
130
0
            h->b_scrambling = p_header[6]&0x30;
131
132
0
            if( p_header[7]&0x80 )    /* has pts */
133
0
            {
134
0
                if( i_header >= 9 + 5 )
135
0
                   (void) ExtractPESTimestamp( &p_header[9], p_header[7] >> 6, &h->i_pts );
136
137
0
                if( ( p_header[7]&0x40 ) &&    /* has dts */
138
0
                    i_header >= 14 + 5 )
139
0
                   (void) ExtractPESTimestamp( &p_header[14], 0x01, &h->i_dts );
140
0
            }
141
0
        }
142
0
        else
143
0
        {
144
            /* FIXME?: WTH do we have undocumented MPEG1 packet stuff here ?
145
               This code path should not be valid, but seems some ppl did
146
               put MPEG1 packets into PS or TS.
147
               Non spec reference for packet format on http://andrewduncan.net/mpeg/mpeg-1.html */
148
0
            i_skip = 6;
149
150
0
            h->b_scrambling = false;
151
152
0
            while( i_skip < 23 && p_header[i_skip] == 0xff )
153
0
            {
154
0
                i_skip++;
155
0
                if( i_header < i_skip + 1 )
156
0
                    return VLC_EGENERIC;
157
0
            }
158
0
            if( i_skip == 23 )
159
0
            {
160
0
                vlc_error( p_logger, "too much MPEG-1 stuffing" );
161
0
                return VLC_EGENERIC;
162
0
            }
163
            /* Skip STD buffer size */
164
0
            if( ( p_header[i_skip] & 0xC0 ) == 0x40 )
165
0
            {
166
0
                i_skip += 2;
167
0
            }
168
169
0
            if( i_header < i_skip + 1 )
170
0
                return VLC_EGENERIC;
171
172
0
            if(  p_header[i_skip]&0x20 )
173
0
            {
174
0
                if( i_header >= i_skip + 5 )
175
0
                    (void) ExtractPESTimestamp( &p_header[i_skip], p_header[i_skip] >> 4, &h->i_pts );
176
177
0
                if( ( p_header[i_skip]&0x10 ) &&     /* has dts */
178
0
                    i_header >= i_skip + 10 )
179
0
                {
180
0
                    (void) ExtractPESTimestamp( &p_header[i_skip+5], 0x01, &h->i_dts );
181
0
                    i_skip += 10;
182
0
                }
183
0
                else
184
0
                {
185
0
                    i_skip += 5;
186
0
                }
187
0
            }
188
0
            else
189
0
            {
190
0
                if( (p_header[i_skip] & 0xFF) != 0x0F ) /* No pts/dts, lowest bits set to 0x0F */
191
0
                    return VLC_EGENERIC;
192
0
                i_skip += 1;
193
0
            }
194
0
        }
195
0
        break;
196
0
    }
197
198
0
    h->i_size = i_skip;
199
0
    return VLC_SUCCESS;
200
0
}
Unexecuted instantiation: ps.c:ParsePESHeader
Unexecuted instantiation: pva.c:ParsePESHeader
Unexecuted instantiation: ty.c:ParsePESHeader
201
202
#endif