Coverage Report

Created: 2026-09-28 07:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/dvbsub.c
Line
Count
Source
1
/*****************************************************************************
2
 * dvbsub.c : DVB subtitles decoder
3
 *            DVB subtitles encoder (developed for Anevia, www.anevia.com)
4
 *****************************************************************************
5
 * Copyright (C) 2003 ANEVIA
6
 * Copyright (C) 2003-2009 VLC authors and VideoLAN
7
 *
8
 * Authors: Gildas Bazin <gbazin@videolan.org>
9
 *          Damien LUCAS <damien.lucas@anevia.com>
10
 *          Laurent Aimar <fenrir@via.ecp.fr>
11
 *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
12
 *          Derk-Jan Hartman <hartman #at# videolan dot org>
13
 *          Simon Hailes <simon _a_ screen.subtitling.com>
14
 *
15
 * This program is free software; you can redistribute it and/or modify it
16
 * under the terms of the GNU Lesser General Public License as published by
17
 * the Free Software Foundation; either version 2.1 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23
 * GNU Lesser General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU Lesser General Public License
26
 * along with this program; if not, write to the Free Software Foundation, Inc.,
27
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
28
 *****************************************************************************/
29
30
/*****************************************************************************
31
 * Preamble
32
 *
33
 * FIXME:
34
 * DVB subtitles coded as strings of characters are not handled correctly.
35
 * The character codes in the string should actually be indexes referring to a
36
 * character table identified in the subtitle descriptor.
37
 *
38
 * The spec is quite vague in this area, but what is meant is perhaps that it
39
 * refers to the character index in the codepage belonging to the language
40
 * specified in the subtitle descriptor. Potentially it's designed for widechar
41
 * (but not for UTF-*) codepages.
42
 *****************************************************************************
43
 *
44
 *****************************************************************************
45
 * Notes on DDS (Display Definition Segment)
46
 * -----------------------------------------
47
 * DDS (Display Definition Segment) tells the decoder how the subtitle image
48
 * relates to the video image.
49
 * For SD, the subtitle image is always considered to be for display at
50
 * 720x576 (although it's assumed that for NTSC, this is 720x480, this
51
 * is not documented well) Also, for SD, the subtitle image is drawn 'on
52
 * the glass' (i.e. after video scaling, letterbox, etc.)
53
 * For 'HD' (subs marked type 0x14/0x24 in PSI), a DDS must be present,
54
 * and the subs area is drawn onto the video area (scales if necessary).
55
 * The DDS tells the decoder what resolution the subtitle images were
56
 * intended for, and hence how to scale the subtitle images for a
57
 * particular video size
58
 * i.e. if HD video is presented as letterbox, the subs will be in the
59
 * same place on the video as if the video was presented on an HD set
60
 * indeed, if the HD video was pillarboxed by the decoder, the subs may
61
 * be cut off as well as the video. The intent here is that the subs can
62
 * be placed accurately on the video - something which was missed in the
63
 * original spec.
64
 *
65
 * A DDS may also specify a window - this is where the subs images are moved so that the (0,0)
66
 * origin of decode is offset.
67
 ********************************************************************************************/
68
69
#ifdef HAVE_CONFIG_H
70
# include "config.h"
71
#endif
72
73
#include <vlc_common.h>
74
#include <vlc_configuration.h>
75
#include <vlc_plugin.h>
76
#include <vlc_codec.h>
77
#include <vlc_sout.h>
78
#include <vlc_arrays.h>
79
80
#include <vlc_bits.h>
81
82
#include <limits.h>
83
#include <stdckdint.h>
84
85
/* #define DEBUG_DVBSUB 1 */
86
87
#define POSX_TEXT N_("Decoding X coordinate")
88
#define POSX_LONGTEXT N_("X coordinate of the rendered subtitle")
89
90
#define POSY_TEXT N_("Decoding Y coordinate")
91
#define POSY_LONGTEXT N_("Y coordinate of the rendered subtitle")
92
93
#define POS_TEXT N_("Subpicture position")
94
#define POS_LONGTEXT N_( \
95
  "You can enforce the subpicture position on the video " \
96
  "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
97
  "also use combinations of these values, e.g. 6=top-right).")
98
99
#define ENC_POSX_TEXT N_("Encoding X coordinate")
100
#define ENC_POSX_LONGTEXT N_("X coordinate of the encoded subtitle" )
101
#define ENC_POSY_TEXT N_("Encoding Y coordinate")
102
#define ENC_POSY_LONGTEXT N_("Y coordinate of the encoded subtitle" )
103
104
static const int pi_pos_values[] = {
105
    0,
106
    SUBPICTURE_ALIGN_LEFT,
107
    SUBPICTURE_ALIGN_RIGHT,
108
    SUBPICTURE_ALIGN_TOP,
109
    SUBPICTURE_ALIGN_BOTTOM,
110
    SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT,
111
    SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_RIGHT,
112
    SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_LEFT,
113
    SUBPICTURE_ALIGN_BOTTOM | SUBPICTURE_ALIGN_RIGHT,
114
};
115
static const char *const ppsz_pos_descriptions[] =
116
{ N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
117
  N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
118
119
/*****************************************************************************
120
 * Module descriptor.
121
 *****************************************************************************/
122
static int  Open ( vlc_object_t * );
123
static void Close( vlc_object_t * );
124
static int Decode( decoder_t *, block_t * );
125
static void Flush( decoder_t * );
126
127
#ifdef ENABLE_SOUT
128
static int OpenEncoder  ( vlc_object_t * );
129
static void CloseEncoder( encoder_t * );
130
static block_t *Encode  ( encoder_t *, subpicture_t * );
131
#endif
132
133
174
vlc_module_begin ()
134
87
#   define DVBSUB_CFG_PREFIX "dvbsub-"
135
87
    set_description( N_("DVB subtitles decoder") )
136
87
    set_shortname( N_("DVB subtitles") )
137
87
    set_capability( "spu decoder", 80 )
138
87
    set_subcategory( SUBCAT_INPUT_SCODEC )
139
87
    set_callbacks( Open, Close )
140
141
87
    add_integer( DVBSUB_CFG_PREFIX "position", 8, POS_TEXT, POS_LONGTEXT )
142
87
        change_integer_list( pi_pos_values, ppsz_pos_descriptions )
143
87
    add_integer( DVBSUB_CFG_PREFIX "x", -1, POSX_TEXT, POSX_LONGTEXT )
144
87
    add_integer( DVBSUB_CFG_PREFIX "y", -1, POSY_TEXT, POSY_LONGTEXT )
145
146
87
#ifdef ENABLE_SOUT
147
87
#   define ENC_CFG_PREFIX "sout-dvbsub-"
148
87
    add_submodule ()
149
87
    set_description( N_("DVB subtitles encoder") )
150
87
    set_capability( "spu encoder", 100 )
151
87
    set_callback( OpenEncoder )
152
153
87
    add_integer( ENC_CFG_PREFIX "x", -1, ENC_POSX_TEXT, ENC_POSX_LONGTEXT )
154
87
    add_integer( ENC_CFG_PREFIX "y", -1, ENC_POSY_TEXT, ENC_POSY_LONGTEXT )
155
87
#endif
156
87
vlc_module_end ()
157
158
static const char *const ppsz_enc_options[] = { "x", "y", NULL };
159
160
/****************************************************************************
161
 * Local structures
162
 ****************************************************************************
163
 * Those structures refer closely to the ETSI 300 743 Object model
164
 ****************************************************************************/
165
166
/* The object definition gives the position of the object in a region [7.2.5] */
167
typedef struct dvbsub_objectdef_s
168
{
169
    int i_id;
170
    int i_type;
171
    int i_x;
172
    int i_y;
173
    int i_fg_pc;
174
    int i_bg_pc;
175
    char *psz_text; /* for string of characters objects */
176
177
} dvbsub_objectdef_t;
178
179
/* The entry in the palette CLUT */
180
typedef struct
181
{
182
    uint8_t                 Y;
183
    uint8_t                 Cr;
184
    uint8_t                 Cb;
185
    uint8_t                 T;
186
187
} dvbsub_color_t;
188
189
/* The displays dimensions [7.2.1] */
190
typedef struct dvbsub_display_s
191
{
192
    uint8_t                 i_id;
193
    uint8_t                 i_version;
194
195
    uint16_t                i_width_minus1;
196
    uint16_t                i_height_minus1;
197
198
    bool                    b_windowed;
199
    /* these values are only relevant if windowed */
200
    int                     i_x;
201
    int                     i_y;
202
    int                     i_max_x;
203
    int                     i_max_y;
204
205
} dvbsub_display_t;
206
207
/* [7.2.4] */
208
typedef struct dvbsub_clut_s
209
{
210
    uint8_t                 i_id;
211
    uint8_t                 i_version;
212
    dvbsub_color_t          c_2b[4];
213
    dvbsub_color_t          c_4b[16];
214
    dvbsub_color_t          c_8b[256];
215
    int                     c_8b_entries;
216
    video_color_range_t     color_range;
217
    int                     dynamic_range_and_colour_gamut;
218
219
    struct dvbsub_clut_s    *p_next;
220
221
} dvbsub_clut_t;
222
223
/* The Region is an area on the image [7.2.3]
224
 * with a list of the object definitions associated and a CLUT */
225
typedef struct dvbsub_region_s
226
{
227
    int i_id;
228
    int i_version;
229
    int i_x;
230
    int i_y;
231
    int i_width;
232
    int i_height;
233
    int i_level_comp;
234
    int i_depth;
235
    int i_clut;
236
237
    uint8_t *p_pixbuf;
238
239
    int                    i_object_defs;
240
    dvbsub_objectdef_t     *p_object_defs;
241
242
    struct dvbsub_region_s *p_next;
243
244
} dvbsub_region_t;
245
246
/* The object definition gives the position of the object in a region */
247
typedef struct dvbsub_regiondef_s
248
{
249
    int i_id;
250
    int i_x;
251
    int i_y;
252
253
} dvbsub_regiondef_t;
254
255
/* The page defines the list of regions [7.2.2] */
256
typedef struct
257
{
258
    int i_id;
259
    int i_timeout; /* in seconds */
260
    int i_state;
261
    int i_version;
262
263
    int                i_region_defs;
264
    dvbsub_regiondef_t *p_region_defs;
265
266
} dvbsub_page_t;
267
268
typedef struct
269
{
270
    bs_t               bs;
271
272
    /* Decoder internal data */
273
    int                i_id;
274
    int                i_ancillary_id;
275
    vlc_tick_t         i_pts;
276
277
    int                i_spu_position;
278
    int                i_spu_x;
279
    int                i_spu_y;
280
281
    bool               b_page;
282
    dvbsub_page_t      *p_page;
283
    dvbsub_region_t    *p_regions;
284
    dvbsub_clut_t      *p_cluts;
285
    /* this is very small, so keep forever */
286
    dvbsub_display_t   display;
287
    dvbsub_clut_t      default_clut;
288
} decoder_sys_t;
289
290
291
/* List of different SEGMENT TYPES */
292
/* According to EN 300-743, table 2 */
293
4.32k
#define DVBSUB_ST_PAGE_COMPOSITION      0x10
294
3.80k
#define DVBSUB_ST_REGION_COMPOSITION    0x11
295
2.88k
#define DVBSUB_ST_CLUT_DEFINITION       0x12
296
4.64k
#define DVBSUB_ST_OBJECT_DATA           0x13
297
4.85k
#define DVBSUB_ST_DISPLAY_DEFINITION    0x14
298
1.77k
#define DVBSUB_ST_ALTERNATE_CLUT        0x16
299
830
#define DVBSUB_ST_ENDOFDISPLAY          0x80
300
975
#define DVBSUB_ST_STUFFING              0xff
301
/* List of different OBJECT TYPES */
302
/* According to EN 300-743, table 6 */
303
0
#define DVBSUB_OT_BASIC_BITMAP          0x00
304
315k
#define DVBSUB_OT_BASIC_CHAR            0x01
305
315k
#define DVBSUB_OT_COMPOSITE_STRING      0x02
306
/* Pixel DATA TYPES */
307
/* According to EN 300-743, table 9 */
308
#define DVBSUB_DT_2BP_CODE_STRING       0x10
309
#define DVBSUB_DT_4BP_CODE_STRING       0x11
310
#define DVBSUB_DT_8BP_CODE_STRING       0x12
311
#define DVBSUB_DT_24_TABLE_DATA         0x20
312
#define DVBSUB_DT_28_TABLE_DATA         0x21
313
#define DVBSUB_DT_48_TABLE_DATA         0x22
314
#define DVBSUB_DT_END_LINE              0xf0
315
/* List of different Page Composition Segment state */
316
/* According to EN 300-743, 7.2.1 table 3 */
317
600
#define DVBSUB_PCS_STATE_ACQUISITION    0x01
318
4.54k
#define DVBSUB_PCS_STATE_CHANGE         0x02
319
/* According to EN 300-743, 7.2.8 table 33 */
320
1.04k
#define DVBSUB_ST_BITDEPTH_8BIT         0x00
321
10.3k
#define DVBSUB_ST_BITDEPTH_10BIT        0x01
322
/* According to EN 300-743, 7.2.8 table 34 */
323
2.32k
#define DVBSUB_ST_COLORIMETRY_CDS       -1
324
4
#define DVBSUB_ST_COLORIMETRY_SDR_709   0x00
325
0
#define DVBSUB_ST_COLORIMETRY_SDR_2020  0x01
326
0
#define DVBSUB_ST_COLORIMETRY_HDR_PQ    0x02
327
523
#define DVBSUB_ST_COLORIMETRY_HDR_HLG   0x03
328
329
/*****************************************************************************
330
 * Local prototypes
331
 *****************************************************************************/
332
static void decode_segment( decoder_t *, bs_t * );
333
static void decode_page_composition( decoder_t *, bs_t *, uint16_t );
334
static void decode_region_composition( decoder_t *, bs_t *, uint16_t );
335
static void decode_object( decoder_t *, bs_t *, uint16_t );
336
static void decode_display_definition( decoder_t *, bs_t *, uint16_t );
337
static void alternative_CLUT( decoder_t *, bs_t *, uint16_t );
338
static void decode_clut( decoder_t *, bs_t *, uint16_t );
339
static void free_all( decoder_t * );
340
341
static void default_clut_init( decoder_t * );
342
static void default_dds_init( decoder_t * );
343
344
static subpicture_t *render( decoder_t * );
345
346
/*****************************************************************************
347
 * Open: probe the decoder and return score
348
 *****************************************************************************
349
 * Tries to launch a decoder and return score so that the interface is able
350
 * to chose.
351
 *****************************************************************************/
352
static int Open( vlc_object_t *p_this )
353
25.7k
{
354
25.7k
    decoder_t     *p_dec = (decoder_t *) p_this;
355
25.7k
    decoder_sys_t *p_sys;
356
25.7k
    int i_posx, i_posy;
357
358
25.7k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_DVBS )
359
23.6k
    {
360
23.6k
        return VLC_EGENERIC;
361
23.6k
    }
362
363
2.12k
    p_dec->pf_decode = Decode;
364
2.12k
    p_dec->pf_flush  = Flush;
365
2.12k
    p_sys = p_dec->p_sys = calloc( 1, sizeof(decoder_sys_t) );
366
2.12k
    if( !p_sys )
367
0
        return VLC_ENOMEM;
368
369
2.12k
    p_sys->i_pts          = VLC_TICK_INVALID;
370
2.12k
    p_sys->i_id           = p_dec->fmt_in->subs.dvb.i_id & 0xFFFF;
371
2.12k
    p_sys->i_ancillary_id = p_dec->fmt_in->subs.dvb.i_id >> 16;
372
373
2.12k
    p_sys->p_regions      = NULL;
374
2.12k
    p_sys->p_cluts        = NULL;
375
2.12k
    p_sys->p_page         = NULL;
376
377
    /* configure for SD res in case DDS is not present */
378
2.12k
    default_dds_init( p_dec );
379
380
2.12k
    p_sys->i_spu_position = var_CreateGetInteger( p_this,
381
2.12k
                                    DVBSUB_CFG_PREFIX "position" );
382
2.12k
    i_posx = var_CreateGetInteger( p_this, DVBSUB_CFG_PREFIX "x" );
383
2.12k
    i_posy = var_CreateGetInteger( p_this, DVBSUB_CFG_PREFIX "y" );
384
385
    /* Check if subpicture position was overridden */
386
2.12k
    p_sys->i_spu_x = p_sys->i_spu_y = 0;
387
388
2.12k
    if( ( i_posx >= 0 ) && ( i_posy >= 0 ) )
389
0
    {
390
0
        p_sys->i_spu_x = i_posx;
391
0
        p_sys->i_spu_y = i_posy;
392
0
    }
393
394
2.12k
    p_dec->fmt_out.i_codec = 0;
395
396
2.12k
    default_clut_init( p_dec );
397
398
2.12k
    return VLC_SUCCESS;
399
2.12k
}
400
401
/*****************************************************************************
402
 * Close:
403
 *****************************************************************************/
