dvbsub.c 80.6 KB
Newer Older
1
/*****************************************************************************
2
3
 * dvbsub.c : DVB subtitles decoder
 *            DVB subtitles encoder (developed for Anevia, www.anevia.com)
4
5
 *****************************************************************************
 * Copyright (C) 2003 ANEVIA
6
 * Copyright (C) 2003-2005 the VideoLAN team
7
 * $Id$
8
 *
gbazin's avatar
gbazin committed
9
10
 * Authors: Gildas Bazin <gbazin@videolan.org>
 *          Damien LUCAS <damien.lucas@anevia.com>
11
 *          Laurent Aimar <fenrir@via.ecp.fr>
12
 *          Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
13
 *          Derk-Jan Hartman <hartman #at# videolan dot org>
14
15
16
17
18
19
20
21
22
23
24
25
26
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
27
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
28
29
30
 *****************************************************************************/
/*****************************************************************************
 * Preamble
31
32
33
 *
 * FIXME:
 * DVB subtitles coded as strings of characters are not handled correctly.
34
 * The character codes in the string should actually be indexes referring to a
35
 * character table identified in the subtitle descriptor.
36
37
38
39
40
 *
 * The spec is quite vague in this area, but what is meant is perhaps that it
 * refers to the character index in the codepage belonging to the language specified
 * in the subtitle descriptor. Potentially it's designed for widechar
 * (but not for UTF-*) codepages.
41
 *****************************************************************************/
42
43
44
45
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

46
#include <vlc/vlc.h>
47
#include <vlc_plugin.h>
zorglub's avatar
zorglub committed
48
49
50
#include <vlc_vout.h>
#include <vlc_codec.h>
#include <vlc_sout.h>
51

52
53
#include "vlc_bits.h"

Jean-Paul Saman's avatar
Jean-Paul Saman committed
54
/* #define DEBUG_DVBSUB 1 */
55

zorglub's avatar
zorglub committed
56
57
#define POSX_TEXT N_("Decoding X coordinate")
#define POSX_LONGTEXT N_("X coordinate of the rendered subtitle")
58

zorglub's avatar
zorglub committed
59
#define POSY_TEXT N_("Decoding Y coordinate")
60
#define POSY_LONGTEXT N_("Y coordinate of the rendered subtitle")
61
62
63
64
65

#define POS_TEXT N_("Subpicture position")
#define POS_LONGTEXT N_( \
  "You can enforce the subpicture position on the video " \
  "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \
zorglub's avatar
zorglub committed
66
  "also use combinations of these values, e.g. 6=top-right).")
67

zorglub's avatar
zorglub committed
68
69
70
71
#define ENC_POSX_TEXT N_("Encoding X coordinate")
#define ENC_POSX_LONGTEXT N_("X coordinate of the encoded subtitle" )
#define ENC_POSY_TEXT N_("Encoding Y coordinate")
#define ENC_POSY_LONGTEXT N_("Y coordinate of the encoded subtitle" )
72

73
74
static const int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };
static const char *const ppsz_pos_descriptions[] =
75
76
{ N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"),
  N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };
77

78
79
80
/*****************************************************************************
 * Module descriptor.
 *****************************************************************************/
81
82
83
84
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
static subpicture_t *Decode( decoder_t *, block_t ** );

85
86
87
static int OpenEncoder  ( vlc_object_t * );
static void CloseEncoder( vlc_object_t * );
static block_t *Encode  ( encoder_t *, subpicture_t * );
88
89

vlc_module_begin();
90
#   define DVBSUB_CFG_PREFIX "dvbsub-"
91
    set_description( N_("DVB subtitles decoder") );
92
    set_capability( "decoder", 50 );
zorglub's avatar
zorglub committed
93
94
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_SCODEC );
95
    set_callbacks( Open, Close );
96

97
    add_integer( DVBSUB_CFG_PREFIX "position", 8, NULL, POS_TEXT, POS_LONGTEXT, true );
98
        change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 );
99
100
    add_integer( DVBSUB_CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, false );
    add_integer( DVBSUB_CFG_PREFIX "y", -1, NULL, POSY_TEXT, POSY_LONGTEXT, false );
101
102
103

#   define ENC_CFG_PREFIX "sout-dvbsub-"
    add_submodule();
104
    set_description( N_("DVB subtitles encoder") );
