Coverage Report

Created: 2026-01-17 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vlc/modules/codec/cvdsub.c
Line
Count
Source
1
/*****************************************************************************
2
 * cvdsub.c : CVD Subtitle decoder
3
 *****************************************************************************
4
 * Copyright (C) 2003, 2004 VLC authors and VideoLAN
5
 *
6
 * Authors: Rocky Bernstein
7
 *          Gildas Bazin <gbazin@videolan.org>
8
 *          Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
9
 *          Laurent Aimar <fenrir@via.ecp.fr>
10
 *
11
 * This program is free software; you can redistribute it and/or modify it
12
 * under the terms of the GNU Lesser General Public License as published by
13
 * the Free Software Foundation; either version 2.1 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
 * GNU Lesser General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Lesser General Public License
22
 * along with this program; if not, write to the Free Software Foundation,
23
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
 *****************************************************************************/
25
26
/*****************************************************************************
27
 * Preamble
28
 *****************************************************************************/
29
#ifdef HAVE_CONFIG_H
30
# include "config.h"
31
#endif
32
33
#include <vlc_common.h>
34
#include <vlc_plugin.h>
35
#include <vlc_codec.h>
36
37
#include <vlc_bits.h>
38
39
#include "../demux/mpeg/timestamps.h"
40
41
#define DEBUG_CVDSUB 1
42
43
/*****************************************************************************
44
 * Module descriptor.
45
 *****************************************************************************/
46
static int  DecoderOpen   ( vlc_object_t * );
47
static int  PacketizerOpen( vlc_object_t * );
48
static void DecoderClose  ( vlc_object_t * );
49
50
108
vlc_module_begin ()
51
54
    set_description( N_("CVD subtitle decoder") )
52
54
    set_capability( "spu decoder", 50 )
53
108
    set_callbacks( DecoderOpen, DecoderClose )
54
55
54
    add_submodule ()
56
54
    set_description( N_("Chaoji VCD subtitle packetizer") )
57
54
    set_capability( "spu packetizer", 50 )
58
108
    set_callbacks( PacketizerOpen, DecoderClose )
59
54
vlc_module_end ()
60
61
/*****************************************************************************
62
 * Local prototypes
63
 *****************************************************************************/
64
static int Decode( decoder_t *, block_t * );
65
static block_t *Packetize  ( decoder_t *, block_t ** );
66
static block_t *Reassemble ( decoder_t *, block_t * );
67
static void ParseMetaInfo  ( decoder_t *, block_t * );
68
static void ParseHeader    ( decoder_t *, block_t * );
69
static subpicture_t *DecodePacket( decoder_t *, block_t * );
70
static void RenderImage( decoder_t *, block_t *, picture_t * );
71
72
28.3k
#define SUBTITLE_BLOCK_EMPTY 0
73
2.16k
#define SUBTITLE_BLOCK_PARTIAL 1
74
#define SUBTITLE_BLOCK_COMPLETE 2
75
76
typedef struct
77
{
78
  int      b_packetizer;
79
80
  int      i_state;    /* data-gathering state for this subtitle */
81
82
  block_t  *p_spu;   /* Bytes of the packet. */
83
84
  size_t   i_spu_size;     /* goal for subtitle_data_pos while gathering,
85
                             size of used subtitle_data later */
86
87
  uint16_t i_image_offset;      /* offset from subtitle_data to compressed
88
                                   image data */
89
  size_t first_field_offset;       /* offset of even raster lines */
90
  size_t second_field_offset;      /* offset of odd raster lines */
91
  size_t metadata_offset;          /* offset to data describing the image */
92
  size_t metadata_length;          /* length of metadata */
93
94
  vlc_tick_t i_duration;   /* how long to display the image, 0 stands
95
                           for "until next subtitle" */
96
97
  uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
98
                                    image when displayed */
99
  uint16_t i_width, i_height;    /* dimensions in pixels of image */
100
101
  uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
102
  uint8_t p_palette_highlight[4][4];
103
} decoder_sys_t;
104
105
static int OpenCommon( vlc_object_t *p_this, bool b_packetizer )
106
28.8k
{
107
28.8k
    decoder_t     *p_dec = (decoder_t*)p_this;
108
28.8k
    decoder_sys_t *p_sys;
109
110
28.8k
    if( p_dec->fmt_in->i_codec != VLC_CODEC_CVD )
111
28.2k
        return VLC_EGENERIC;
112
113
560
    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
114
560
    if( !p_sys )
115
0
        return VLC_ENOMEM;
116
117
560
    p_sys->b_packetizer  = b_packetizer;
118
119
560
    p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
120
560
    p_sys->p_spu   = NULL;
121
122
560
    if( b_packetizer )
123
280
    {
124
280
        p_dec->pf_packetize    = Packetize;
125
280
        p_dec->fmt_out.i_codec = VLC_CODEC_CVD;
126
280
    }
127
280
    else
128
280
    {
129
280
        p_dec->pf_decode       = Decode;
130
280
        p_dec->fmt_out.i_codec = VLC_CODEC_YUVP;
131
280
    }
132
133
560
    return VLC_SUCCESS;
134
560
}
135
/*****************************************************************************
136
 * DecoderOpen: open/initialize the cvdsub decoder.
137
 *****************************************************************************/
