dvbsub.c 54.1 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
7
 * Copyright (C) 2003-2004 VideoLAN
 * $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
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *
 * 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
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/
/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
33
#include <vlc/sout.h>
34

35
36
#include "vlc_bits.h"

37
//#define DEBUG_DVBSUB 1
38

39
40
41
/*****************************************************************************
 * Module descriptor.
 *****************************************************************************/
42
43
44
45
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );
static subpicture_t *Decode( decoder_t *, block_t ** );

46
47
48
static int OpenEncoder  ( vlc_object_t * );
static void CloseEncoder( vlc_object_t * );
static block_t *Encode  ( encoder_t *, subpicture_t * );
49
50

vlc_module_begin();
bigben's avatar
bigben committed
51
    set_description( _("DVB subtitles decoder") );
52
53
    set_capability( "decoder", 50 );
    set_callbacks( Open, Close );
54
55
56
57
58
59

#   define ENC_CFG_PREFIX "sout-dvbsub-"
    add_submodule();
    set_description( _("DVB subtitles encoder") );
    set_capability( "encoder", 100 );
    set_callbacks( OpenEncoder, CloseEncoder );
60
61
vlc_module_end();

62
63
static const char *ppsz_enc_options[] = { NULL };

64
65
66
67
68
69
70
71
72
/****************************************************************************
 * Local structures
 ****************************************************************************
 * Those structures refer closely to the ETSI 300 743 Object model
 ****************************************************************************/

/* The object definition gives the position of the object in a region */
typedef struct dvbsub_objectdef_s
{
gbazin's avatar
gbazin committed
73
74
75
76
77
78
    int i_id;
    int i_type;
    int i_x;
    int i_y;
    int i_fg_pc;
    int i_bg_pc;
79

80
81
} dvbsub_objectdef_t;

gbazin's avatar
gbazin committed
82
83
/* The entry in the palette CLUT */
typedef struct
84
{
gbazin's avatar
gbazin committed
85
86
87
88
    uint8_t                 Y;
    uint8_t                 Cr;
    uint8_t                 Cb;
    uint8_t                 T;
89

gbazin's avatar
gbazin committed
90
} dvbsub_color_t;
91

gbazin's avatar
gbazin committed
92
93
/* */
typedef struct dvbsub_clut_s
94
{
gbazin's avatar
gbazin committed
95
96
97
98
99
    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];
100

gbazin's avatar
gbazin committed
101
102
103
    struct dvbsub_clut_s    *p_next;

} dvbsub_clut_t;
104

105
/* The Region is an aera on the image
106
 * with a list of the object definitions associated and a CLUT */
107
108
typedef struct dvbsub_region_s
{
gbazin's avatar
gbazin committed
109
110
111
112
113
114
115
116
117
    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;
118

gbazin's avatar
gbazin committed
119
    uint8_t *p_pixbuf;
120

gbazin's avatar
gbazin committed
121
122
    int                    i_object_defs;
    dvbsub_objectdef_t     *p_object_defs;
123

gbazin's avatar
gbazin committed
124
    struct dvbsub_region_s *p_next;
125

gbazin's avatar
gbazin committed
126
} dvbsub_region_t;
127

gbazin's avatar
gbazin committed
128
129
/* The object definition gives the position of the object in a region */
typedef struct dvbsub_regiondef_s
130
{
gbazin's avatar
gbazin committed
131
132
133
    int i_id;
    int i_x;
    int i_y;
134

gbazin's avatar
gbazin committed
135
} dvbsub_regiondef_t;
136

gbazin's avatar
gbazin committed
137
/* The page defines the list of regions */
138
139
typedef struct
{
gbazin's avatar
gbazin committed
140
141
142
143
    int i_id;
    int i_timeout;
    int i_state;
    int i_version;
144

gbazin's avatar
gbazin committed
145
146
147
148
    int                i_region_defs;
    dvbsub_regiondef_t *p_region_defs;

} dvbsub_page_t;
149

