Coverage Report

Created: 2026-08-13 07:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/spudec/spudec.c
Line
Count
Source
1
/*****************************************************************************
2
 * spudec.c : SPU decoder thread
3
 *****************************************************************************
4
 * Copyright (C) 2000-2001, 2006 VLC authors and VideoLAN
5
 *
6
 * Authors: Sam Hocevar <sam@zoy.org>
7
 *          Laurent Aimar <fenrir@via.ecp.fr>
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
#ifdef HAVE_CONFIG_H
28
# include "config.h"
29
#endif
30
31
#include <vlc_common.h>
32
#include <vlc_plugin.h>
33
#include <vlc_codec.h>
34
35
#include "spudec.h"
36
37
/*****************************************************************************
38
 * Module descriptor.
39
 *****************************************************************************/
40
static int  DecoderOpen   ( vlc_object_t * );
41
static int  PacketizerOpen( vlc_object_t * );
42
static void Close         ( vlc_object_t * );
43
44
#define DVDSUBTRANS_DISABLE_TEXT N_("Disable DVD subtitle transparency")
45
#define DVDSUBTRANS_DISABLE_LONGTEXT N_("Removes all transparency effects " \
46
                                        "used in DVD subtitles.")
47
48
168
vlc_module_begin ()
49
84
    set_description( N_("DVD subtitles decoder") )
50
84
    set_shortname( N_("DVD subtitles") )
51
84
    set_capability( "spu decoder", 75 )
52
84
    set_subcategory( SUBCAT_INPUT_SCODEC )
53
84
    set_callbacks( DecoderOpen, Close )
54
55
84
    add_bool( "dvdsub-transparency", false,
56
84
              DVDSUBTRANS_DISABLE_TEXT, DVDSUBTRANS_DISABLE_LONGTEXT )
57
84
    add_submodule ()
58
84
    set_description( N_("DVD subtitles packetizer") )
59
84
    set_capability( "spu packetizer", 50 )
60
168
    set_callbacks( PacketizerOpen, Close )
61
84
vlc_module_end ()
62
63
/*****************************************************************************
64
 * Local prototypes
65
 *****************************************************************************/
66
static block_t *      Reassemble( decoder_t *, block_t * );
67
static int            Decode    ( decoder_t *, block_t * );
68
static block_t *      Packetize ( decoder_t *, block_t ** );
69
70
static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
71
45.0k
{
72
45.0k
    decoder_t     *p_dec = (decoder_t*)p_this;
73
45.0k
    decoder_sys_t *p_sys;
74
75
45.0k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_SPU )
76
42.1k
        return VLC_EGENERIC;
77
78
2.91k
    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
79
2.91k
    if( !p_sys )
80
0
        return VLC_ENOMEM;
81
82
2.91k
    p_sys->b_packetizer = b_packetizer;
83
2.91k
    p_sys->b_disabletrans = var_InheritBool( p_dec, "dvdsub-transparency" );
84
    /* a track marked forced shows only its forced captions */
85
2.91k
    p_sys->b_forcedonly = p_dec->fmt_in->subs.b_forced;
86
2.91k
    p_sys->i_spu_size = 0;
87
2.91k
    p_sys->buffer     = NULL;
88
2.91k
    p_sys->buffer_size = 0;
89
2.91k
    p_sys->i_spu      = 0;
90
2.91k
    p_sys->p_block    = NULL;
91
92
2.91k
    if( b_packetizer )
93
1.45k
    {
94
1.45k
        p_dec->pf_packetize  = Packetize;
95
1.45k
        es_format_Copy( &p_dec->fmt_out, p_dec->fmt_in );
96
1.45k
        p_dec->fmt_out.i_codec = VLC_CODEC_SPU;
97
1.45k
    }
98
1.45k
    else
99
1.45k
    {
100
1.45k
        p_dec->fmt_out.i_codec = VLC_CODEC_SPU;
101
1.45k
        p_dec->pf_decode    = Decode;
102
1.45k
    }
103
104
2.91k
    return VLC_SUCCESS;
105
2.91k
}
106
107
static int DecoderOpen( vlc_object_t *p_this )
108
22.4k
{
109
22.4k
    return OpenCommon( p_this, false );
110
22.4k
}
111
112
static int PacketizerOpen( vlc_object_t *p_this )
113
22.6k
{
114
22.6k
    return OpenCommon( p_this, true );
115
22.6k
}
116
117
/*****************************************************************************
118
 * Close:
119
 *****************************************************************************/
120
static void Close( vlc_object_t *p_this )
121
2.91k
{
122
2.91k
    decoder_t     *p_dec = (decoder_t*)p_this;
123
2.91k
    decoder_sys_t *p_sys = p_dec->p_sys;
124
125
2.91k
    if( p_sys->p_block )
126
370
    {
127
370
        block_ChainRelease( p_sys->p_block );
128
370
    }
129
130
2.91k
    free( p_sys->buffer );
131
2.91k
    free( p_sys );
132
2.91k
}
133
134
/*****************************************************************************
135
 * Decode:
136
 *****************************************************************************/