138
static int DecoderOpen( vlc_object_t *p_this )
139
12.9k
{
140
12.9k
    return OpenCommon( p_this, false );
141
12.9k
}
142
143
/*****************************************************************************
144
 * PacketizerOpen: open/initialize the cvdsub packetizer.
145
 *****************************************************************************/
146
static int PacketizerOpen( vlc_object_t *p_this )
147
15.8k
{
148
15.8k
    return OpenCommon( p_this, true );
149
15.8k
}
150
151
/*****************************************************************************
152
 * DecoderClose: closes the cvdsub decoder/packetizer.
153
 *****************************************************************************/
154
void DecoderClose( vlc_object_t *p_this )
155
560
{
156
560
    decoder_t     *p_dec = (decoder_t*)p_this;
157
560
    decoder_sys_t *p_sys = p_dec->p_sys;
158
159
560
    if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
160
560
    free( p_sys );
161
560
}
162
163
/*****************************************************************************
164
 * Decode:
165
 *****************************************************************************/
166
static int Decode( decoder_t *p_dec, block_t *p_block )
167
10.5k
{
168
10.5k
    block_t *p_data;
169
170
10.5k
    if( p_block == NULL ) /* No Drain */
171
9.19k
        return VLCDEC_SUCCESS;
172
173
1.38k
    if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
174
0
    {
175
0
        block_Release( p_block );
176
0
        return VLCDEC_SUCCESS;
177
0
    }
178
179
1.38k
    if( !(p_data = Reassemble( p_dec, p_block )) )
180
287
        return VLCDEC_SUCCESS;
181
182
    /* Parse and decode */
183
1.10k
    subpicture_t *p_spu = DecodePacket( p_dec, p_data );
184
1.10k
    block_Release( p_data );
185
1.10k
    if( p_spu != NULL )
186
1.09k
        decoder_QueueSub( p_dec, p_spu );
187
1.10k
    return VLCDEC_SUCCESS;
188
1.38k
}
189
190
/*****************************************************************************
191
 * Packetize:
192
 *****************************************************************************/