150
151
struct decoder_sys_t
{
152
153
154
    bs_t            bs;

    /* Decoder internal data */
155
156
157
    int             i_id;
    int             i_ancillary_id;
    mtime_t         i_pts;
158

159
160
    dvbsub_page_t   *p_page;
    dvbsub_region_t *p_regions;
gbazin's avatar
gbazin committed
161
    dvbsub_clut_t   *p_cluts;
162
    dvbsub_clut_t   default_clut;
163
164
165
};


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
// List of different SEGMENT TYPES
// According to EN 300-743, table 2
#define DVBSUB_ST_PAGE_COMPOSITION      0x10
#define DVBSUB_ST_REGION_COMPOSITION    0x11
#define DVBSUB_ST_CLUT_DEFINITION       0x12
#define DVBSUB_ST_OBJECT_DATA           0x13
#define DVBSUB_ST_ENDOFDISPLAY          0x80
#define DVBSUB_ST_STUFFING              0xff
// List of different OBJECT TYPES
// According to EN 300-743, table 6
#define DVBSUB_OT_BASIC_BITMAP          0x00
#define DVBSUB_OT_BASIC_CHAR            0x01
#define DVBSUB_OT_COMPOSITE_STRING      0x02
// Pixel DATA TYPES
// According to EN 300-743, table 9
#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
188
189
190
191
// List of different Page Composition Segment state
// According to EN 300-743, 7.2.1 table 3
#define DVBSUB_PCS_STATE_ACQUISITION    0x01
#define DVBSUB_PCS_STATE_CHANGE         0x10
192
193
194
195

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
196
197
198
199
200
201
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 * );
static void decode_clut( decoder_t *, bs_t * );
static void free_all( decoder_t * );
202

203
static void default_clut_init( decoder_t * );
204

gbazin's avatar
gbazin committed
205
206
static subpicture_t *render( decoder_t * );

207
/*****************************************************************************
208
 * Open: probe the decoder and return score
209
210
211
212
 *****************************************************************************
 * Tries to launch a decoder and return score so that the interface is able
 * to chose.
 *****************************************************************************/
213
static int Open( vlc_object_t *p_this )
214
{
215
    decoder_t     *p_dec = (decoder_t *) p_this;
216
217
    decoder_sys_t *p_sys;

gbazin's avatar
   
gbazin committed
218
    if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') )
219
220
221
    {
        return VLC_EGENERIC;
    }
222

223
    p_dec->pf_decode_sub = Decode;
224
    p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) );
gbazin's avatar
gbazin committed
225
    memset( p_sys, 0, sizeof(decoder_sys_t) );
226

227
228
229
230
    p_sys->i_pts          = 0;
    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;
    p_sys->p_regions      = NULL;
gbazin's avatar
gbazin committed
231
232
    p_sys->p_cluts        = NULL;
    p_sys->p_page         = NULL;
233
234
235

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

236
237
    default_clut_init( p_dec );

238
239
    return VLC_SUCCESS;
}
240
241
242
243
244
245
246
247
248

/*****************************************************************************
 * 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;

249
    free_all( p_dec );
250
    free( p_sys );
251
252
}

253
/*****************************************************************************
254
 * Decode:
255
 *****************************************************************************/
256
static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
257
{
258
259
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
260
    subpicture_t  *p_spu = NULL;
261

262
    if( pp_block == NULL || *pp_block == NULL ) return NULL;
263
264
265
    p_block = *pp_block;
    *pp_block = NULL;

266
267
    p_sys->i_pts = p_block->i_pts;
    if( p_sys->i_pts <= 0 )
268
    {
gbazin's avatar
gbazin committed
269
270
271
#ifdef DEBUG_DVBSUB
        /* Some DVB channels send stuffing segments in non-dated packets so
         * don't complain too loudly. */
272
        msg_Warn( p_dec, "non dated subtitle" );
gbazin's avatar
gbazin committed
273
#endif
274
        block_Release( p_block );
275
        return NULL;
276
277
    }

278
279
280
    bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer );

    if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */
281
    {
282
283
        msg_Dbg( p_dec, "invalid data identifier" );
        block_Release( p_block );
284
        return NULL;
285
    }
286

gbazin's avatar
gbazin committed
287
    if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */
288
289
290
    {
        msg_Dbg( p_dec, "invalid subtitle stream id" );
        block_Release( p_block );
291
        return NULL;
292
    }
293

gbazin's avatar
gbazin committed
294
295
296
297
#ifdef DEBUG_DVBSUB
    msg_Dbg( p_dec, "subtitle packet received: "I64Fd, p_sys->i_pts );
#endif

298
299
300
301
    while( bs_show( &p_sys->bs, 8 ) == 0x0f ) /* Sync byte */
    {
        decode_segment( p_dec, &p_sys->bs );
    }
302

303
304
305
306
    if( bs_read( &p_sys->bs, 8 ) != 0xff ) /* End marker */
    {
        msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" );
        block_Release( p_block );
307
        return NULL;
308
    }
309

310
311
    /* Check if the page is to be displayed */
    if( p_sys->p_page ) p_spu = render( p_dec );
312
313

    block_Release( p_block );
314
315

    return p_spu;
316
}
317

318
/* following functions are local */
319

320
/*****************************************************************************
321
 * default_clut_init: default clut as defined in EN 300-743 section 10
322
 *****************************************************************************/
323
static void default_clut_init( decoder_t *p_dec )
324
{
325
326
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t i;
327

328
329
330
#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;
331

332
333
334
335
    /* 4 entries CLUT */
    for( i = 0; i < 4; i++ )
    {
        uint8_t R = 0, G = 0, B = 0, T = 0;
336

337
338
339
340
        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;
341

342
343
344
345
        p_sys->default_clut.c_2b[i].Y = RGB_TO_Y(R,G,B);
        p_sys->default_clut.c_2b[i].Cr = RGB_TO_U(R,G,B);
        p_sys->default_clut.c_2b[i].Cb = RGB_TO_V(R,G,B);
        p_sys->default_clut.c_2b[i].T = T;
346
    }
347
348

    /* 16 entries CLUT */
349
350
    for( i = 0; i < 16; i++ )
    {
351
        uint8_t R = 0, G = 0, B = 0, T = 0;
352

353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
        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;
        }
372

373
374
375
376
377
        p_sys->default_clut.c_4b[i].Y = RGB_TO_Y(R,G,B);
        p_sys->default_clut.c_4b[i].Cr = RGB_TO_U(R,G,B);
        p_sys->default_clut.c_4b[i].Cb = RGB_TO_V(R,G,B);
        p_sys->default_clut.c_4b[i].T = T;
    }
378

379
380
381
    /* 256 entries CLUT (TODO) */
    memset( p_sys->default_clut.c_8b, 0xFF, 256 * sizeof(dvbsub_color_t) );
}
382

383
static void decode_segment( decoder_t *p_dec, bs_t *s )
384
{
385
    decoder_sys_t *p_sys = p_dec->p_sys;
386
387
388
389
    int i_type;
    int i_page_id;
    int i_size;

390
    /* sync_byte (already checked) */
391
392
393
394
395
396
397
398
399
400
401
    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 );

402
    if( i_page_id != p_sys->i_id && i_page_id != p_sys->i_ancillary_id )
403
    {
404
#ifdef DEBUG_DVBSUB
405
406
        msg_Dbg( p_dec, "subtitle skipped (page id: %i, %i)",
                 i_page_id, p_sys->i_id );
407
#endif
408
        bs_skip( s,  8 * ( 2 + i_size ) );
409
410
        return;
    }
411

412
413
414
415
416
417
418
#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

419
    switch( i_type )