105
106
    set_capability( "encoder", 100 );
    set_callbacks( OpenEncoder, CloseEncoder );
107

108
109
    add_integer( ENC_CFG_PREFIX "x", -1, NULL, ENC_POSX_TEXT, ENC_POSX_LONGTEXT, false );
    add_integer( ENC_CFG_PREFIX "y", -1, NULL, ENC_POSY_TEXT, ENC_POSY_LONGTEXT, false );
110
    add_obsolete_integer( ENC_CFG_PREFIX "timeout" ); /* Suppressed since 0.8.5 */
111
112
vlc_module_end();

113
static const char *const ppsz_enc_options[] = { "x", "y", NULL };
114

115
116
117
118
119
120
/****************************************************************************
 * Local structures
 ****************************************************************************
 * Those structures refer closely to the ETSI 300 743 Object model
 ****************************************************************************/

121
/* The object definition gives the position of the object in a region [7.2.5] */
122
123
typedef struct dvbsub_objectdef_s
{
gbazin's avatar
gbazin committed
124
125
126
127
128
129
    int i_id;
    int i_type;
    int i_x;
    int i_y;
    int i_fg_pc;
    int i_bg_pc;
130
    char *psz_text; /* for string of characters objects */
131

132
133
} dvbsub_objectdef_t;

gbazin's avatar
gbazin committed
134
135
/* The entry in the palette CLUT */
typedef struct
136
{
gbazin's avatar
gbazin committed
137
138
139
140
    uint8_t                 Y;
    uint8_t                 Cr;
    uint8_t                 Cb;
    uint8_t                 T;
141

gbazin's avatar
gbazin committed
142
} dvbsub_color_t;
143

144
145
146
147
148
149
150
151
152
/* The displays dimensions [7.2.1] */
typedef struct dvbsub_display_s
{
    uint8_t                 i_id;
    uint8_t                 i_version;

    int                     i_width;
    int                     i_height;

153
    bool              b_windowed;
154
155
156
157
158
159
160
161
    int                     i_x;
    int                     i_y;
    int                     i_max_x;
    int                     i_max_y;

} dvbsub_display_t;

/* [7.2.4] */
gbazin's avatar
gbazin committed
162
typedef struct dvbsub_clut_s
163
{
gbazin's avatar
gbazin committed
164
165
166
167
168
    uint8_t                 i_id;
    uint8_t                 i_version;
    dvbsub_color_t          c_2b[4];
    dvbsub_color_t          c_4b[16];
    dvbsub_color_t          c_8b[256];
169

gbazin's avatar
gbazin committed
170
171
172
    struct dvbsub_clut_s    *p_next;

} dvbsub_clut_t;
173

174
/* The Region is an aera on the image [7.2.3]
175
 * with a list of the object definitions associated and a CLUT */
176
177
typedef struct dvbsub_region_s
{
gbazin's avatar
gbazin committed
178
179
180
181
182
183
184
185
186
    int i_id;
    int i_version;
    int i_x;
    int i_y;
    int i_width;
    int i_height;
    int i_level_comp;
    int i_depth;
    int i_clut;
187

gbazin's avatar
gbazin committed
188
    uint8_t *p_pixbuf;
189

gbazin's avatar
gbazin committed
190
191
    int                    i_object_defs;
    dvbsub_objectdef_t     *p_object_defs;
192

gbazin's avatar
gbazin committed
193
    struct dvbsub_region_s *p_next;
194

gbazin's avatar
gbazin committed
195
} dvbsub_region_t;
196

gbazin's avatar
gbazin committed
197
198
/* The object definition gives the position of the object in a region */
typedef struct dvbsub_regiondef_s
199
{
gbazin's avatar
gbazin committed
200
201
202
    int i_id;
    int i_x;
    int i_y;
203

gbazin's avatar
gbazin committed
204
} dvbsub_regiondef_t;
205

206
/* The page defines the list of regions [7.2.2] */
207
208
typedef struct
{
gbazin's avatar
gbazin committed
209
    int i_id;
210
    int i_timeout; /* in seconds */
gbazin's avatar
gbazin committed
211
212
    int i_state;
    int i_version;
213

gbazin's avatar
gbazin committed
214
215
216
217
    int                i_region_defs;
    dvbsub_regiondef_t *p_region_defs;

} dvbsub_page_t;
218