193
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
194
10.5k
{
195
10.5k
    block_t *p_block, *p_spu;
196
197
10.5k
    if( pp_block == NULL || *pp_block == NULL ) return NULL;
198
199
8.91k
    p_block = *pp_block;
200
8.91k
    *pp_block = NULL;
201
202
8.91k
    if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
203
204
1.38k
    p_spu->i_dts = p_spu->i_pts;
205
1.38k
    p_spu->i_length = VLC_TICK_INVALID;
206
207
1.38k
    return p_spu;
208
8.91k
}
209
210
211
/*****************************************************************************
212
 Reassemble:
213
214
 Data for single screen subtitle may come in several non-contiguous
215
 packets of a stream. This routine is called when the next packet in
216
 the stream comes in. The job of this routine is to parse the header,
217
 if this is the beginning, and combine the packets into one complete
218
 subtitle unit.
219
220
 If everything is complete, we will return a block. Otherwise return
221
 NULL.
222
223
 *****************************************************************************/
224
19.6k
#define SPU_HEADER_LEN 1
225
226
static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
227
10.3k
{
228
10.3k
    decoder_sys_t *p_sys = p_dec->p_sys;
229
230
10.3k
    if( p_block->i_buffer < SPU_HEADER_LEN )
231
0
    {
232
0
        msg_Dbg( p_dec, "invalid packet header (size %zu < %u)" ,
233
0
                 p_block->i_buffer, SPU_HEADER_LEN );
234
0
        block_Release( p_block );
235
0
        return NULL;
236
0
    }
237
238
    /* From the scant data on the format, there is only only way known
239
     * to detect the first packet in a subtitle.  The first packet
240
     * seems to have a valid PTS while later packets for the same
241
     * image don't. */
242
10.3k
    if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == VLC_TICK_INVALID )
243
5.65k
    {
244
5.65k
        msg_Warn( p_dec, "first packet expected but no PTS present");
245
5.65k
        block_Release( p_block );
246
5.65k
        return NULL;
247
5.65k
    }
248
249
4.64k
    p_block->p_buffer += SPU_HEADER_LEN;
250
4.64k
    p_block->i_buffer -= SPU_HEADER_LEN;
251
252
    /* First packet in the subtitle block */
253
4.64k
    if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY ) ParseHeader( p_dec, p_block );
254
255
4.64k
    block_ChainAppend( &p_sys->p_spu, p_block );
256
4.64k
    p_sys->p_spu = block_ChainGather( p_sys->p_spu );
257
258
4.64k
    if( p_sys->p_spu->i_buffer >= p_sys->i_spu_size )
259
2.48k
    {
260
2.48k
        block_t *p_spu = p_sys->p_spu;
261
262
2.48k
        if( p_spu->i_buffer != p_sys->i_spu_size )
263
2.45k
        {
264
2.45k
            msg_Warn( p_dec, "SPU packets size=%zu should be %zu",
265
2.45k
                      p_spu->i_buffer, p_sys->i_spu_size );
266
2.45k
        }
267
268
2.48k
        msg_Dbg( p_dec, "subtitle packet complete, size=%zuu", p_spu->i_buffer);
269
270
2.48k
        ParseMetaInfo( p_dec, p_spu );
271
272
2.48k
        p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
273
2.48k
        p_sys->p_spu = 0;
274
2.48k
        return p_spu;
275
2.48k
    }
276
2.16k
    else
277
2.16k
    {
278
        /* Not last block in subtitle, so wait for another. */
279
2.16k
        p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
280
2.16k
    }
281
282
2.16k
    return NULL;