137
static int Decode( decoder_t *p_dec, block_t *p_block )
138
79.6k
{
139
79.6k
    decoder_sys_t *p_sys = p_dec->p_sys;
140
79.6k
    block_t       *p_spu_block;
141
142
79.6k
    if( p_block == NULL ) /* No Drain */
143
69.2k
        return VLCDEC_SUCCESS;
144
10.4k
    p_spu_block = Reassemble( p_dec, p_block );
145
146
10.4k
    if( ! p_spu_block )
147
0
    {
148
0
        return VLCDEC_SUCCESS;
149
0
    }
150
151
10.4k
    size_t block_size;
152
10.4k
    vlc_frame_ChainProperties( p_spu_block, NULL, &block_size, NULL );
153
10.4k
    if ( p_sys->buffer_size < block_size )
154
371
    {
155
371
        void *bigger = realloc( p_sys->buffer, block_size );
156
371
        if ( unlikely(bigger == NULL) )
157
0
        {
158
0
            return VLCDEC_ECRITICAL;
159
0
        }
160
371
        p_sys->buffer = bigger;
161
371
        p_sys->buffer_size = block_size;
162
371
    }
163
10.4k
    p_sys->i_spu = block_ChainExtract( p_spu_block, p_sys->buffer, block_size );
164
10.4k
    p_sys->i_pts = p_spu_block->i_pts;
165
10.4k
    block_ChainRelease( p_spu_block );
166
167
    /* Parse and decode */
168
10.4k
    ParsePacket( p_dec, decoder_QueueSub );
169
170
    /* reinit context */
171
10.4k
    p_sys->i_spu_size = 0;
172
10.4k
    p_sys->i_rle_size = 0;
173
10.4k
    p_sys->i_spu      = 0;
174
10.4k
    p_sys->p_block    = NULL;
175
176
10.4k
    return VLCDEC_SUCCESS;
177
10.4k
}
178
179
/*****************************************************************************
180
 * Packetize:
181
 *****************************************************************************/
182
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
183
79.6k
{
184
79.6k
    decoder_sys_t *p_sys = p_dec->p_sys;
185
79.6k
    if( pp_block == NULL ) /* No Drain */
186
1.45k
        return NULL;
187
78.2k
    block_t *p_block = *pp_block; *pp_block = NULL;
188
78.2k
    if( p_block == NULL )
189
10.4k
        return NULL;
190
191
67.8k
    block_t *p_spu = Reassemble( p_dec, p_block );
192
193
67.8k
    if( ! p_spu )
194
57.4k
    {
195
57.4k
        return NULL;
196
57.4k
    }
197
198
10.4k
    p_spu->i_dts = p_spu->i_pts;
199
10.4k
    p_spu->i_length = VLC_TICK_INVALID;
200
201
    /* reinit context */
202
10.4k
    p_sys->i_spu_size = 0;
203
10.4k
    p_sys->i_rle_size = 0;
204
10.4k
    p_sys->i_spu      = 0;
205
10.4k
    p_sys->p_block    = NULL;
206
207
10.4k
    return block_ChainGather( p_spu );
208
67.8k
}
209
210
/*****************************************************************************
211
 * Reassemble:
212
 *****************************************************************************/
213
static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
214
78.2k
{
215
78.2k
    decoder_sys_t *p_sys = p_dec->p_sys;
216
217
78.2k
    if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
218
0
    {
219
0
        block_Release( p_block );
220
0
        return NULL;
221
0
    }
222
223
78.2k
    if( p_sys->i_spu_size <= 0 &&
224
25.0k
        ( p_block->i_pts == VLC_TICK_INVALID || p_block->i_buffer < 4 ) )
225
1.32k
    {
226
1.32k
        msg_Dbg( p_dec, "invalid starting packet (size < 4 or pts <=0)" );
227
1.32k
        msg_Dbg( p_dec, "spu size: %d, i_pts: %"PRId64" i_buffer: %zu",
228
1.32k
                 p_sys->i_spu_size, p_block->i_pts, p_block->i_buffer );
229
1.32k
        block_Release( p_block );
230
1.32k
        return NULL;
231
1.32k
    }
232
233
76.9k
    block_ChainAppend( &p_sys->p_block, p_block );
234
76.9k
    p_sys->i_spu += p_block->i_buffer;
235
236
76.9k
    if( p_sys->i_spu_size <= 0 )
237
23.7k
    {
238
23.7k
        p_sys->i_spu_size = ( p_block->p_buffer[0] << 8 )|
239
23.7k
            p_block->p_buffer[1];
240
23.7k
        p_sys->i_rle_size = ( ( p_block->p_buffer[2] << 8 )|
241
23.7k
            p_block->p_buffer[3] ) - 4;
242
243
        /* msg_Dbg( p_dec, "i_spu_size=%d i_rle=%d",
244
                    p_sys->i_spu_size, p_sys->i_rle_size ); */
245
246
23.7k
        if( p_sys->i_spu_size <= 0 || p_sys->i_rle_size >= p_sys->i_spu_size )
247
2.53k
        {
248
2.53k
            p_sys->i_spu_size = 0;
249
2.53k
            p_sys->i_rle_size = 0;
250
2.53k
            p_sys->i_spu      = 0;
251
2.53k
            p_sys->p_block    = NULL;
252
253
2.53k
            block_Release( p_block );
254
2.53k
            return NULL;
255
2.53k
        }
256
23.7k
    }
257
258
74.3k
    if( p_sys->i_spu >= p_sys->i_spu_size )
259
20.8k
    {
260
        /* We have a complete sub */
261
20.8k
        if( p_sys->i_spu > p_sys->i_spu_size )
262
20.8k
            msg_Dbg( p_dec, "SPU packets size=%d should be %d",
263
20.8k
                     p_sys->i_spu, p_sys->i_spu_size );
264
265
20.8k
        return p_sys->p_block;
266
20.8k
    }
267
53.5k
    return NULL;
268
74.3k
}