219
220
struct decoder_sys_t
{
221
222
223
    bs_t            bs;

    /* Decoder internal data */
224
225
226
    int             i_id;
    int             i_ancillary_id;
    mtime_t         i_pts;
227

228
    bool      b_absolute;
229
230
231
    int             i_spu_position;
    int             i_spu_x;
    int             i_spu_y;
232

233
    bool      b_page;
234
235
    dvbsub_page_t   *p_page;
    dvbsub_region_t *p_regions;
gbazin's avatar
gbazin committed
236
    dvbsub_clut_t   *p_cluts;
237
238
    dvbsub_display_t *p_display;
    dvbsub_clut_t    default_clut;
239
240
241
};


242
243
/* List of different SEGMENT TYPES */
/* According to EN 300-743, table 2 */
244
245
246
247
#define DVBSUB_ST_PAGE_COMPOSITION      0x10
#define DVBSUB_ST_REGION_COMPOSITION    0x11
#define DVBSUB_ST_CLUT_DEFINITION       0x12
#define DVBSUB_ST_OBJECT_DATA           0x13
248
#define DVBSUB_ST_DISPLAY_DEFINITION    0x14
249
250
#define DVBSUB_ST_ENDOFDISPLAY          0x80
#define DVBSUB_ST_STUFFING              0xff
251
252
/* List of different OBJECT TYPES */
/* According to EN 300-743, table 6 */
253
254
255
#define DVBSUB_OT_BASIC_BITMAP          0x00
#define DVBSUB_OT_BASIC_CHAR            0x01
#define DVBSUB_OT_COMPOSITE_STRING      0x02
256
/* Pixel DATA TYPES */
257
/* According to EN 300-743, table 9 */
258
259
260
261
262
263
264
#define DVBSUB_DT_2BP_CODE_STRING       0x10
#define DVBSUB_DT_4BP_CODE_STRING       0x11
#define DVBSUB_DT_8BP_CODE_STRING       0x12
#define DVBSUB_DT_24_TABLE_DATA         0x20
#define DVBSUB_DT_28_TABLE_DATA         0x21
#define DVBSUB_DT_48_TABLE_DATA         0x22
#define DVBSUB_DT_END_LINE              0xf0
265
266
/* List of different Page Composition Segment state */
/* According to EN 300-743, 7.2.1 table 3 */
267
#define DVBSUB_PCS_STATE_ACQUISITION    0x01
268
#define DVBSUB_PCS_STATE_CHANGE         0x02
269
270
271
272

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
273
274
275
276
static void decode_segment( decoder_t *, bs_t * );
static void decode_page_composition( decoder_t *, bs_t * );
static void decode_region_composition( decoder_t *, bs_t * );
static void decode_object( decoder_t *, bs_t * );
277
static void decode_display_definition( decoder_t *, bs_t * );
278
279
static void decode_clut( decoder_t *, bs_t * );
static void free_all( decoder_t * );
280

281
static void default_clut_init( decoder_t * );
282

gbazin's avatar
gbazin committed
283
284
static subpicture_t *render( decoder_t * );

285
/*****************************************************************************
286
 * Open: probe the decoder and return score
287
288
289
290
 *****************************************************************************
 * Tries to launch a decoder and return score so that the interface is able
 * to chose.
 *****************************************************************************/