420
    {
421
    case DVBSUB_ST_PAGE_COMPOSITION:
422
#ifdef DEBUG_DVBSUB
423
        msg_Dbg( p_dec, "decode_page_composition" );
424
#endif
425
        decode_page_composition( p_dec, s );
426
        break;
427
428

    case DVBSUB_ST_REGION_COMPOSITION:
429
#ifdef DEBUG_DVBSUB
430
        msg_Dbg( p_dec, "decode_region_composition" );
431
#endif
432
        decode_region_composition( p_dec, s );
433
        break;
434
435

    case DVBSUB_ST_CLUT_DEFINITION:
436
#ifdef DEBUG_DVBSUB
437
        msg_Dbg( p_dec, "decode_clut" );
438
#endif
439
        decode_clut( p_dec, s );
440
        break;
441

442
443
    case DVBSUB_ST_OBJECT_DATA:
#ifdef DEBUG_DVBSUB
444
        msg_Dbg( p_dec, "decode_object" );
445
#endif
446
        decode_object( p_dec, s );
447
        break;
448

449
450
    case DVBSUB_ST_ENDOFDISPLAY:
#ifdef DEBUG_DVBSUB
451
        msg_Dbg( p_dec, "end of display" );
452
#endif
453
        bs_skip( s,  8 * ( 2 + i_size ) );
454
        break;
455

456
    case DVBSUB_ST_STUFFING:
457
458
459
460
461
462
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "skip stuffing" );
#endif
        bs_skip( s,  8 * ( 2 + i_size ) );
        break;

463
464
465
466
    default:
        msg_Warn( p_dec, "unsupported segment type: (%04x)", i_type );
        bs_skip( s,  8 * ( 2 + i_size ) );
        break;
467
468
469
    }
}

470
static void decode_clut( decoder_t *p_dec, bs_t *s )
471
{
472
473
474
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint16_t      i_segment_length;
    uint16_t      i_processed_length;
475
    dvbsub_clut_t *p_clut, *p_next;
gbazin's avatar
gbazin committed
476
    int           i_id, i_version;
477
478

    i_segment_length = bs_read( s, 16 );
gbazin's avatar
gbazin committed
479
480
    i_id             = bs_read( s, 8 );
    i_version        = bs_read( s, 4 );
481

gbazin's avatar
gbazin committed
482
483
484
485
486
487
488
489
    /* 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 */
    if( p_clut && p_clut->i_version == i_version )
490
    {
491
        /* Nothing to do */
gbazin's avatar
gbazin committed
492
        bs_skip( s, 8 * i_segment_length - 12 );
493
        return;
494
    }
495

gbazin's avatar
gbazin committed
496
    if( !p_clut )
497
    {
gbazin's avatar
gbazin committed
498
499
500
501
502
503
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "new clut: %i", i_id );
#endif
        p_clut = malloc( sizeof(dvbsub_clut_t) );
        p_clut->p_next = p_sys->p_cluts;
        p_sys->p_cluts = p_clut;
504
    }
505

506
    /* Initialize to default clut */
507
    p_next = p_clut->p_next;
508
    *p_clut = p_sys->default_clut;
509
    p_clut->p_next = p_next;
510

511
    /* We don't have this version of the CLUT: Parse it */
gbazin's avatar
gbazin committed
512
513
    p_clut->i_version = i_version;
    p_clut->i_id = i_id;
514
515
516
    bs_skip( s, 4 ); /* Reserved bits */
    i_processed_length = 2;
    while( i_processed_length < i_segment_length )
517
    {
518
519
520
521
522
523
524
525
526
527
        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 ) )
528
        {
529
530
531
532
533
            y  = bs_read( s, 8 );
            cr = bs_read( s, 8 );
            cb = bs_read( s, 8 );
            t  = bs_read( s, 8 );
            i_processed_length += 6;
534
535
536
        }
        else
        {
gbazin's avatar
gbazin committed
537
538
539
540
            y  = bs_read( s, 6 ) << 2;
            cr = bs_read( s, 4 ) << 4;
            cb = bs_read( s, 4 ) << 4;
            t  = bs_read( s, 2 ) << 6;
541
542
543
            i_processed_length += 4;
        }

