Coverage Report

Created: 2026-03-07 07:40

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
104
vlc_module_begin ()
45
52
    set_subcategory( SUBCAT_SOUT_PACKETIZER )
46
52
    set_description( N_("Copy packetizer") )
47
52
    set_capability( "video packetizer", 1 )
48
104
    set_callbacks( Open, Close )
49
52
    add_submodule()
50
52
        set_capability( "audio packetizer", 1 )
51
104
        set_callbacks( Open, Close )
52
52
    add_submodule()
53
52
        set_capability( "spu packetizer", 1 )
54
104
        set_callbacks( Open, Close )
55
52
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
1.91M
{
80
1.91M
    decoder_t     *p_dec = (decoder_t*)p_this;
81
1.91M
    decoder_sys_t *p_sys;
82
83
1.91M
    if( p_dec->fmt_in->i_cat != AUDIO_ES &&
84
44.8k
        p_dec->fmt_in->i_cat != VIDEO_ES &&
85
19.0k
        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
1.91M
    p_dec->p_sys = p_sys = malloc( sizeof(*p_sys) );
92
1.91M
    if (unlikely(p_sys == NULL))
93
0
        return VLC_ENOMEM;
94
95
1.91M
    p_sys->p_block    = NULL;
96
1.91M
    switch( p_dec->fmt_in->i_codec )
97
1.91M
    {
98
241
    case VLC_CODEC_WMV3:
99
241
        p_sys->pf_parse = ParseWMV3;
100
241
        break;
101
1.91M
    default:
102
1.91M
        p_sys->pf_parse = NULL;
103
1.91M
        break;
104
1.91M
    }
105
106
1.91M
    vlc_fourcc_t fcc = p_dec->fmt_in->i_codec;
107
    /* Fix the value of the fourcc for audio */
108
1.91M
    if( p_dec->fmt_in->i_cat == AUDIO_ES )
109
1.86M
    {
110
1.86M
        fcc = vlc_fourcc_GetCodecAudio( p_dec->fmt_in->i_codec,
111
1.86M
                                                     p_dec->fmt_in->audio.i_bitspersample );
112
1.86M
        if( !fcc )
113
1.20k
        {
114
1.20k
            msg_Err( p_dec, "unknown raw audio sample size" );
115
1.20k
            free( p_sys );
116
1.20k
            return VLC_EGENERIC;
117
1.20k
        }
118
1.86M
    }
119
120
    /* Create the output format */
121
1.91M
    es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in );
122
1.91M
    p_dec->fmt_out.i_codec = fcc;
123
1.91M
    if( p_dec->fmt_in->i_cat == SPU_ES )
124
19.0k
        p_dec->pf_packetize = PacketizeSub;
125
1.89M
    else
126
1.89M
        p_dec->pf_packetize = Packetize;
127
1.91M
    p_dec->pf_flush = Flush;
128
1.91M
    p_dec->pf_get_cc = NULL;
129
130
1.91M
    return VLC_SUCCESS;
131
1.91M
}
132
133
/*****************************************************************************
134
 * Close:
135
 *****************************************************************************/