283
4.64k
}
284
285
/*
286
  We do not have information on the subtitle format used on CVD's
287
  except the submux sample code and a couple of samples of dubious
288
  origin. Thus, this is the result of reading some code whose
289
  correctness is not known and some experimentation.
290
291
  CVD subtitles are different in several ways from SVCD OGT subtitles.
292
  Image comes first and metadata is at the end.  So that the metadata
293
  can be found easily, the subtitle packet starts with two bytes
294
  (everything is big-endian again) that give the total size of the
295
  subtitle data and the offset to the metadata - i.e. size of the
296
  image data plus the four bytes at the beginning.
297
298
  Image data comes interlaced is run-length encoded.  Each field is a
299
  four-bit nibble. Each nibble contains a two-bit repeat count and a
300
  two-bit color number so that up to three pixels can be described in
301
  four bits.  The function of a 0 repeat count is unknown; it might be
302
  used for RLE extension.  However when the full nibble is zero, the
303
  rest of the line is filled with the color value in the next nibble.
304
  It is unknown what happens if the color value is greater than three.
305
  The rest seems to use a 4-entries palette.  It is not impossible
306
  that the fill-line complete case above is not as described and the
307
  zero repeat count means fill line.  The sample code never produces
308
  this, so it may be untested.
309
*/
310
311
static void ParseHeader( decoder_t *p_dec, block_t *p_block )
312
2.59k
{
313
2.59k
    decoder_sys_t *p_sys = p_dec->p_sys;
314
2.59k
    uint8_t *p = p_block->p_buffer;
315
316
2.59k
    p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
317
318
2.59k
    p_sys->metadata_offset = (p[0] <<  8) +   p[1]; p +=2;
319
2.59k
    if ( p_sys->i_spu_size > p_sys->metadata_offset )
320
1.51k
        p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
321
1.08k
    else
322
1.08k
        p_sys->metadata_length = 0; // unusable metadata
323
324
2.59k
    p_sys->i_image_offset = 4;
325
326
2.59k
#ifdef DEBUG_CVDSUB
327
2.59k
    msg_Dbg( p_dec, "total size: %zu  metadata size: %zu",
328
2.59k
             p_sys->i_spu_size, p_sys->metadata_length );
329
2.59k
#endif
330
2.59k
}
331
332
/*
333
  We parse the metadata information here.
334
335
  Although metadata information does not have to come in a fixed field
336
  order, every metadata field consists of a tag byte followed by
337
  parameters. In all cases known, the size including tag byte is
338
  exactly four bytes in length.
339
*/
340
341
2.09k
#define ExtractXY(x, y) x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
342
2.09k
                        y = ((p[2]&0x03)<<8) + p[3];