404
static void Close( vlc_object_t *p_this )
405
2.12k
{
406
2.12k
    decoder_t     *p_dec = (decoder_t*) p_this;
407
2.12k
    decoder_sys_t *p_sys = p_dec->p_sys;
408
409
2.12k
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" );
410
2.12k
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" );
411
2.12k
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" );
412
413
2.12k
    free_all( p_dec );
414
2.12k
    free( p_sys );
415
2.12k
}
416
417
/*****************************************************************************
418
 * Flush:
419
 *****************************************************************************/
420
static void Flush( decoder_t *p_dec )
421
0
{
422
0
    decoder_sys_t *p_sys = p_dec->p_sys;
423
424
0
    p_sys->i_pts = VLC_TICK_INVALID;
425
0
}
426
427
/*****************************************************************************
428
 * Decode:
429
 *****************************************************************************/
430
static int Decode( decoder_t *p_dec, block_t *p_block )
431
12.9k
{
432
12.9k
    decoder_sys_t *p_sys = p_dec->p_sys;
433
434
12.9k
    if( p_block == NULL ) /* No Drain */
435
7.52k
        return VLCDEC_SUCCESS;
436
437
5.38k
    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
438
0
    {
439
0
        Flush( p_dec );
440
0
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
441
0
            goto end;
442
0
    }
443
444
    /* configure for SD res in case DDS is not present */
445
    /* a change of PTS is a good indication we must get a new DDS */
446
5.38k
    if( p_sys->i_pts != p_block->i_pts )
447
3.86k
        default_dds_init( p_dec );
448
449
5.38k
    p_sys->i_pts = p_block->i_pts;
450
5.38k
    if( p_sys->i_pts == VLC_TICK_INVALID )
451
2
    {
452
#ifdef DEBUG_DVBSUB
453
        /* Some DVB channels send stuffing segments in non-dated packets so
454
         * don't complain too loudly. */
455
        msg_Warn( p_dec, "non dated subtitle" );
456
#endif
457
2
        goto end;
458
2
    }
459
460
5.38k
    bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );
461
462
5.38k
    if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */
463
47
    {
464
47
        msg_Dbg( p_dec, "invalid data identifier" );
465
47
        goto end;
466
47
    }
467
468
5.33k
    if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */
469
62
    {
470
62
        msg_Dbg( p_dec, "invalid subtitle stream id" );
471
62
        goto end;
472
62
    }
473
474
#ifdef DEBUG_DVBSUB
475
    msg_Dbg( p_dec, "subtitle packet received: %"PRId64, p_sys->i_pts );
476
#endif
477
478
5.27k
    p_sys->b_page = false;
479
480
5.27k
    uint8_t i_sync_byte = bs_read( &p_sys->bs, 8 );
481
30.6k
    while( i_sync_byte == 0x0f ) /* Sync byte */
482
25.3k
    {
483
25.3k
        decode_segment( p_dec, &p_sys->bs );
484
25.3k
        i_sync_byte = bs_read( &p_sys->bs, 8 );
485
25.3k
    }
486
487
5.27k
    if( ( i_sync_byte & 0x3f ) != 0x3f ) /* End marker */
488
4.10k
    {
489
4.10k
        msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" );
490
4.10k
        goto end;
491
4.10k
    }
492
493
    /* Check if the page is to be displayed */
494
1.17k
    if( p_sys->p_page && p_sys->b_page )
495
588
    {
496
588
        subpicture_t *p_spu = render( p_dec );
497
588
        if( p_spu != NULL )
498
588
            decoder_QueueSub( p_dec, p_spu );
499
588
    }
500
501
5.38k
end:
502
5.38k
    block_Release(p_block);
503
5.38k
    return VLCDEC_SUCCESS;
504
1.17k
}
505
506
/* following functions are local */
507
508
/*****************************************************************************
509
 * default_clut_init: default clut as defined in EN 300-743 section 10
510
 *****************************************************************************/
511
static void default_clut_init( decoder_t *p_dec )
512
2.12k
{
513
2.12k
    decoder_sys_t *p_sys = p_dec->p_sys;
514
2.12k
    uint8_t i;
515
516
42.5k
#define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;
517
42.5k
#define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;
518
42.5k
#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256;
519
520
    /* 4 entries CLUT */
521
10.6k
    for( i = 0; i < 4; i++ )
522
8.50k
    {
523
8.50k
        uint8_t R = 0, G = 0, B = 0, T = 0;
524
525
8.50k
        if( !(i & 0x2) && !(i & 0x1) ) T = 0xFF;
526
6.37k
        else if( !(i & 0x2) && (i & 0x1) ) R = G = B = 0xFF;
527
4.25k
        else if( (i & 0x2) && !(i & 0x1) ) R = G = B = 0;
528
2.12k
        else R = G = B = 0x7F;
529
530
8.50k
        p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B);
531
8.50k
        p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B);
532
8.50k
        p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B);
533
8.50k
        p_sys->default_clut.c_2b[i].T = T;
534
8.50k
    }
535
536
    /* 16 entries CLUT */
537
36.1k
    for( i = 0; i < 16; i++ )
538
34.0k
    {
539
34.0k
        uint8_t R = 0, G = 0, B = 0, T = 0;
540
541
34.0k
        if( !(i & 0x8) )
542
17.0k
        {
543
17.0k
            if( !(i & 0x4) && !(i & 0x2) && !(i & 0x1) )
544
2.12k
            {
545
2.12k
                T = 0xFF;
546
2.12k
            }
547
14.8k
            else
548
14.8k
            {
549
14.8k
                R = (i & 0x1) ? 0xFF : 0;
550
14.8k
                G = (i & 0x2) ? 0xFF : 0;
551
14.8k
                B = (i & 0x4) ? 0xFF : 0;
552
14.8k
            }
553
17.0k
        }
554
17.0k
        else
555
17.0k
        {
556
17.0k
            R = (i & 0x1) ? 0x7F : 0;
557
17.0k
            G = (i & 0x2) ? 0x7F : 0;
558
17.0k
            B = (i & 0x4) ? 0x7F : 0;
559
17.0k
        }
560
561
34.0k
        p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B);
562
34.0k
        p_sys->default_clut.c_4b[i].Cr = RGB_TO_V(R,G,B);
563
34.0k
        p_sys->default_clut.c_4b[i].Cb = RGB_TO_U(R,G,B);
564
34.0k
        p_sys->default_clut.c_4b[i].T = T;
565
34.0k
    }
566
567
    /* 256 entries CLUT */
568
2.12k
    memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) );
569
2.12k
    p_sys->default_clut.c_8b_entries = 256;
570
2.12k
    p_sys->default_clut.color_range = COLOR_RANGE_LIMITED;
571
2.12k
    p_sys->default_clut.dynamic_range_and_colour_gamut = DVBSUB_ST_COLORIMETRY_CDS;
572
2.12k
}
573
574
static void decode_segment( decoder_t *p_dec, bs_t *s )
575
25.3k
{
576
25.3k
    decoder_sys_t *p_sys = p_dec->p_sys;
577
25.3k
    int i_type;
578
25.3k
    int i_page_id;
579
25.3k
    int i_size;
580
581
    /* sync_byte (already checked) */
582
    //bs_skip( s, 8 );
583
584
    /* segment type */
585
25.3k
    i_type = bs_read( s, 8 );
586
587
    /* page id */
588
25.3k
    i_page_id = bs_read( s, 16 );
589
590
    /* segment size */
591
25.3k
    i_size = bs_read( s, 16 );
592
593
25.3k
    if( ( i_page_id != p_sys->i_id ) &&
594
741
        ( i_page_id != p_sys->i_ancillary_id ) )
595
741
    {
596
#ifdef DEBUG_DVBSUB
597
        msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)",
598
                 i_page_id, p_sys->i_id );
599
#endif
600
741
        bs_skip( s,  8 * i_size );
601
741
        return;
602
741
    }
603
604
24.6k
    if( ( p_sys->i_ancillary_id != p_sys->i_id ) &&
605
0
        ( i_type == DVBSUB_ST_PAGE_COMPOSITION ) &&
606
0
        ( i_page_id == p_sys->i_ancillary_id ) )
607
0
    {
608
#ifdef DEBUG_DVBSUB
609
        msg_Dbg( p_dec, "skipped invalid ancillary subtitle packet" );
610
#endif
611
0
        bs_skip( s,  8 * i_size );
612
0
        return;
613
0
    }
614
615
#ifdef DEBUG_DVBSUB
616
    if( i_page_id == p_sys->i_id )
617
        msg_Dbg( p_dec, "segment (id: %i)", i_page_id );
618
    else
619
        msg_Dbg( p_dec, "ancillary segment (id: %i)", i_page_id );
620
#endif
621
622
24.6k
    switch( i_type )
623
24.6k
    {
624
4.32k
    case DVBSUB_ST_PAGE_COMPOSITION:
625
#ifdef DEBUG_DVBSUB
626
        msg_Dbg( p_dec, "decode_page_composition" );
627
#endif
628
4.32k
        decode_page_composition( p_dec, s, i_size );
629
4.32k
        break;
630
631
3.80k
    case DVBSUB_ST_REGION_COMPOSITION:
632
#ifdef DEBUG_DVBSUB
633
        msg_Dbg( p_dec, "decode_region_composition" );
634
#endif
635
3.80k
        decode_region_composition( p_dec, s, i_size );
636
3.80k
        break;
637
638
2.88k
    case DVBSUB_ST_CLUT_DEFINITION:
639
#ifdef DEBUG_DVBSUB
640
        msg_Dbg( p_dec, "decode_clut" );
641
#endif
642
2.88k
        decode_clut( p_dec, s, i_size );
643
2.88k
        break;
644
645
4.64k
    case DVBSUB_ST_OBJECT_DATA:
646
#ifdef DEBUG_DVBSUB
647
        msg_Dbg( p_dec, "decode_object" );
648
#endif
649
4.64k
        decode_object( p_dec, s, i_size );
650
4.64k
        break;
651
652
4.85k
    case DVBSUB_ST_DISPLAY_DEFINITION:
653
#ifdef DEBUG_DVBSUB
654
        msg_Dbg( p_dec, "decode_display_definition" );
655
#endif
656
4.85k
        decode_display_definition( p_dec, s, i_size );
657
4.85k
        break;
658
659
1.77k
    case DVBSUB_ST_ALTERNATE_CLUT:
660
#ifdef DEBUG_DVBSUB
661
        msg_Dbg( p_dec, "alternative_CLUT" );
662
#endif
663
1.77k
        alternative_CLUT( p_dec, s, i_size );
664
1.77k
        break;
665
666
830
    case DVBSUB_ST_ENDOFDISPLAY:
667
#ifdef DEBUG_DVBSUB
668
        msg_Dbg( p_dec, "end of display" );
669
#endif
670
830
        bs_skip( s,  8 * i_size );
671
830
        break;
672
673
975
    case DVBSUB_ST_STUFFING:
674
#ifdef DEBUG_DVBSUB
675
        msg_Dbg( p_dec, "skip stuffing" );
676
#endif
677
975
        bs_skip( s,  8 * i_size );
678
975
        break;
679
680
559
    default:
681
559
        msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type );
682
559
        bs_skip( s,  8 * i_size );
683
559
        break;
684
24.6k
    }