291
static int Open( vlc_object_t *p_this )
292
{
293
    decoder_t     *p_dec = (decoder_t *) p_this;
294
    decoder_sys_t *p_sys;
295
    vlc_value_t    val;
296
    int i_posx, i_posy;
297

gbazin's avatar
   
gbazin committed
298
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') )
299
300
301
    {
        return VLC_EGENERIC;
    }
302

303
    p_dec->pf_decode_sub = Decode;
304
    p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
Jean-Paul Saman's avatar
Jean-Paul Saman committed
305
306
    if( !p_sys )
        return VLC_ENOMEM;
gbazin's avatar
gbazin committed
307
    memset( p_sys, 0, sizeof(decoder_sys_t) );
308

309
    p_sys->i_pts          = (mtime_t) 0;
310
311
    p_sys->i_id           = p_dec->fmt_in.subs.dvb.i_id & 0xFFFF;
    p_sys->i_ancillary_id = p_dec->fmt_in.subs.dvb.i_id >> 16;
312

313
    p_sys->p_regions      = NULL;
gbazin's avatar
gbazin committed
314
315
    p_sys->p_cluts        = NULL;
    p_sys->p_page         = NULL;
316
    p_sys->p_display      = NULL;
317

318
319
    var_Create( p_this, DVBSUB_CFG_PREFIX "position",
                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
320
321
    var_Get( p_this, DVBSUB_CFG_PREFIX "position", &val );
    p_sys->i_spu_position = val.i_int;
322
323
    var_Create( p_this, DVBSUB_CFG_PREFIX "x",
                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
324
    var_Get( p_this, DVBSUB_CFG_PREFIX "x", &val );
325
326
327
    i_posx = val.i_int;
    var_Create( p_this, DVBSUB_CFG_PREFIX "y",
                VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
328
    var_Get( p_this, DVBSUB_CFG_PREFIX "y", &val );
329
    i_posy = val.i_int;
330

331
    /* Check if subpicture position was overridden */
332
    p_sys->b_absolute = false;
333
334
    p_sys->i_spu_x = p_sys->i_spu_y = 0;

335
    if( ( i_posx >= 0 ) && ( i_posy >= 0 ) )
336
    {
337
        p_sys->b_absolute = true;
338
339
        p_sys->i_spu_x = i_posx;
        p_sys->i_spu_y = i_posy;
340
    }
341

342
343
    es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) );

344
345
    default_clut_init( p_dec );

346
347
    return VLC_SUCCESS;
}
348
349
350
351
352
353
354
355
356

/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
{
    decoder_t     *p_dec = (decoder_t*) p_this;
    decoder_sys_t *p_sys = p_dec->p_sys;

357
358
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" );
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" );
359
    var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" );
360

361
    free_all( p_dec );
362
    free( p_sys );
363
364
}

365
/*****************************************************************************
366
 * Decode:
367
 *****************************************************************************/
368
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
369
{
370
371
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
372
    subpicture_t  *p_spu = NULL;
373

374
    if( ( pp_block == NULL ) || ( *pp_block == NULL ) ) return NULL;
375
376
377
    p_block = *pp_block;
    *pp_block = NULL;

378
379
    p_sys->i_pts = p_block->i_pts;
    if( p_sys->i_pts <= 0 )
380
    {
gbazin's avatar
gbazin committed
381
382
383
#ifdef DEBUG_DVBSUB
        /* Some DVB channels send stuffing segments in non-dated packets so
         * don't complain too loudly. */
384
        msg_Warn( p_dec, "non dated subtitle" );
gbazin's avatar
gbazin committed
385
#endif
386
        block_Release( p_block );
387
        return NULL;
388
389
    }

390
391
392
    bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );

    if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */
393
    {
394
395
        msg_Dbg( p_dec, "invalid data identifier" );
        block_Release( p_block );
396
        return NULL;
397
    }
398

gbazin's avatar
gbazin committed
399
    if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */
400
401
402
    {
        msg_Dbg( p_dec, "invalid subtitle stream id" );
        block_Release( p_block );
403
        return NULL;
404
    }
405

gbazin's avatar
gbazin committed
406
#ifdef DEBUG_DVBSUB
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
407
    msg_Dbg( p_dec, "subtitle packet received: %"PRId64, p_sys->i_pts );
gbazin's avatar
gbazin committed
408
409
#endif

410
    p_sys->b_page = false;
411
412
413
414
    while( bs_show( &p_sys->bs, 8 ) == 0x0f ) /* Sync byte */
    {
        decode_segment( p_dec, &p_sys->bs );
    }
415

416
417
418
419
    if( bs_read( &p_sys->bs, 8 ) != 0xff ) /* End marker */
    {
        msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" );
        block_Release( p_block );
420
        return NULL;
421
    }
422

423
    /* Check if the page is to be displayed */
424
425
    if( p_sys->p_page && p_sys->b_page )
        p_spu = render( p_dec );
426
427

    block_Release( p_block );
428
429

    return p_spu;
430
}
431

432
/* following functions are local */
433

434
/*****************************************************************************
435
 * default_clut_init: default clut as defined in EN 300-743 section 10
436
 *****************************************************************************/