gbazin's avatar
gbazin committed
544
545
546
547
548
549
550
551
552
553
        /* 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;
        }

554
        /* According to EN 300-743 section 7.2.3 note 1, type should
gbazin's avatar
gbazin committed
555
         * not have more than 1 bit set to one, but some streams don't
556
         * respect this note. */
557

558
        if( i_type & 0x04 && i_id < 4 )
559
        {
560
561
562
563
            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;
564
        }
565
        if( i_type & 0x02 && i_id < 16 )
566
        {
567
568
569
570
            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;
571
        }
572
        if( i_type & 0x01 )
573
        {
574
575
576
577
            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;
578
        }
579
580
581
    }
}

582
static void decode_page_composition( decoder_t *p_dec, bs_t *s )
583
{
584
    decoder_sys_t *p_sys = p_dec->p_sys;
gbazin's avatar
gbazin committed
585
    int i_version, i_state, i_segment_length, i_timeout, i;
586

gbazin's avatar
gbazin committed
587
    /* A page is composed by 0 or more region */
588

589
    i_segment_length = bs_read( s, 16 );
590
    i_timeout = bs_read( s, 8 );
gbazin's avatar
gbazin committed
591
    i_version = bs_read( s, 4 );
592
    i_state = bs_read( s, 2 );
593
594
    bs_skip( s, 2 ); /* Reserved */

595
596
597
598
599
600
601
602
    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 );
    }
603
604
    else if( !p_sys->p_page && i_state != DVBSUB_PCS_STATE_ACQUISITION &&
             i_state != DVBSUB_PCS_STATE_CHANGE )
605
606
    {
        /* Not a full PCS, we need to wait for one */
gbazin's avatar
gbazin committed
607
        msg_Dbg( p_dec, "didn't receive an acquisition page yet" );
608
609

#if 0 /* Try to start decoding even without an acquisition page */
610
        bs_skip( s,  8 * (i_segment_length - 2) );
611
        return;
gbazin's avatar
gbazin committed
612
#endif
613
614
    }

gbazin's avatar
gbazin committed
615
#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
616
    if( i_state == DVBSUB_PCS_STATE_ACQUISITION )
gbazin's avatar
gbazin committed
617
618
        msg_Dbg( p_dec, "acquisition page composition" );
#endif
619

620
    /* Check version number */
gbazin's avatar
gbazin committed
621
    if( p_sys->p_page && p_sys->p_page->i_version == i_version )
622
623
624
625
626
627
628
629
630
631
    {
        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 );
        p_sys->p_page->i_region_defs = 0;
    }
632

633
    if( !p_sys->p_page )
634
    {
gbazin's avatar
gbazin committed
635
636
637
#ifdef DEBUG_DVBSUB
        msg_Dbg( p_dec, "new page" );
#endif
638
639
        /* Allocate a new page */
        p_sys->p_page = malloc( sizeof(dvbsub_page_t) );
640
641
    }

gbazin's avatar
gbazin committed
642
    p_sys->p_page->i_version = i_version;
643
644
645
646
647
648
649
650
651
652
    p_sys->p_page->i_timeout = i_timeout;

    /* 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) );
    for( i = 0; i < p_sys->p_page->i_region_defs; i++ )
653
    {
654
        p_sys->p_page->p_region_defs[i].i_id = bs_read( s, 8 );
655
        bs_skip( s, 8 ); /* Reserved */
656
657
658
659
660
661
662
663
        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 );

#ifdef DEBUG_DVBSUB
        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 );
#endif
664
665
666
    }
}