685
24.6k
}
686
687
static void decode_clut( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
688
2.88k
{
689
2.88k
    decoder_sys_t *p_sys = p_dec->p_sys;
690
2.88k
    uint16_t      i_processed_length;
691
2.88k
    dvbsub_clut_t *p_clut, *p_next;
692
2.88k
    int           i_id, i_version;
693
694
2.88k
    i_id             = bs_read( s, 8 );
695
2.88k
    i_version        = bs_read( s, 4 );
696
697
    /* Check if we already have this clut */
698
5.60k
    for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
699
4.92k
    {
700
4.92k
        if( p_clut->i_id == i_id ) break;
701
4.92k
    }
702
703
    /* Check version number */
704
2.88k
    if( p_clut && ( p_clut->i_version == i_version ) )
705
2.13k
    {
706
        /* Nothing to do */
707
2.13k
        bs_skip( s, 8 * i_segment_length - 12 );
708
2.13k
        return;
709
2.13k
    }
710
711
750
    if( !p_clut )
712
678
    {
713
#ifdef DEBUG_DVBSUB
714
        msg_Dbg( p_dec, "new clut: %i", i_id );
715
#endif
716
678
        p_clut = malloc( sizeof( dvbsub_clut_t ) );
717
678
        if( !p_clut )
718
0
            return;
719
678
        p_clut->p_next = p_sys->p_cluts;
720
678
        p_sys->p_cluts = p_clut;
721
678
    }
722
723
    /* Initialize to default clut */
724
750
    p_next = p_clut->p_next;
725
750
    *p_clut = p_sys->default_clut;
726
750
    p_clut->p_next = p_next;
727
728
    /* We don't have this version of the CLUT: Parse it */
729
750
    p_clut->i_version = i_version;
730
750
    p_clut->i_id = i_id;
731
750
    bs_skip( s, 4 ); /* Reserved bits */
732
750
    i_processed_length = 2;
733
333k
    while( i_processed_length < i_segment_length )
734
332k
    {
735
332k
        uint8_t y, cb, cr, t;
736
332k
        uint_fast8_t cid = bs_read( s, 8 );
737
332k
        uint_fast8_t type = bs_read( s, 3 );
738
739
332k
        bs_skip( s, 4 );
740
741
332k
        p_clut->color_range = bs_read( s, 1 ) ? COLOR_RANGE_FULL : COLOR_RANGE_LIMITED;
742
332k
        if( p_clut->color_range == COLOR_RANGE_FULL )
743
1.97k
        {
744
1.97k
            y  = bs_read( s, 8 );
745
1.97k
            cr = bs_read( s, 8 );
746
1.97k
            cb = bs_read( s, 8 );
747
1.97k
            t  = bs_read( s, 8 );
748
1.97k
            i_processed_length += 6;
749
1.97k
        }
750
330k
        else
751
330k
        {
752
330k
            y  = bs_read( s, 6 ) << 2;
753
330k
            cr = bs_read( s, 4 ) << 4;
754
330k
            cb = bs_read( s, 4 ) << 4;
755
330k
            t  = bs_read( s, 2 ) << 6;
756
330k
            i_processed_length += 4;
757
330k
        }
758
759
        /* We are not entirely compliant here as full transparency is indicated
760
         * with a luma value of zero, not a transparency value of 0xff
761
         * (full transparency would actually be 0xff + 1). */
762
332k
        if( y == 0 )
763
330k
        {
764
330k
            cr = cb = 0;
765
330k
            t  = 0xff;
766
330k
        }
767
768
        /* According to EN 300-743 section 7.2.3 note 1, type should
769
         * not have more than 1 bit set to one, but some streams don't
770
         * respect this note. */
771
332k
        if( ( type & 0x04 ) && ( cid < 4 ) )
772
656
        {
773
656
            p_clut->c_2b[cid].Y = y;
774
656
            p_clut->c_2b[cid].Cr = cr;
775
656
            p_clut->c_2b[cid].Cb = cb;
776
656
            p_clut->c_2b[cid].T = t;
777
656
        }
778
332k
        if( ( type & 0x02 ) && ( cid < 16 ) )
779
690
        {
780
690
            p_clut->c_4b[cid].Y = y;
781
690
            p_clut->c_4b[cid].Cr = cr;
782
690
            p_clut->c_4b[cid].Cb = cb;
783
690
            p_clut->c_4b[cid].T = t;
784
690
        }
785
332k
        if( type & 0x01 )
786
1.76k
        {
787
1.76k
            p_clut->c_8b[cid].Y = y;
788
1.76k
            p_clut->c_8b[cid].Cr = cr;
789
1.76k
            p_clut->c_8b[cid].Cb = cb;
790
1.76k
            p_clut->c_8b[cid].T = t;
791
1.76k
        }
792
332k
    }
793
750
}
794
795
static void decode_page_composition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
796
4.32k
{
797
4.32k
    decoder_sys_t *p_sys = p_dec->p_sys;
798
4.32k
    int i_version, i_state, i_timeout, i;
799
800
    /* A page is composed by 0 or more region */
801
4.32k
    i_timeout = bs_read( s, 8 );
802
4.32k
    i_version = bs_read( s, 4 );
803
4.32k
    i_state = bs_read( s, 2 );
804
4.32k
    bs_skip( s, 2 ); /* Reserved */
805
806
4.32k
    if( i_state == DVBSUB_PCS_STATE_CHANGE )
807
11
    {
808
        /* End of an epoch, reset decoder buffer */
809
#ifdef DEBUG_DVBSUB
810
        msg_Dbg( p_dec, "page composition mode change" );
811
#endif
812
11
        free_all( p_dec );
813
11
    }
814
4.31k
    else if( !p_sys->p_page && ( i_state != DVBSUB_PCS_STATE_ACQUISITION ) &&
815
218
             ( i_state != DVBSUB_PCS_STATE_CHANGE ) )
816
218
    {
817
        /* Not a full PCS, we need to wait for one */
818
218
        msg_Dbg( p_dec, "didn't receive an acquisition page yet" );
819
820
#if 0
821
        /* Try to start decoding even without an acquisition page */
822
        bs_skip( s,  8 * (i_segment_length - 2) );
823
        return;
824
#endif
825
218
    }
826
827
#ifdef DEBUG_DVBSUB
828
    if( i_state == DVBSUB_PCS_STATE_ACQUISITION )
829
        msg_Dbg( p_dec, "acquisition page composition" );
830
#endif
831
832
    /* Check version number */
833
4.32k
    if( p_sys->p_page && ( p_sys->p_page->i_version == i_version ) )
834
2.15k
    {
835
2.15k
        bs_skip( s,  8 * (i_segment_length - 2) );
836
2.15k
        return;
837
2.15k
    }
838
2.17k
    else if( p_sys->p_page )
839
1.56k
    {
840
1.56k
        if( p_sys->p_page->i_region_defs )
841
1.55k
            free( p_sys->p_page->p_region_defs );
842
1.56k
        p_sys->p_page->p_region_defs = NULL;
843
1.56k
        p_sys->p_page->i_region_defs = 0;
844
1.56k
    }
845
846
2.17k
    if( !p_sys->p_page )
847
611
    {
848
#ifdef DEBUG_DVBSUB
849
        msg_Dbg( p_dec, "new page" );
850
#endif
851
        /* Allocate a new page */
852
611
        p_sys->p_page = malloc( sizeof(dvbsub_page_t) );
853
611
        if( !p_sys->p_page )
854
0
            return;
855
611
    }
856
857
2.17k
    p_sys->p_page->i_version = i_version;
858
2.17k
    p_sys->p_page->i_timeout = i_timeout;
859
2.17k
    p_sys->b_page = true;
860
2.17k
    p_sys->p_page->p_region_defs = NULL;
861
2.17k
    p_sys->p_page->i_region_defs = 0;
862
863
    /* Number of regions */
864
2.17k
    uint16_t i_region_defs = (i_segment_length - 2) / 6;
865
866
2.17k
    if( i_region_defs == 0 ) return;
867
868
2.16k
    p_sys->p_page->p_region_defs =
869
2.16k
        vlc_alloc( i_region_defs, sizeof(dvbsub_regiondef_t) );
870
2.16k
    if( p_sys->p_page->p_region_defs )
871
2.16k
    {
872
2.16k
        p_sys->p_page->i_region_defs = i_region_defs;
873
68.0k
        for( i = 0; i < p_sys->p_page->i_region_defs; i++ )
874
65.8k
        {
875
65.8k
            p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 );
876
65.8k
            bs_skip( s, 8 ); /* Reserved */
877
65.8k
            p_sys->p_page->p_region_defs[i].i_x = bs_read( s, 16 );
878
65.8k
            p_sys->p_page->p_region_defs[i].i_y = bs_read( s, 16 );
879
880
#ifdef DEBUG_DVBSUB
881
            msg_Dbg( p_dec, "page_composition, region %i (%i,%i)",
882
                    i, p_sys->p_page->p_region_defs[i].i_x,
883
                    p_sys->p_page->p_region_defs[i].i_y );
884
#endif
885
65.8k
        }
886
2.16k
    }
887
2.16k
}
888
889
static void decode_region_composition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
890
3.80k
{
891
3.80k
    decoder_sys_t *p_sys = p_dec->p_sys;
892
3.80k
    dvbsub_region_t *p_region, **pp_region = &p_sys->p_regions;
893
3.80k
    int i_processed_length, i_id, i_version;
894
3.80k
    int i_width, i_height, i_level_comp, i_depth, i_clut;
895
3.80k
    int i_8_bg, i_4_bg, i_2_bg;
896
3.80k
    bool b_fill;
897
898
3.80k
    i_id = bs_read( s, 8 );
899
3.80k
    i_version = bs_read( s, 4 );
900
901
    /* Check if we already have this region */
902
4.87k
    for( p_region = p_sys->p_regions; p_region != NULL;
903
3.80k
         p_region = p_region->p_next )
904
3.94k
    {
905
3.94k
        pp_region = &p_region->p_next;
906
3.94k
        if( p_region->i_id == i_id ) break;
907
3.94k
    }
908
909
    /* Check version number */
910
3.80k
    if( p_region && ( p_region->i_version == i_version ) )
911
2.81k
    {
912
2.81k
        bs_skip( s, 8 * (i_segment_length - 1) - 4 );
913
2.81k
        return;
914
2.81k
    }
915
916
997
    if( !p_region )
917
930
    {
918
#ifdef DEBUG_DVBSUB
919
        msg_Dbg( p_dec, "new region: %i", i_id );
920
#endif
921
930
        p_region = *pp_region = calloc( 1, sizeof(dvbsub_region_t) );
922
930
        if( !p_region )
923
0
            return;
924
930
        p_region->p_object_defs = NULL;
925
930
        p_region->p_pixbuf = NULL;
926
930
        p_region->p_next = NULL;
927
930
    }
928
929
    /* Region attributes */
930
997
    p_region->i_id = i_id;
931
997
    p_region->i_version = i_version;
932
997
    b_fill = bs_read( s, 1 );
933
997
    bs_skip( s, 3 ); /* Reserved */
934
935
997
    i_width = bs_read( s, 16 );
936
997
    i_height = bs_read( s, 16 );
937
#ifdef DEBUG_DVBSUB
938
    msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height );
939
#endif
940
997
    i_level_comp = bs_read( s, 3 );
941
997
    i_depth = bs_read( s, 3 );
942
997
    bs_skip( s, 2 ); /* Reserved */
943
997
    i_clut = bs_read( s, 8 );
944
945
997
    i_8_bg = bs_read( s, 8 );
946
997
    i_4_bg = bs_read( s, 4 );
947
997
    i_2_bg = bs_read( s, 2 );
948
997
    bs_skip( s, 2 ); /* Reserved */
949
950
    /* Free old object defs */
951
10.3k
    while( p_region->i_object_defs )
952
9.32k
        free( p_region->p_object_defs[--p_region->i_object_defs].psz_text );
953
954
997
    free( p_region->p_object_defs );
955
997
    p_region->p_object_defs = NULL;
956
957
    /* Extra sanity checks */
958
997
    if( ( p_region->i_width != i_width ) ||
959
67
        ( p_region->i_height != i_height ) )
960
941
    {
961
941
        if( p_region->p_pixbuf )
962
13
        {
963
13
            msg_Dbg( p_dec, "region size changed (%dx%d->%dx%d)",
964
13
                     p_region->i_width, p_region->i_height, i_width, i_height );
965
13
        }
966
967
941
        size_t i_alloc;
968
941
        if( ckd_mul( &i_alloc, i_width, i_height ) || i_alloc == 0 )
969
11
        {
970
11
            free( p_region->p_pixbuf );
971
11
            p_region->p_pixbuf = NULL;
972
11
        }
973
930
        else
974
930
        {
975
930
            void *r_pixbuf = realloc( p_region->p_pixbuf, i_alloc );
976
930
            if( unlikely( r_pixbuf == NULL ) )
977
0
            {
978
0
                free( p_region->p_pixbuf );
979
0
                p_region->p_pixbuf = NULL;
980
0
            }
981
930
            else
982
930
                p_region->p_pixbuf = r_pixbuf;
983
930
            p_region->i_depth = 0;
984
930
        }
985
986
941
        b_fill = !!p_region->p_pixbuf;
987
941
    }
988
989
997
    if( p_region->i_depth &&
990
53
        ( ( p_region->i_depth != i_depth ) ||
991
44
          ( p_region->i_level_comp != i_level_comp ) ||
992
43
          ( p_region->i_clut != i_clut) ) )
993
13
    {
994
13
        msg_Dbg( p_dec, "region parameters changed (not allowed)" );
995
13
    }
996
997
    /* Erase background of region */
998
997
    if( b_fill )
999
955
    {
1000
955
        int i_background = ( i_depth == 1 ) ? i_2_bg :
1001
955
            ( ( i_depth == 2 ) ? i_4_bg : i_8_bg );
1002
955
        memset( p_region->p_pixbuf, i_background, (size_t)i_width * i_height );
1003
955
    }
1004
1005
997
    p_region->i_width = i_width;
1006
997
    p_region->i_height = i_height;
1007
997
    p_region->i_level_comp = i_level_comp;
1008
997
    p_region->i_depth = i_depth;
1009
997
    p_region->i_clut = i_clut;
1010
1011
    /* List of objects in the region */
1012
997
    i_processed_length = 10;
1013
1014
    /* Entry can be 6 or 8 bytes */
1015
997
    unsigned max_object_defs;
1016
997
    if( i_segment_length < 10 )
1017
11
        max_object_defs = 0;
1018
986
    else
1019
986
        max_object_defs = (i_segment_length - i_processed_length) / 6;
1020
997
    p_region->i_object_defs = 0;
1021
997
    p_region->p_object_defs = malloc( max_object_defs * sizeof(dvbsub_objectdef_t) );
1022
997
    if( !p_region->p_object_defs )
1023
0
        return;
1024
1025
316k
    while( i_processed_length + 6 <= i_segment_length )
1026
315k
    {
1027
315k
        dvbsub_objectdef_t *p_obj;
1028
1029
        /* We parse object properties */
1030
315k
        p_obj = &p_region->p_object_defs[p_region->i_object_defs];
1031
315k
        p_obj->i_id         = bs_read( s, 16 );
1032
315k
        p_obj->i_type       = bs_read( s, 2 );
1033
315k
        bs_skip( s, 2 ); /* Provider */
1034
315k
        p_obj->i_x          = bs_read( s, 12 );
1035
315k
        bs_skip( s, 4 ); /* Reserved */
1036
315k
        p_obj->i_y          = bs_read( s, 12 );
1037
315k
        p_obj->psz_text     = NULL;
1038
1039
315k
        i_processed_length += 6;
1040
1041
315k
        if( ( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ) ||
1042
315k
            ( p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING ) )
1043
199
        {
1044
199
            if( i_processed_length + 2 > i_segment_length )
1045
20
                break;
1046
179
            p_obj->i_fg_pc =  bs_read( s, 8 );
1047
179
            p_obj->i_bg_pc =  bs_read( s, 8 );
1048
179
            i_processed_length += 2;
1049
179
        }
1050
315k
        p_region->i_object_defs++;
1051
315k
    }