437
static void default_clut_init( decoder_t *p_dec )
438
{
439
440
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t i;
441

442
443
444
#define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;
#define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;
#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256;
445

446
447
448
449
    /* 4 entries CLUT */
    for( i = 0; i < 4; i++ )
    {
        uint8_t R = 0, G = 0, B = 0, T = 0;
450

451
452
453
454
        if( !(i & 0x2) && !(i & 0x1) ) T = 0xFF;
        else if( !(i & 0x2) && (i & 0x1) ) R = G = B = 0xFF;
        else if( (i & 0x2) && !(i & 0x1) ) R = G = B = 0;
        else R = G = B = 0x7F;
455

456
457
        p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B);
        p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B);
458
        p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B);
459
        p_sys->default_clut.c_2b[i].T = T;
460
    }
461
462

    /* 16 entries CLUT */
463
464
    for( i = 0; i < 16; i++ )
    {
465
        uint8_t R = 0, G = 0, B = 0, T = 0;
466

467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
        if( !(i & 0x8) )
        {
            if( !(i & 0x4) && !(i & 0x2) && !(i & 0x1) )
            {
                T = 0xFF;
            }
            else
            {
                R = (i & 0x1) ? 0xFF : 0;
                G = (i & 0x2) ? 0xFF : 0;
                B = (i & 0x4) ? 0xFF : 0;
            }
        }
        else
        {
            R = (i & 0x1) ? 0x7F : 0;
            G = (i & 0x2) ? 0x7F : 0;
            B = (i & 0x4) ? 0x7F : 0;
        }
486

487
        p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B);
488
489
        p_sys->default_clut.c_4b[i].Cr = RGB_TO_V(R,G,B);
        p_sys->default_clut.c_4b[i].Cb = RGB_TO_U(R,G,B);
490
491
        p_sys->default_clut.c_4b[i].T = T;
    }
492

493
    /* 256 entries CLUT */
494
495
    memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) );
}
496

497
static void decode_segment( decoder_t *p_dec, bs_t *s )
498
{
499
    decoder_sys_t *p_sys = p_dec->p_sys;
500
501
502
503
    int i_type;
    int i_page_id;
    int i_size;

504
    /* sync_byte (already checked) */
505
506
507
508
509
510
511
512
513
514
515
    bs_skip( s, 8 );

    /* segment type */
    i_type = bs_read( s, 8 );

    /* page id */
    i_page_id = bs_read( s, 16 );

    /* segment size */
    i_size = bs_show( s, 16 );

516
517
    if( ( i_page_id != p_sys->i_id ) &&
        ( i_page_id != p_sys->i_ancillary_id ) )
518
    {
519
#ifdef DEBUG_DVBSUB
520
521
        msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)",
                 i_page_id, p_sys->i_id );
522
#endif
523
        bs_skip( s,  8 * ( 2 + i_size ) );
524
525
        return;
    }
526

527
528
529
    if( ( p_sys->i_ancillary_id != p_sys->i_id ) &&
        ( i_type == DVBSUB_ST_PAGE_COMPOSITION ) &&
        ( i_page_id == p_sys->i_ancillary_id ) )
530
531
532
533
534
535
536
537
    {
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "skipped invalid ancillary subtitle packet" );
#endif
        bs_skip( s,  8 * ( 2 + i_size ) );
        return;
    }

538
539
540
541
542
543
544
#ifdef DEBUG_DVBSUB
    if( i_page_id == p_sys->i_id )
        msg_Dbg( p_dec, "segment (id: %i)", i_page_id );
    else
        msg_Dbg( p_dec, "ancillary segment (id: %i)", i_page_id );
#endif

545
    switch( i_type )
546
    {
547
    case DVBSUB_ST_PAGE_COMPOSITION:
548
#ifdef DEBUG_DVBSUB
549
        msg_Dbg( p_dec, "decode_page_composition" );
550
#endif
551
        decode_page_composition( p_dec, s );
552
        break;
553
554

    case DVBSUB_ST_REGION_COMPOSITION:
555
#ifdef DEBUG_DVBSUB
556
        msg_Dbg( p_dec, "decode_region_composition" );
557
#endif
558
        decode_region_composition( p_dec, s );
559
        break;
560
561

    case DVBSUB_ST_CLUT_DEFINITION:
562
#ifdef DEBUG_DVBSUB
563
        msg_Dbg( p_dec, "decode_clut" );
564
#endif
565
        decode_clut( p_dec, s );
566
        break;
567

568
569
    case DVBSUB_ST_OBJECT_DATA:
#ifdef DEBUG_DVBSUB
570
        msg_Dbg( p_dec, "decode_object" );
571
#endif
572
        decode_object( p_dec, s );
573
        break;
574

575
576
577
578
579
580
581
    case DVBSUB_ST_DISPLAY_DEFINITION:
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "decode_display_definition" );
#endif
        decode_display_definition( p_dec, s );
        break;

