Coverage Report

Created: 2026-05-21 08:06

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