1052
997
}
1053
1054
/* ETSI 300 743 [7.2.8] */
1055
static void alternative_CLUT( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
1056
1.77k
{
1057
1.77k
    decoder_sys_t *p_sys = p_dec->p_sys;
1058
1.77k
    uint16_t      i_processed_length;
1059
1.77k
    int           i_id, i_version;
1060
1.77k
    dvbsub_clut_t *p_clut;
1061
1062
1.77k
    i_id = bs_read( s, 8 );
1063
1.77k
    i_version = bs_read( s, 4 );
1064
1065
    /* Check if we already have this clut */
1066
2.61k
    for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
1067
2.12k
    {
1068
2.12k
        if( p_clut->i_id == i_id )
1069
1.28k
        {
1070
            /* Check version number */
1071
1.28k
            if( p_clut->i_version == i_version )
1072
1.25k
            {
1073
                /* Nothing to do */
1074
1.25k
                bs_skip( s, 8 * i_segment_length - 12 );
1075
1.25k
                return;
1076
1.25k
            }
1077
1078
30
            break;
1079
1.28k
        }
1080
2.12k
    }
1081
1082
523
    if( !p_clut )
1083
493
    {
1084
#ifdef DEBUG_DVBSUB
1085
        msg_Dbg( p_dec, "new alternative clut: %i", i_id );
1086
#endif
1087
493
        p_clut = malloc( sizeof( dvbsub_clut_t ) );
1088
493
        if( !p_clut )
1089
0
            return;
1090
493
        p_clut->p_next = p_sys->p_cluts;
1091
493
        p_sys->p_cluts = p_clut;
1092
493
    }
1093
1094
    /* We don't have this version of the CLUT: Parse it */
1095
523
    p_clut->i_version = i_version;
1096
523
    p_clut->i_id = i_id;
1097
1098
523
    bs_skip( s, 4 ); // reserved_zero_future_use
1099
1100
    // CLUT_parameters
1101
523
    int CLUT_entry_max_number = bs_read( s, 2 );
1102
523
    int colour_component_type = bs_read( s, 2 );
1103
523
    int output_bit_depth = bs_read( s, 3 );
1104
523
    bs_skip( s, 1 ); // reserved_zero_future_use
1105
523
    int dynamic_range_and_colour_gamut = bs_read( s, 8 );
1106
1107
523
    bool error = false;
1108
523
    i_processed_length = 4;
1109
523
    if (output_bit_depth != DVBSUB_ST_BITDEPTH_8BIT &&
1110
100
        output_bit_depth != DVBSUB_ST_BITDEPTH_10BIT)
1111
93
    {
1112
93
        msg_Err( p_dec, "unsupported alternative clut bitdepth: %i", output_bit_depth );
1113
93
        error = true;
1114
93
    }
1115
523
    if (CLUT_entry_max_number != 0) // 0: 256 entries
1116
190
    {
1117
190
        msg_Err( p_dec, "unsupported alternative clut max entries: %i", CLUT_entry_max_number );
1118
190
        error = true;
1119
190
    }
1120
523
    if (colour_component_type != 0) // 0: YCbCr
1121
138
    {
1122
138
        msg_Err( p_dec, "unsupported alternative clut component type: %i", colour_component_type );
1123
138
        error = true;
1124
138
    }
1125
523
    if (dynamic_range_and_colour_gamut > DVBSUB_ST_COLORIMETRY_HDR_HLG)
1126
87
    {
1127
87
        msg_Err( p_dec, "unsupported alternative clut color range: %i", dynamic_range_and_colour_gamut );
1128
87
        error = true;
1129
87
    }
1130
523
    if (error)
1131
219
        goto done;
1132
1133
304
    p_clut->c_8b_entries = 0;
1134
10.4k
    while( i_processed_length < i_segment_length )
1135
10.2k
    {
1136
10.2k
        uint8_t y, cb, cr, t;
1137
10.2k
        if (output_bit_depth == DVBSUB_ST_BITDEPTH_10BIT)
1138
26
        {
1139
            // TODO: apply the palette locally to keep 10-bit values
1140
26
            y  = bs_read( s, 10 ) >> 2;
1141
26
            cr = bs_read( s, 10 ) >> 2;
1142
26
            cb = bs_read( s, 10 ) >> 2;
1143
26
            t  = bs_read( s, 10 ) >> 2;
1144
26
            i_processed_length += 5;
1145
26
        }
1146
10.2k
        else
1147
10.2k
        {
1148
10.2k
            y  = bs_read( s, 8 );
1149
10.2k
            cr = bs_read( s, 8 );
1150
10.2k
            cb = bs_read( s, 8 );
1151
10.2k
            t  = bs_read( s, 8 );
1152
10.2k
            i_processed_length += 4;
1153
10.2k
        }
1154
1155
        /* We are not entirely compliant here as full transparency is indicated
1156
         * with a luma value of zero, not a transparency value of 0xff
1157
         * (full transparency would actually be 0xff + 1). */
1158
10.2k
        if( y == 0 )
1159
9.28k
        {
1160
9.28k
            cr = cb = 0;
1161
9.28k
            t  = 0xff;
1162
9.28k
        }
1163
1164
10.2k
        p_clut->c_8b[p_clut->c_8b_entries].Y = y;
1165
10.2k
        p_clut->c_8b[p_clut->c_8b_entries].Cr = cr;
1166
10.2k
        p_clut->c_8b[p_clut->c_8b_entries].Cb = cb;
1167
10.2k
        p_clut->c_8b[p_clut->c_8b_entries].T = t;
1168
10.2k
        p_clut->c_8b_entries++;
1169
10.2k
        if (p_clut->c_8b_entries >= (int)ARRAY_SIZE(p_clut->c_8b))
1170
37
            break;
1171
10.2k
    }
1172
304
    p_clut->dynamic_range_and_colour_gamut = dynamic_range_and_colour_gamut;
1173
304
    p_clut->color_range = COLOR_RANGE_FULL;
1174
523
done:
1175
523
    bs_skip( s, 8 * (i_segment_length - i_processed_length) );
1176
523
}
1177
1178
/* ETSI 300 743 [7.2.1] */
1179
static void decode_display_definition( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
1180
4.85k
{
1181
4.85k
    decoder_sys_t *p_sys = p_dec->p_sys;
1182
4.85k
    uint16_t      i_processed_length = 40;
1183
4.85k
    int           i_version;
1184
1185
4.85k
    i_version        = bs_read( s, 4 );
1186
1187
    /* Check version number */
1188
4.85k
    if( p_sys->display.i_version == i_version )
1189
1.36k
    {
1190
        /* The definition did not change */
1191
1.36k
        bs_skip( s, 8*i_segment_length - 4 );
1192
1.36k
        return;
1193
1.36k
    }
1194
1195
#ifdef DEBUG_DVBSUB
1196
    msg_Dbg( p_dec, "new display definition: %i", i_version );
1197
#endif
1198
1199
    /* We don't have this version of the display definition: Parse it */
1200
3.48k
    p_sys->display.i_version = i_version;
1201
3.48k
    p_sys->display.b_windowed = bs_read( s, 1 );
1202
3.48k
    bs_skip( s, 3 ); /* Reserved bits */
1203
3.48k
    p_sys->display.i_width_minus1 = bs_read( s, 16 );
1204
3.48k
    p_sys->display.i_height_minus1 = bs_read( s, 16 );
1205
1206
3.48k
    if( p_sys->display.b_windowed )
1207
17
    {
1208
#ifdef DEBUG_DVBSUB
1209
        msg_Dbg( p_dec, "display definition with offsets (windowed)" );
1210
#endif
1211
        /* Coordinates are measured from the top left corner */
1212
17
        p_sys->display.i_x     = bs_read( s, 16 );
1213
17
        p_sys->display.i_max_x = bs_read( s, 16 );
1214
17
        p_sys->display.i_y     = bs_read( s, 16 );
1215
17
        p_sys->display.i_max_y = bs_read( s, 16 );
1216
17
        i_processed_length += 64;
1217
17
    }
1218
3.46k
    else
1219
3.46k
    {
1220
        /* if not windowed, setup the window variables to good defaults */
1221
        /* not necessary, but to avoid future confusion.. */
1222
3.46k
        p_sys->display.i_x     = 0;
1223
3.46k
        p_sys->display.i_max_x = p_sys->display.i_width_minus1;
1224
3.46k
        p_sys->display.i_y     = 0;
1225
3.46k
        p_sys->display.i_max_y = p_sys->display.i_height_minus1;
1226
3.46k
    }
1227
1228
3.48k
    if( i_processed_length != i_segment_length*8 )
1229
83
    {
1230
83
        msg_Err( p_dec, "processed length %d bytes != segment length %d bytes",
1231
83
                 i_processed_length / 8 , i_segment_length );
1232
83
    }
1233
1234
#ifdef DEBUG_DVBSUB
1235
    msg_Dbg( p_dec, "version: %d, width: %d, height: %d",
1236
             p_sys->display.i_version, (int)p_sys->display.i_width_minus1+1, (int)p_sys->display.i_height_minus1+1 );
1237
    if( p_sys->display.b_windowed )
1238
        msg_Dbg( p_dec, "xmin: %d, xmax: %d, ymin: %d, ymax: %d",
1239
                 p_sys->display.i_x, p_sys->display.i_max_x, p_sys->display.i_y, p_sys->display.i_max_y );
1240
#endif
1241
3.48k
}
1242
1243
static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int,
1244
                                 const uint8_t *, int );
1245
static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );
1246
static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );
1247
static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );
1248
1249
static void decode_object( decoder_t *p_dec, bs_t *s, uint16_t i_segment_length )
1250
4.64k
{
1251
4.64k
    decoder_sys_t *p_sys = p_dec->p_sys;
1252
4.64k
    dvbsub_region_t *p_region;
1253
4.64k
    int i_coding_method, i_id, i;
1254
1255
    /* ETSI 300-743 v1.5.1 section 7.2.5 'Object data segment'
1256
     * sync_byte, segment_type, page_id and i_segment_length have already been processed.
1257
     */
1258
4.64k
    i_id             = bs_read( s, 16 );
1259
4.64k
    bs_skip( s, 4 ); /* version */
1260
4.64k
    i_coding_method  = bs_read( s, 2 );
1261
1262
4.64k
    if( i_coding_method > 1 )
1263
27
    {
1264
27
        msg_Dbg( p_dec, "unknown DVB subtitling coding %d is not handled!", i_coding_method );
1265
27
        bs_skip( s, 8 * (i_segment_length - 2) - 6 );
1266
27
        return;
1267
27
    }
1268
1269
    /* Check if the object needs to be rendered in at least one
1270
     * of the regions */
1271
7.46k
    for( p_region = p_sys->p_regions; p_region != NULL;
1272
4.61k
         p_region = p_region->p_next )
1273
5.59k
    {
1274
83.5k
        for( i = 0; i < p_region->i_object_defs; i++ )
1275
80.7k
            if( p_region->p_object_defs[i].i_id == i_id ) break;
1276
1277
5.59k
        if( i != p_region->i_object_defs ) break;
1278
5.59k
    }
1279
4.61k
    if( !p_region )
1280
1.87k
    {
1281
1.87k
        bs_skip( s, 8 * (i_segment_length - 2) - 6 );
1282
1.87k
        return;
1283
1.87k
    }
1284
1285
#ifdef DEBUG_DVBSUB
1286
    msg_Dbg( p_dec, "new object: %i", i_id );
1287
#endif
1288
1289
2.73k
    bs_skip( s, 1 ); /* non_modify_color */
1290
2.73k
    bs_skip( s, 1 ); /* Reserved */
1291
1292
2.73k
    if( i_coding_method == 0x00 )
1293
2.71k
    {
1294
2.71k
        int i_topfield, i_bottomfield;
1295
2.71k
        const uint8_t *p_topfield, *p_bottomfield;
1296
1297
2.71k
        i_topfield    = bs_read( s, 16 );
1298
2.71k
        i_bottomfield = bs_read( s, 16 );
1299
2.71k
        p_topfield    = s->p_start + bs_pos( s ) / 8;
1300
2.71k
        p_bottomfield = p_topfield + i_topfield;
1301
1302
2.71k
        bs_skip( s, 8 * (i_segment_length - 7) );
1303
1304
        /* Sanity check */
1305
2.71k
        if( ( i_segment_length < ( i_topfield + i_bottomfield + 7 ) ) ||
1306
1.78k
            ( ( p_topfield + i_topfield + i_bottomfield ) > s->p_end ) )
1307
940
        {
1308
940
            msg_Dbg( p_dec, "corrupted object data" );
1309
940
            return;
1310
940
        }
1311
1312
4.57k
        for( p_region = p_sys->p_regions; p_region != NULL;
1313
2.79k
             p_region = p_region->p_next )
1314
2.79k
        {
1315
320k
            for( i = 0; i < p_region->i_object_defs; i++ )
1316
317k
            {
1317
317k
                if( p_region->p_object_defs[i].i_id != i_id ) continue;
1318
1319
315k
                dvbsub_render_pdata( p_dec, p_region,
1320
315k
                                     p_region->p_object_defs[i].i_x,
1321
315k
                                     p_region->p_object_defs[i].i_y,
1322
315k
                                     p_topfield, i_topfield );
1323
1324
315k
                if( i_bottomfield )
1325
1
                {
1326
1
                    dvbsub_render_pdata( p_dec, p_region,
1327
1
                                         p_region->p_object_defs[i].i_x,
1328
1
                                         p_region->p_object_defs[i].i_y + 1,
1329
1
                                         p_bottomfield, i_bottomfield );
1330
1
                }
1331
315k
                else
1332
315k
                {
1333
                    /* Duplicate the top field */
1334
315k
                    dvbsub_render_pdata( p_dec, p_region,
1335
315k
                                         p_region->p_object_defs[i].i_x,
1336
315k
                                         p_region->p_object_defs[i].i_y + 1,
1337
315k
                                         p_topfield, i_topfield );
1338
315k
                }
1339
315k
            }
1340
2.79k
        }
1341
1.77k
    }
1342
20
    else
1343
20
    {
1344
        /* DVB subtitling as characters */
1345
20
        int i_number_of_codes = bs_read( s, 8 );
1346
20
        const uint8_t* p_start = s->p_start + bs_pos( s ) / 8;
1347
1348
        /* Sanity check */
1349
20
        if( ( i_segment_length < ( i_number_of_codes*2 + 4 ) ) ||
1350
18
            ( ( p_start + i_number_of_codes*2 ) > s->p_end ) )
1351
2
        {
1352
2
            msg_Dbg( p_dec, "corrupted object data" );
1353
2
            return;
1354
2
        }
1355
1356
57
        for( p_region = p_sys->p_regions; p_region != NULL;
1357
39
             p_region = p_region->p_next )
1358
39
        {
1359
5.06k
            for( i = 0; i < p_region->i_object_defs; i++ )
1360
5.02k
            {
1361
5.02k
                int j;
1362
1363
5.02k
                if( p_region->p_object_defs[i].i_id != i_id ) continue;
1364
1365
5.00k
                char *psz_text = realloc( p_region->p_object_defs[i].psz_text, i_number_of_codes + 1 );
1366
5.00k
                if( unlikely( psz_text == NULL ) )
1367
0
                {
1368
0
                    free( p_region->p_object_defs[i].psz_text );
1369
0
                    p_region->p_object_defs[i].psz_text = NULL;
1370
0
                    continue;
1371
0
                }
1372
5.00k
                p_region->p_object_defs[i].psz_text = psz_text;
1373
1374
                /* FIXME 16bits -> char ??? See Preamble */
1375
5.00k
                for( j = 0; j < i_number_of_codes; j++ )
1376
0
                {
1377
0
                    psz_text[j] = (char)(bs_read( s, 16 ) & 0xFF);
1378
0
                }
1379
                /* Null terminate the string */
1380
5.00k
                psz_text[j] = 0;
1381
5.00k
            }
1382
39
        }
1383
18
    }
1384
1385
#ifdef DEBUG_DVBSUB
1386
    msg_Dbg( p_dec, "end object: %i", i_id );
1387
#endif
1388
2.73k
}
1389
1390
static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region,
1391
                                 int i_x, int i_y,
1392
                                 const uint8_t *p_field, int i_field )
1393
631k
{
1394
631k
    uint8_t *p_pixbuf;
1395
631k
    int i_offset = 0;
1396
631k
    bs_t bs;
1397
1398
    /* Sanity check */
1399
631k
    if( !p_region->p_pixbuf )
1400
80.4k
    {
1401
80.4k
        msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id );
1402
80.4k
        return;
1403
80.4k
    }
1404
551k
    if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height ||
1405
551k
        i_x >= p_region->i_width )
1406
262
    {
1407
262
        msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y );
1408
262
        return;
1409
262
    }
1410
1411
551k
    p_pixbuf = p_region->p_pixbuf + (size_t)i_y * p_region->i_width;
1412
551k
    bs_init( &bs, p_field, i_field );
1413
1414
9.52M
    while( !bs_eof( &bs ) )
1415
8.97M
    {
1416
        /* Sanity check */
1417
8.97M
        if( i_y >= p_region->i_height ) return;
1418
1419
8.97M
        switch( bs_read( &bs, 8 ) )
1420
8.97M
        {
1421
597k
        case 0x10:
1422
597k
            dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
1423
597k
                              &i_offset );
1424
597k
            break;
1425
1426
534k
        case 0x11:
1427
534k
            dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
1428
534k
                              &i_offset );
1429
534k
            break;
1430
1431
471k
        case 0x12:
1432
471k
            dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
1433
471k
                              &i_offset );
1434
471k
            break;
1435
1436
510k
        case 0x20:
1437
1.03M
        case 0x21:
1438
1.54M
        case 0x22:
1439
            /* We don't use map tables */
1440
1.54M
            break;
1441
1442
510k
        case 0xf0: /* End of line code */
1443
510k
            p_pixbuf += 2*p_region->i_width;
1444
510k
            i_offset = 0; i_y += 2;
1445
510k
            break;
1446
8.97M
        }
1447
8.97M
    }
