Coverage Report

Created: 2023-06-07 07:26

/src/vlc/modules/packetizer/packetizer_helper.h
Line
Count
Source (jump to first uncovered line)
1
/*****************************************************************************
2
 * packetizer_helper.h: Packetizer helpers
3
 *****************************************************************************
4
 * Copyright (C) 2009 Laurent Aimar
5
 *
6
 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
7
 *
8
 * This program is free software; you can redistribute it and/or modify it
9
 * under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation; either version 2.1 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
 * GNU Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program; if not, write to the Free Software Foundation,
20
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21
 *****************************************************************************/
22
23
#ifndef VLC_PACKETIZER_HELPER_H_
24
#define VLC_PACKETIZER_HELPER_H_
25
26
#include <vlc_block.h>
27
28
enum
29
{
30
    STATE_NOSYNC,
31
    STATE_SYNC,
32
    STATE_HEADER,
33
    STATE_NEXT_SYNC,
34
    STATE_GET_DATA,
35
    STATE_SEND_DATA,
36
    STATE_CUSTOM_FIRST,
37
};
38
39
typedef void (*packetizer_reset_t)( void *p_private, bool b_flush );
40
typedef block_t *(*packetizer_parse_t)( void *p_private, bool *pb_ts_used, block_t * );
41
typedef block_t *(*packetizer_drain_t)( void *p_private );
42
typedef int (*packetizer_validate_t)( void *p_private, block_t * );
43
44
typedef struct
45
{
46
    int i_state;
47
    block_bytestream_t bytestream;
48
    size_t i_offset;
49
50
    int i_startcode;
51
    const uint8_t *p_startcode;
52
    block_startcode_helper_t pf_startcode_helper;
53
54
    int i_au_prepend;
55
    const uint8_t *p_au_prepend;
56
57
    unsigned i_au_min_size;
58
59
    void *p_private;
60
    packetizer_reset_t    pf_reset;
61
    packetizer_parse_t    pf_parse;
62
    packetizer_validate_t pf_validate;
63
    packetizer_drain_t    pf_drain;
64
65
} packetizer_t;
66
67
static inline void packetizer_Init( packetizer_t *p_pack,
68
                                    const uint8_t *p_startcode, int i_startcode,
69
                                    block_startcode_helper_t pf_start_helper,
70
                                    const uint8_t *p_au_prepend, int i_au_prepend,
71
                                    unsigned i_au_min_size,
72
                                    packetizer_reset_t pf_reset,
73
                                    packetizer_parse_t pf_parse,
74
                                    packetizer_validate_t pf_validate,
75
                                    packetizer_drain_t pf_drain,
76
                                    void *p_private )