136
static void Close( vlc_object_t *p_this )
137
1.91M
{
138
1.91M
    decoder_t     *p_dec = (decoder_t*)p_this;
139
1.91M
    decoder_sys_t *p_sys = p_dec->p_sys;
140
141
1.91M
    if( p_sys->p_block )
142
1.85M
    {
143
1.85M
        block_ChainRelease( p_sys->p_block );
144
1.85M
    }
145
146
1.91M
    free( p_dec->p_sys );
147
1.91M
}
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
93.7M
{
165
93.7M
    block_t *p_block;
166
93.7M
    decoder_sys_t *p_sys = p_dec->p_sys;
167
93.7M
    block_t *p_ret = p_sys->p_block;
168
169
93.7M
    if( pp_block == NULL || *pp_block == NULL )
170
46.2M
        return NULL;
171
47.4M
    if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
172
0
    {
173
0
        block_Release( *pp_block );
174
0
        return NULL;
175
0
    }
176
177
47.4M
    p_block = *pp_block;
178
47.4M
    *pp_block = NULL;
179
180
47.4M
    if( p_block->i_dts == VLC_TICK_INVALID )
181
90.3k
    {
182
90.3k
        p_block->i_dts = p_block->i_pts;
183
90.3k
    }
184
185
47.4M
    if( p_block->i_dts == VLC_TICK_INVALID )
186
90.2k
    {
187
90.2k
        msg_Dbg( p_dec, "need valid dts" );
188
90.2k
        block_Release( p_block );
189
90.2k
        return NULL;
190
90.2k
    }
191
192
47.3M
    if( p_ret != NULL && p_block->i_pts > p_ret->i_pts )
193
45.0M
    {
194
45.0M
        if (p_dec->fmt_in->i_codec != VLC_CODEC_OPUS)
195
44.8M
            p_ret->i_length = p_block->i_pts - p_ret->i_pts;
196
45.0M
    }
197
47.3M
    p_sys->p_block = p_block;
198
199
47.3M
    if( p_ret && p_sys->pf_parse )
200
199
        p_sys->pf_parse( p_dec, p_ret );
201
47.3M
    return p_ret;
202
47.4M
}
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.74M
{
209
1.74M
    block_t *p_block;
210
211
1.74M
    if( pp_block == NULL || *pp_block == NULL )
212
880k
        return NULL;
213
864k
    if( (*pp_block)->i_flags&(BLOCK_FLAG_CORRUPTED) )
214
995
    {
215
995
        block_Release( *pp_block );
216
995
        return NULL;
217
995
    }
218
219
863k
    p_block = *pp_block;
220
863k
    *pp_block = NULL;
221
222
863k
    if( p_block->i_dts == VLC_TICK_INVALID )
223
10.8k
    {
224
10.8k
        p_block->i_dts = p_block->i_pts;
225
10.8k
    }
226
227
863k
    if( p_block->i_dts == VLC_TICK_INVALID )
228
1.32k
    {
229
1.32k
        msg_Dbg( p_dec, "need valid dts" );
230
1.32k
        block_Release( p_block );
231
1.32k
        return NULL;
232
1.32k
    }
233
234
862k
    return p_block;
235
863k
}
236
237
/* Parse WMV3 packet and extract frame type information */
238
static void ParseWMV3( decoder_t *p_dec, block_t *p_block )
239
199
{
240
199
    bs_t s;
241
242
    /* Parse Sequence header */
243
199
    bs_init( &s, p_dec->fmt_in->p_extra, p_dec->fmt_in->i_extra );
244
199
    if( bs_read( &s, 2 ) == 3 )
245
0
        return;
246
199
    bs_skip( &s, 22 );
247
199
    const bool b_range_reduction = bs_read( &s, 1 );
248
199
    const bool b_has_frames = bs_read( &s, 3 ) > 0;
249
199
    bs_skip( &s, 2 );
250
199
    const bool b_frame_interpolation = bs_read( &s, 1 );
251
199
    if( bs_eof( &s ) )
252
0
        return;
253
254
    /* Parse frame type */
255
199
    bs_init( &s, p_block->p_buffer, p_block->i_buffer );
256
199
    bs_skip( &s, b_frame_interpolation +
257
199
                 2 +
258
199
                 b_range_reduction );
259
260
199
    p_block->i_flags &= ~BLOCK_FLAG_TYPE_MASK;
261
199
    if( bs_read( &s, 1 ) )
262
142
        p_block->i_flags |= BLOCK_FLAG_TYPE_P;
263
57
    else if( !b_has_frames || bs_read( &s, 1 ) )
264
56
        p_block->i_flags |= BLOCK_FLAG_TYPE_I;
265
1
    else
266
1
        p_block->i_flags |= BLOCK_FLAG_TYPE_B;
267
199
}
268