1448
551k
}
1449
1450
static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
1451
597k
{
1452
597k
    bool b_stop = false;
1453
1454
1.27M
    while( !b_stop && !bs_eof( s ) )
1455
678k
    {
1456
678k
        int i_count = 0, i_color = 0;
1457
1458
678k
        i_color = bs_read( s, 2 );
1459
678k
        if( i_color != 0x00 )
1460
51.4k
        {
1461
51.4k
            i_count = 1;
1462
51.4k
        }
1463
626k
        else
1464
626k
        {
1465
626k
            if( bs_read( s, 1 ) == 0x01 )         // Switch1
1466
23.8k
            {
1467
23.8k
                i_count = 3 + bs_read( s, 3 );
1468
23.8k
                i_color = bs_read( s, 2 );
1469
23.8k
            }
1470
603k
            else
1471
603k
            {
1472
603k
                if( bs_read( s, 1 ) == 0x00 )     //Switch2
1473
591k
                {
1474
591k
                    switch( bs_read( s, 2 ) )     //Switch3
1475
591k
                    {
1476
591k
                    case 0x00:
1477
591k
                        b_stop = true;
1478
591k
                        break;
1479
17
                    case 0x01:
1480
17
                        i_count = 2;
1481
17
                        break;
1482
57
                    case 0x02:
1483
57
                        i_count =  12 + bs_read( s, 4 );
1484
57
                        i_color = bs_read( s, 2 );
1485
57
                        break;
1486
10
                    case 0x03:
1487
10
                        i_count =  29 + bs_read( s, 8 );
1488
10
                        i_color = bs_read( s, 2 );
1489
10
                        break;
1490
0
                    default:
1491
0
                        break;
1492
591k
                    }
1493
591k
                }
1494
11.5k
                else
1495
11.5k
                {
1496
                    /* 1 pixel color 0 */
1497
11.5k
                    i_count = 1;
1498
11.5k
                }
1499
603k
            }
1500
626k
        }
1501
1502
678k
        if( !i_count ) continue;
1503
1504
        /* Sanity check */
1505
86.9k
        if( ( i_count + *pi_off ) > i_width ) break;
1506
1507
86.8k
        if( i_count == 1 ) p[*pi_off] = i_color;
1508
23.9k
        else memset( ( p + *pi_off ), i_color, i_count );
1509
1510
86.8k
        (*pi_off) += i_count;
1511
86.8k
    }
1512
1513
597k
    bs_align( s );
1514
597k
}
1515
1516
static void dvbsub_pdata4bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
1517
534k
{
1518
534k
    bool b_stop = false;
1519
1520
1.83M
    while( !b_stop && !bs_eof( s ) )
1521
1.32M
    {
1522
1.32M
        int i_count = 0, i_color = 0;
1523
1524
1.32M
        i_color = bs_read( s, 4 );
1525
1.32M
        if( i_color != 0x00 )
1526
708k
        {
1527
            /* Add 1 pixel */
1528
708k
            i_count = 1;
1529
708k
        }
1530
612k
        else
1531
612k
        {
1532
612k
            if( bs_read( s, 1 ) == 0x00 )           // Switch1
1533
524k
            {
1534
524k
                i_count = bs_read( s, 3 );
1535
524k
                if( i_count != 0x00 )
1536
12.9k
                {
1537
12.9k
                    i_count += 2;
1538
12.9k
                }
1539
511k
                else b_stop = true;
1540
524k
            }
1541
87.1k
            else
1542
87.1k
            {
1543
87.1k
                if( bs_read( s, 1 ) == 0x00)        //Switch2
1544
45.6k
                {
1545
45.6k
                    i_count =  4 + bs_read( s, 2 );
1546
45.6k
                    i_color = bs_read( s, 4 );
1547
45.6k
                }
1548
41.5k
                else
1549
41.5k
                {
1550
41.5k
                    switch ( bs_read( s, 2 ) )     //Switch3
1551
41.5k
                    {
1552
13
                    case 0x0:
1553
13
                        i_count = 1;
1554
13
                        break;
1555
41.5k
                    case 0x1:
1556
41.5k
                        i_count = 2;
1557
41.5k
                        break;
1558
12
                    case 0x2:
1559
12
                        i_count = 9 + bs_read( s, 4 );
1560
12
                        i_color = bs_read( s, 4 );
1561
12
                        break;
1562
10
                    case 0x3:
1563
10
                        i_count= 25 + bs_read( s, 8 );
1564
10
                        i_color = bs_read( s, 4 );
1565
10
                        break;
1566
41.5k
                    }
1567
41.5k
                }
1568
87.1k
            }
1569
612k
        }
1570
1571
1.32M
        if( !i_count ) continue;
1572
1573
        /* Sanity check */
1574
808k
        if( ( i_count + *pi_off ) > i_width ) break;
1575
1576
785k
        if( i_count == 1 ) p[*pi_off] = i_color;
1577
88.5k
        else memset( ( p + *pi_off ), i_color, i_count );
1578
1579
785k
        (*pi_off) += i_count;
1580
785k
    }
1581
1582
534k
    bs_align( s );
1583
534k
}
1584
1585
static void dvbsub_pdata8bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
1586
471k
{
1587
471k
    bool b_stop = false;
1588
1589
919k
    while( !b_stop && !bs_eof( s ) )
1590
482k
    {
1591
482k
        int i_count = 0, i_color = 0;
1592
1593
482k
        i_color = bs_read( s, 8 );
1594
482k
        if( i_color != 0x00 )
1595
11.6k
        {
1596
            /* Add 1 pixel */
1597
11.6k
            i_count = 1;
1598
11.6k
        }
1599
471k
        else
1600
471k
        {
1601
471k
            if( bs_read( s, 1 ) == 0x00 )           // Switch1
1602
471k
            {
1603
471k
                i_count = bs_read( s, 7 );
1604
471k
                if( i_count == 0x00 )
1605
436k
                    b_stop = true;
1606
471k
            }
1607
17
            else
1608
17
            {
1609
17
                i_count = bs_read( s, 7 );
1610
17
                i_color = bs_read( s, 8 );
1611
17
            }
1612
471k
        }
1613
1614
482k
        if( !i_count ) continue;
1615
1616
        /* Sanity check */
1617
46.2k
        if( ( i_count + *pi_off ) > i_width ) break;
1618
1619
11.6k
        if( i_count == 1 ) p[*pi_off] = i_color;
1620
22
        else memset( ( p + *pi_off ), i_color, i_count );
1621
1622
11.6k
        (*pi_off) += i_count;
1623
11.6k
    }
1624
1625
471k
    bs_align( s );
1626
471k
}
1627
1628
static void free_all( decoder_t *p_dec )
1629
2.13k
{
1630
2.13k
    decoder_sys_t *p_sys = p_dec->p_sys;
1631
2.13k
    dvbsub_region_t *p_reg, *p_reg_next;
1632
2.13k
    dvbsub_clut_t *p_clut, *p_clut_next;
1633
1634
    /*free( p_sys->p_display ); No longer malloced */
1635
1636
3.30k
    for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut_next )
1637
1.17k
    {
1638
1.17k
        p_clut_next = p_clut->p_next;
1639
1.17k
        free( p_clut );
1640
1.17k
    }
1641
2.13k
    p_sys->p_cluts = NULL;
1642
1643
3.06k
    for( p_reg = p_sys->p_regions; p_reg != NULL; p_reg = p_reg_next )
1644
930
    {
1645
930
        p_reg_next = p_reg->p_next;
1646
307k
        for( int i = 0; i < p_reg->i_object_defs; i++ )
1647
306k
            free( p_reg->p_object_defs[i].psz_text );
1648
930
        free( p_reg->p_object_defs );
1649
930
        free( p_reg->p_pixbuf );
1650
930
        free( p_reg );
1651
930
    }
1652
2.13k
    p_sys->p_regions = NULL;
1653
1654
2.13k
    if( p_sys->p_page )
1655
611
    {
1656
611
        if( p_sys->p_page->i_region_defs )
1657
608
            free( p_sys->p_page->p_region_defs );
1658
611
        free( p_sys->p_page );
1659
611
    }
1660
2.13k
    p_sys->p_page = NULL;
1661
2.13k
}
1662
1663
static subpicture_t *render( decoder_t *p_dec )
1664
588
{
1665
588
    decoder_sys_t *p_sys = p_dec->p_sys;
1666
588
    subpicture_t *p_spu;
1667
588
    int i, j;
1668
588
    int i_base_x;
1669
588
    int i_base_y;
1670
1671
588
    if ( p_sys->p_page == NULL)
1672
0
    {
1673
0
        return NULL;
1674
0
    }
1675
1676
    /* Allocate the subpicture internal data. */
1677
588
    p_spu = decoder_NewSubpicture( p_dec, NULL );
1678
588
    if( !p_spu )
1679
0
        return NULL;
1680
1681
    /* Set the pf_render callback */
1682
588
    p_spu->i_start = p_sys->i_pts;
1683
    //p_spu->i_stop = (vlc_tick_t) 0;
1684
588
    p_spu->b_ephemer = true;
1685
    //p_spu->b_fade = true;
1686
    //p_spu->i_stop = p_spu->i_start + (vlc_tick_t) (i_timeout * 1000000);
1687
588
    p_spu->b_subtitle = true;
1688
1689
    /* Correct positioning of SPU */
1690
588
    i_base_x = p_sys->i_spu_x;
1691
588
    i_base_y = p_sys->i_spu_y;
1692
1693
588
    p_spu->i_original_picture_width = (unsigned)p_sys->display.i_width_minus1 + 1;
1694
588
    p_spu->i_original_picture_height = (unsigned)p_sys->display.i_height_minus1 + 1;
1695
1696
588
    if( p_sys->display.b_windowed )
1697
0
    {
1698
        /* From en_300743v01 - */
1699
        /* the DDS is there to indicate intended size/position of text */
1700
        /* the intended video area is ->i_width/height */
1701
        /* the window is within this... SO... we should leave i_original_picture_width etc. as is */
1702
        /* and ONLY change i_base_x.  effectively i_max_x/y are only there to limit memory requirements*/
1703
        /* we COULD use the upper limits to limit rendering to within these? */
1704
1705
        /* see notes on DDS at the top of the file */
1706
0
        i_base_x += p_sys->display.i_x;
1707
0
        i_base_y += p_sys->display.i_y;
1708
0
    }
1709
1710
    /* Loop on region definitions */
1711
#ifdef DEBUG_DVBSUB
1712
    msg_Dbg( p_dec, "rendering %i regions", p_sys->p_page->i_region_defs );
1713
#endif
1714
1715
1.27k
    for( i = 0; i < p_sys->p_page->i_region_defs; i++ )
1716
691
    {
1717
691
        dvbsub_region_t     *p_region;
1718
691
        dvbsub_regiondef_t  *p_regiondef;
1719
691
        dvbsub_clut_t       *p_clut;
1720
691
        dvbsub_color_t      *p_color;
1721
691
        subpicture_region_t *p_spu_region;
1722
691
        uint8_t *p_src, *p_dst;
1723
691
        video_format_t fmt;
1724
691
        video_palette_t palette;
1725
691
        int i_pitch;
1726
1727
691
        p_regiondef = &p_sys->p_page->p_region_defs[i];
1728
1729
        /* Find associated region */
1730
1.49k
        for( p_region = p_sys->p_regions; p_region != NULL;
1731
802
             p_region = p_region->p_next )
1732
1.03k
        {
1733
1.03k
            if( p_regiondef->i_id == p_region->i_id ) break;
1734
1.03k
        }
1735
1736
#ifdef DEBUG_DVBSUB
1737
        /* if a region exists, then print it's size */
1738
        if (p_region)
1739
        {
1740
                msg_Dbg( p_dec, "rendering region %i (%i,%i) to (%i,%i)", i,
1741
                        p_regiondef->i_x, p_regiondef->i_y,
1742
                p_regiondef->i_x + p_region->i_width,
1743
                p_regiondef->i_y + p_region->i_height );
1744
        }
1745
        else
1746
        {
1747
                msg_Dbg( p_dec, "rendering region %i (%i,%i) (no region matched to render)", i,
1748
                      p_regiondef->i_x, p_regiondef->i_y );
1749
        }
1750
#endif
1751
1752
691
        if( !p_region || !p_region->p_pixbuf )
1753
461
        {
1754
461
            msg_Dbg( p_dec, "region %i not found or invalid", p_regiondef->i_id );
1755
461
            continue;
1756
461
        }
1757
1758
        /* Find associated CLUT */
1759
472
        for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
1760
441
        {
1761
441
            if( p_region->i_clut == p_clut->i_id ) break;
1762
441
        }
1763
230
        if( !p_clut )
1764
31
        {
1765
31
            msg_Dbg( p_dec, "clut %i not found", p_region->i_clut );
1766
31
            continue;
1767
31
        }
1768
1769
        /* FIXME: don't create a subpicture region with VLC CODEC YUVP
1770
         * when it actually is a TEXT region */
1771
1772
        /* Create new SPU region */
1773
199
        video_format_Init( &fmt, VLC_CODEC_YUVP );
1774
199
        fmt.i_sar_num = 0; /* 0 means use aspect ratio of background video */
1775
199
        fmt.i_sar_den = 1;
1776
199
        fmt.i_width = fmt.i_visible_width = p_region->i_width;
1777
199
        fmt.i_height = fmt.i_visible_height = p_region->i_height;
1778
199
        fmt.i_x_offset = fmt.i_y_offset = 0;
1779
199
        fmt.p_palette = &palette;
1780
199
        fmt.p_palette->i_entries = ( p_region->i_depth == 1 ) ? 4 :
1781
199
            ( ( p_region->i_depth == 2 ) ? 16 : p_clut->c_8b_entries );
1782
199
        p_color = ( p_region->i_depth == 1 ) ? p_clut->c_2b :
1783
199
            ( ( p_region->i_depth == 2 ) ? p_clut->c_4b : p_clut->c_8b );
1784
50.1k
        for( j = 0; j < fmt.p_palette->i_entries; j++ )
1785
49.9k
        {
1786
49.9k
            fmt.p_palette->palette[j][0] = p_color[j].Y;
1787
49.9k
            fmt.p_palette->palette[j][1] = p_color[j].Cb; /* U == Cb */
1788
49.9k
            fmt.p_palette->palette[j][2] = p_color[j].Cr; /* V == Cr */
1789
49.9k
            fmt.p_palette->palette[j][3] = 0xff - p_color[j].T;
1790
49.9k
        }
1791
199
        switch (p_clut->dynamic_range_and_colour_gamut)
1792
199
        {
1793
195
            case DVBSUB_ST_COLORIMETRY_CDS:
1794
195
                fmt.space = COLOR_SPACE_BT601;
1795
195
                fmt.primaries = COLOR_PRIMARIES_BT601_525;
1796
195
                fmt.transfer = TRANSFER_FUNC_BT709;
1797
195
                break;
1798
4
            case DVBSUB_ST_COLORIMETRY_SDR_709:
1799
4
                fmt.space = COLOR_SPACE_BT709;
1800
4
                fmt.primaries = COLOR_PRIMARIES_BT709;
1801
4
                fmt.transfer = TRANSFER_FUNC_BT709;
1802
4
                break;
1803
0
            case DVBSUB_ST_COLORIMETRY_SDR_2020:
1804
0
                fmt.space = COLOR_SPACE_BT2020;
1805
0
                fmt.primaries = COLOR_PRIMARIES_BT2020;
1806
0
                fmt.transfer = TRANSFER_FUNC_BT709;
1807
0
                break;
1808
0
            case DVBSUB_ST_COLORIMETRY_HDR_PQ:
1809
0
                fmt.space = COLOR_SPACE_BT2020;
1810
0
                fmt.primaries = COLOR_PRIMARIES_BT2020;
1811
0
                fmt.transfer = TRANSFER_FUNC_SMPTE_ST2084;
1812
0
                break;
1813
0
            case DVBSUB_ST_COLORIMETRY_HDR_HLG:
1814
0
                fmt.space = COLOR_SPACE_BT2020;
1815
0
                fmt.primaries = COLOR_PRIMARIES_BT2020;
1816
0
                fmt.transfer = TRANSFER_FUNC_HLG;
1817
0
                break;
1818
199
        }
1819
199
        fmt.color_range = p_clut->color_range;
1820
1821
199
        p_spu_region = subpicture_region_New( &fmt );
1822
199
        fmt.p_palette = NULL; /* was stack var */
1823
199
        video_format_Clean( &fmt );
1824
199
        if( !p_spu_region )
1825
0
        {
1826
0
            msg_Err( p_dec, "cannot allocate SPU region" );
1827
0
            continue;
1828
0
        }
1829
199
        p_spu_region->b_absolute = true; p_spu_region->b_in_window = false;
1830
199
        p_spu_region->i_x = i_base_x + p_regiondef->i_x;
1831
199
        p_spu_region->i_y = i_base_y + p_regiondef->i_y;
1832
199
        p_spu_region->i_align = p_sys->i_spu_position;
1833
199
        vlc_spu_regions_push(&p_spu->regions, p_spu_region);
1834
1835
199
        p_src = p_region->p_pixbuf;
1836
199
        p_dst = p_spu_region->p_picture->Y_PIXELS;
1837
199
        i_pitch = p_spu_region->p_picture->Y_PITCH;
1838
1839
        /* Copy pixel buffer */
1840
3.48k
        for( j = 0; j < p_region->i_height; j++ )
1841
3.28k
        {
1842
3.28k
            memcpy( p_dst, p_src, p_region->i_width );
1843
3.28k
            p_src += p_region->i_width;
1844
3.28k
            p_dst += i_pitch;
1845
3.28k
        }
1846
1847
        /* Check subtitles encoded as strings of characters
1848
         * (since there are not rendered in the pixbuffer) */
1849
29.6k
        for( j = 0; j < p_region->i_object_defs; j++ )
1850
29.4k
        {
1851
29.4k
            dvbsub_objectdef_t *p_object_def = &p_region->p_object_defs[j];
1852
1853
29.4k
            if( ( p_object_def->i_type != 1 ) || !p_object_def->psz_text )
1854
29.4k
                continue;
1855
1856
            /* Create new SPU region */
1857
0
            p_spu_region = subpicture_region_NewText();
1858
0
            if( !p_spu_region )
1859
0
            {
1860
0
                msg_Err( p_dec, "cannot allocate SPU region" );
1861
0
                continue;
1862
0
            }
1863
1864
0
            p_spu_region->fmt.i_sar_num = 1;
1865
0
            p_spu_region->fmt.i_sar_den = 1;
1866
0
            p_spu_region->fmt.i_width = p_spu_region->fmt.i_visible_width = p_region->i_width;
1867
0
            p_spu_region->fmt.i_height = p_spu_region->fmt.i_visible_height = p_region->i_height;
1868
1869
0
            p_spu_region->p_text = text_segment_New( p_object_def->psz_text );
1870
0
            p_spu_region->b_absolute = true; p_spu_region->b_in_window = false;
1871
0
            p_spu_region->i_x = i_base_x + p_regiondef->i_x + p_object_def->i_x;
1872
0
            p_spu_region->i_y = i_base_y + p_regiondef->i_y + p_object_def->i_y;
1873
0
            p_spu_region->i_align = p_sys->i_spu_position;
1874
0
            vlc_spu_regions_push(&p_spu->regions, p_spu_region);
1875
0
        }
1876
199
    }
1877
1878
588
    return p_spu;
1879
588
}
1880
1881
/*****************************************************************************
1882
 * encoder_sys_t : encoder descriptor
1883
 *****************************************************************************/