77
0
{
78
0
    p_pack->i_state = STATE_NOSYNC;
79
0
    block_BytestreamInit( &p_pack->bytestream );
80
0
    p_pack->i_offset = 0;
81
82
0
    p_pack->i_au_prepend = i_au_prepend;
83
0
    p_pack->p_au_prepend = p_au_prepend;
84
0
    p_pack->i_au_min_size = i_au_min_size;
85
86
0
    p_pack->i_startcode = i_startcode;
87
0
    p_pack->p_startcode = p_startcode;
88
0
    p_pack->pf_startcode_helper = pf_start_helper;
89
0
    p_pack->pf_reset = pf_reset;
90
0
    p_pack->pf_parse = pf_parse;
91
0
    p_pack->pf_validate = pf_validate;
92
0
    p_pack->pf_drain = pf_drain;
93
0
    p_pack->p_private = p_private;
94
0
}
Unexecuted instantiation: a52.c:packetizer_Init
Unexecuted instantiation: dts.c:packetizer_Init
Unexecuted instantiation: flac.c:packetizer_Init
Unexecuted instantiation: h264.c:packetizer_Init
Unexecuted instantiation: hevc.c:packetizer_Init
Unexecuted instantiation: mlp.c:packetizer_Init
Unexecuted instantiation: mpeg4audio.c:packetizer_Init
Unexecuted instantiation: mpeg4video.c:packetizer_Init
Unexecuted instantiation: mpegaudio.c:packetizer_Init
Unexecuted instantiation: mpegvideo.c:packetizer_Init
Unexecuted instantiation: vc1.c:packetizer_Init
95
96
static inline void packetizer_Clean( packetizer_t *p_pack )
97
0
{
98
0
    block_BytestreamRelease( &p_pack->bytestream );
99
0
}
Unexecuted instantiation: a52.c:packetizer_Clean
Unexecuted instantiation: dts.c:packetizer_Clean
Unexecuted instantiation: flac.c:packetizer_Clean
Unexecuted instantiation: h264.c:packetizer_Clean
Unexecuted instantiation: hevc.c:packetizer_Clean
Unexecuted instantiation: mlp.c:packetizer_Clean
Unexecuted instantiation: mpeg4audio.c:packetizer_Clean
Unexecuted instantiation: mpeg4video.c:packetizer_Clean
Unexecuted instantiation: mpegaudio.c:packetizer_Clean
Unexecuted instantiation: mpegvideo.c:packetizer_Clean
Unexecuted instantiation: vc1.c:packetizer_Clean
100
101
static inline void packetizer_Flush( packetizer_t *p_pack )
102
0
{
103
0
    p_pack->i_state = STATE_NOSYNC;
104
0
    block_BytestreamEmpty( &p_pack->bytestream );
105
0
    p_pack->i_offset = 0;
106
0
    p_pack->pf_reset( p_pack->p_private, true );
107
0
}
Unexecuted instantiation: a52.c:packetizer_Flush
Unexecuted instantiation: dts.c:packetizer_Flush
Unexecuted instantiation: flac.c:packetizer_Flush
Unexecuted instantiation: h264.c:packetizer_Flush
Unexecuted instantiation: hevc.c:packetizer_Flush
Unexecuted instantiation: mlp.c:packetizer_Flush
Unexecuted instantiation: mpeg4audio.c:packetizer_Flush
Unexecuted instantiation: mpeg4video.c:packetizer_Flush
Unexecuted instantiation: mpegaudio.c:packetizer_Flush
Unexecuted instantiation: mpegvideo.c:packetizer_Flush
Unexecuted instantiation: vc1.c:packetizer_Flush
108
109
static block_t *packetizer_PacketizeBlock( packetizer_t *p_pack, block_t **pp_block )
110
0
{
111
0
    block_t *p_block = ( pp_block ) ? *pp_block : NULL;
112
113
0
    if( p_block == NULL && p_pack->bytestream.p_block == NULL )
114
0
        return NULL;
115
116
0
    if( p_block && unlikely( p_block->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) )
117
0
    {
118
0
        block_t *p_drained = packetizer_PacketizeBlock( p_pack, NULL );
119
0
        if( p_drained )
120
0
            return p_drained;
121
122
0
        p_pack->i_state = STATE_NOSYNC;
123
0
        block_BytestreamEmpty( &p_pack->bytestream );
124
0
        p_pack->i_offset = 0;
125
0
        p_pack->pf_reset( p_pack->p_private, false );
126
0
    }
127
128
0
    if( p_block )
129
0
        block_BytestreamPush( &p_pack->bytestream, p_block );
130
131
0
    for( ;; )
132
0
    {
133
0
        bool b_used_ts;
134
0
        block_t *p_pic;
135
136
0
        switch( p_pack->i_state )
137
0
        {
138
0
        case STATE_NOSYNC:
139
            /* Find a startcode */
140
0
            if( !block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
141
0
                                                p_pack->p_startcode, p_pack->i_startcode,
142
0
                                                p_pack->pf_startcode_helper, NULL ) )
143
0
                p_pack->i_state = STATE_NEXT_SYNC;
144
145
0
            if( p_pack->i_offset )
146
0
            {
147
0
                block_SkipBytes( &p_pack->bytestream, p_pack->i_offset );
148
0
                p_pack->i_offset = 0;
149
0
                block_BytestreamFlush( &p_pack->bytestream );
150
0
            }
151
152
0
            if( p_pack->i_state != STATE_NEXT_SYNC )
153
0
                return NULL; /* Need more data */
154
155
0
            p_pack->i_offset = 1; /* To find next startcode */
156
            /* fallthrough */
157
158
0
        case STATE_NEXT_SYNC:
159
            /* Find the next startcode */
160
0
            if( block_FindStartcodeFromOffset( &p_pack->bytestream, &p_pack->i_offset,
161
0
                                               p_pack->p_startcode, p_pack->i_startcode,
162
0
                                               p_pack->pf_startcode_helper, NULL ) )
163
0
            {
164
0
                if( pp_block /* not flushing */ || !p_pack->bytestream.p_chain )
165
0
                    return NULL; /* Need more data */
166
167
                /* When flushing and we don't find a startcode, suppose that
168
                 * the data extend up to the end */
169
0
                p_pack->i_offset = block_BytestreamRemaining(&p_pack->bytestream);
170
0
                if( p_pack->i_offset == 0 )
171
0
                    return NULL;
172
173
0
                if( p_pack->i_offset <= (size_t)p_pack->i_startcode &&
174
0
                    (p_pack->bytestream.p_block->i_flags & BLOCK_FLAG_AU_END) == 0 )
175
0
                    return NULL;
176
0
            }
177
178
0
            block_BytestreamFlush( &p_pack->bytestream );
179
180
            /* Get the new fragment and set the pts/dts */
181
0
            block_t *p_block_bytestream = p_pack->bytestream.p_block;
182
183
0
            p_pic = block_Alloc( p_pack->i_offset + p_pack->i_au_prepend );
184
0
            p_pic->i_pts = p_block_bytestream->i_pts;
185
0
            p_pic->i_dts = p_block_bytestream->i_dts;
186
187
            /* Do not wait for next sync code if notified block ends AU */
188
0
            if( (p_block_bytestream->i_flags & BLOCK_FLAG_AU_END) &&
189
0
                 p_block_bytestream->i_buffer == p_pack->i_offset )
190
0
            {
191
0
                p_pic->i_flags |= BLOCK_FLAG_AU_END;
192
0
            }
193
194
0
            block_GetBytes( &p_pack->bytestream, &p_pic->p_buffer[p_pack->i_au_prepend],
195
0
                            p_pic->i_buffer - p_pack->i_au_prepend );
196
0
            if( p_pack->i_au_prepend > 0 )
197
0
                memcpy( p_pic->p_buffer, p_pack->p_au_prepend, p_pack->i_au_prepend );
198
199
0
            p_pack->i_offset = 0;
200
201
            /* Parse the NAL */
202
0
            if( p_pic->i_buffer < p_pack->i_au_min_size )
203
0
            {
204
0
                block_Release( p_pic );
205
0
                p_pic = NULL;
206
0
            }
207
0
            else
208
0
            {
209
0
                p_pic = p_pack->pf_parse( p_pack->p_private, &b_used_ts, p_pic );
210
0
                if( b_used_ts )
211
0
                {
212
0
                    p_block_bytestream->i_dts = VLC_TICK_INVALID;
213
0
                    p_block_bytestream->i_pts = VLC_TICK_INVALID;
214
0
                }
215
0
            }
216
217
0
            if( !p_pic )
218
0
            {
219
0
                p_pack->i_state = STATE_NOSYNC;
220
0
                break;
221
0
            }
222
0
            if( p_pack->pf_validate( p_pack->p_private, p_pic ) )
223
0
            {
224
0
                p_pack->i_state = STATE_NOSYNC;
225
0
                block_Release( p_pic );
226
0
                break;
227
0
            }
228
229
            /* So p_block doesn't get re-added several times */
230
0
            if( pp_block )
231
0
                *pp_block = block_BytestreamPop( &p_pack->bytestream );
232
233
0
            p_pack->i_state = STATE_NOSYNC;
234
235
0
            return p_pic;
236
0
        }
237
0
    }