343
344
static void ParseMetaInfo( decoder_t *p_dec, block_t *p_spu  )
345
2.48k
{
346
    /* Last packet in subtitle block. */
347
348
2.48k
    decoder_sys_t *p_sys = p_dec->p_sys;
349
2.48k
    uint8_t       *p     = p_spu->p_buffer + p_sys->metadata_offset;
350
2.48k
    uint8_t       *p_end = p + p_sys->metadata_length;
351
352
209k
    for( ; &p[3] < p_end; p += 4 )
353
207k
    {
354
207k
        switch( p[0] )
355
207k
        {
356
746
        case 0x04: /* subtitle duration in 1/90000ths of a second */
357
746
            p_sys->i_duration = FROM_SCALE_NZ( (p[1]<<16) + (p[2]<<8) + p[3] );
358
359
746
#ifdef DEBUG_CVDSUB
360
746
            msg_Dbg( p_dec, "subtitle display duration %"PRIu64" ms",
361
746
                     MS_FROM_VLC_TICK(p_sys->i_duration) );
362
746
#endif
363
746
            break;
364
365
338
        case 0x0c: /* unknown */
366
338
#ifdef DEBUG_CVDSUB
367
338
            msg_Dbg( p_dec, "subtitle command unknown "
368
338
                     "0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8,
369
338
                     p[0], p[1], p[2], p[3] );
370
338
#endif
371
338
            break;
372
373
945
        case 0x17: /* coordinates of subtitle upper left x, y position */
374
945
            ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
375
376
945
#ifdef DEBUG_CVDSUB
377
945
            msg_Dbg( p_dec, "start position (%"PRIu16",%"PRIu16")",
378
945
                     p_sys->i_x_start, p_sys->i_y_start );
379
945
#endif
380
945
            break;
381
382
1.15k
        case 0x1f: /* coordinates of subtitle bottom right x, y position */
383
1.15k
        {
384
1.15k
            int lastx;
385
1.15k
            int lasty;
386
1.15k
            ExtractXY(lastx, lasty);
387
1.15k
            p_sys->i_width  = lastx - p_sys->i_x_start + 1;
388
1.15k
            p_sys->i_height = lasty - p_sys->i_y_start + 1;
389
390
1.15k
#ifdef DEBUG_CVDSUB
391
1.15k
            msg_Dbg( p_dec, "end position (%d,%d), w x h: %"PRIu16"x%"PRIu16,
392
1.15k
                     lastx, lasty, p_sys->i_width, p_sys->i_height );
393
1.15k
#endif
394
1.15k
            break;
395
0
        }
396
397
3.17k
        case 0x24:
398
9.54k
        case 0x25:
399
10.0k
        case 0x26:
400
10.1k
        case 0x27:
401
10.1k
        {
402
10.1k
            uint8_t v = p[0] - 0x24;
403
404
10.1k
#ifdef DEBUG_CVDSUB
405
            /* Primary Palette */
406
10.1k
            msg_Dbg( p_dec, "primary palette %"PRIu8" (y,u,v): "
407
10.1k
                     "(0x%02"PRIx8",0x%02"PRIx8",0x%02"PRIx8")",
408
10.1k
                     v, p[1], p[2], p[3] );
409
10.1k
#endif
410
411
10.1k
            p_sys->p_palette[v][0] = p[1]; /* Y */
412
10.1k
            p_sys->p_palette[v][1] = p[2]; /* Cb / U */
413
10.1k
            p_sys->p_palette[v][2] = p[3]; /* Cr / V */
414
10.1k
            break;
415
10.0k
        }
416
417
1.09k
        case 0x2c:
418
2.79k
        case 0x2d:
419
4.59k
        case 0x2e:
420
5.69k
        case 0x2f:
421
5.69k
        {
422
5.69k
            uint8_t v = p[0] - 0x2c;
423
424
5.69k
#ifdef DEBUG_CVDSUB
425
5.69k
            msg_Dbg( p_dec,"highlight palette %"PRIu8" (y,u,v): "
426
5.69k
                     "(0x%02"PRIx8",0x%02"PRIx8",0x%02"PRIx8")",
427
5.69k
                     v, p[1], p[2], p[3] );
428
5.69k
#endif
429
430
            /* Highlight Palette */
431
5.69k
            p_sys->p_palette_highlight[v][0] = p[1]; /* Y */
432
5.69k
            p_sys->p_palette_highlight[v][1] = p[2]; /* Cb / U */
433
5.69k
            p_sys->p_palette_highlight[v][2] = p[3]; /* Cr / V */
434
5.69k
            break;
435
4.59k
        }
436
437
1.34k
        case 0x37:
438
            /* transparency for primary palette */
439
1.34k
            p_sys->p_palette[0][3] = (p[3] & 0x0f) << 4;
440
1.34k
            p_sys->p_palette[1][3] = (p[3] >> 4) << 4;
441
1.34k
            p_sys->p_palette[2][3] = (p[2] & 0x0f) << 4;
442
1.34k
            p_sys->p_palette[3][3] = (p[2] >> 4) << 4;
443
444
1.34k
#ifdef DEBUG_CVDSUB
445
1.34k
            msg_Dbg( p_dec, "transparency for primary palette 0..3: "
446
1.34k
                     "0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8,
447
1.34k
                     p_sys->p_palette[0][3], p_sys->p_palette[1][3],
448
1.34k
                     p_sys->p_palette[2][3], p_sys->p_palette[3][3]);
449
1.34k
#endif
450
1.34k
            break;
451
452
752
        case 0x3f:
453
            /* transparency for highlight palette */
454
752
            p_sys->p_palette_highlight[0][3] = (p[2] & 0x0f) << 4;
455
752
            p_sys->p_palette_highlight[1][3] = (p[2] >> 4) << 4;
456
752
            p_sys->p_palette_highlight[2][3] = (p[1] & 0x0f) << 4;
457
752
            p_sys->p_palette_highlight[3][3] = (p[1] >> 4) << 4;
458
459
752
#ifdef DEBUG_CVDSUB
460
752
            msg_Dbg( p_dec, "transparency for highlight palette 0..3: "
461
752
                     "0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8,
462
752
                     p_sys->p_palette_highlight[0][3],
463
752
                     p_sys->p_palette_highlight[1][3],
464
752
                     p_sys->p_palette_highlight[2][3],
465
752
                     p_sys->p_palette_highlight[3][3] );
466
752
#endif
467
752
            break;
468
469
455
        case 0x47:
470
            /* offset to start of even rows of interlaced image, we correct
471
             * to make it relative to i_image_offset (usually 4) */
472
455
            p_sys->first_field_offset =
473
455
                (p[2] << 8) + p[3] - p_sys->i_image_offset;
474
455
#ifdef DEBUG_CVDSUB
475
455
            msg_Dbg( p_dec, "1st_field_offset %zu",
476
455
                     p_sys->first_field_offset );
477
455
#endif
478
455
            break;
479
480
779
        case 0x4f:
481
            /* offset to start of odd rows of interlaced image, we correct
482
             * to make it relative to i_image_offset (usually 4) */
483
779
            p_sys->second_field_offset =
484
779
                (p[2] << 8) + p[3] - p_sys->i_image_offset;
485
779
#ifdef DEBUG_CVDSUB
486
779
            msg_Dbg( p_dec, "2nd_field_offset %zu",
487
779
                     p_sys->second_field_offset);
488
779
#endif
489
779
            break;
490
491
184k
        default:
492
184k
#ifdef DEBUG_CVDSUB
493
184k
            msg_Warn( p_dec, "unknown sequence in control header "
494
207k
                      "0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8" 0x%02"PRIx8,
495
207k
                      p[0], p[1], p[2], p[3]);
496
207k
#endif
497
207k
        }
498
207k
    }
499
2.48k
}
500
501
/*****************************************************************************
502
 * DecodePacket: parse and decode an SPU packet
503
 *****************************************************************************
504
 * This function parses and decodes an SPU packet and, if valid, returns a
505
 * subpicture.
506
 *****************************************************************************/