667
static void decode_region_composition( decoder_t *p_dec, bs_t *s )
668
{
669
670
    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
671
672
673
674
    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;
    vlc_bool_t b_fill;
675
676

    i_segment_length = bs_read( s, 16 );
gbazin's avatar
gbazin committed
677
678
    i_id = bs_read( s, 8 );
    i_version = bs_read( s, 4 );
679
680
681
682

    /* Check if we already have this region */
    for( p_region = p_sys->p_regions; p_region != NULL;
         p_region = p_region->p_next )
683
    {
684
        pp_region = &p_region->p_next;
gbazin's avatar
gbazin committed
685
        if( p_region->i_id == i_id ) break;
686
687
    }

688
    /* Check version number */
gbazin's avatar
gbazin committed
689
    if( p_region && p_region->i_version == i_version )
690
    {
gbazin's avatar
gbazin committed
691
        bs_skip( s, 8 * (i_segment_length - 1) - 4 );
692
        return;
693
    }
694

695
    if( !p_region )
696
    {
697
#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
698
        msg_Dbg( p_dec, "new region: %i", i_id );
699
700
#endif
        p_region = *pp_region = malloc( sizeof(dvbsub_region_t) );
gbazin's avatar
gbazin committed
701
702
703
        memset( p_region, 0, sizeof(dvbsub_region_t) );
        p_region->p_object_defs = NULL;
        p_region->p_pixbuf = NULL;
704
        p_region->p_next = NULL;
705
    }
706
707

    /* Region attributes */
gbazin's avatar
gbazin committed
708
709
710
    p_region->i_id = i_id;
    p_region->i_version = i_version;
    b_fill = bs_read( s, 1 );
711
    bs_skip( s, 3 ); /* Reserved */
gbazin's avatar
gbazin committed
712
713
714
715
716

    i_width = bs_read( s, 16 );
    i_height = bs_read( s, 16 );
    i_level_comp = bs_read( s, 3 );
    i_depth = bs_read( s, 3 );
717
    bs_skip( s, 2 ); /* Reserved */
gbazin's avatar
gbazin committed
718
719
720
721
722
    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 );
723
    bs_skip( s, 2 ); /* Reserved */
724
    p_region->i_object_defs    = 0;
725

gbazin's avatar
gbazin committed
726
727
728
729
730
731
732
733
734
735
    /* Extra sanity checks */
    if( p_region->i_width != i_width || p_region->i_height != i_height )
    {
        if( p_region->p_pixbuf )
        {
            msg_Dbg( p_dec, "region size changed (not allowed)" );
            free( p_region->p_pixbuf );
        }

        p_region->p_pixbuf = malloc( i_height * i_width );
736
        p_region->i_depth = 0;
gbazin's avatar
gbazin committed
737
738
        b_fill = VLC_TRUE;
    }
739
740
    if( p_region->i_depth && (p_region->i_depth != i_depth ||
        p_region->i_level_comp != i_level_comp || p_region->i_clut != i_clut) )
gbazin's avatar
gbazin committed
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
    {
        msg_Dbg( p_dec, "region parameters changed (not allowed)" );
    }

    /* Erase background of region */
    if( b_fill )
    {
        int i_background = (p_region->i_depth == 1) ? i_2_bg :
            (p_region->i_depth == 2) ? i_4_bg : i_8_bg;
        memset( p_region->p_pixbuf, i_background, i_width * i_height );
    }

    p_region->i_width = i_width;
    p_region->i_height = i_height;
    p_region->i_level_comp = i_level_comp;
    p_region->i_depth = i_depth;
    p_region->i_clut = i_clut;

759
    /* List of objects in the region */
760
761
    i_processed_length = 10;
    while( i_processed_length < i_segment_length )
