Coverage Report

Created: 2026-05-30 08:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/packetizer/copy.c
Line
Count
Source
1
/*****************************************************************************
2
 * copy.c
3
 *****************************************************************************
4
 * Copyright (C) 2001, 2002, 2006 VLC authors and VideoLAN
5
 *
6
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7
 *          Eric Petit <titer@videolan.org>
8
 *
9
 * This program is free software; you can redistribute it and/or modify it
10
 * under the terms of the GNU Lesser General Public License as published by
11
 * the Free Software Foundation; either version 2.1 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
 * GNU Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public License
20
 * along with this program; if not, write to the Free Software Foundation,
21
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22
 *****************************************************************************/
23
24
/*****************************************************************************
25
 * Preamble
26
 *****************************************************************************/
27
28
#ifdef HAVE_CONFIG_H
29
# include "config.h"
30
#endif
31
32
#include <vlc_common.h>
33
#include <vlc_plugin.h>
34
#include <vlc_codec.h>
35
#include <vlc_block.h>
36
#include <vlc_bits.h>
37
38
/*****************************************************************************
39
 * Module descriptor
40
 *****************************************************************************/
41
static int  Open ( vlc_object_t * );
42
static void Close( vlc_object_t * );
43
44
150
vlc_module_begin ()
45
75
    set_subcategory( SUBCAT_SOUT_PACKETIZER )
46
75
    set_description( N_("Copy packetizer") )
47
75
    set_capability( "video packetizer", 1 )
48
150
    set_callbacks( Open, Close )
49
75
    add_submodule()
50
75
        set_capability( "audio packetizer", 1 )
51
150
        set_callbacks( Open, Close )
52
75
    add_submodule()
53
75
        set_capability( "spu packetizer", 1 )
54
150
        set_callbacks( Open, Close )
55
75
vlc_module_end ()
56
57
/*****************************************************************************
58
 * Local prototypes
59
 *****************************************************************************/
60
typedef struct
61
{
62
    block_t *p_block;
63
    void (*pf_parse)( decoder_t *, block_t * );
64
} decoder_sys_t;
65
66
static block_t *Packetize   ( decoder_t *, block_t ** );
67
static block_t *PacketizeSub( decoder_t *, block_t ** );
68
static void Flush( decoder_t * );
69
70
static void ParseWMV3( decoder_t *, block_t * );
71
72
/*****************************************************************************
73
 * Open: probe the packetizer and return score
74
 *****************************************************************************
75
 * Tries to launch a decoder and return score so that the interface is able
76
 * to choose.
77
 *****************************************************************************/
78
static int Open( vlc_object_t *p_this )
79
2.15M
{
80
2.15M
    decoder_t     *p_dec = (decoder_t*)p_this;
81
2.15M
    decoder_sys_t *p_sys;
82
83
2.15M
    if( p_dec->fmt_in->i_cat != AUDIO_ES &&
84
40.4k
        p_dec->fmt_in->i_cat != VIDEO_ES &&
85
21.7k
        p_dec->fmt_in->i_cat != SPU_ES )
86
0
    {
87
0
        msg_Err( p_dec, "invalid ES type" );
88
0
        return VLC_EGENERIC;
89
0
    }
90
91
2.15M
    p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
92
2.15M
    if (unlikely(p_sys == NULL))
93
0
        return VLC_ENOMEM;
94
95
2.15M
    p_sys->p_block    = NULL;
96
2.15M
    switch( p_dec->fmt_in->i_codec )
97
2.15M
    {
98
172
    case VLC_CODEC_WMV3:
99
172
        p_sys->pf_parse = ParseWMV3;
100
172
        break;
101
2.15M
    default:
102
2.15M
        p_sys->pf_parse = NULL;
103
2.15M
        break;
104
2.15M
    }
105
106
2.15M
    vlc_fourcc_t fcc = p_dec->fmt_in->i_codec;
107
    /* Fix the value of the fourcc for audio */
108
2.15M
    if( p_dec->fmt_in->i_cat == AUDIO_ES )
109
2.11M
    {
110
2.11M
        fcc = vlc_fourcc_GetCodecAudio( p_dec->fmt_in->i_codec,
111
2.11M
                                                     p_dec->fmt_in->audio.i_bitspersample );
112
2.11M
        if( !fcc )
113
318
        {
114
318
            msg_Err( p_dec, "unknown raw audio sample size" );
115
318
            free( p_sys );
116
318
            return VLC_EGENERIC;
117
318
        }
118
2.11M
    }
119
120
    /* Create the output format */
121
2.15M
    es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in );
122
2.15M
    p_dec->fmt_out.i_codec = fcc;
123
2.15M
    if( p_dec->fmt_in->i_cat == SPU_ES )
124
21.7k
        p_dec->pf_packetize = PacketizeSub;
125
2.13M
    else
126
2.13M
        p_dec->pf_packetize = Packetize;
127
2.15M
    p_dec->pf_flush = Flush;
128
2.15M
    p_dec->pf_get_cc = NULL;
129
130
2.15M
    return VLC_SUCCESS;
131
2.15M
}
132
133
/*****************************************************************************
134
 * Close:
135
 *****************************************************************************/