507
static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
508
1.10k
{
509
1.10k
    decoder_sys_t *p_sys = p_dec->p_sys;
510
1.10k
    subpicture_t  *p_spu;
511
1.10k
    subpicture_region_t *p_region;
512
1.10k
    video_format_t fmt;
513
1.10k
    video_palette_t palette;
514
1.10k
    int i;
515
516
    /* Allocate the subpicture internal data. */
517
1.10k
    p_spu = decoder_NewSubpicture( p_dec, NULL );
518
1.10k
    if( !p_spu ) return NULL;
519
520
1.10k
    p_spu->i_start = p_data->i_pts;
521
1.10k
    p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
522
1.10k
    p_spu->b_ephemer = true;
523
524
    /* Create new SPU region */
525
1.10k
    video_format_Init( &fmt, VLC_CODEC_YUVP );
526
1.10k
    fmt.i_sar_num = 1;
527
1.10k
    fmt.i_sar_den = 1;
528
1.10k
    fmt.i_width = fmt.i_visible_width = p_sys->i_width;
529
1.10k
    fmt.i_height = fmt.i_visible_height = p_sys->i_height;
530
1.10k
    fmt.i_x_offset = fmt.i_y_offset = 0;
531
1.10k
    fmt.p_palette = &palette;
532
1.10k
    fmt.p_palette->i_entries = 4;
533
5.50k
    for( i = 0; i < fmt.p_palette->i_entries; i++ )
534
4.40k
        memcpy( fmt.p_palette->palette[i], p_sys->p_palette[i], 4 );
535
536
1.10k
    p_region = subpicture_region_New( &fmt );
537
1.10k
    if( !p_region )
538
10
    {
539
10
        msg_Err( p_dec, "cannot allocate SPU region" );
540
10
        subpicture_Delete( p_spu );
541
10
        return NULL;
542
10
    }
543
544
1.09k
    vlc_spu_regions_push(&p_spu->regions, p_region);
545
1.09k
    p_region->b_absolute = true; p_region->b_in_window = false;
546
1.09k
    p_region->i_x = p_sys->i_x_start;
547
1.09k
    p_region->i_x = p_region->i_x * 3 / 4; /* FIXME: use aspect ratio for x? */
548
1.09k
    p_region->i_y = p_sys->i_y_start;
549
550
1.09k
    RenderImage( p_dec, p_data, p_region->p_picture );
551
552
1.09k
    return p_spu;
553
1.10k
}
554
555
/*****************************************************************************
556
 * ParseImage: parse and render the image part of the subtitle
557
 *****************************************************************************
558
 This part parses the subtitle graphical data and renders it.
559
560
 Image data comes interlaced and is run-length encoded (RLE). Each
561
 field is a four-bit nibbles that is further subdivided in a two-bit
562
 repeat count and a two-bit color number - up to three pixels can be
563
 described in four bits.  What a 0 repeat count means is unknown.  It
564
 might be used for RLE extension.  There is a special case of a 0
565
 repeat count though.  When the full nibble is zero, the rest of the
566
 line is filled with the color value in the next nibble.  It is
567
 unknown what happens if the color value is greater than three.  The
568
 rest seems to use a 4-entries palette.  It is not impossible that the
569
 fill-line complete case above is not as described and the zero repeat
570
 count means fill line.  The sample code never produces this, so it
571
 may be untested.
572
573
 However we'll transform this so that that the RLE is expanded and
574
 interlacing will also be removed. On output each pixel entry will by
575
 a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
576
577
 *****************************************************************************/