762
    {
763
764
        dvbsub_objectdef_t *p_obj;

765
        /* We create a new object */
766
767
768
769
        p_region->i_object_defs++;
        p_region->p_object_defs =
            realloc( p_region->p_object_defs,
                     sizeof(dvbsub_objectdef_t) * p_region->i_object_defs );
770
771

        /* We parse object properties */
772
        p_obj = &p_region->p_object_defs[p_region->i_object_defs - 1];
773
774
        p_obj->i_id         = bs_read( s, 16 );
        p_obj->i_type       = bs_read( s, 2 );
gbazin's avatar
gbazin committed
775
        bs_skip( s, 2 ); /* Provider */
776
        p_obj->i_x          = bs_read( s, 12 );
777
        bs_skip( s, 4 ); /* Reserved */
778
        p_obj->i_y          = bs_read( s, 12 );
779
780
781
782
783
784
785
786
787
788

        i_processed_length += 6;

        if( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ||
            p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING )
        {
            p_obj->i_fg_pc =  bs_read( s, 8 );
            p_obj->i_bg_pc =  bs_read( s, 8 );
            i_processed_length += 2;
        }
789
790
791
    }
}

gbazin's avatar
gbazin committed
792
793
static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int,
                                 uint8_t *, int );
794
795
796
static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );
static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );
static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );
797

798
static void decode_object( decoder_t *p_dec, bs_t *s )
799
{
gbazin's avatar
gbazin committed
800
801
802
803
804
805
806
807
808
    decoder_sys_t *p_sys = p_dec->p_sys;
    dvbsub_region_t *p_region;
    int i_segment_length, i_coding_method, i_version, i_id, i;
    vlc_bool_t b_non_modify_color;

    i_segment_length = bs_read( s, 16 );
    i_id             = bs_read( s, 16 );
    i_version        = bs_read( s, 4 );
    i_coding_method  = bs_read( s, 2 );
809
810
811
812
813

    if( i_coding_method )
    {
        /* TODO: DVB subtitling as characters */
        msg_Dbg( p_dec, "DVB subtitling as characters is not handled!" );
gbazin's avatar
gbazin committed
814
        bs_skip( s, 8 * (i_segment_length - 2) - 6 );
815
816
        return;
    }
817

gbazin's avatar
gbazin committed
818
819
820
821
    /* Check if the object needs to be rendered in at least one
     * of the regions */
    for( p_region = p_sys->p_regions; p_region != NULL;
         p_region = p_region->p_next )
822
    {
gbazin's avatar
gbazin committed
823
824
        for( i = 0; i < p_region->i_object_defs; i++ )
            if( p_region->p_object_defs[i].i_id == i_id ) break;
825

gbazin's avatar
gbazin committed
826
        if( i != p_region->i_object_defs ) break;
827
    }
gbazin's avatar
gbazin committed
828
    if( !p_region )
829
    {
gbazin's avatar
gbazin committed
830
831
        bs_skip( s, 8 * (i_segment_length - 2) - 6 );
        return;
832
833
834
    }

#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
835
    msg_Dbg( p_dec, "new object: %i", i_id );
836
#endif
837

gbazin's avatar
gbazin committed
838
    b_non_modify_color = bs_read( s, 1 );
839
840
    bs_skip( s, 1 ); /* Reserved */

gbazin's avatar
gbazin committed
841
    if( i_coding_method == 0x00 )
842
    {
gbazin's avatar
gbazin committed
843
844
        int i_topfield, i_bottomfield;
        uint8_t *p_topfield, *p_bottomfield;
845

gbazin's avatar
gbazin committed
846
847
848
849
        i_topfield    = bs_read( s, 16 );
        i_bottomfield = bs_read( s, 16 );
        p_topfield    = s->p_start + bs_pos( s ) / 8;
        p_bottomfield = p_topfield + i_topfield;
850

851
852
853
854
        bs_skip( s, 8 * (i_segment_length - 7) );

        /* Sanity check */
        if( i_segment_length < i_topfield + i_bottomfield + 7 ||
855
            p_topfield + i_topfield + i_bottomfield > s->p_end )
856
857
858
859
860
        {
            msg_Dbg( p_dec, "corrupted object data" );
            return;
        }

gbazin's avatar
gbazin committed
861
862
863
864
865
866
867
868
869
870
871
        for( p_region = p_sys->p_regions; p_region != NULL;
             p_region = p_region->p_next )
        {
            for( i = 0; i < p_region->i_object_defs; i++ )
            {
                if( p_region->p_object_defs[i].i_id != i_id ) continue;

                dvbsub_render_pdata( p_dec, p_region,
                                     p_region->p_object_defs[i].i_x,
                                     p_region->p_object_defs[i].i_y,
                                     p_topfield, i_topfield );
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887

                if( i_bottomfield )
                {
                    dvbsub_render_pdata( p_dec, p_region,
                                         p_region->p_object_defs[i].i_x,
                                         p_region->p_object_defs[i].i_y + 1,
                                         p_bottomfield, i_bottomfield );
                }
                else
                {
                    /* Duplicate the top field */
                    dvbsub_render_pdata( p_dec, p_region,
                                         p_region->p_object_defs[i].i_x,
                                         p_region->p_object_defs[i].i_y + 1,
                                         p_topfield, i_topfield );
                }
gbazin's avatar
gbazin committed
888
889
            }
        }
890
891
892
    }
    else
    {
893
        /* TODO: DVB subtitling as characters */
894
    }
895
896

#ifdef DEBUG_DVBSUB
gbazin's avatar
gbazin committed
897
    msg_Dbg( p_dec, "end object: %i", i_id );
898
#endif
899
}
900