582
583
    case DVBSUB_ST_ENDOFDISPLAY:
#ifdef DEBUG_DVBSUB
584
        msg_Dbg( p_dec, "end of display" );
585
#endif
586
        bs_skip( s,  8 * ( 2 + i_size ) );
587
        break;
588

589
    case DVBSUB_ST_STUFFING:
590
591
592
593
594
595
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "skip stuffing" );
#endif
        bs_skip( s,  8 * ( 2 + i_size ) );
        break;

596
597
598
599
    default:
        msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type );
        bs_skip( s,  8 * ( 2 + i_size ) );
        break;
600
601
602
    }
}

603
static void decode_clut( decoder_t *p_dec, bs_t *s )
604
{
605
606
607
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint16_t      i_segment_length;
    uint16_t      i_processed_length;
608
    dvbsub_clut_t *p_clut, *p_next;
gbazin's avatar
gbazin committed
609
    int           i_id, i_version;
610
611

    i_segment_length = bs_read( s, 16 );
gbazin's avatar
gbazin committed
612
613
    i_id             = bs_read( s, 8 );
    i_version        = bs_read( s, 4 );
614

gbazin's avatar
gbazin committed
615
616
617
618
619
620
621
    /* Check if we already have this clut */
    for( p_clut = p_sys->p_cluts; p_clut != NULL; p_clut = p_clut->p_next )
    {
        if( p_clut->i_id == i_id ) break;
    }

    /* Check version number */
622
    if( p_clut && ( p_clut->i_version == i_version ) )
623
    {
624
        /* Nothing to do */
gbazin's avatar
gbazin committed
625
        bs_skip( s, 8 * i_segment_length - 12 );
626
        return;
627
    }
628

gbazin's avatar
gbazin committed
629
    if( !p_clut )
630
    {
gbazin's avatar
gbazin committed
631
632
633
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "new clut: %i", i_id );
#endif
634
635
636
        p_clut = malloc( sizeof( dvbsub_clut_t ) );
        if( !p_clut )
            return;
gbazin's avatar
gbazin committed
637
638
        p_clut->p_next = p_sys->p_cluts;
        p_sys->p_cluts = p_clut;
639
    }
640

641
    /* Initialize to default clut */
642
    p_next = p_clut->p_next;
643
    *p_clut = p_sys->default_clut;
644
    p_clut->p_next = p_next;
645

646
    /* We don't have this version of the CLUT: Parse it */
gbazin's avatar
gbazin committed
647
648
    p_clut->i_version = i_version;
    p_clut->i_id = i_id;
649
650
651
    bs_skip( s, 4 ); /* Reserved bits */
    i_processed_length = 2;
    while( i_processed_length < i_segment_length )