578
static void RenderImage( decoder_t *p_dec, block_t *p_data,
579
                         picture_t *dst_pic )
580
1.09k
{
581
1.09k
    decoder_sys_t *p_sys = p_dec->p_sys;
582
1.09k
    uint8_t *p_dest = dst_pic->Y_PIXELS;
583
1.09k
    int i_field;            /* The subtitles are interlaced */
584
1.09k
    int i_row, i_column;    /* scanline row/column number */
585
1.09k
    uint8_t i_color, i_count;
586
1.09k
    bs_t bs;
587
588
1.09k
    bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
589
1.09k
             p_data->i_buffer - p_sys->i_image_offset );
590
591
3.27k
    for( i_field = 0; i_field < 2; i_field++ )
592
2.18k
    {
593
709k
        for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
594
707k
        {
595
1.60M
            for( i_column = 0; i_column < p_sys->i_width; i_column++ )
596
895k
            {
597
895k
                uint8_t i_val = bs_read( &bs, 4 );
598
599
895k
                if( i_val == 0 )
600
628k
                {
601
                    /* Fill the rest of the line with next color */
602
628k
                    i_color = bs_read( &bs, 4 );
603
604
628k
                    memset( &p_dest[i_row * dst_pic->Y_PITCH +
605
628k
                                    i_column], i_color,
606
628k
                            p_sys->i_width - i_column );
607
628k
                    i_column = p_sys->i_width;
608
628k
                    continue;
609
628k
                }
610
266k
                else
611
266k
                {
612
                    /* Normal case: get color and repeat count */
613
266k
                    i_count = (i_val >> 2);
614
266k
                    i_color = i_val & 0x3;
615
616
266k
                    i_count = __MIN( i_count, p_sys->i_width - i_column );
617
618
266k
                    memset( &p_dest[i_row * dst_pic->Y_PITCH +
619
266k
                                    i_column], i_color, i_count );
620
266k
                    i_column += i_count - 1;
621
266k
                    continue;
622
266k
                }
623
895k
            }
624
625
707k
            bs_align( &bs );
626
707k
        }
627
2.18k
    }
628
1.09k
}