1884
typedef struct encoder_region_t
1885
{
1886
    int i_width;
1887
    int i_height;
1888
1889
} encoder_region_t;
1890
1891
typedef struct
1892
{
1893
    unsigned int i_page_ver;
1894
    unsigned int i_region_ver;
1895
    unsigned int i_clut_ver;
1896
1897
    size_t           i_regions;
1898
    encoder_region_t *p_regions;
1899
1900
    vlc_tick_t i_pts;
1901
1902
    /* subpicture positioning */
1903
    int i_offset_x;
1904
    int i_offset_y;
1905
} encoder_sys_t;
1906
1907
#ifdef ENABLE_SOUT
1908
static void encode_page_composition( encoder_t *, bs_t *, const subpicture_t * );
1909
static void encode_clut( encoder_t *, bs_t *, subpicture_region_t * );
1910
static void encode_region_composition( encoder_t *, bs_t *, const subpicture_t * );
1911
static void encode_object( encoder_t *, bs_t *, const subpicture_t * );
1912
1913
/*****************************************************************************
1914
 * OpenEncoder: probe the encoder and return score
1915
 *****************************************************************************/
1916
static int OpenEncoder( vlc_object_t *p_this )
1917
0
{
1918
0
    encoder_t *p_enc = (encoder_t *)p_this;
1919
0
    encoder_sys_t *p_sys;
1920
1921
0
    if( ( p_enc->fmt_out.i_codec != VLC_CODEC_DVBS ) &&
1922
0
        !p_enc->obj.force )
1923
0
    {
1924
0
        return VLC_EGENERIC;
1925
0
    }
1926
1927
    /* Allocate the memory needed to store the decoder's structure */
1928
0
    p_sys = malloc(sizeof(encoder_sys_t));
1929
0
    if (p_sys == NULL)
1930
0
        return VLC_ENOMEM;
1931
0
    p_enc->p_sys = p_sys;
1932
1933
0
    p_enc->fmt_out.i_codec = VLC_CODEC_DVBS;
1934
0
    p_enc->fmt_out.subs.dvb.i_id  = 1 << 16 | 1;
1935
1936
0
    config_ChainParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
1937
1938
0
    p_sys->i_page_ver = 0;
1939
0
    p_sys->i_region_ver = 0;
1940
0
    p_sys->i_clut_ver = 0;
1941
0
    p_sys->i_regions = 0;
1942
0
    p_sys->p_regions = 0;
1943
1944
0
    p_sys->i_offset_x = var_CreateGetInteger( p_this, ENC_CFG_PREFIX "x" );
1945
0
    p_sys->i_offset_y = var_CreateGetInteger( p_this, ENC_CFG_PREFIX "y" );
1946
1947
0
    static const struct vlc_encoder_operations ops =
1948
0
    {
1949
0
        .close = CloseEncoder,
1950
0
        .encode_sub = Encode,
1951
0
    };
1952
0
    p_enc->ops = &ops;
1953
1954
0
    return VLC_SUCCESS;
1955
0
}
1956
1957
/* FIXME: this routine is a hack to convert VLC_CODEC_YUVA
1958
 *        into VLC_CODEC_YUVP
1959
 */
1960
static void YuvaYuvp( subpicture_t *p_subpic )
1961
0
{
1962
0
    const subpicture_region_t *p_region;
1963
1964
0
    vlc_spu_regions_foreach_const(p_region, &p_subpic->regions)
1965
0
    {
1966
0
        video_format_t *p_fmt = &p_region->p_picture->format;
1967
0
        int i = 0, j = 0, n = 0, p = 0;
1968
0
        int i_max_entries = 256;
1969
1970
#ifdef RANDOM_DITHERING
1971
        int i_seed = 0xdeadbeef; /* random seed */
1972
#else
1973
0
        int *pi_delta;
1974
0
#endif
1975
0
        int i_pixels = p_region->p_picture->p[0].i_visible_lines
1976
0
                        * p_region->p_picture->Y_PITCH;
1977
0
        int i_iterator = p_region->p_picture->p[0].i_visible_lines * 3 / 4
1978
0
                            * p_region->p_picture->Y_PITCH
1979
0
                        + p_region->p_picture->Y_PITCH * 1 / 3;
1980
0
        int i_tolerance = 0;
1981
1982
#ifdef DEBUG_DVBSUB1
1983
        /* p_enc not valid here */
1984
        msg_Dbg( p_enc, "YuvaYuvp: i_pixels=%d, i_iterator=%d", i_pixels, i_iterator );
1985
#endif
1986
0
        p_fmt->i_chroma = VLC_CODEC_YUVP;
1987
0
        p_fmt->p_palette = (video_palette_t *) malloc( sizeof( video_palette_t ) );
1988
0
        if( !p_fmt->p_palette ) break;
1989
0
        p_fmt->p_palette->i_entries = 0;
1990
1991
        /* Find best iterator using Euclide’s algorithm */
1992
0
        for( ; i_iterator > 1 ; i_iterator-- )
1993
0
        {
1994
0
            int a = i_pixels;
1995
0
            int b = i_iterator;
1996
0
            int c;
1997
1998
0
            while( b )
1999
0
            {
2000
0
                c = a % b;
2001
0
                a = b;
2002
0
                b = c;
2003
0
            }
2004
2005
0
            if( a == 1 )
2006
0
            {
2007
0
                break;
2008
0
            }
2009
0
        }
2010
2011
        /* Count colors, build best palette */
2012
0
        for( i_tolerance = 0; i_tolerance < 128; i_tolerance++ )
2013
0
        {
2014
0
            bool b_success = true;
2015
0
            p_fmt->p_palette->i_entries = 0;
2016
2017
0
            for( i = 0; i < i_pixels ; )
2018
0
            {
2019
0
                uint8_t y, u, v, a;
2020
0
                y = p_region->p_picture->Y_PIXELS[i];
2021
0
                u = p_region->p_picture->U_PIXELS[i];
2022
0
                v = p_region->p_picture->V_PIXELS[i];
2023
0
                a = p_region->p_picture->A_PIXELS[i];
2024
0
                for( j = 0; j < p_fmt->p_palette->i_entries; j++ )
2025
0
                {
2026
0
                    if( abs((int)p_fmt->p_palette->palette[j][0] - (int)y) <= i_tolerance &&
2027
0
                        abs((int)p_fmt->p_palette->palette[j][1] - (int)u) <= i_tolerance &&
2028
0
                        abs((int)p_fmt->p_palette->palette[j][2] - (int)v) <= i_tolerance &&
2029
0
                        abs((int)p_fmt->p_palette->palette[j][3] - (int)a) <= i_tolerance / 2 )
2030
0
                    {
2031
0
                        break;
2032
0
                    }
2033
0
                }
2034
0
                if( j == p_fmt->p_palette->i_entries )
2035
0
                {
2036
0
                    p_fmt->p_palette->palette[j][0] = y;
2037
0
                    p_fmt->p_palette->palette[j][1] = u;
2038
0
                    p_fmt->p_palette->palette[j][2] = v;
2039
0
                    p_fmt->p_palette->palette[j][3] = a;
2040
0
                    p_fmt->p_palette->i_entries++;
2041
0
                }
2042
0
                if( p_fmt->p_palette->i_entries >= i_max_entries )
2043
0
                {
2044
0
                    b_success = false;
2045
0
                    break;
2046
0
                }
2047
0
                i += i_iterator;
2048
0
                if( i > i_pixels )
2049
0
                {
2050
0
                    i -= i_pixels;
2051
0
                }
2052
0
            }
2053
2054
0
            if( b_success )
2055
0
            {
2056
0
                break;
2057
0
            }
2058
0
        }
2059
2060
#ifdef DEBUG_DVBSUB1
2061
        /* p_enc not valid here */
2062
        msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
2063
#endif
2064
2065
0
#ifndef RANDOM_DITHERING
2066
0
        pi_delta = calloc( ( p_region->p_picture->Y_PITCH + 1 ) * 4, sizeof(int) );
2067
0
        if (unlikely(pi_delta == NULL))
2068
0
            return;
2069
0
#endif
2070
2071
        /* Fill image with our new colours */
2072
0
        for( p = 0; p < p_region->p_picture->p[0].i_visible_lines ; p++ )
2073
0
        {
2074
0
            int i_ydelta = 0, i_udelta = 0, i_vdelta = 0, i_adelta = 0;
2075
2076
0
            for( n = 0; n < p_region->p_picture->Y_PITCH ; n++ )
2077
0
            {
2078
0
                int i_offset = p * p_region->p_picture->Y_PITCH + n;
2079
0
                int y, u, v, a;
2080
0
                int i_mindist, i_best;
2081
2082
0
                y = p_region->p_picture->Y_PIXELS[i_offset];
2083
0
                u = p_region->p_picture->U_PIXELS[i_offset];
2084
0
                v = p_region->p_picture->V_PIXELS[i_offset];
2085
0
                a = p_region->p_picture->A_PIXELS[i_offset];
2086
2087
                /* Add dithering compensation */
2088
#ifdef RANDOM_DITHERING
2089
                y += ((i_seed & 0xff) - 0x80) * i_tolerance / 0x80;
2090
                u += (((i_seed >> 8) & 0xff) - 0x80) * i_tolerance / 0x80;
2091
                v += (((i_seed >> 16) & 0xff) - 0x80) * i_tolerance / 0x80;
2092
                a += (((i_seed >> 24) & 0xff) - 0x80) * i_tolerance / 0x80;
2093
#else
2094
0
                y += i_ydelta + pi_delta[ n * 4 + 0 ];
2095
0
                u += i_udelta + pi_delta[ n * 4 + 1 ];
2096
0
                v += i_vdelta + pi_delta[ n * 4 + 2 ];
2097
0
                a += i_adelta + pi_delta[ n * 4 + 3 ];
2098
0
#endif
2099
2100
                /* Find best colour in palette */
2101
0
                for( i_mindist = INT_MAX, i_best = 0, j = 0; j < p_fmt->p_palette->i_entries; j++ )
2102
0
                {
2103
0
                    int i_dist = 0;
2104
2105
0
                    i_dist += abs((int)p_fmt->p_palette->palette[j][0] - y);
2106
0
                    i_dist += abs((int)p_fmt->p_palette->palette[j][1] - u);
2107
0
                    i_dist += abs((int)p_fmt->p_palette->palette[j][2] - v);
2108
0
                    i_dist += 2 * abs((int)p_fmt->p_palette->palette[j][3] - a);
2109
2110
0
                    if( i_dist < i_mindist )
2111
0
                    {
2112
0
                        i_mindist = i_dist;
2113
0
                        i_best = j;
2114
0
                    }
2115
0
                }
2116
2117
                /* Set pixel to best color */
2118
0
                p_region->p_picture->Y_PIXELS[i_offset] = i_best;
2119
2120
                /* Update dithering state */
2121
#ifdef RANDOM_DITHERING
2122
                i_seed = (i_seed * 0x1283837) ^ 0x789479 ^ (i_seed >> 13);
2123
#else
2124
0
                i_ydelta = y - (int)p_fmt->p_palette->palette[i_best][0];
2125
0
                i_udelta = u - (int)p_fmt->p_palette->palette[i_best][1];
2126
0
                i_vdelta = v - (int)p_fmt->p_palette->palette[i_best][2];
2127
0
                i_adelta = a - (int)p_fmt->p_palette->palette[i_best][3];
2128
0
                pi_delta[ n * 4 + 0 ] = i_ydelta * 3 / 8;
2129
0
                pi_delta[ n * 4 + 1 ] = i_udelta * 3 / 8;
2130
0
                pi_delta[ n * 4 + 2 ] = i_vdelta * 3 / 8;
2131
0
                pi_delta[ n * 4 + 3 ] = i_adelta * 3 / 8;
2132
0
                i_ydelta = i_ydelta * 5 / 8;
2133
0
                i_udelta = i_udelta * 5 / 8;
2134
0
                i_vdelta = i_vdelta * 5 / 8;
2135
0
                i_adelta = i_adelta * 5 / 8;
2136
0
#endif
2137
0
            }
2138
0
        }
2139
0
#ifndef RANDOM_DITHERING
2140
0
        free( pi_delta );
2141
0
#endif
2142
2143
        /* pad palette */
2144
0
        for( i = p_fmt->p_palette->i_entries; i < i_max_entries; i++ )
2145
0
            memset(p_fmt->p_palette->palette[i], 0, sizeof(p_fmt->p_palette->palette[i]));
2146
0
        p_fmt->p_palette->i_entries = i_max_entries;
2147
#ifdef DEBUG_DVBSUB1
2148
        /* p_enc not valid here */
2149
        msg_Dbg( p_enc, "best palette has %d colors", p_fmt->p_palette->i_entries );
2150
#endif
2151
0
    }
2152
0
} /* End of hack */
2153
2154
/****************************************************************************
2155
 * Encode: the whole thing
2156
 ****************************************************************************/