652
    {
653
654
655
656
657
658
659
660
661
662
        uint8_t y, cb, cr, t;
        uint8_t i_id;
        uint8_t i_type;

        i_id = bs_read( s, 8 );
        i_type = bs_read( s, 3 );

        bs_skip( s, 4 );

        if( bs_read( s, 1 ) )
663
        {
664
665
666
667
668
            y  = bs_read( s, 8 );
            cr = bs_read( s, 8 );
            cb = bs_read( s, 8 );
            t  = bs_read( s, 8 );
            i_processed_length += 6;
669
670
671
        }
        else
        {
gbazin's avatar
gbazin committed
672
673
674
675
            y  = bs_read( s, 6 ) << 2;
            cr = bs_read( s, 4 ) << 4;
            cb = bs_read( s, 4 ) << 4;
            t  = bs_read( s, 2 ) << 6;
676
677
678
            i_processed_length += 4;
        }

gbazin's avatar
gbazin committed
679
680
681
682
683
684
685
686
687
        /* We are not entirely compliant here as full transparency is indicated
         * with a luma value of zero, not a transparency value of 0xff
         * (full transparency would actually be 0xff + 1). */
        if( y == 0 )
        {
            cr = cb = 0;
            t  = 0xff;
        }

688
        /* According to EN 300-743 section 7.2.3 note 1, type should
gbazin's avatar
gbazin committed
689
         * not have more than 1 bit set to one, but some streams don't
690
         * respect this note. */
691
        if( ( i_type & 0x04 ) && ( i_id < 4 ) )
692
        {
693
694
695
696
            p_clut->c_2b[i_id].Y = y;
            p_clut->c_2b[i_id].Cr = cr;
            p_clut->c_2b[i_id].Cb = cb;
            p_clut->c_2b[i_id].T = t;
697
        }
698
        if( ( i_type & 0x02 ) && ( i_id < 16 ) )
699
        {
700
701
702
703
            p_clut->c_4b[i_id].Y = y;
            p_clut->c_4b[i_id].Cr = cr;
            p_clut->c_4b[i_id].Cb = cb;
            p_clut->c_4b[i_id].T = t;
704
        }
705
        if( i_type & 0x01 )
706
        {
707
708
709
710
            p_clut->c_8b[i_id].Y = y;
            p_clut->c_8b[i_id].Cr = cr;
            p_clut->c_8b[i_id].Cb = cb;
            p_clut->c_8b[i_id].T = t;
711
        }
712
713
714
    }
}

715
static void decode_page_composition( decoder_t *p_dec, bs_t *s )
716
{
717
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
gbazin committed
718
    int i_version, i_state, i_segment_length, i_timeout, i;
719

gbazin's avatar
gbazin committed
720
    /* A page is composed by 0 or more region */
721
    i_segment_length = bs_read( s, 16 );
722
    i_timeout = bs_read( s, 8 );
gbazin's avatar
gbazin committed
723
    i_version = bs_read( s, 4 );
724
    i_state = bs_read( s, 2 );
725
726
    bs_skip( s, 2 ); /* Reserved */

727
728
729
730
731
732
733
734
    if( i_state == DVBSUB_PCS_STATE_CHANGE )
    {
        /* End of an epoch, reset decoder buffer */
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "page composition mode change" );
#endif
        free_all( p_dec );
    }
735
736
    else if( !p_sys->p_page && ( i_state != DVBSUB_PCS_STATE_ACQUISITION ) &&
             ( i_state != DVBSUB_PCS_STATE_CHANGE ) )
737
738
    {
        /* Not a full PCS, we need to wait for one */
gbazin's avatar
gbazin committed
739
        msg_Dbg( p_dec, "didn't receive an acquisition page yet" );
740

741
742
#if 0
        /* Try to start decoding even without an acquisition page */
743
        bs_skip( s,  8 * (i_segment_length - 2) );
744
        return;
gbazin's avatar
gbazin committed
745
#endif
746
747
    }

gbazin's avatar
gbazin committed
748
#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
749
    if( i_state == DVBSUB_PCS_STATE_ACQUISITION )
gbazin's avatar
gbazin committed
750
751
        msg_Dbg( p_dec, "acquisition page composition" );
#endif
752

753
    /* Check version number */
754
    if( p_sys->p_page && ( p_sys->p_page->i_version == i_version ) )
755
756
757
758
759
760
761
762
    {
        bs_skip( s,  8 * (i_segment_length - 2) );
        return;
    }
    else if( p_sys->p_page )
    {
        if( p_sys->p_page->i_region_defs )
            free( p_sys->p_page->p_region_defs );
763
        p_sys->p_page->p_region_defs = NULL;
764
765
        p_sys->p_page->i_region_defs = 0;
    }
766

767
    if( !p_sys->p_page )
768
    {
gbazin's avatar
gbazin committed
769
770
771
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "new page" );
#endif
772
773
        /* Allocate a new page */
        p_sys->p_page = malloc( sizeof(dvbsub_page_t) );
774
775
        if( !p_sys->p_page )
            return;
776
777
    }

gbazin's avatar
gbazin committed
778
    p_sys->p_page->i_version = i_version;
779
    p_sys->p_page->i_timeout = i_timeout;
780
    p_sys->b_page = true;
781
782
783
784
785
786
787
788

    /* Number of regions */
    p_sys->p_page->i_region_defs = (i_segment_length - 2) / 6;

    if( p_sys->p_page->i_region_defs == 0 ) return;

    p_sys->p_page->p_region_defs =
        malloc( p_sys->p_page->i_region_defs * sizeof(dvbsub_region_t) );