136
static void Close( vlc_object_t *p_this )
137
2.15M
{
138
2.15M
    decoder_t     *p_dec = (decoder_t*)p_this;
139
2.15M
    decoder_sys_t *p_sys = p_dec->p_sys;
140
141
2.15M
    if( p_sys->p_block )
142
2.11M
    {
143
2.11M
        block_ChainRelease( p_sys->p_block );
144
2.11M
    }
145
146
2.15M
    free( p_dec->p_sys );
147
2.15M
}
148
149
static void Flush( decoder_t *p_dec )
150
0
{
151
0
    decoder_sys_t *p_sys = p_dec->p_sys;
152
0
    block_t *p_ret = p_sys->p_block;
153
0
    if ( p_ret )
154
0
    {
155
0
        block_Release( p_ret );
156
0
        p_sys->p_block = NULL;
157
0
    }
158
0
}
159
160
/*****************************************************************************
161
 * Packetize: packetize an unit (here copy a complete block )
162
 *****************************************************************************/
163
static block_t *Packetize ( decoder_t *p_dec, block_t **pp_block )
164
133M
{
165
133M
    block_t *p_block;
166
133M
    decoder_sys_t *p_sys = p_dec->p_sys;
167
133M
    block_t *p_ret = p_sys->p_block;
168
169
133M
    if( pp_block == NULL || *pp_block == NULL )
170
66.8M
        return NULL;
171
66.8M
    if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
172
0
    {
173
0
        block_Release( *pp_block );
174
0
        return NULL;
175
0
    }
176
177
66.8M
    p_block = *pp_block;
178
66.8M
    *pp_block = NULL;
179
180
66.8M
    if( p_block->i_dts == VLC_TICK_INVALID )
181
7.30k
    {
182
7.30k
        p_block->i_dts = p_block->i_pts;
183
7.30k
    }
184
185
66.8M
    if( p_block->i_dts == VLC_TICK_INVALID )
186
7.23k
    {
187
7.23k
        msg_Dbg( p_dec, "need valid dts" );
188
7.23k
        block_Release( p_block );
189
7.23k
        return NULL;
190
7.23k
    }
191
192
66.8M
    if( p_ret != NULL && p_block->i_pts > p_ret->i_pts )
193
64.1M
    {
194
64.1M
        if (p_dec->fmt_in->i_codec != VLC_CODEC_OPUS)
195
63.8M
            p_ret->i_length = p_block->i_pts - p_ret->i_pts;
196
64.1M
    }
197
66.8M
    p_sys->p_block = p_block;
198
199
66.8M
    if( p_ret && p_sys->pf_parse )
200
248
        p_sys->pf_parse( p_dec, p_ret );
201
66.8M
    return p_ret;
202
66.8M
}
203
204
/*****************************************************************************
205
 * PacketizeSub: packetize an unit (here copy a complete block )
206
 *****************************************************************************/
207
static block_t *PacketizeSub( decoder_t *p_dec, block_t **pp_block )
208
1.31M
{
209
1.31M
    block_t *p_block;
210
211
1.31M
    if( pp_block == NULL || *pp_block == NULL )
212
663k
        return NULL;
213
652k
    if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
214
2.49k
    {
215
2.49k
        block_Release( *pp_block );
216
2.49k
        return NULL;
217
2.49k
    }
218
219
649k
    p_block = *pp_block;
220
649k
    *pp_block = NULL;
221
222
649k
    if( p_block->i_dts == VLC_TICK_INVALID )
223
17.8k
    {
224
17.8k
        p_block->i_dts = p_block->i_pts;
225
17.8k
    }
226
227
649k
    if( p_block->i_dts == VLC_TICK_INVALID )
228
7.57k
    {
229
7.57k
        msg_Dbg( p_dec, "need valid dts" );
230
7.57k
        block_Release( p_block );
231
7.57k
        return NULL;
232
7.57k
    }
233
234
642k
    return p_block;
235
649k
}
236
237
/* Parse WMV3 packet and extract frame type information */
238
static void ParseWMV3( decoder_t *p_dec, block_t *p_block )
239
248
{
240
248
    bs_t s;
241
242
    /* Parse Sequence header */
243
248
    bs_init( &s, p_dec->fmt_in->p_extra, p_dec->fmt_in->i_extra );
244
248
    if( bs_read( &s, 2 ) == 3 )
245
0
        return;
246
248
    bs_skip( &s, 22 );
247
248
    const bool b_range_reduction = bs_read( &s, 1 );
248
248
    const bool b_has_frames = bs_read( &s, 3 ) > 0;
249
248
    bs_skip( &s, 2 );
250
248
    const bool b_frame_interpolation = bs_read( &s, 1 );
251
248
    if( bs_eof( &s ) )
252
3
        return;
253
254
    /* Parse frame type */
255
245
    bs_init( &s, p_block->p_buffer, p_block->i_buffer );
256
245
    bs_skip( &s, b_frame_interpolation +
257
245
                 2 +
258
245
                 b_range_reduction );
259
260
245
    p_block->i_flags &= ~BLOCK_FLAG_TYPE_MASK;
261
245
    if( bs_read( &s, 1 ) )
262
161
        p_block->i_flags |= BLOCK_FLAG_TYPE_P;
263
84
    else if( !b_has_frames || bs_read( &s, 1 ) )
264
67
        p_block->i_flags |= BLOCK_FLAG_TYPE_I;
265
17
    else
266
17
        p_block->i_flags |= BLOCK_FLAG_TYPE_B;
267
245
}
268