238
0
}
Unexecuted instantiation: a52.c:packetizer_PacketizeBlock
Unexecuted instantiation: dts.c:packetizer_PacketizeBlock
Unexecuted instantiation: flac.c:packetizer_PacketizeBlock
Unexecuted instantiation: h264.c:packetizer_PacketizeBlock
Unexecuted instantiation: hevc.c:packetizer_PacketizeBlock
Unexecuted instantiation: mlp.c:packetizer_PacketizeBlock
Unexecuted instantiation: mpeg4audio.c:packetizer_PacketizeBlock
Unexecuted instantiation: mpeg4video.c:packetizer_PacketizeBlock
Unexecuted instantiation: mpegaudio.c:packetizer_PacketizeBlock
Unexecuted instantiation: mpegvideo.c:packetizer_PacketizeBlock
Unexecuted instantiation: vc1.c:packetizer_PacketizeBlock
239
240
static block_t *packetizer_Packetize( packetizer_t *p_pack, block_t **pp_block )
241
0
{
242
0
    block_t *p_out = packetizer_PacketizeBlock( p_pack, pp_block );
243
0
    if( p_out )
244
0
        return p_out;
245
    /* handle caller drain */
246
0
    if( pp_block == NULL && p_pack->pf_drain )
247
0
    {
248
0
        p_out = p_pack->pf_drain( p_pack->p_private );
249
0
        if( p_out && p_pack->pf_validate( p_pack->p_private, p_out ) )
250
0
        {
251
0
            block_Release( p_out );
252
0
            p_out = NULL;
253
0
        }
254
0
    }
255
0
    return p_out;
256
0
}
Unexecuted instantiation: a52.c:packetizer_Packetize
Unexecuted instantiation: dts.c:packetizer_Packetize
Unexecuted instantiation: flac.c:packetizer_Packetize
Unexecuted instantiation: h264.c:packetizer_Packetize
Unexecuted instantiation: hevc.c:packetizer_Packetize
Unexecuted instantiation: mlp.c:packetizer_Packetize
Unexecuted instantiation: mpeg4audio.c:packetizer_Packetize
Unexecuted instantiation: mpeg4video.c:packetizer_Packetize
Unexecuted instantiation: mpegaudio.c:packetizer_Packetize
Unexecuted instantiation: mpegvideo.c:packetizer_Packetize
Unexecuted instantiation: vc1.c:packetizer_Packetize
257
258
static inline void packetizer_Header( packetizer_t *p_pack,
259
                                      const uint8_t *p_header, int i_header )