789
    if( p_sys->p_page->p_region_defs )
790
    {
791
792
793
794
795
796
        for( i = 0; i < p_sys->p_page->i_region_defs; i++ )
        {
            p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 );
            bs_skip( s, 8 ); /* Reserved */
            p_sys->p_page->p_region_defs[i].i_x = bs_read( s, 16 );
            p_sys->p_page->p_region_defs[i].i_y = bs_read( s, 16 );
797
798

#ifdef DEBUG_DVBSUB
799
800
801
            msg_Dbg( p_dec, "page_composition, region %i (%i,%i)",
                    i, p_sys->p_page->p_region_defs[i].i_x,
                    p_sys->p_page->p_region_defs[i].i_y );
802
#endif
803
        }
804
805
806
    }
}

807
static void decode_region_composition( decoder_t *p_dec, bs_t *s )
808
{
809
810
    decoder_sys_t *p_sys = p_dec->p_sys;
    dvbsub_region_t *p_region, **pp_region = &p_sys->p_regions;
gbazin's avatar
gbazin committed
811
812
813
    int i_segment_length, i_processed_length, i_id, i_version;
    int i_width, i_height, i_level_comp, i_depth, i_clut;
    int i_8_bg, i_4_bg, i_2_bg;
814
    bool b_fill;
815
816

    i_segment_length = bs_read( s, 16 );
gbazin's avatar
gbazin committed
817
818
    i_id = bs_read( s, 8 );
    i_version = bs_read( s, 4 );
819
820
821
822

    /* Check if we already have this region */
    for( p_region = p_sys->p_regions; p_region != NULL;
         p_region = p_region->p_next )
823
    {
824
        pp_region = &p_region->p_next;
gbazin's avatar
gbazin committed
825
        if( p_region->i_id == i_id ) break;
826
827
    }

828
    /* Check version number */
829
    if( p_region && ( p_region->i_version == i_version ) )
830
    {
gbazin's avatar
gbazin committed
831
        bs_skip( s, 8 * (i_segment_length - 1) - 4 );
832
        return;
833
    }
834

835
    if( !p_region )
836
    {
837
#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
838
        msg_Dbg( p_dec, "new region: %i", i_id );
839
840
#endif
        p_region = *pp_region = malloc( sizeof(dvbsub_region_t) );
841
842
843
844
845
846
847
        if( p_region )
        {
            memset( p_region, 0, sizeof(dvbsub_region_t) );
            p_region->p_object_defs = NULL;
            p_region->p_pixbuf = NULL;
            p_region->p_next = NULL;
        }
848
    }
849
850

    /* Region attributes */
gbazin's avatar
gbazin committed
851
852
853
    p_region->i_id = i_id;
    p_region->i_version = i_version;
    b_fill = bs_read( s, 1 );
854
    bs_skip( s, 3 ); /* Reserved */
gbazin's avatar
gbazin committed
855
856
857

    i_width = bs_read( s, 16 );
    i_height = bs_read( s, 16 );
858
859
860
#ifdef DEBUG_DVBSUB
    msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height );
#endif
gbazin's avatar
gbazin committed
861
862
    i_level_comp = bs_read( s, 3 );
    i_depth = bs_read( s, 3 );
863
    bs_skip( s, 2 ); /* Reserved */
gbazin's avatar
gbazin committed
864
865
866
867
868
    i_clut = bs_read( s, 8 );

    i_8_bg = bs_read( s, 8 );
    i_4_bg = bs_read( s, 4 );
    i_2_bg = bs_read( s, 2 );
869
    bs_skip( s, 2 ); /* Reserved */
870
871
872

    /* Free old object defs */
    while( p_region->i_object_defs )
873
        free( p_region->p_object_defs[--p_region->i_object_defs].psz_text );
874

875
    free( p_region->p_object_defs );
876
    p_region->p_object_defs = NULL;
877

gbazin's avatar
gbazin committed
878
    /* Extra sanity checks */
879
880
    if( ( p_region->i_width != i_width ) ||
        ( p_region->i_height != i_height ) )
gbazin's avatar
gbazin committed
881
882
883
    {
        if( p_region->p_pixbuf )
        {
884
885
            msg_Dbg( p_dec, "region size changed (%dx%d->%dx%d)",
                     p_regi