/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 |