260
0
{
261
0
    block_t *p_init = block_Alloc( i_header );
262
0
    if( !p_init )
263
0
        return;
264
265
0
    memcpy( p_init->p_buffer, p_header, i_header );
266
267
0
    block_t *p_pic;
268
0
    while( ( p_pic = packetizer_Packetize( p_pack, &p_init ) ) )
269
0
        block_Release( p_pic ); /* Should not happen (only sequence header) */
270
0
    while( ( p_pic = packetizer_Packetize( p_pack, NULL ) ) )
271
0
        block_Release( p_pic );
272
273
0
    p_pack->i_state = STATE_NOSYNC;
274
0
    block_BytestreamEmpty( &p_pack->bytestream );
275
0
    p_pack->i_offset = 0;
276
0
}
Unexecuted instantiation: a52.c:packetizer_Header
Unexecuted instantiation: dts.c:packetizer_Header
Unexecuted instantiation: flac.c:packetizer_Header
Unexecuted instantiation: h264.c:packetizer_Header
Unexecuted instantiation: hevc.c:packetizer_Header
Unexecuted instantiation: mlp.c:packetizer_Header
Unexecuted instantiation: mpeg4audio.c:packetizer_Header
Unexecuted instantiation: mpeg4video.c:packetizer_Header
Unexecuted instantiation: mpegaudio.c:packetizer_Header
Unexecuted instantiation: mpegvideo.c:packetizer_Header
Unexecuted instantiation: vc1.c:packetizer_Header
277
278
#endif
279