gbazin's avatar
gbazin committed
901
902
903
static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region,
                                 int i_x, int i_y,
                                 uint8_t *p_field, int i_field )
904
{
905
    uint8_t *p_pixbuf;
gbazin's avatar
gbazin committed
906
    int i_offset = 0;
907
908
909
910
911
912
913
914
915
916
917
918
919
920
    bs_t bs;

    /* Sanity check */
    if( !p_region->p_pixbuf )
    {
        msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id );
        return;
    }
    if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height ||
        i_x >= p_region->i_width )
    {
        msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y );
        return;
    }
921

922
    p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width;
gbazin's avatar
gbazin committed
923
    bs_init( &bs, p_field, i_field );
924

gbazin's avatar
gbazin committed
925
    while( !bs_eof( &bs ) )
926
    {
927
928
929
        /* Sanity check */
        if( i_y >= p_region->i_height ) return;

gbazin's avatar
gbazin committed
930
        switch( bs_read( &bs, 8 ) )
931
        {
gbazin's avatar
gbazin committed
932
        case 0x10:
933
934
            dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
                              &i_offset );
gbazin's avatar
gbazin committed
935
            break;
936

gbazin's avatar
gbazin committed
937
        case 0x11:
938
939
            dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
                              &i_offset );
gbazin's avatar
gbazin committed
940
            break;
941

gbazin's avatar
gbazin committed
942
        case 0x12:
943
944
            dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,
                              &i_offset );
gbazin's avatar
gbazin committed
945
            break;
946

gbazin's avatar
gbazin committed
947
948
949
950
951
        case 0x20:
        case 0x21:
        case 0x22:
            /* We don't use map tables */
            break;
952
953
954
955

        case 0xf0: /* End of line code */
            p_pixbuf += 2*p_region->i_width;
            i_offset = 0; i_y += 2;
gbazin's avatar
gbazin committed
956
            break;
957
958
959
960
        }
    }
}

961
static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off )
962
963
964
{
    vlc_bool_t b_stop = 0;

gbazin's avatar
gbazin committed
965
    while( !b_stop && !bs_eof( s ) )
966
    {
967
968
        int i_count = 0, i_color = 0;

969
970
        if( (i_color = bs_read( s, 2 )) != 0x00 )
        {
971
            i_count = 1;
972
973
974
        }
        else
        {
975
            if( bs_read( s, 1 ) == 0x01 )         // Switch1
gbazin's avatar