2157
static block_t *Encode( encoder_t *p_enc, subpicture_t *p_subpic )
2158
0
{
2159
0
    subpicture_region_t *p_region = NULL;
2160
0
    bs_t bits, *s = &bits;
2161
0
    block_t *p_block;
2162
2163
0
    if( !p_subpic || vlc_spu_regions_is_empty(&p_subpic->regions) ) return NULL;
2164
2165
    /* FIXME: this is a hack to convert VLC_CODEC_YUVA into
2166
     *  VLC_CODEC_YUVP
2167
     */
2168
0
    p_region = vlc_spu_regions_first_or_null(&p_subpic->regions);
2169
    /* Sanity check */
2170
0
    if( !p_region ) return NULL;
2171
2172
0
    if( !subpicture_region_IsText( p_region ) )
2173
0
    {
2174
0
        if( p_region->p_picture->format.i_chroma == VLC_CODEC_YUVA )
2175
0
        {
2176
0
            YuvaYuvp( p_subpic );
2177
0
        }
2178
2179
0
        if( p_region->p_picture->format.i_chroma != VLC_CODEC_YUVP )
2180
0
        {
2181
0
            msg_Err( p_enc, "chroma %4.4s not supported", (char *)&p_region->p_picture->format.i_chroma );
2182
0
            return NULL;
2183
0
        }
2184
2185
0
        if( p_region->p_picture->format.p_palette )
2186
0
        {
2187
0
            switch( p_region->p_picture->format.p_palette->i_entries )
2188
0
            {
2189
0
                case 0:
2190
0
                case 4:
2191
0
                case 16:
2192
0
                case 256:
2193
0
                    break;
2194
0
                default:
2195
0
                    msg_Err( p_enc, "subpicture palette (%d) not handled",
2196
0
                                p_region->p_picture->format.p_palette->i_entries );
2197
0
                    return NULL;
2198
0
            }
2199
0
        }
2200
0
    }
2201
    /* End of hack */
2202
2203
#ifdef DEBUG_DVBSUB
2204
    msg_Dbg( p_enc, "encoding subpicture" );
2205
#endif
2206
0
    p_block = block_Alloc( 64000 );
2207
0
    if( unlikely(p_block == NULL) )
2208
0
        return NULL;
2209
2210
0
    bs_init( s, p_block->p_buffer, p_block->i_buffer );
2211
2212
0
    bs_write( s, 8, 0x20 ); /* Data identifier */
2213
0
    bs_write( s, 8, 0x0 );  /* Subtitle stream id */
2214
2215
0
    encode_page_composition( p_enc, s, p_subpic );
2216
0
    encode_region_composition( p_enc, s, p_subpic );
2217
0
    encode_clut( p_enc, s, p_region );
2218
0
    encode_object( p_enc, s, p_subpic );
2219
2220
    /* End of display */
2221
0
    bs_write( s, 8, 0x0f ); /* Sync byte */
2222
0
    bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY ); /* Segment type */
2223
0
    bs_write( s, 16, 1 );  /* Page id */
2224
0
    bs_write( s, 16, 0 );  /* Segment length */
2225
2226
0
    bs_write( s, 8, 0xff );/* End marker */
2227
0
    p_block->i_buffer = bs_pos( s ) / 8;
2228
0
    p_block->i_pts = p_block->i_dts = p_subpic->i_start;
2229
0
    if( !p_subpic->b_ephemer &&
2230
0
        ( p_subpic->i_stop != VLC_TICK_INVALID && p_subpic->i_stop > p_subpic->i_start ) )
2231
0
    {
2232
0
        block_t *p_block_stop;
2233
2234
0
        p_block->i_length = p_subpic->i_stop - p_subpic->i_start;
2235
2236
        /* Send another (empty) subtitle to signal the end of display */
2237
0
        p_block_stop = block_Alloc( 64000 );
2238
0
        if( unlikely(p_block_stop == NULL) )
2239
0
        {
2240
0
            block_Release(p_block);
2241
0
            return NULL;
2242
0
        }
2243
2244
0
        bs_init( s, p_block_stop->p_buffer, p_block_stop->i_buffer );
2245
0
        bs_write( s, 8, 0x20 ); /* Data identifier */
2246
0
        bs_write( s, 8, 0x0 );  /* Subtitle stream id */
2247
0
        encode_page_composition( p_enc, s, 0 );
2248
0
        bs_write( s, 8, 0x0f ); /* Sync byte */
2249
0
        bs_write( s, 8, DVBSUB_ST_ENDOFDISPLAY ); /* Segment type */
2250
0
        bs_write( s, 16, 1 );  /* Page id */
2251
0
        bs_write( s, 16, 0 );  /* Segment length */
2252
0
        bs_write( s, 8, 0xff );/* End marker */
2253
0
        p_block_stop->i_buffer = bs_pos( s ) / 8;
2254
0
        p_block_stop->i_pts = p_block_stop->i_dts = p_subpic->i_stop;
2255
0
        block_ChainAppend( &p_block, p_block_stop );
2256
0
        p_block_stop->i_length = VLC_TICK_FROM_MS(100); /* p_subpic->i_stop - p_subpic->i_start; */
2257
0
    }
2258
#ifdef DEBUG_DVBSUB
2259
    msg_Dbg( p_enc, "subpicture encoded properly" );
2260
#endif
2261
0
    return p_block;
2262
0
}
2263
2264
/*****************************************************************************
2265
 * CloseEncoder: encoder destruction
2266
 *****************************************************************************/
2267
static void CloseEncoder( encoder_t *p_enc )
2268
0
{
2269
0
    encoder_sys_t *p_sys = p_enc->p_sys;
2270
2271
0
    var_Destroy( p_enc , ENC_CFG_PREFIX "x" );
2272
0
    var_Destroy( p_enc , ENC_CFG_PREFIX "y" );
2273
2274
0
    if( p_sys->i_regions ) free( p_sys->p_regions );
2275
0
    free( p_sys );
2276
0
}
2277
2278
static void encode_page_composition( encoder_t *p_enc, bs_t *s,
2279
                                     const subpicture_t *p_subpic )
2280
0
{
2281
0
    encoder_sys_t *p_sys = p_enc->p_sys;
2282
0
    const subpicture_region_t *p_region;
2283
0
    bool b_mode_change = false;
2284
0
    unsigned int i_regions;
2285
0
    int i_timeout;
2286
2287
0
    bs_write( s, 8, 0x0f ); /* Sync byte */
2288
0
    bs_write( s, 8, DVBSUB_ST_PAGE_COMPOSITION ); /* Segment type */
2289
0
    bs_write( s, 16, 1 ); /* Page id */
2290
2291
0
    i_regions = 0;
2292
0
    if (p_subpic)
2293
0
    vlc_spu_regions_foreach_const(p_region, &p_subpic->regions)
2294
0
    {
2295
0
        if( i_regions >= p_sys->i_regions )
2296
0
        {
2297
0
            encoder_region_t region;
2298
0
            region.i_width = region.i_height = 0;
2299
0
            p_sys->p_regions = xrealloc( p_sys->p_regions,
2300
0
                          sizeof(encoder_region_t) * (p_sys->i_regions + 1) );
2301
0
            p_sys->p_regions[p_sys->i_regions++] = region;
2302
0
        }
2303
2304
0
        if( ( p_sys->p_regions[i_regions].i_width <
2305
0
              (int)p_region->fmt.i_visible_width ) ||
2306
0
            ( p_sys->p_regions[i_regions].i_width >
2307
0
              (int)p_region->fmt.i_visible_width ) )
2308
0
        {
2309
0
            b_mode_change = true;
2310
0
            msg_Dbg( p_enc, "region %u width change: %i -> %i",
2311
0
                     i_regions, p_sys->p_regions[i_regions].i_width,
2312
0
                     p_region->fmt.i_visible_width );
2313
0
            p_sys->p_regions[i_regions].i_width =
2314
0
                p_region->fmt.i_visible_width;
2315
0
        }
2316
0
        if( p_sys->p_regions[i_regions].i_height <
2317
0
             (int)p_region->fmt.i_visible_height )
2318
0
        {
2319
0
            b_mode_change = true;
2320
0
            msg_Dbg( p_enc, "region %u height change: %i -> %i",
2321
0
                     i_regions, p_sys->p_regions[i_regions].i_height,
2322
0
                     p_region->fmt.i_visible_height );
2323
0
            p_sys->p_regions[i_regions].i_height =
2324
0
                p_region->fmt.i_visible_height;
2325
0
        }
2326
0
        i_regions++;
2327
0
    }
2328
2329
0
    bs_write( s, 16, i_regions * 6 + 2 ); /* Segment length */
2330
2331
0
    i_timeout = 0;
2332
0
    if( p_subpic && !p_subpic->b_ephemer &&
2333
0
        ( p_subpic->i_stop != VLC_TICK_INVALID && p_subpic->i_stop > p_subpic->i_start ) )
2334
0
    {
2335
0
        i_timeout = SEC_FROM_VLC_TICK(p_subpic->i_stop - p_subpic->i_start);
2336
0
    }
2337
2338
0
    bs_write( s, 8, i_timeout ); /* Timeout */
2339
0
    bs_write( s, 4, p_sys->i_page_ver++ );
2340
0
    bs_write( s, 2, b_mode_change ?
2341
0
              DVBSUB_PCS_STATE_CHANGE : DVBSUB_PCS_STATE_ACQUISITION );
2342
0
    bs_write( s, 2, 0 ); /* Reserved */
2343
2344
0
    i_regions = 0;
2345
0
    if (p_subpic)
2346
0
    vlc_spu_regions_foreach_const(p_region, &p_subpic->regions)
2347
0
    {
2348
0
        bs_write( s, 8, i_regions );
2349
0
        bs_write( s, 8, 0 ); /* Reserved */
2350
0
        if( (p_sys->i_offset_x > 0) && (p_sys->i_offset_y > 0) )
2351
0
        {
2352
0
            bs_write( s, 16, p_sys->i_offset_x ); /* override x position */
2353
0
            bs_write( s, 16, p_sys->i_offset_y ); /* override y position */
2354
0
        }
2355
0
        else
2356
0
        {
2357
0
            bs_write( s, 16, p_region->i_x );
2358
0
            bs_write( s, 16, p_region->i_y );
2359
0
        }
2360
0
        i_regions++;
2361
0
    }
2362
0
}
2363
2364
static void encode_clut( encoder_t *p_enc, bs_t *s, subpicture_region_t *p_region )
2365
0
{
2366
0
    encoder_sys_t *p_sys = p_enc->p_sys;
2367
0
    video_palette_t *p_pal, empty_palette = { .i_entries = 4 };
2368
2369
    /* Sanity check */
2370
0
    if( !p_region ) return;
2371
2372
0
    if( !subpicture_region_IsText( p_region ) && p_region->p_picture->format.i_chroma == VLC_CODEC_YUVP )
2373
0
    {
2374
0
        p_pal = p_region->p_picture->format.p_palette;
2375
0
    }
2376
0
    else
2377
0
        p_pal = &empty_palette;
2378
2379
0
    bs_write( s, 8, 0x0f ); /* Sync byte */
2380
0
    bs_write( s, 8, DVBSUB_ST_CLUT_DEFINITION ); /* Segment type */
2381
0
    bs_write( s, 16, 1 );  /* Page id */
2382
2383
0
    bs_write( s, 16, p_pal->i_entries * 6 + 2 ); /* Segment length */
2384
0
    bs_write( s, 8, 1 ); /* Clut id */
2385
0
    bs_write( s, 4, p_sys->i_clut_ver++ );
2386
0
    bs_write( s, 4, 0 ); /* Reserved */
2387
2388
0
    for( int i = 0; i < p_pal->i_entries; i++ )
2389
0
    {
2390
0
        bs_write( s, 8, i ); /* Clut entry id */
2391
0
        bs_write( s, 1, p_pal->i_entries == 4 );   /* 2bit/entry flag */
2392
0
        bs_write( s, 1, p_pal->i_entries == 16 );  /* 4bit/entry flag */
2393
0
        bs_write( s, 1, p_pal->i_entries == 256 ); /* 8bit/entry flag */
2394
0
        bs_write( s, 4, 0 ); /* Reserved */
2395
0
        bs_write( s, 1, 1 ); /* Full range flag */
2396
0
        bs_write( s, 8, p_pal->palette[i][3] ?  /* Y value */
2397
0
                  (p_pal->palette[i][0] ? p_pal->palette[i][0] : 16) : 0 );
2398
0
        bs_write( s, 8, p_pal->palette[i][1] ); /* Cr value */
2399
0
        bs_write( s, 8, p_pal->palette[i][2] ); /* Cb value */
2400
0
        bs_write( s, 8, 0xff - p_pal->palette[i][3] ); /* T value */
2401
0
    }
2402
0
}
2403
2404
static void encode_region_composition( encoder_t *p_enc, bs_t *s,
2405
                                       const subpicture_t *p_subpic )
2406
0
{
2407
0
    encoder_sys_t *p_sys = p_enc->p_sys;
2408
0
    const subpicture_region_t *p_region;
2409
0
    unsigned int i_region;
2410
2411
0
    i_region = 0;
2412
0
    vlc_spu_regions_foreach_const(p_region, &p_subpic->regions)
2413
0
    {
2414
0
        int i_entries = 4, i_depth = 0x1, i_bg = 0;
2415
0
        bool b_text = subpicture_region_IsText( p_region );
2416
2417
0
        if( !b_text )
2418
0
        {
2419
0
            video_palette_t *p_pal = p_region->p_picture->format.p_palette;
2420
2421
0
            if( !p_pal )
2422
0
            {
2423
0
                msg_Err( p_enc, "subpicture has no palette - ignoring it" );
2424
0
                break;
2425
0
            }
2426
2427
0
            i_entries = p_pal->i_entries;
2428
0
            i_depth = i_entries == 4 ? 0x1 : i_entries == 16 ? 0x2 : 0x3;
2429
2430
0
            for( i_bg = 0; i_bg < p_pal->i_entries; i_bg++ )
2431
0
            {
2432
0
                if( !p_pal->palette[i_bg][3] ) break;
2433
0
            }
2434
0
        }
2435
2436
0
        bs_write( s, 8, 0x0f ); /* Sync byte */
2437
0
        bs_write( s, 8, DVBSUB_ST_REGION_COMPOSITION ); /* Segment type */
2438
0
        bs_write( s, 16, 1 );   /* Page id */
2439
2440
0
        bs_write( s, 16, 10 + 6 + (b_text ? 2 : 0) ); /* Segment length */
2441
0
        bs_write( s, 8, i_region );
2442
0
        bs_write( s, 4, p_sys->i_region_ver++ );
2443
2444
        /* Region attributes */
2445
0
        bs_write( s, 1, i_bg < i_entries ); /* Fill */
2446
0
        bs_write( s, 3, 0 ); /* Reserved */
2447
0
        bs_write( s, 16, p_sys->p_regions[i_region].i_width );
2448
0
        bs_write( s, 16, p_sys->p_regions[i_region].i_height );
2449
0
        bs_write( s, 3, i_depth );  /* Region level of compatibility */
2450
0
        bs_write( s, 3, i_depth  ); /* Region depth */
2451
0
        bs_write( s, 2, 0 ); /* Reserved */
2452
0
        bs_write( s, 8, 1 ); /* Clut id */
2453
0
        bs_write( s, 8, i_bg ); /* region 8bit pixel code */
2454
0
        bs_write( s, 4, i_bg ); /* region 4bit pixel code */
2455
0
        bs_write( s, 2, i_bg ); /* region 2bit pixel code */
2456
0
        bs_write( s, 2, 0 ); /* Reserved */
2457
2458
        /* In our implementation we only have 1 object per region */
2459
0
        bs_write( s, 16, i_region );
2460
0
        bs_write( s, 2, b_text ? DVBSUB_OT_BASIC_CHAR:DVBSUB_OT_BASIC_BITMAP );
2461
0
        bs_write( s, 2, 0 ); /* object provider flag */
2462
0
        bs_write( s, 12, 0 );/* object horizontal position */
2463
0
        bs_write( s, 4, 0 ); /* Reserved */
2464
0
        bs_write( s, 12, 0 );/* object vertical position */
2465
2466
0
        if( b_text )
2467
0
        {
2468
0
            bs_write( s, 8, 1 ); /* foreground pixel code */
2469
0
            bs_write( s, 8, 0 ); /* background pixel code */
2470
0
        }
2471
0
        i_region++;
2472
0
    }
2473
0
}
2474
2475
static void encode_pixel_data( encoder_t *p_enc, bs_t *s,
2476
                               const subpicture_region_t *p_region,
2477
                               bool b_top );
2478
2479
static void encode_object( encoder_t *p_enc, bs_t *s, const subpicture_t *p_subpic )
2480
0
{
2481
0
    encoder_sys_t *p_sys = p_enc->p_sys;
2482
0
    const subpicture_region_t *p_region;
2483
0
    int i_region;
2484
2485
0
    int i_length_pos, i_update_pos, i_pixel_data_pos;
2486
2487
0
    i_region = 0;
2488
0
    vlc_spu_regions_foreach_const(p_region, &p_subpic->regions)
2489
0
    {
2490
0
        bs_write( s, 8, 0x0f ); /* Sync byte */
2491
0
        bs_write( s, 8, DVBSUB_ST_OBJECT_DATA ); /* Segment type */
2492
0
        bs_write( s, 16, 1 ); /* Page id */
2493
2494
0
        i_length_pos = bs_pos( s );
2495
0
        bs_write( s, 16, 0 ); /* Segment length */
2496
0
        bs_write( s, 16, i_region ); /* Object id */
2497
0
        bs_write( s, 4, p_sys->i_region_ver++ );
2498
2499
        /* object coding method */
2500
0
        if (subpicture_region_IsText( p_region ))
2501
0
            bs_write( s, 2, 1 );
2502
0
        else if ( p_region->p_picture->format.i_chroma == VLC_CODEC_YUVP )
2503
0
            bs_write( s, 2, 0 );
2504
0
        else
2505
0
        {
2506
0
            msg_Err( p_enc, "FOURCC %4.4s not supported by encoder.",
2507
0
                     (const char*)&p_region->p_picture->format.i_chroma );
2508
0
            i_region++;
2509
0
            continue;
2510
0
        }
2511
2512
0
        bs_write( s, 1, 0 ); /* non modifying color flag */
2513
0
        bs_write( s, 1, 0 ); /* Reserved */
2514
2515
0
        if(subpicture_region_IsText( p_region ))
2516
0
        {
2517
0
            int i_size, i;
2518
2519
0
            if( !p_region->p_text )
2520
0
            {
2521
0
                i_region++;
2522
0
                continue;
2523
0
            }
2524
2525
0
            i_size = __MIN( strlen( p_region->p_text->psz_text ), 256 );
2526
2527
0
            bs_write( s, 8, i_size ); /* number of characters in string */
2528
0
            for( i = 0; i < i_size; i++ )
2529
0
            {
2530
0
                bs_write( s, 16, p_region->p_text->psz_text[i] );
2531
0
            }
2532
2533
            /* Update segment length */
2534
0
            SetWBE( &s->p_start[i_length_pos/8],
2535
0
                    (bs_pos(s) - i_length_pos)/8 -2 );
2536
0
            i_region++;
2537
0
            continue;
2538
0
        }
2539
2540
        /* Coding of a bitmap object */
2541
0
        i_update_pos = bs_pos( s );
2542
0
        bs_write( s, 16, 0 ); /* topfield data block length */
2543
0
        bs_write( s, 16, 0 ); /* bottomfield data block length */
2544
2545
        /* Top field */
2546
0
        i_pixel_data_pos = bs_pos( s );
2547
0
        encode_pixel_data( p_enc, s, p_region, true );
2548
0
        i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8;
2549
0
        SetWBE( &s->p_start[i_update_pos/8], i_pixel_data_pos );
2550
2551
        /* Bottom field */
2552
0
        i_pixel_data_pos = bs_pos( s );
2553
0
        encode_pixel_data( p_enc, s, p_region, false );
2554
0
        i_pixel_data_pos = ( bs_pos( s ) - i_pixel_data_pos ) / 8;
2555
0
        SetWBE( &s->p_start[i_update_pos/8+2], i_pixel_data_pos );
2556
2557
        /* Stuffing for word alignment */
2558
0
        bs_align_0( s );
2559
0
        if( bs_pos( s ) % 16 ) bs_write( s, 8, 0 );
2560
2561
        /* Update segment length */
2562
0
        SetWBE( &s->p_start[i_length_pos/8], (bs_pos(s) - i_length_pos)/8 -2 );
2563
0
        i_region++;
2564
0
    }
2565
0
}
2566
2567
static void encode_pixel_line_2bp( bs_t *s, const subpicture_region_t *p_region,
2568
                                   int i_line );
2569
static void encode_pixel_line_4bp( bs_t *s, const subpicture_region_t *p_region,
2570
                                   int i_line );
2571
static void encode_pixel_line_8bp( bs_t *s, const subpicture_region_t *p_region,
2572
                                   int i_line );
2573
static void encode_pixel_data( encoder_t *p_enc, bs_t *s,
2574
                               const subpicture_region_t *p_region,
2575
                               bool b_top )
2576
0
{
2577
0
    unsigned int i_line;
2578
2579
    /* Encode line by line */
2580
0
    for( i_line = !b_top; i_line < p_region->fmt.i_visible_height;
2581
0
         i_line += 2 )
2582
0
    {
2583
0
        switch( p_region->p_picture->format.p_palette->i_entries )
2584
0
        {
2585
0
        case 0:
2586
0
            break;
2587
2588
0
        case 4:
2589
0
            bs_write( s, 8, 0x10 ); /* 2 bit/pixel code string */
2590
0
            encode_pixel_line_2bp( s, p_region, i_line );
2591
0
            break;
2592
2593
0
        case 16:
2594
0
            bs_write( s, 8, 0x11 ); /* 4 bit/pixel code string */
2595
0
            encode_pixel_line_4bp( s, p_region, i_line );
2596
0
            break;
2597
2598
0
        case 256:
2599
0
            bs_write( s, 8, 0x12 ); /* 8 bit/pixel code string */
2600
0
            encode_pixel_line_8bp( s, p_region, i_line );
2601
0
            break;
2602
2603
0
        default:
2604
0
            msg_Err( p_enc, "subpicture palette (%i) not handled",
2605
0
                     p_region->p_picture->format.p_palette->i_entries );
2606
0
            break;
2607
0
        }
2608
2609
0
        bs_write( s, 8, 0xf0 ); /* End of object line code */
2610
0
    }
2611
0
}
2612
2613
static void encode_pixel_line_2bp( bs_t *s, const subpicture_region_t *p_region,
2614
                                   int i_line )
2615
0
{
2616
0
    unsigned int i, i_length = 0;
2617
0
    int i_pitch = p_region->p_picture->p->i_pitch;
2618
0
    uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ];
2619
0
    int i_last_pixel = p_data[0];
2620
2621
0
    for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
2622
0
    {
2623
0
        if( ( i != p_region->fmt.i_visible_width ) &&
2624
0
            ( p_data[i] == i_last_pixel ) && ( i_length != 284 ) )
2625
0
        {
2626
0
            i_length++;
2627
0
            continue;
2628
0
        }
2629
2630
0
        if( ( i_length == 1 ) || ( i_length == 11 ) || ( i_length == 28 ) )
2631
0
        {
2632
            /* 2bit/pixel code */
2633
0
            if( i_last_pixel )
2634
0
                bs_write( s, 2, i_last_pixel );
2635
0
            else
2636
0
            {
2637
0
                bs_write( s, 2, 0 );
2638
0
                bs_write( s, 1, 0 );
2639
0
                bs_write( s, 1, 1 ); /* pseudo color 0 */
2640
0
            }
2641
0
            i_length--;
2642
0
        }
2643
2644
0
        if( i_length == 2 )
2645
0
        {
2646
0
            if( i_last_pixel )
2647
0
            {
2648
0
                bs_write( s, 2, i_last_pixel );
2649
0
                bs_write( s, 2, i_last_pixel );
2650
0
            }
2651
0
            else
2652
0
            {
2653
0
                bs_write( s, 2, 0 );
2654
0
                bs_write( s, 1, 0 );
2655
0
                bs_write( s, 1, 0 );
2656
0
                bs_write( s, 2, 1 ); /* 2 * pseudo color 0 */
2657
0
            }
2658
0
        }
2659
0
        else if( i_length > 2 )
2660
0
        {
2661
0
            bs_write( s, 2, 0 );
2662
0
            if( i_length <= 10 )
2663
0
            {
2664
0
                bs_write( s, 1, 1 );
2665
0
                bs_write( s, 3, i_length - 3 );
2666
0
                bs_write( s, 2, i_last_pixel );
2667
0
            }
2668
0
            else
2669
0
            {
2670
0
                bs_write( s, 1, 0 );
2671
0
                bs_write( s, 1, 0 );
2672
2673
0
                if( i_length <= 27 )
2674
0
                {
2675
0
                    bs_write( s, 2, 2 );
2676
0
                    bs_write( s, 4, i_length - 12 );
2677
0
                    bs_write( s, 2, i_last_pixel );
2678
0
                }
2679
0
                else
2680
0
                {
2681
0
                    bs_write( s, 2, 3 );
2682
0
                    bs_write( s, 8, i_length - 29 );
2683
0
                    bs_write( s, 2, i_last_pixel );
2684
0
                }
2685
0
            }
2686
0
        }
2687
2688
0
        if( i == p_region->fmt.i_visible_width ) break;
2689
2690
0
        i_last_pixel = p_data[i];
2691
0
        i_length = 1;
2692
0
    }
2693
2694
    /* Stop */
2695
0
    bs_write( s, 2, 0 );
2696
0
    bs_write( s, 1, 0 );
2697
0
    bs_write( s, 1, 0 );
2698
0
    bs_write( s, 2, 0 );
2699
2700
    /* Stuffing */
2701
0
    bs_align_0( s );
2702
0
}
2703
2704
static void encode_pixel_line_4bp( bs_t *s, const subpicture_region_t *p_region,
2705
                                   int i_line )
2706
0
{
2707
0
    unsigned int i, i_length = 0;
2708
0
    int i_pitch = p_region->p_picture->p->i_pitch;
2709
0
    uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ];
2710
0
    int i_last_pixel = p_data[0];
2711
2712
0
    for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
2713
0
    {
2714
0
        if( i != p_region->fmt.i_visible_width &&
2715
0
            p_data[i] == i_last_pixel && i_length != 280 )
2716
0
        {
2717
0
            i_length++;
2718
0
            continue;
2719
0
        }
2720
2721
0
        if( ( i_length == 1 ) ||
2722
0
            ( ( i_length == 3 ) && i_last_pixel ) ||
2723
0
            ( i_length == 8 ) )
2724
0
        {
2725
            /* 4bit/pixel code */
2726
0
            if( i_last_pixel )
2727
0
                bs_write( s, 4, i_last_pixel );
2728
0
            else
2729
0
            {
2730
0
                bs_write( s, 4, 0 );
2731
0
                bs_write( s, 1, 1 );
2732
0
                bs_write( s, 1, 1 );
2733
0
                bs_write( s, 2, 0 ); /* pseudo color 0 */
2734
0
            }
2735
0
            i_length--;
2736
0
        }
2737
2738
0
        if( i_length == 2 )
2739
0
        {
2740
0
            if( i_last_pixel )
2741
0
            {
2742
0
                bs_write( s, 4, i_last_pixel );
2743
0
                bs_write( s, 4, i_last_pixel );
2744
0
            }
2745
0
            else
2746
0
            {
2747
0
                bs_write( s, 4, 0 );
2748
0
                bs_write( s, 1, 1 );
2749
0
                bs_write( s, 1, 1 );
2750
0
                bs_write( s, 2, 1 ); /* 2 * pseudo color 0 */
2751
0
            }
2752
0
        }
2753
0
        else if( !i_last_pixel && ( i_length >= 3 ) && ( i_length <= 9 ) )
2754
0
        {
2755
0
            bs_write( s, 4, 0 );
2756
0
            bs_write( s, 1, 0 );
2757
0
            bs_write( s, 3, i_length - 2 ); /* (i_length - 2) * color 0 */
2758
0
        }
2759
0
        else if( i_length > 2 )
2760
0
        {
2761
0
            bs_write( s, 4, 0 );
2762
0
            bs_write( s, 1, 1 );
2763
2764
0
            if( i_length <= 7 )
2765
0
            {
2766
0
                bs_write( s, 1, 0 );
2767
0
                bs_write( s, 2, i_length - 4 );
2768
0
                bs_write( s, 4, i_last_pixel );
2769
0
            }
2770
0
            else
2771
0
            {
2772
0
                bs_write( s, 1, 1 );
2773
2774
0
                if( i_length <= 24 )
2775
0
                {
2776
0
                    bs_write( s, 2, 2 );
2777
0
                    bs_write( s, 4, i_length - 9 );
2778
0
                    bs_write( s, 4, i_last_pixel );
2779
0
                }
2780
0
                else
2781
0
                {
2782
0
                    bs_write( s, 2, 3 );
2783
0
                    bs_write( s, 8, i_length - 25 );
2784
0
                    bs_write( s, 4, i_last_pixel );
2785
0
                }
2786
0
            }
2787
0
        }
2788
2789
0
        if( i == p_region->fmt.i_visible_width ) break;
2790
2791
0
        i_last_pixel = p_data[i];
2792
0
        i_length = 1;
2793
0
    }
2794
2795
    /* Stop */
2796
0
    bs_write( s, 8, 0 );
2797
2798
    /* Stuffing */
2799
0
    bs_align_0( s );
2800
0
}
2801
2802
static void encode_pixel_line_8bp( bs_t *s, const subpicture_region_t *p_region,
2803
                                   int i_line )
2804
0
{
2805
0
    unsigned int i, i_length = 0;
2806
0
    int i_pitch = p_region->p_picture->p->i_pitch;
2807
0
    uint8_t *p_data = &p_region->p_picture->p->p_pixels[ i_pitch * i_line ];
2808
0
    int i_last_pixel = p_data[0];
2809
2810
0
    for( i = 0; i <= p_region->fmt.i_visible_width; i++ )
2811
0
    {
2812
0
        if( ( i != p_region->fmt.i_visible_width ) &&
2813
0
            ( p_data[i] == i_last_pixel ) && ( i_length != 127 ) )
2814
0
        {
2815
0
            i_length++;
2816
0
            continue;
2817
0
        }
2818
2819
0
        if( ( i_length == 1 ) && i_last_pixel )
2820
0
        {
2821
            /* 8bit/pixel code */
2822
0
            bs_write( s, 8, i_last_pixel );
2823
0
        }
2824
0
        else if( ( i_length == 2 ) && i_last_pixel )
2825
0
        {
2826
            /* 8bit/pixel code */
2827
0
            bs_write( s, 8, i_last_pixel );
2828
0
            bs_write( s, 8, i_last_pixel );
2829
0
        }
2830
0
        else if( i_length <= 127 )
2831
0
        {
2832
0
            bs_write( s, 8, 0 );
2833
2834
0
            if( !i_last_pixel )
2835
0
            {
2836
0
                bs_write( s, 1, 0 );
2837
0
                bs_write( s, 7, i_length ); /* pseudo color 0 */
2838
0
            }
2839
0
            else
2840
0
            {
2841
0
                bs_write( s, 1, 1 );
2842
0
                bs_write( s, 7, i_length );
2843
0
                bs_write( s, 8, i_last_pixel );
2844
0
            }
2845
0
        }
2846
2847
0
        if( i == p_region->fmt.i_visible_width ) break;
2848
2849
0
        i_last_pixel = p_data[i];
2850
0
        i_length = 1;
2851
0
    }
2852
2853
    /* Stop */
2854
0
    bs_write( s, 8, 0 );
2855
0
    bs_write( s, 8, 0 );
2856
2857
    /* Stuffing */
2858
0
    bs_align_0( s );
2859
0
}
2860
2861
#endif
2862
2863
static void default_dds_init( decoder_t * p_dec )
2864
5.99k
{
2865
5.99k
    decoder_sys_t *p_sys = p_dec->p_sys;
2866
2867
    /* see notes on DDS at the top of the file */
2868
2869
    /* configure for SD res in case DDS is not present */
2870
5.99k
    p_sys->display.i_version = 0xff; /* an invalid version so it's always different */
2871
5.99k
    p_sys->display.i_width_minus1 = 720-1;
2872
5.99k
    p_sys->display.i_height_minus1 = 576-1;
2873
    p_sys->display.b_windowed = false;
2874
5.99k
}