~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to src/video_output/vout_subpictures.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 * vout_subpictures.c : subpicture management functions
3
3
 *****************************************************************************
4
 
 * Copyright (C) 2000-2005 the VideoLAN team
5
 
 * $Id$
 
4
 * Copyright (C) 2000-2007 the VideoLAN team
 
5
 * $Id: f171693c1c3b20eb5e38e9b8716ad4a37c066059 $
6
6
 *
7
7
 * Authors: Vincent Seguin <seguin@via.ecp.fr>
8
8
 *          Samuel Hocevar <sam@zoy.org>
26
26
/*****************************************************************************
27
27
 * Preamble
28
28
 *****************************************************************************/
29
 
#include <stdlib.h>                                                /* free() */
30
 
#include <stdio.h>                                              /* sprintf() */
31
 
#include <string.h>                                            /* strerror() */
32
 
 
33
 
#include <vlc/vlc.h>
34
 
 
35
 
#include "vlc_block.h"
36
 
#include "vlc_video.h"
37
 
#include "video_output.h"
38
 
#include "vlc_spu.h"
39
 
#include "vlc_filter.h"
 
29
#ifdef HAVE_CONFIG_H
 
30
# include "config.h"
 
31
#endif
 
32
 
 
33
#include <vlc_common.h>
 
34
#include <vlc_vout.h>
 
35
#include <vlc_block.h>
 
36
#include <vlc_filter.h>
 
37
#include <vlc_osd.h>
 
38
#include "../libvlc.h"
 
39
 
 
40
#include <assert.h>
40
41
 
41
42
/*****************************************************************************
42
43
 * Local prototypes
54
55
static picture_t *spu_new_video_buffer( filter_t * );
55
56
static void spu_del_video_buffer( filter_t *, picture_t * );
56
57
 
 
58
static int spu_ParseChain( spu_t * );
 
59
static int SubFilterCallback( vlc_object_t *, char const *,
 
60
                              vlc_value_t, vlc_value_t, void * );
 
61
 
 
62
static int sub_filter_allocation_init( filter_t *, void * );
 
63
static void sub_filter_allocation_clear( filter_t * );
57
64
struct filter_owner_sys_t
58
65
{
59
66
    spu_t *p_spu;
60
67
    int i_channel;
61
68
};
62
69
 
 
70
enum {
 
71
    SCALE_DEFAULT,
 
72
    SCALE_TEXT,
 
73
    SCALE_SIZE
 
74
};
 
75
 
 
76
static void FilterRelease( filter_t *p_filter )
 
77
{
 
78
    if( p_filter->p_module )
 
79
        module_Unneed( p_filter, p_filter->p_module );
 
80
 
 
81
    vlc_object_detach( p_filter );
 
82
    vlc_object_release( p_filter );
 
83
}
 
84
 
63
85
/**
64
86
 * Creates the subpicture unit
65
87
 *
68
90
spu_t *__spu_Create( vlc_object_t *p_this )
69
91
{
70
92
    int i_index;
71
 
    spu_t *p_spu = vlc_object_create( p_this, VLC_OBJECT_SPU );
 
93
    spu_t *p_spu = vlc_custom_create( p_this, sizeof( spu_t ),
 
94
                                      VLC_OBJECT_GENERIC, "subpicture" );
72
95
 
73
96
    for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++)
74
97
    {
78
101
    p_spu->p_blend = NULL;
79
102
    p_spu->p_text = NULL;
80
103
    p_spu->p_scale = NULL;
81
 
    p_spu->i_filter = 0;
 
104
    p_spu->p_scale_yuvp = NULL;
82
105
    p_spu->pf_control = spu_vaControlDefault;
83
106
 
84
107
    /* Register the default subpicture channel */
85
108
    p_spu->i_channel = 2;
86
109
 
87
 
    vlc_mutex_init( p_this, &p_spu->subpicture_lock );
 
110
    vlc_mutex_init( &p_spu->subpicture_lock );
88
111
 
89
112
    vlc_object_attach( p_spu, p_this );
90
113
 
 
114
    p_spu->p_chain = filter_chain_New( p_spu, "sub filter", false,
 
115
                                       sub_filter_allocation_init,
 
116
                                       sub_filter_allocation_clear,
 
117
                                       p_spu );
91
118
    return p_spu;
92
119
}
93
120
 
98
125
 */
99
126
int spu_Init( spu_t *p_spu )
100
127
{
101
 
    char *psz_filter, *psz_filter_orig;
102
128
    vlc_value_t val;
103
129
 
104
130
    /* If the user requested a sub margin, we force the position. */
107
133
    p_spu->i_margin = val.i_int;
108
134
 
109
135
    var_Create( p_spu, "sub-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
110
 
    var_Get( p_spu, "sub-filter", &val );
111
 
    psz_filter = psz_filter_orig = val.psz_string;
112
 
    while( psz_filter && *psz_filter )
 
136
    var_AddCallback( p_spu, "sub-filter", SubFilterCallback, p_spu );
 
137
 
 
138
    spu_ParseChain( p_spu );
 
139
 
 
140
    return VLC_SUCCESS;
 
141
}
 
142
 
 
143
int spu_ParseChain( spu_t *p_spu )
 
144
{
 
145
    char *psz_parser = var_GetString( p_spu, "sub-filter" );
 
146
    if( filter_chain_AppendFromString( p_spu->p_chain, psz_parser ) < 0 )
113
147
    {
114
 
        char *psz_parser = strchr( psz_filter, ':' );
115
 
 
116
 
        if( psz_parser ) *psz_parser++ = 0;
117
 
 
118
 
        p_spu->pp_filter[p_spu->i_filter] =
119
 
            vlc_object_create( p_spu, VLC_OBJECT_FILTER );
120
 
        vlc_object_attach( p_spu->pp_filter[p_spu->i_filter], p_spu );
121
 
        p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_new = sub_new_buffer;
122
 
        p_spu->pp_filter[p_spu->i_filter]->pf_sub_buffer_del = sub_del_buffer;
123
 
        p_spu->pp_filter[p_spu->i_filter]->p_module =
124
 
            module_Need( p_spu->pp_filter[p_spu->i_filter],
125
 
                         "sub filter", psz_filter, 0 );
126
 
        if( p_spu->pp_filter[p_spu->i_filter]->p_module )
127
 
        {
128
 
            filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) );
129
 
            p_spu->pp_filter[p_spu->i_filter]->p_owner = p_sys;
130
 
            spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel );
131
 
            p_sys->p_spu = p_spu;
132
 
            p_spu->i_filter++;
133
 
        }
134
 
        else
135
 
        {
136
 
            msg_Dbg( p_spu, "no sub filter found" );
137
 
            vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
138
 
            vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
139
 
        }
140
 
 
141
 
        if( p_spu->i_filter >= 10 )
142
 
        {
143
 
            msg_Dbg( p_spu, "can't add anymore filters" );
144
 
            break;
145
 
        }
146
 
 
147
 
        psz_filter = psz_parser;
 
148
        free( psz_parser );
 
149
        return VLC_EGENERIC;
148
150
    }
149
 
    if( psz_filter_orig ) free( psz_filter_orig );
150
151
 
151
 
    return VLC_EGENERIC;
 
152
    free( psz_parser );
 
153
    return VLC_SUCCESS;
152
154
}
153
155
 
154
156
/**
160
162
{
161
163
    int i_index;
162
164
 
163
 
    vlc_object_detach( p_spu );
164
 
 
165
165
    /* Destroy all remaining subpictures */
166
166
    for( i_index = 0; i_index < VOUT_MAX_SUBPICTURES; i_index++ )
167
167
    {
172
172
    }
173
173
 
174
174
    if( p_spu->p_blend )
175
 
    {
176
 
        if( p_spu->p_blend->p_module )
177
 
            module_Unneed( p_spu->p_blend, p_spu->p_blend->p_module );
178
 
 
179
 
        vlc_object_detach( p_spu->p_blend );
180
 
        vlc_object_destroy( p_spu->p_blend );
181
 
    }
 
175
        FilterRelease( p_spu->p_blend );
182
176
 
183
177
    if( p_spu->p_text )
184
 
    {
185
 
        if( p_spu->p_text->p_module )
186
 
            module_Unneed( p_spu->p_text, p_spu->p_text->p_module );
 
178
        FilterRelease( p_spu->p_text );
187
179
 
188
 
        vlc_object_detach( p_spu->p_text );
189
 
        vlc_object_destroy( p_spu->p_text );
190
 
    }
 
180
    if( p_spu->p_scale_yuvp )
 
181
        FilterRelease( p_spu->p_scale_yuvp );
191
182
 
192
183
    if( p_spu->p_scale )
193
 
    {
194
 
        if( p_spu->p_scale->p_module )
195
 
            module_Unneed( p_spu->p_scale, p_spu->p_scale->p_module );
196
 
 
197
 
        vlc_object_detach( p_spu->p_scale );
198
 
        vlc_object_destroy( p_spu->p_scale );
199
 
    }
200
 
 
201
 
    while( p_spu->i_filter-- )
202
 
    {
203
 
        module_Unneed( p_spu->pp_filter[p_spu->i_filter],
204
 
                       p_spu->pp_filter[p_spu->i_filter]->p_module );
205
 
        free( p_spu->pp_filter[p_spu->i_filter]->p_owner );
206
 
        vlc_object_detach( p_spu->pp_filter[p_spu->i_filter] );
207
 
        vlc_object_destroy( p_spu->pp_filter[p_spu->i_filter] );
208
 
    }
 
184
        FilterRelease( p_spu->p_scale );
 
185
 
 
186
    filter_chain_Delete( p_spu->p_chain );
209
187
 
210
188
    vlc_mutex_destroy( &p_spu->subpicture_lock );
211
 
    vlc_object_destroy( p_spu );
 
189
    vlc_object_release( p_spu );
212
190
}
213
191
 
214
192
/**
217
195
 * \param p_this the object in which to destroy the subpicture unit
218
196
 * \param b_attach to select attach or detach
219
197
 */
220
 
void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, vlc_bool_t b_attach )
 
198
void spu_Attach( spu_t *p_spu, vlc_object_t *p_this, bool b_attach )
221
199
{
222
200
    vlc_object_t *p_input;
223
201
 
246
224
 */
247
225
static void RegionPictureRelease( picture_t *p_pic )
248
226
{
249
 
    if( p_pic->p_data_orig ) free( p_pic->p_data_orig );
 
227
    free( p_pic->p_data_orig );
 
228
    /* We use pf_release nullity to know if the picture has already been released. */
 
229
    p_pic->pf_release = NULL;
250
230
}
251
231
subpicture_region_t *__spu_CreateRegion( vlc_object_t *p_this,
252
232
                                         video_format_t *p_fmt )
255
235
    if( !p_region ) return NULL;
256
236
 
257
237
    memset( p_region, 0, sizeof(subpicture_region_t) );
258
 
    p_region->p_next = 0;
259
 
    p_region->p_cache = 0;
 
238
    p_region->i_alpha = 0xff;
 
239
    p_region->p_next = NULL;
 
240
    p_region->p_cache = NULL;
260
241
    p_region->fmt = *p_fmt;
261
 
    p_region->psz_text = 0;
 
242
    p_region->psz_text = NULL;
262
243
    p_region->p_style = NULL;
263
244
 
264
245
    if( p_fmt->i_chroma == VLC_FOURCC('Y','U','V','P') )
276
257
    if( !p_region->picture.i_planes )
277
258
    {
278
259
        free( p_region );
279
 
        if( p_fmt->p_palette ) free( p_fmt->p_palette );
 
260
        free( p_fmt->p_palette );
280
261
        return NULL;
281
262
    }
282
263
 
297
278
                                       picture_t *p_pic )
298
279
{
299
280
    subpicture_region_t *p_region = malloc( sizeof(subpicture_region_t) );
 
281
    (void)p_this;
 
282
    if( !p_region ) return NULL;
300
283
    memset( p_region, 0, sizeof(subpicture_region_t) );
 
284
    p_region->i_alpha = 0xff;
301
285
    p_region->p_next = 0;
302
286
    p_region->p_cache = 0;
303
287
    p_region->fmt = *p_fmt;
326
310
    if( !p_region ) return;
327
311
    if( p_region->picture.pf_release )
328
312
        p_region->picture.pf_release( &p_region->picture );
329
 
    if( p_region->fmt.p_palette ) free( p_region->fmt.p_palette );
 
313
    free( p_region->fmt.p_palette );
330
314
    if( p_region->p_cache ) __spu_DestroyRegion( p_this, p_region->p_cache );
331
315
 
332
 
    if( p_region->psz_text )
333
 
        free( p_region->psz_text );
 
316
    free( p_region->psz_text );
 
317
    free( p_region->psz_html );
334
318
    //free( p_region->p_style ); FIXME --fenrir plugin does not allocate the memory for it. I think it might lead to segfault, video renderer can live longer than the decoder
335
319
    free( p_region );
336
320
}
407
391
    /* Copy subpicture information, set some default values */
408
392
    memset( p_subpic, 0, sizeof(subpicture_t) );
409
393
    p_subpic->i_status   = RESERVED_SUBPICTURE;
410
 
    p_subpic->b_absolute = VLC_TRUE;
411
 
    p_subpic->b_pausable = VLC_FALSE;
412
 
    p_subpic->b_fade     = VLC_FALSE;
 
394
    p_subpic->b_absolute = true;
 
395
    p_subpic->b_pausable = false;
 
396
    p_subpic->b_fade     = false;
413
397
    p_subpic->i_alpha    = 0xFF;
414
 
    p_subpic->p_region   = 0;
415
 
    p_subpic->pf_render  = 0;
416
 
    p_subpic->pf_destroy = 0;
417
 
    p_subpic->p_sys      = 0;
 
398
    p_subpic->p_region   = NULL;
 
399
    p_subpic->pf_render  = NULL;
 
400
    p_subpic->pf_destroy = NULL;
 
401
    p_subpic->p_sys      = NULL;
418
402
    vlc_mutex_unlock( &p_spu->subpicture_lock );
419
403
 
420
404
    p_subpic->pf_create_region = __spu_CreateRegion;
474
458
 *****************************************************************************
475
459
 * This function renders all sub picture units in the list.
476
460
 *****************************************************************************/
 
461
static void SpuRenderCreateBlend( spu_t *p_spu, vlc_fourcc_t i_chroma, int i_aspect )
 
462
{
 
463
    filter_t *p_blend;
 
464
 
 
465
    assert( !p_spu->p_blend );
 
466
 
 
467
    p_spu->p_blend =
 
468
    p_blend        = vlc_custom_create( p_spu, sizeof(filter_t),
 
469
                                        VLC_OBJECT_GENERIC, "blend" );
 
470
    if( !p_blend )
 
471
        return;
 
472
 
 
473
    es_format_Init( &p_blend->fmt_in, VIDEO_ES, 0 );
 
474
 
 
475
    es_format_Init( &p_blend->fmt_out, VIDEO_ES, 0 );
 
476
    p_blend->fmt_out.video.i_x_offset = 0;
 
477
    p_blend->fmt_out.video.i_y_offset = 0;
 
478
    p_blend->fmt_out.video.i_chroma = i_chroma;
 
479
    p_blend->fmt_out.video.i_aspect = i_aspect;
 
480
 
 
481
    /* The blend module will be loaded when needed with the real
 
482
    * input format */
 
483
    p_blend->p_module = NULL;
 
484
 
 
485
    /* */
 
486
    vlc_object_attach( p_blend, p_spu );
 
487
}
 
488
static void SpuRenderUpdateBlend( spu_t *p_spu, int i_out_width, int i_out_height, const video_format_t *p_in_fmt )
 
489
{
 
490
    filter_t *p_blend = p_spu->p_blend;
 
491
 
 
492
    assert( p_blend );
 
493
 
 
494
    /* */
 
495
    if( p_blend->p_module && p_blend->fmt_in.video.i_chroma != p_in_fmt->i_chroma )
 
496
    {
 
497
        /* The chroma is not the same, we need to reload the blend module
 
498
         * XXX to match the old behaviour just test !p_blend->fmt_in.video.i_chroma */
 
499
        module_Unneed( p_blend, p_blend->p_module );
 
500
        p_blend->p_module = NULL;
 
501
    }
 
502
 
 
503
    /* */
 
504
    p_blend->fmt_in.video = *p_in_fmt;
 
505
 
 
506
    /* */
 
507
    p_blend->fmt_out.video.i_width =
 
508
    p_blend->fmt_out.video.i_visible_width = i_out_width;
 
509
    p_blend->fmt_out.video.i_height =
 
510
    p_blend->fmt_out.video.i_visible_height = i_out_height;
 
511
 
 
512
    /* */
 
513
    if( !p_blend->p_module )
 
514
        p_blend->p_module = module_Need( p_blend, "video blending", 0, 0 );
 
515
}
 
516
static void SpuRenderCreateAndLoadText( spu_t *p_spu, int i_width, int i_height )
 
517
{
 
518
    filter_t *p_text;
 
519
 
 
520
    assert( !p_spu->p_text );
 
521
 
 
522
    p_spu->p_text =
 
523
    p_text        = vlc_custom_create( p_spu, sizeof(filter_t),
 
524
                                       VLC_OBJECT_GENERIC, "spu text" );
 
525
    if( !p_text )
 
526
        return;
 
527
 
 
528
    es_format_Init( &p_text->fmt_in, VIDEO_ES, 0 );
 
529
 
 
530
    es_format_Init( &p_text->fmt_out, VIDEO_ES, 0 );
 
531
    p_text->fmt_out.video.i_width =
 
532
    p_text->fmt_out.video.i_visible_width = i_width;
 
533
    p_text->fmt_out.video.i_height =
 
534
    p_text->fmt_out.video.i_visible_height = i_height;
 
535
 
 
536
    p_text->pf_sub_buffer_new = spu_new_buffer;
 
537
    p_text->pf_sub_buffer_del = spu_del_buffer;
 
538
 
 
539
    vlc_object_attach( p_text, p_spu );
 
540
 
 
541
    /* FIXME TOCHECK shouldn't module_Need( , , psz_modulename, false ) do the
 
542
     * same than these 2 calls ? */
 
543
    char *psz_modulename = var_CreateGetString( p_spu, "text-renderer" );
 
544
    if( psz_modulename && *psz_modulename )
 
545
    {
 
546
        p_text->p_module = module_Need( p_text, "text renderer",
 
547
                                        psz_modulename, true );
 
548
    }
 
549
    free( psz_modulename );
 
550
 
 
551
    if( !p_text->p_module )
 
552
        p_text->p_module = module_Need( p_text, "text renderer", NULL, false );
 
553
}
 
554
 
 
555
static filter_t *CreateAndLoadScale( vlc_object_t *p_obj, vlc_fourcc_t i_chroma )
 
556
{
 
557
    filter_t *p_scale;
 
558
 
 
559
    p_scale = vlc_custom_create( p_obj, sizeof(filter_t),
 
560
                                 VLC_OBJECT_GENERIC, "scale" );
 
561
    if( !p_scale )
 
562
        return NULL;
 
563
 
 
564
    es_format_Init( &p_scale->fmt_in, VIDEO_ES, 0 );
 
565
    p_scale->fmt_in.video.i_chroma = i_chroma;
 
566
    p_scale->fmt_in.video.i_width =
 
567
    p_scale->fmt_in.video.i_height = 32;
 
568
 
 
569
    es_format_Init( &p_scale->fmt_out, VIDEO_ES, 0 );
 
570
    p_scale->fmt_out.video.i_chroma = i_chroma;
 
571
    p_scale->fmt_out.video.i_width =
 
572
    p_scale->fmt_out.video.i_height = 16;
 
573
 
 
574
    p_scale->pf_vout_buffer_new = spu_new_video_buffer;
 
575
    p_scale->pf_vout_buffer_del = spu_del_video_buffer;
 
576
 
 
577
    vlc_object_attach( p_scale, p_obj );
 
578
    p_scale->p_module = module_Need( p_scale, "video filter2", 0, 0 );
 
579
 
 
580
    return p_scale;
 
581
}
 
582
 
 
583
static void SpuRenderCreateAndLoadScale( spu_t *p_spu )
 
584
{
 
585
    /* FIXME: We'll also be using it for YUVA and RGBA blending ... */
 
586
 
 
587
    assert( !p_spu->p_scale );
 
588
    assert( !p_spu->p_scale_yuvp );
 
589
    p_spu->p_scale = CreateAndLoadScale( VLC_OBJECT(p_spu), VLC_FOURCC('Y','U','V','A') );
 
590
    p_spu->p_scale_yuvp = p_spu->p_scale_yuvp = CreateAndLoadScale( VLC_OBJECT(p_spu), VLC_FOURCC('Y','U','V','P') );
 
591
}
 
592
 
 
593
static void SpuRenderText( spu_t *p_spu, bool *pb_rerender_text,
 
594
                           subpicture_t *p_subpic, subpicture_region_t *p_region, int i_min_scale_ratio )
 
595
{
 
596
    assert( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') );
 
597
 
 
598
    if( !p_spu->p_text || !p_spu->p_text->p_module )
 
599
        goto exit;
 
600
 
 
601
    /* Setup 3 variables which can be used to render
 
602
     * time-dependent text (and effects). The first indicates
 
603
     * the total amount of time the text will be on screen,
 
604
     * the second the amount of time it has already been on
 
605
     * screen (can be a negative value as text is layed out
 
606
     * before it is rendered) and the third is a feedback
 
607
     * variable from the renderer - if the renderer sets it
 
608
     * then this particular text is time-dependent, eg. the
 
609
     * visual progress bar inside the text in karaoke and the
 
610
     * text needs to be rendered multiple times in order for
 
611
     * the effect to work - we therefore need to return the
 
612
     * region to its original state at the end of the loop,
 
613
     * instead of leaving it in YUVA or YUVP.
 
614
     * Any renderer which is unaware of how to render
 
615
     * time-dependent text can happily ignore the variables
 
616
     * and render the text the same as usual - it should at
 
617
     * least show up on screen, but the effect won't change
 
618
     * the text over time.
 
619
     */
 
620
 
 
621
    /* FIXME why these variables are recreated every time and not
 
622
     * when text renderer module was created ? */
 
623
    var_Create( p_spu->p_text, "spu-duration", VLC_VAR_TIME );
 
624
    var_Create( p_spu->p_text, "spu-elapsed", VLC_VAR_TIME );
 
625
    var_Create( p_spu->p_text, "text-rerender", VLC_VAR_BOOL );
 
626
    var_Create( p_spu->p_text, "scale", VLC_VAR_INTEGER );
 
627
 
 
628
    var_SetTime( p_spu->p_text, "spu-duration", p_subpic->i_stop - p_subpic->i_start );
 
629
    var_SetTime( p_spu->p_text, "spu-elapsed", mdate() - p_subpic->i_start );
 
630
    var_SetBool( p_spu->p_text, "text-rerender", false );
 
631
    var_SetInteger( p_spu->p_text, "scale", i_min_scale_ratio );
 
632
 
 
633
    if( p_spu->p_text->pf_render_html && p_region->psz_html )
 
634
    {
 
635
        p_spu->p_text->pf_render_html( p_spu->p_text,
 
636
                                       p_region, p_region );
 
637
    }
 
638
    else if( p_spu->p_text->pf_render_text )
 
639
    {
 
640
        p_spu->p_text->pf_render_text( p_spu->p_text,
 
641
                                       p_region, p_region );
 
642
    }
 
643
    *pb_rerender_text = var_GetBool( p_spu->p_text, "text-rerender" );
 
644
 
 
645
    var_Destroy( p_spu->p_text, "spu-duration" );
 
646
    var_Destroy( p_spu->p_text, "spu-elapsed" );
 
647
    var_Destroy( p_spu->p_text, "text-rerender" );
 
648
    var_Destroy( p_spu->p_text, "scale" );
 
649
 
 
650
exit:
 
651
    p_region->i_align |= SUBPICTURE_RENDERED;
 
652
}
 
653
 
 
654
static void SpuRenderRegion( spu_t *p_spu,
 
655
                             picture_t *p_pic_dst, picture_t *p_pic_src,
 
656
                             subpicture_t *p_subpic, subpicture_region_t *p_region,
 
657
                             const int i_scale_width_orig, const int i_scale_height_orig,
 
658
                             const int pi_subpic_x[SCALE_SIZE],
 
659
                             const int pi_scale_width[SCALE_SIZE],
 
660
                             const int pi_scale_height[SCALE_SIZE],
 
661
                             const video_format_t *p_fmt )
 
662
{
 
663
    video_format_t fmt_original;
 
664
    bool b_rerender_text;
 
665
    bool b_restore_format = false;
 
666
    int i_fade_alpha;
 
667
    int i_x_offset;
 
668
    int i_y_offset;
 
669
    int i_scale_idx;
 
670
    int i_inv_scale_x;
 
671
    int i_inv_scale_y;
 
672
    filter_t *p_scale;
 
673
 
 
674
    vlc_assert_locked( &p_spu->subpicture_lock );
 
675
 
 
676
    fmt_original = p_region->fmt;
 
677
    b_rerender_text = false;
 
678
    if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
 
679
    {
 
680
        SpuRenderText( p_spu, &b_rerender_text, p_subpic, p_region, __MIN(i_scale_width_orig, i_scale_height_orig) );
 
681
        b_restore_format = b_rerender_text;
 
682
 
 
683
        /* Check if the rendering has failed ... */
 
684
        if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
 
685
            goto exit;
 
686
    }
 
687
 
 
688
    if( p_region->i_align & SUBPICTURE_RENDERED )
 
689
    {
 
690
        /* We are using a region which come from rendered text */
 
691
        i_scale_idx   = SCALE_TEXT;
 
692
        i_inv_scale_x = i_scale_width_orig;
 
693
        i_inv_scale_y = i_scale_height_orig;
 
694
    }
 
695
    else
 
696
    {
 
697
        i_scale_idx   = SCALE_DEFAULT;
 
698
        i_inv_scale_x = 1000;
 
699
        i_inv_scale_y = 1000;
 
700
    }
 
701
 
 
702
    i_x_offset = (p_region->i_x + pi_subpic_x[ i_scale_idx ]) * i_inv_scale_x / 1000;
 
703
    i_y_offset = (p_region->i_y + p_subpic->i_y) * i_inv_scale_y / 1000;
 
704
 
 
705
    /* Force palette if requested
 
706
     * FIXME b_force_palette and b_force_crop are applied to all subpictures using palette
 
707
     * instead of only the right one (being the dvd spu).
 
708
     */
 
709
    const bool b_using_palette = p_region->fmt.i_chroma == VLC_FOURCC('Y','U','V','P');
 
710
    const bool b_force_palette = b_using_palette && p_spu->b_force_palette;
 
711
    const bool b_force_crop    = b_force_palette && p_spu->b_force_crop;
 
712
 
 
713
    if( b_force_palette )
 
714
    {
 
715
        /* It looks so wrong I won't comment
 
716
         * p_palette->palette is [256][4] with a int i_entries
 
717
         * p_spu->palette is [4][4]
 
718
         * */
 
719
        p_region->fmt.p_palette->i_entries = 4;
 
720
        memcpy( p_region->fmt.p_palette->palette, p_spu->palette, 4*sizeof(uint32_t) );
 
721
    }
 
722
 
 
723
    if( b_using_palette )
 
724
        p_scale = p_spu->p_scale_yuvp;
 
725
    else
 
726
        p_scale = p_spu->p_scale;
 
727
 
 
728
    if( p_scale &&
 
729
        ( ( pi_scale_width[i_scale_idx]  > 0 && pi_scale_width[i_scale_idx]  != 1000 ) ||
 
730
          ( pi_scale_height[i_scale_idx] > 0 && pi_scale_height[i_scale_idx] != 1000 ) ||
 
731
          ( b_force_palette ) ) )
 
732
    {
 
733
        const unsigned i_dst_width  = p_region->fmt.i_width  * pi_scale_width[i_scale_idx] / 1000;
 
734
        const unsigned i_dst_height = p_region->fmt.i_height * pi_scale_height[i_scale_idx] / 1000;
 
735
 
 
736
        /* Destroy if cache is unusable */
 
737
        if( p_region->p_cache )
 
738
        {
 
739
            if( p_region->p_cache->fmt.i_width  != i_dst_width ||
 
740
                p_region->p_cache->fmt.i_height != i_dst_height ||
 
741
                b_force_palette )
 
742
            {
 
743
                p_subpic->pf_destroy_region( VLC_OBJECT(p_spu),
 
744
                                             p_region->p_cache );
 
745
                p_region->p_cache = NULL;
 
746
            }
 
747
        }
 
748
 
 
749
        /* Scale if needed into cache */
 
750
        if( !p_region->p_cache )
 
751
        {
 
752
            picture_t *p_pic;
 
753
 
 
754
            p_scale->fmt_in.video = p_region->fmt;
 
755
            p_scale->fmt_out.video = p_region->fmt;
 
756
 
 
757
            p_region->p_cache =
 
758
                p_subpic->pf_create_region( VLC_OBJECT(p_spu),
 
759
                                            &p_scale->fmt_out.video );
 
760
            p_region->p_cache->p_next = p_region->p_next;
 
761
 
 
762
            if( p_scale->fmt_out.video.p_palette )
 
763
                *p_scale->fmt_out.video.p_palette =
 
764
                    *p_region->fmt.p_palette;
 
765
 
 
766
            vout_CopyPicture( p_spu, &p_region->p_cache->picture,
 
767
                              &p_region->picture );
 
768
 
 
769
            p_scale->fmt_out.video.i_width = i_dst_width;
 
770
            p_scale->fmt_out.video.i_height = i_dst_height;
 
771
 
 
772
            p_scale->fmt_out.video.i_visible_width =
 
773
                p_region->fmt.i_visible_width * pi_scale_width[ i_scale_idx ] / 1000;
 
774
            p_scale->fmt_out.video.i_visible_height =
 
775
                p_region->fmt.i_visible_height * pi_scale_height[ i_scale_idx ] / 1000;
 
776
 
 
777
            p_region->p_cache->fmt = p_scale->fmt_out.video;
 
778
            p_region->p_cache->i_x = p_region->i_x * pi_scale_width[ i_scale_idx ] / 1000;
 
779
            p_region->p_cache->i_y = p_region->i_y * pi_scale_height[ i_scale_idx ] / 1000;
 
780
            p_region->p_cache->i_align = p_region->i_align;
 
781
            p_region->p_cache->i_alpha = p_region->i_alpha;
 
782
 
 
783
            p_pic = NULL;
 
784
            if( p_scale->p_module )
 
785
                p_pic = p_scale->pf_video_filter( p_scale, &p_region->p_cache->picture );
 
786
            else
 
787
                msg_Err( p_spu, "scaling failed (module not loaded)" );
 
788
 
 
789
            if( p_pic )
 
790
            {
 
791
                p_region->p_cache->picture = *p_pic;
 
792
                free( p_pic );
 
793
            }
 
794
            else
 
795
            {
 
796
                p_subpic->pf_destroy_region( VLC_OBJECT(p_spu),
 
797
                                             p_region->p_cache );
 
798
                p_region->p_cache = NULL;
 
799
            }
 
800
        }
 
801
 
 
802
        /* And use the scaled picture */
 
803
        if( p_region->p_cache )
 
804
        {
 
805
            p_region = p_region->p_cache;
 
806
            fmt_original = p_region->fmt;
 
807
        }
 
808
    }
 
809
 
 
810
    if( p_region->i_align & SUBPICTURE_ALIGN_BOTTOM )
 
811
    {
 
812
        i_y_offset = p_fmt->i_height - p_region->fmt.i_height -
 
813
            (p_subpic->i_y + p_region->i_y) * i_inv_scale_y / 1000;
 
814
    }
 
815
    else if ( !(p_region->i_align & SUBPICTURE_ALIGN_TOP) )
 
816
    {
 
817
        i_y_offset = p_fmt->i_height / 2 - p_region->fmt.i_height / 2;
 
818
    }
 
819
 
 
820
    if( p_region->i_align & SUBPICTURE_ALIGN_RIGHT )
 
821
    {
 
822
        i_x_offset = p_fmt->i_width - p_region->fmt.i_width -
 
823
            (pi_subpic_x[ i_scale_idx ] + p_region->i_x)
 
824
            * i_inv_scale_x / 1000;
 
825
    }
 
826
    else if ( !(p_region->i_align & SUBPICTURE_ALIGN_LEFT) )
 
827
    {
 
828
        i_x_offset = p_fmt->i_width / 2 - p_region->fmt.i_width / 2;
 
829
    }
 
830
 
 
831
    if( p_subpic->b_absolute )
 
832
    {
 
833
        i_x_offset = (p_region->i_x +
 
834
            pi_subpic_x[ i_scale_idx ] *
 
835
                             pi_scale_width[ i_scale_idx ] / 1000)
 
836
            * i_inv_scale_x / 1000;
 
837
        i_y_offset = (p_region->i_y +
 
838
            p_subpic->i_y * pi_scale_height[ i_scale_idx ] / 1000)
 
839
            * i_inv_scale_y / 1000;
 
840
 
 
841
    }
 
842
 
 
843
    i_x_offset = __MAX( i_x_offset, 0 );
 
844
    i_y_offset = __MAX( i_y_offset, 0 );
 
845
 
 
846
    if( p_spu->i_margin != 0 && !b_force_crop )
 
847
    {
 
848
        int i_diff = 0;
 
849
        int i_low = (i_y_offset - p_spu->i_margin) * i_inv_scale_y / 1000;
 
850
        int i_high = i_low + p_region->fmt.i_height;
 
851
 
 
852
        /* crop extra margin to keep within bounds */
 
853
        if( i_low < 0 )
 
854
            i_diff = i_low;
 
855
        if( i_high > (int)p_fmt->i_height )
 
856
            i_diff = i_high - p_fmt->i_height;
 
857
        i_y_offset -= ( p_spu->i_margin * i_inv_scale_y / 1000 + i_diff );
 
858
    }
 
859
 
 
860
    /* Force cropping if requested */
 
861
    if( b_force_crop )
 
862
    {
 
863
        video_format_t *p_fmt = &p_region->fmt;
 
864
        int i_crop_x = p_spu->i_crop_x * pi_scale_width[ i_scale_idx ] / 1000
 
865
                            * i_inv_scale_x / 1000;
 
866
        int i_crop_y = p_spu->i_crop_y * pi_scale_height[ i_scale_idx ] / 1000
 
867
                            * i_inv_scale_y / 1000;
 
868
        int i_crop_width = p_spu->i_crop_width * pi_scale_width[ i_scale_idx ] / 1000
 
869
                            * i_inv_scale_x / 1000;
 
870
        int i_crop_height = p_spu->i_crop_height * pi_scale_height[ i_scale_idx ] / 1000
 
871
                            * i_inv_scale_y / 1000;
 
872
 
 
873
        /* Find the intersection */
 
874
        if( i_crop_x + i_crop_width <= i_x_offset ||
 
875
            i_x_offset + (int)p_fmt->i_visible_width < i_crop_x ||
 
876
            i_crop_y + i_crop_height <= i_y_offset ||
 
877
            i_y_offset + (int)p_fmt->i_visible_height < i_crop_y )
 
878
        {
 
879
            /* No intersection */
 
880
            p_fmt->i_visible_width = p_fmt->i_visible_height = 0;
 
881
        }
 
882
        else
 
883
        {
 
884
            int i_x, i_y, i_x_end, i_y_end;
 
885
            i_x = __MAX( i_crop_x, i_x_offset );
 
886
            i_y = __MAX( i_crop_y, i_y_offset );
 
887
            i_x_end = __MIN( i_crop_x + i_crop_width,
 
888
                           i_x_offset + (int)p_fmt->i_visible_width );
 
889
            i_y_end = __MIN( i_crop_y + i_crop_height,
 
890
                           i_y_offset + (int)p_fmt->i_visible_height );
 
891
 
 
892
            p_fmt->i_x_offset = i_x - i_x_offset;
 
893
            p_fmt->i_y_offset = i_y - i_y_offset;
 
894
            p_fmt->i_visible_width = i_x_end - i_x;
 
895
            p_fmt->i_visible_height = i_y_end - i_y;
 
896
 
 
897
            i_x_offset = i_x;
 
898
            i_y_offset = i_y;
 
899
        }
 
900
        b_restore_format = true;
 
901
    }
 
902
 
 
903
    i_x_offset = __MAX( i_x_offset, 0 );
 
904
    i_y_offset = __MAX( i_y_offset, 0 );
 
905
 
 
906
    /* Compute alpha blend value */
 
907
    i_fade_alpha = 255;
 
908
    if( p_subpic->b_fade )
 
909
    {
 
910
        mtime_t i_fade_start = ( p_subpic->i_stop +
 
911
                                 p_subpic->i_start ) / 2;
 
912
        mtime_t i_now = mdate();
 
913
        if( i_now >= i_fade_start && p_subpic->i_stop > i_fade_start )
 
914
        {
 
915
            i_fade_alpha = 255 * ( p_subpic->i_stop - i_now ) /
 
916
                           ( p_subpic->i_stop - i_fade_start );
 
917
        }
 
918
    }
 
919
 
 
920
    /* Update the blender */
 
921
    SpuRenderUpdateBlend( p_spu, p_fmt->i_width, p_fmt->i_height, &p_region->fmt );
 
922
 
 
923
    if( p_spu->p_blend->p_module )
 
924
    {
 
925
        p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,
 
926
            p_pic_src, &p_region->picture, i_x_offset, i_y_offset,
 
927
            i_fade_alpha * p_subpic->i_alpha * p_region->i_alpha / 65025 );
 
928
    }
 
929
    else
 
930
    {
 
931
        msg_Err( p_spu, "blending %4.4s to %4.4s failed",
 
932
                 (char *)&p_spu->p_blend->fmt_out.video.i_chroma,
 
933
                 (char *)&p_spu->p_blend->fmt_out.video.i_chroma );
 
934
    }
 
935
 
 
936
exit:
 
937
    if( b_rerender_text )
 
938
    {
 
939
        /* Some forms of subtitles need to be re-rendered more than
 
940
         * once, eg. karaoke. We therefore restore the region to its
 
941
         * pre-rendered state, so the next time through everything is
 
942
         * calculated again.
 
943
         */
 
944
        p_region->picture.pf_release( &p_region->picture );
 
945
        memset( &p_region->picture, 0, sizeof( picture_t ) );
 
946
        p_region->i_align &= ~SUBPICTURE_RENDERED;
 
947
    }
 
948
    if( b_restore_format )
 
949
        p_region->fmt = fmt_original;
 
950
}
 
951
 
477
952
void spu_RenderSubpictures( spu_t *p_spu, video_format_t *p_fmt,
478
953
                            picture_t *p_pic_dst, picture_t *p_pic_src,
479
954
                            subpicture_t *p_subpic,
480
955
                            int i_scale_width_orig, int i_scale_height_orig )
481
956
{
 
957
    int i_source_video_width;
 
958
    int i_source_video_height;
 
959
    subpicture_t *p_subpic_v;
 
960
 
482
961
    /* Get lock */
483
962
    vlc_mutex_lock( &p_spu->subpicture_lock );
484
963
 
 
964
    for( p_subpic_v = p_subpic;
 
965
            p_subpic_v != NULL && p_subpic_v->i_status != FREE_SUBPICTURE;
 
966
            p_subpic_v = p_subpic_v->p_next )
 
967
    {
 
968
        if( p_subpic_v->pf_pre_render )
 
969
            p_subpic_v->pf_pre_render( p_fmt, p_spu, p_subpic_v );
 
970
    }
 
971
 
 
972
    if( i_scale_width_orig <= 0 )
 
973
        i_scale_width_orig = 1000;
 
974
    if( i_scale_height_orig <= 0 )
 
975
        i_scale_height_orig = 1000;
 
976
 
 
977
    i_source_video_width  = p_fmt->i_width  * 1000 / i_scale_width_orig;
 
978
    i_source_video_height = p_fmt->i_height * 1000 / i_scale_height_orig;
 
979
 
485
980
    /* Check i_status again to make sure spudec hasn't destroyed the subpic */
486
 
    while( p_subpic != NULL && p_subpic->i_status != FREE_SUBPICTURE )
 
981
    for( ; ( p_subpic != NULL ) && ( p_subpic->i_status != FREE_SUBPICTURE ); p_subpic = p_subpic->p_next )
487
982
    {
488
 
        subpicture_region_t *p_region = p_subpic->p_region;
489
 
        int i_scale_width, i_scale_height;
490
 
        int i_subpic_x = p_subpic->i_x;
491
 
 
492
 
        /* Load the blending module */
493
 
        if( !p_spu->p_blend && p_region )
494
 
        {
495
 
            p_spu->p_blend = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
496
 
            vlc_object_attach( p_spu->p_blend, p_spu );
497
 
            p_spu->p_blend->fmt_out.video.i_x_offset =
498
 
                p_spu->p_blend->fmt_out.video.i_y_offset = 0;
499
 
            p_spu->p_blend->fmt_out.video.i_aspect = p_fmt->i_aspect;
500
 
            p_spu->p_blend->fmt_out.video.i_chroma = p_fmt->i_chroma;
501
 
            p_spu->p_blend->fmt_in.video.i_chroma = VLC_FOURCC('Y','U','V','P');
502
 
 
503
 
            p_spu->p_blend->p_module =
504
 
                module_Need( p_spu->p_blend, "video blending", 0, 0 );
505
 
        }
506
 
 
507
 
        /* Load the text rendering module */
508
 
        if( !p_spu->p_text && p_region && p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
509
 
        {
510
 
            char *psz_modulename = NULL;
511
 
 
512
 
            p_spu->p_text = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
513
 
            vlc_object_attach( p_spu->p_text, p_spu );
514
 
 
515
 
            p_spu->p_text->fmt_out.video.i_width =
516
 
                p_spu->p_text->fmt_out.video.i_visible_width =
517
 
                p_fmt->i_width;
518
 
            p_spu->p_text->fmt_out.video.i_height =
519
 
                p_spu->p_text->fmt_out.video.i_visible_height =
520
 
                p_fmt->i_height;
521
 
 
522
 
            p_spu->p_text->pf_sub_buffer_new = spu_new_buffer;
523
 
            p_spu->p_text->pf_sub_buffer_del = spu_del_buffer;
524
 
 
525
 
            psz_modulename = var_CreateGetString( p_spu, "text-renderer" );
526
 
            if( psz_modulename && *psz_modulename )
527
 
            {
528
 
                p_spu->p_text->p_module =
529
 
                    module_Need( p_spu->p_text, "text renderer", psz_modulename, VLC_TRUE );
530
 
            }
531
 
            if( !p_spu->p_text->p_module )
532
 
            {
533
 
                p_spu->p_text->p_module =
534
 
                    module_Need( p_spu->p_text, "text renderer", 0, 0 );
535
 
            }
536
 
            if( psz_modulename ) free( psz_modulename );
537
 
        }
 
983
        subpicture_region_t *p_region;
 
984
        int pi_scale_width[ SCALE_SIZE ];
 
985
        int pi_scale_height[ SCALE_SIZE ];
 
986
        int pi_subpic_x[ SCALE_SIZE ];
 
987
        int k;
 
988
 
 
989
        /* If the source video and subtitles stream agree on the size of
 
990
         * the video then disregard all further references to the subtitle
 
991
         * stream.
 
992
         */
 
993
        if( ( i_source_video_height == p_subpic->i_original_picture_height ) &&
 
994
            ( i_source_video_width  == p_subpic->i_original_picture_width ) )
 
995
        {
 
996
            /* FIXME this looks wrong */
 
997
            p_subpic->i_original_picture_height = 0;
 
998
            p_subpic->i_original_picture_width = 0;
 
999
        }
 
1000
 
 
1001
        for( k = 0; k < SCALE_SIZE ; k++ )
 
1002
            pi_subpic_x[ k ] = p_subpic->i_x;
 
1003
 
 
1004
        if( p_subpic->pf_update_regions )
 
1005
        {
 
1006
            /* TODO do not reverse the scaling that was done before calling
 
1007
             * spu_RenderSubpictures, just pass it along (or do it inside
 
1008
             * spu_RenderSubpictures) */
 
1009
            video_format_t fmt_org = *p_fmt;
 
1010
            fmt_org.i_width =
 
1011
            fmt_org.i_visible_width = i_source_video_width;
 
1012
            fmt_org.i_height =
 
1013
            fmt_org.i_visible_height = i_source_video_height;
 
1014
 
 
1015
            p_subpic->pf_update_regions( &fmt_org, p_spu, p_subpic, mdate() );
 
1016
        }
 
1017
 
 
1018
        /* */
 
1019
        p_region = p_subpic->p_region;
 
1020
        if( !p_region )
 
1021
            continue;
 
1022
 
 
1023
        /* Create the blending module */
 
1024
        if( !p_spu->p_blend )
 
1025
            SpuRenderCreateBlend( p_spu, p_fmt->i_chroma, p_fmt->i_aspect );
 
1026
 
 
1027
        /* Load the text rendering module; it is possible there is a
 
1028
         * text region somewhere in the subpicture other than the first
 
1029
         * element in the region list, so just load it anyway as we'll
 
1030
         * probably want it sooner or later. */
 
1031
        if( !p_spu->p_text )
 
1032
            SpuRenderCreateAndLoadText( p_spu, p_fmt->i_width, p_fmt->i_height );
 
1033
 
538
1034
        if( p_spu->p_text )
539
1035
        {
540
 
            if( p_subpic->i_original_picture_height > 0 &&
541
 
                p_subpic->i_original_picture_width  > 0 )
542
 
            {
543
 
                p_spu->p_text->fmt_out.video.i_width =
544
 
                    p_spu->p_text->fmt_out.video.i_visible_width =
545
 
                    p_subpic->i_original_picture_width;
546
 
                p_spu->p_text->fmt_out.video.i_height =
547
 
                    p_spu->p_text->fmt_out.video.i_visible_height =
548
 
                    p_subpic->i_original_picture_height;
549
 
            }
550
 
            else
551
 
            {
552
 
                p_spu->p_text->fmt_out.video.i_width =
553
 
                    p_spu->p_text->fmt_out.video.i_visible_width =
554
 
                    p_fmt->i_width;
555
 
                p_spu->p_text->fmt_out.video.i_height =
556
 
                    p_spu->p_text->fmt_out.video.i_visible_height =
557
 
                    p_fmt->i_height;
558
 
            }
559
 
        }
560
 
 
561
 
        i_scale_width = i_scale_width_orig;
562
 
        i_scale_height = i_scale_height_orig;
 
1036
            subpicture_region_t *p_text_region = p_subpic->p_region;
 
1037
 
 
1038
            /* Only overwrite the size fields if the region is still in
 
1039
             * pre-rendered TEXT format. We have to traverse the subregion
 
1040
             * list because if more than one subregion is present, the text
 
1041
             * region isn't guarentteed to be the first in the list, and
 
1042
             * only text regions use this flag. All of this effort assists
 
1043
             * with the rescaling of text that has been rendered at native
 
1044
             * resolution, rather than video resolution.
 
1045
             */
 
1046
            while( p_text_region &&
 
1047
                   p_text_region->fmt.i_chroma != VLC_FOURCC('T','E','X','T') )
 
1048
            {
 
1049
                p_text_region = p_text_region->p_next;
 
1050
            }
 
1051
 
 
1052
            if( p_text_region &&
 
1053
                ( ( p_text_region->i_align & SUBPICTURE_RENDERED ) == 0 ) )
 
1054
            {
 
1055
                if( p_subpic->i_original_picture_height > 0 &&
 
1056
                    p_subpic->i_original_picture_width  > 0 )
 
1057
                {
 
1058
                    p_spu->p_text->fmt_out.video.i_width =
 
1059
                    p_spu->p_text->fmt_out.video.i_visible_width =
 
1060
                        p_subpic->i_original_picture_width;
 
1061
                    p_spu->p_text->fmt_out.video.i_height =
 
1062
                    p_spu->p_text->fmt_out.video.i_visible_height =
 
1063
                        p_subpic->i_original_picture_height;
 
1064
                }
 
1065
                else
 
1066
                {
 
1067
                    p_spu->p_text->fmt_out.video.i_width =
 
1068
                    p_spu->p_text->fmt_out.video.i_visible_width =
 
1069
                        p_fmt->i_width;
 
1070
                    p_spu->p_text->fmt_out.video.i_height =
 
1071
                    p_spu->p_text->fmt_out.video.i_visible_height =
 
1072
                        p_fmt->i_height;
 
1073
                }
 
1074
            }
 
1075
 
 
1076
            /* XXX for text:
 
1077
             *  scale[] allows to pass from rendered size (by text module) to video output size */
 
1078
            pi_scale_width[SCALE_TEXT] = p_fmt->i_width * 1000 /
 
1079
                                          p_spu->p_text->fmt_out.video.i_width;
 
1080
            pi_scale_height[SCALE_TEXT]= p_fmt->i_height * 1000 /
 
1081
                                          p_spu->p_text->fmt_out.video.i_height;
 
1082
        }
 
1083
        else
 
1084
        {
 
1085
            /* Just set a value to avoid using invalid memory while looping over the array */
 
1086
            pi_scale_width[SCALE_TEXT] =
 
1087
            pi_scale_height[SCALE_TEXT]= 1000;
 
1088
        }
 
1089
 
 
1090
        /* XXX for default:
 
1091
         *  scale[] allows to pass from native (either video or original) size to output size */
563
1092
 
564
1093
        if( p_subpic->i_original_picture_height > 0 &&
565
1094
            p_subpic->i_original_picture_width  > 0 )
566
1095
        {
567
 
            i_scale_width = i_scale_width * p_fmt->i_width /
568
 
                             p_subpic->i_original_picture_width;
569
 
            i_scale_height = i_scale_height * p_fmt->i_height /
570
 
                             p_subpic->i_original_picture_height;
571
 
        }
572
 
        else if( p_subpic->i_original_picture_height > 0 )
573
 
        {
574
 
            i_scale_height = i_scale_height * p_fmt->i_height /
575
 
                             p_subpic->i_original_picture_height;
576
 
            i_scale_width = i_scale_height * i_scale_height / p_fmt->i_height; 
 
1096
            pi_scale_width[SCALE_DEFAULT]  = p_fmt->i_width  * 1000 / p_subpic->i_original_picture_width;
 
1097
            pi_scale_height[SCALE_DEFAULT] = p_fmt->i_height * 1000 / p_subpic->i_original_picture_height;
 
1098
        }
 
1099
        else
 
1100
        {
 
1101
            pi_scale_width[ SCALE_DEFAULT ]  = i_scale_width_orig;
 
1102
            pi_scale_height[ SCALE_DEFAULT ] = i_scale_height_orig;
 
1103
        }
 
1104
 
 
1105
        for( k = 0; k < SCALE_SIZE ; k++ )
 
1106
        {
 
1107
            /* Case of both width and height being specified has been dealt
 
1108
             * with above by instead rendering to an output pane of the
 
1109
             * explicit dimensions specified - we don't need to scale it.
 
1110
             */
 
1111
            if( p_subpic->i_original_picture_height > 0 &&
 
1112
                p_subpic->i_original_picture_width <= 0 )
 
1113
            {
 
1114
                pi_scale_height[ k ] = pi_scale_height[ k ] * i_source_video_height /
 
1115
                                 p_subpic->i_original_picture_height;
 
1116
                pi_scale_width[ k ]  = pi_scale_width[ k ]  * i_source_video_height /
 
1117
                                 p_subpic->i_original_picture_height;
 
1118
            }
577
1119
        }
578
1120
 
579
1121
        /* Set default subpicture aspect ratio */
580
 
        if( p_region && p_region->fmt.i_aspect &&
581
 
            (!p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den) )
582
 
        {
583
 
            p_region->fmt.i_sar_den = p_region->fmt.i_aspect;
584
 
            p_region->fmt.i_sar_num = VOUT_ASPECT_FACTOR;
585
 
        }
586
 
        if( p_region &&
587
 
            (!p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den) )
588
 
        {
589
 
            p_region->fmt.i_sar_den = p_fmt->i_sar_den;
590
 
            p_region->fmt.i_sar_num = p_fmt->i_sar_num;
 
1122
        if( !p_region->fmt.i_sar_num || !p_region->fmt.i_sar_den )
 
1123
        {
 
1124
            if( p_region->fmt.i_aspect != 0 )
 
1125
            {
 
1126
                p_region->fmt.i_sar_den = p_region->fmt.i_aspect;
 
1127
                p_region->fmt.i_sar_num = VOUT_ASPECT_FACTOR;
 
1128
            }
 
1129
            else
 
1130
            {
 
1131
                p_region->fmt.i_sar_den = p_fmt->i_sar_den;
 
1132
                p_region->fmt.i_sar_num = p_fmt->i_sar_num;
 
1133
            }
591
1134
        }
592
1135
 
593
1136
        /* Take care of the aspect ratio */
594
 
        if( p_region && p_region->fmt.i_sar_num * p_fmt->i_sar_den !=
595
 
            p_region->fmt.i_sar_den * p_fmt->i_sar_num )
596
 
        {
597
 
            i_scale_width = i_scale_width *
598
 
                (int64_t)p_region->fmt.i_sar_num * p_fmt->i_sar_den /
599
 
                p_region->fmt.i_sar_den / p_fmt->i_sar_num;
600
 
            i_subpic_x = p_subpic->i_x * i_scale_width / 1000;
601
 
        }
602
 
 
603
 
        /* Load the scaling module */
604
 
        if( !p_spu->p_scale && (i_scale_width != 1000 ||
605
 
            i_scale_height != 1000) )
606
 
        {
607
 
            p_spu->p_scale = vlc_object_create( p_spu, VLC_OBJECT_FILTER );
608
 
            vlc_object_attach( p_spu->p_scale, p_spu );
609
 
            p_spu->p_scale->fmt_out.video.i_chroma =
610
 
                p_spu->p_scale->fmt_in.video.i_chroma =
611
 
                    VLC_FOURCC('Y','U','V','P');
612
 
            p_spu->p_scale->fmt_in.video.i_width =
613
 
                p_spu->p_scale->fmt_in.video.i_height = 32;
614
 
            p_spu->p_scale->fmt_out.video.i_width =
615
 
                p_spu->p_scale->fmt_out.video.i_height = 16;
616
 
 
617
 
            p_spu->p_scale->pf_vout_buffer_new = spu_new_video_buffer;
618
 
            p_spu->p_scale->pf_vout_buffer_del = spu_del_video_buffer;
619
 
            p_spu->p_scale->p_module =
620
 
                module_Need( p_spu->p_scale, "video filter2", 0, 0 );
621
 
        }
622
 
 
623
 
        while( p_region && p_spu->p_blend && p_spu->p_blend->pf_video_blend )
624
 
        {
625
 
            int i_fade_alpha = 255;
626
 
            int i_x_offset = p_region->i_x + i_subpic_x;
627
 
            int i_y_offset = p_region->i_y + p_subpic->i_y;
628
 
 
629
 
            if( p_region->fmt.i_chroma == VLC_FOURCC('T','E','X','T') )
630
 
            {
631
 
                if( p_spu->p_text && p_spu->p_text->p_module &&
632
 
                    p_spu->p_text->pf_render_text )
633
 
                {
634
 
                    p_region->i_align = p_subpic->i_flags;
635
 
                    p_spu->p_text->pf_render_text( p_spu->p_text,
636
 
                                                   p_region, p_region ); 
637
 
                }
638
 
            }
639
 
 
640
 
            /* Force palette if requested */
641
 
            if( p_spu->b_force_palette &&
642
 
                (VLC_FOURCC('Y','U','V','P') == p_region->fmt.i_chroma) )
643
 
            {
644
 
                memcpy( p_region->fmt.p_palette->palette,
645
 
                        p_spu->palette, 16 );
646
 
            }
647
 
 
648
 
            /* Scale SPU if necessary */
649
 
            if( p_region->p_cache )
650
 
            {
651
 
                if( i_scale_width * p_region->fmt.i_width / 1000 !=
652
 
                    p_region->p_cache->fmt.i_width ||
653
 
                    i_scale_height * p_region->fmt.i_height / 1000 !=
654
 
                    p_region->p_cache->fmt.i_height )
655
 
                {
656
 
                    p_subpic->pf_destroy_region( VLC_OBJECT(p_spu),
657
 
                                                 p_region->p_cache );
658
 
                    p_region->p_cache = 0;
659
 
                }
660
 
            }
661
 
 
662
 
            if( (i_scale_width != 1000 || i_scale_height != 1000) &&
663
 
                p_spu->p_scale && !p_region->p_cache )
664
 
            {
665
 
                picture_t *p_pic;
666
 
 
667
 
                p_spu->p_scale->fmt_in.video = p_region->fmt;
668
 
                p_spu->p_scale->fmt_out.video = p_region->fmt;
669
 
 
670
 
                p_region->p_cache =
671
 
                    p_subpic->pf_create_region( VLC_OBJECT(p_spu),
672
 
                        &p_spu->p_scale->fmt_out.video );
673
 
                if( p_spu->p_scale->fmt_out.video.p_palette )
674
 
                    *p_spu->p_scale->fmt_out.video.p_palette =
675
 
                        *p_region->fmt.p_palette;
676
 
                p_region->p_cache->p_next = p_region->p_next;
677
 
 
678
 
                vout_CopyPicture( p_spu, &p_region->p_cache->picture,
679
 
                                  &p_region->picture );
680
 
 
681
 
                p_spu->p_scale->fmt_out.video.i_width =
682
 
                    p_region->fmt.i_width * i_scale_width / 1000;
683
 
                p_spu->p_scale->fmt_out.video.i_visible_width =
684
 
                    p_region->fmt.i_visible_width * i_scale_width / 1000;
685
 
                p_spu->p_scale->fmt_out.video.i_height =
686
 
                    p_region->fmt.i_height * i_scale_height / 1000;
687
 
                p_spu->p_scale->fmt_out.video.i_visible_height =
688
 
                    p_region->fmt.i_visible_height * i_scale_height / 1000;
689
 
                p_region->p_cache->fmt = p_spu->p_scale->fmt_out.video;
690
 
                p_region->p_cache->i_x = p_region->i_x * i_scale_width / 1000;
691
 
                p_region->p_cache->i_y = p_region->i_y * i_scale_height / 1000;
692
 
 
693
 
                p_pic = p_spu->p_scale->pf_video_filter(
694
 
                                 p_spu->p_scale, &p_region->p_cache->picture );
695
 
                if( p_pic )
696
 
                {
697
 
                    picture_t p_pic_tmp = p_region->p_cache->picture;
698
 
                    p_region->p_cache->picture = *p_pic;
699
 
                    *p_pic = p_pic_tmp;
700
 
                    free( p_pic );
701
 
                }
702
 
            }
703
 
            if( (i_scale_width != 1000 || i_scale_height != 1000) &&
704
 
                p_spu->p_scale && p_region->p_cache )
705
 
            {
706
 
                p_region = p_region->p_cache;
707
 
            }
708
 
 
709
 
            if( p_subpic->i_flags & SUBPICTURE_ALIGN_BOTTOM )
710
 
            {
711
 
                i_y_offset = p_fmt->i_height - p_region->fmt.i_height -
712
 
                    p_subpic->i_y;
713
 
            }
714
 
            else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_TOP) )
715
 
            {
716
 
                i_y_offset = p_fmt->i_height / 2 - p_region->fmt.i_height / 2;
717
 
            }
718
 
 
719
 
            if( p_subpic->i_flags & SUBPICTURE_ALIGN_RIGHT )
720
 
            {
721
 
                i_x_offset = p_fmt->i_width - p_region->fmt.i_width -
722
 
                    i_subpic_x;
723
 
            }
724
 
            else if ( !(p_subpic->i_flags & SUBPICTURE_ALIGN_LEFT) )
725
 
            {
726
 
                i_x_offset = p_fmt->i_width / 2 - p_region->fmt.i_width / 2;
727
 
            }
728
 
 
729
 
            if( p_subpic->b_absolute )
730
 
            {
731
 
                i_x_offset = p_region->i_x +
732
 
                    i_subpic_x * i_scale_width / 1000;
733
 
                i_y_offset = p_region->i_y +
734
 
                    p_subpic->i_y * i_scale_height / 1000;
735
 
 
736
 
            }
737
 
            
738
 
            i_x_offset = __MAX( i_x_offset, 0 );
739
 
            i_y_offset = __MAX( i_y_offset, 0 );
740
 
 
741
 
            if( p_spu->i_margin != 0 && p_spu->b_force_crop == VLC_FALSE )
742
 
            {
743
 
                int i_diff = 0;
744
 
                int i_low = i_y_offset - p_spu->i_margin;
745
 
                int i_high = i_y_offset + p_region->fmt.i_height - p_spu->i_margin;
746
 
 
747
 
                /* crop extra margin to keep within bounds */
748
 
                if( i_low < 0 ) i_diff = i_low;
749
 
                if( i_high > (int)p_fmt->i_height ) i_diff = i_high - p_fmt->i_height;
750
 
                i_y_offset -= ( p_spu->i_margin + i_diff );
751
 
            }
752
 
 
753
 
            p_spu->p_blend->fmt_in.video = p_region->fmt;
754
 
 
755
 
            /* Force cropping if requested */
756
 
            if( p_spu->b_force_crop )
757
 
            {
758
 
                video_format_t *p_fmt = &p_spu->p_blend->fmt_in.video;
759
 
                int i_crop_x = p_spu->i_crop_x * i_scale_width / 1000;
760
 
                int i_crop_y = p_spu->i_crop_y * i_scale_height / 1000;
761
 
                int i_crop_width = p_spu->i_crop_width * i_scale_width / 1000;
762
 
                int i_crop_height = p_spu->i_crop_height * i_scale_height/1000;
763
 
 
764
 
                /* Find the intersection */
765
 
                if( i_crop_x + i_crop_width <= i_x_offset ||
766
 
                    i_x_offset + (int)p_fmt->i_visible_width < i_crop_x ||
767
 
                    i_crop_y + i_crop_height <= i_y_offset ||
768
 
                    i_y_offset + (int)p_fmt->i_visible_height < i_crop_y )
769
 
                {
770
 
                    /* No intersection */
771
 
                    p_fmt->i_visible_width = p_fmt->i_visible_height = 0;
772
 
                }
773
 
                else
774
 
                {
775
 
                    int i_x, i_y, i_x_end, i_y_end;
776
 
                    i_x = __MAX( i_crop_x, i_x_offset );
777
 
                    i_y = __MAX( i_crop_y, i_y_offset );
778
 
                    i_x_end = __MIN( i_crop_x + i_crop_width,
779
 
                                   i_x_offset + (int)p_fmt->i_visible_width );
780
 
                    i_y_end = __MIN( i_crop_y + i_crop_height,
781
 
                                   i_y_offset + (int)p_fmt->i_visible_height );
782
 
 
783
 
                    p_fmt->i_x_offset = i_x - i_x_offset;
784
 
                    p_fmt->i_y_offset = i_y - i_y_offset;
785
 
                    p_fmt->i_visible_width = i_x_end - i_x;
786
 
                    p_fmt->i_visible_height = i_y_end - i_y;
787
 
 
788
 
                    i_x_offset = i_x;
789
 
                    i_y_offset = i_y;
790
 
                }
791
 
            }
792
 
 
793
 
            /* Update the output picture size */
794
 
            p_spu->p_blend->fmt_out.video.i_width =
795
 
                p_spu->p_blend->fmt_out.video.i_visible_width =
796
 
                    p_fmt->i_width;
797
 
            p_spu->p_blend->fmt_out.video.i_height =
798
 
                p_spu->p_blend->fmt_out.video.i_visible_height =
799
 
                    p_fmt->i_height;
800
 
 
801
 
            if( p_subpic->b_fade )
802
 
            {
803
 
                mtime_t i_fade_start = ( p_subpic->i_stop +
804
 
                                         p_subpic->i_start ) / 2;
805
 
                mtime_t i_now = mdate();
806
 
                if( i_now >= i_fade_start && p_subpic->i_stop > i_fade_start )
807
 
                {
808
 
                    i_fade_alpha = 255 * ( p_subpic->i_stop - i_now ) /
809
 
                                   ( p_subpic->i_stop - i_fade_start );
810
 
                }
811
 
            }
812
 
 
813
 
            i_x_offset = __MAX( i_x_offset, 0 );
814
 
            i_y_offset = __MAX( i_y_offset, 0 );
815
 
 
816
 
            p_spu->p_blend->pf_video_blend( p_spu->p_blend, p_pic_dst,
817
 
                p_pic_src, &p_region->picture, i_x_offset, i_y_offset,
818
 
                i_fade_alpha * p_subpic->i_alpha / 255 );
819
 
 
820
 
            p_region = p_region->p_next;
821
 
        }
822
 
 
823
 
        p_subpic = p_subpic->p_next;
 
1137
        if( ( p_region->fmt.i_sar_num * p_fmt->i_sar_den ) !=
 
1138
            ( p_region->fmt.i_sar_den * p_fmt->i_sar_num ) )
 
1139
        {
 
1140
            for( k = 0; k < SCALE_SIZE; k++ )
 
1141
            {
 
1142
                pi_scale_width[k] = pi_scale_width[ k ] *
 
1143
                    (int64_t)p_region->fmt.i_sar_num * p_fmt->i_sar_den /
 
1144
                    p_region->fmt.i_sar_den / p_fmt->i_sar_num;
 
1145
 
 
1146
                pi_subpic_x[k] = p_subpic->i_x * pi_scale_width[ k ] / 1000;
 
1147
            }
 
1148
        }
 
1149
 
 
1150
        /* Load the scaling module when needed */
 
1151
        if( !p_spu->p_scale )
 
1152
        {
 
1153
            bool b_scale_used = false;
 
1154
 
 
1155
            for( k = 0; k < SCALE_SIZE; k++ )
 
1156
            {
 
1157
                const int i_scale_w = pi_scale_width[k];
 
1158
                const int i_scale_h = pi_scale_height[k];
 
1159
                if( ( i_scale_w > 0 && i_scale_w != 1000 ) || ( i_scale_h > 0 && i_scale_h != 1000 ) )
 
1160
                    b_scale_used = true;
 
1161
            }
 
1162
 
 
1163
            if( b_scale_used )
 
1164
                SpuRenderCreateAndLoadScale( p_spu );
 
1165
        }
 
1166
 
 
1167
        for( ; p_region != NULL; p_region = p_region->p_next )
 
1168
            SpuRenderRegion( p_spu, p_pic_dst, p_pic_src,
 
1169
                             p_subpic, p_region, i_scale_width_orig, i_scale_height_orig,
 
1170
                             pi_subpic_x, pi_scale_width, pi_scale_height,
 
1171
                             p_fmt );
824
1172
    }
825
1173
 
826
1174
    vlc_mutex_unlock( &p_spu->subpicture_lock );
838
1186
 * more difficult to guess if a subpicture has to be rendered or not.
839
1187
 *****************************************************************************/
840
1188
subpicture_t *spu_SortSubpictures( spu_t *p_spu, mtime_t display_date,
841
 
                                   vlc_bool_t b_paused )
 
1189
                                   bool b_paused )
842
1190
{
843
1191
    int i_index, i_channel;
844
1192
    subpicture_t *p_subpic = NULL;
846
1194
    mtime_t      ephemer_date;
847
1195
 
848
1196
    /* Run subpicture filters */
849
 
    for( i_index = 0; i_index < p_spu->i_filter; i_index++ )
850
 
    {
851
 
        subpicture_t *p_subpic_filter;
852
 
        p_subpic_filter = p_spu->pp_filter[i_index]->
853
 
            pf_sub_filter( p_spu->pp_filter[i_index], display_date );
854
 
        if( p_subpic_filter )
855
 
        {
856
 
            spu_DisplaySubpicture( p_spu, p_subpic_filter );
857
 
        }
858
 
    }
 
1197
    filter_chain_SubFilter( p_spu->p_chain, display_date );
859
1198
 
860
1199
    /* We get an easily parsable chained list of subpictures which
861
1200
     * ends with NULL since p_subpic was initialized to NULL. */
936
1275
 * This function destroys the subpictures which belong to the spu channel
937
1276
 * corresponding to i_channel_id.
938
1277
 *****************************************************************************/
939
 
static void SpuClearChannel( spu_t *p_spu, int i_channel )
 
1278
static void SpuClearChannel( spu_t *p_spu, int i_channel, bool b_locked )
940
1279
{
941
1280
    int          i_subpic;                               /* subpicture index */
942
1281
    subpicture_t *p_subpic = NULL;                  /* first free subpicture */
943
1282
 
944
 
    vlc_mutex_lock( &p_spu->subpicture_lock );
 
1283
    if( !b_locked )
 
1284
        vlc_mutex_lock( &p_spu->subpicture_lock );
945
1285
 
946
1286
    for( i_subpic = 0; i_subpic < VOUT_MAX_SUBPICTURES; i_subpic++ )
947
1287
    {
967
1307
        }
968
1308
    }
969
1309
 
970
 
    vlc_mutex_unlock( &p_spu->subpicture_lock );
 
1310
    if( !b_locked )
 
1311
        vlc_mutex_unlock( &p_spu->subpicture_lock );
971
1312
}
972
1313
 
973
1314
/*****************************************************************************
982
1323
    case SPU_CHANNEL_REGISTER:
983
1324
        pi = (int *)va_arg( args, int * );
984
1325
        if( pi ) *pi = p_spu->i_channel++;
985
 
        msg_Dbg( p_spu, "Registering subpicture channel, ID: %i",
986
 
                 p_spu->i_channel - 1 );
987
1326
        break;
988
1327
 
989
1328
    case SPU_CHANNEL_CLEAR:
990
1329
        i = (int)va_arg( args, int );
991
 
        SpuClearChannel( p_spu, i );
 
1330
        SpuClearChannel( p_spu, i, false );
992
1331
        break;
993
1332
 
994
1333
    default:
1013
1352
{
1014
1353
    vlc_value_t val;
1015
1354
 
1016
 
    p_spu->b_force_palette = VLC_FALSE;
1017
 
    p_spu->b_force_crop = VLC_FALSE;
1018
 
 
1019
 
    if( var_Get( p_object, "highlight", &val ) || !val.b_bool ) return;
1020
 
 
1021
 
    p_spu->b_force_crop = VLC_TRUE;
 
1355
    vlc_mutex_lock( &p_spu->subpicture_lock );
 
1356
 
 
1357
    p_spu->b_force_palette = false;
 
1358
    p_spu->b_force_crop = false;
 
1359
 
 
1360
    if( var_Get( p_object, "highlight", &val ) || !val.b_bool )
 
1361
    {
 
1362
        vlc_mutex_unlock( &p_spu->subpicture_lock );
 
1363
        return;
 
1364
    }
 
1365
 
 
1366
    p_spu->b_force_crop = true;
1022
1367
    var_Get( p_object, "x-start", &val );
1023
1368
    p_spu->i_crop_x = val.i_int;
1024
1369
    var_Get( p_object, "y-start", &val );
1031
1376
    if( var_Get( p_object, "menu-palette", &val ) == VLC_SUCCESS )
1032
1377
    {
1033
1378
        memcpy( p_spu->palette, val.p_address, 16 );
1034
 
        p_spu->b_force_palette = VLC_TRUE;
 
1379
        p_spu->b_force_palette = true;
1035
1380
    }
 
1381
    vlc_mutex_unlock( &p_spu->subpicture_lock );
1036
1382
 
1037
1383
    msg_Dbg( p_object, "crop: %i,%i,%i,%i, palette forced: %i",
1038
1384
             p_spu->i_crop_x, p_spu->i_crop_y,
1048
1394
static int CropCallback( vlc_object_t *p_object, char const *psz_var,
1049
1395
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
1050
1396
{
 
1397
    (void)psz_var; (void)oldval; (void)newval;
1051
1398
    UpdateSPU( (spu_t *)p_data, p_object );
1052
1399
    return VLC_SUCCESS;
1053
1400
}
1071
1418
 
1072
1419
static subpicture_t *spu_new_buffer( filter_t *p_filter )
1073
1420
{
 
1421
    (void)p_filter;
1074
1422
    subpicture_t *p_subpic = (subpicture_t *)malloc(sizeof(subpicture_t));
 
1423
    if( !p_subpic ) return NULL;
1075
1424
    memset( p_subpic, 0, sizeof(subpicture_t) );
1076
 
    p_subpic->b_absolute = VLC_TRUE;
 
1425
    p_subpic->b_absolute = true;
1077
1426
 
1078
1427
    p_subpic->pf_create_region = __spu_CreateRegion;
1079
1428
    p_subpic->pf_make_region = __spu_MakeRegion;
1097
1446
static picture_t *spu_new_video_buffer( filter_t *p_filter )
1098
1447
{
1099
1448
    picture_t *p_picture = malloc( sizeof(picture_t) );
1100
 
 
 
1449
    if( !p_picture ) return NULL;
1101
1450
    if( vout_AllocatePicture( p_filter, p_picture,
1102
1451
                              p_filter->fmt_out.video.i_chroma,
1103
1452
                              p_filter->fmt_out.video.i_width,
1116
1465
 
1117
1466
static void spu_del_video_buffer( filter_t *p_filter, picture_t *p_pic )
1118
1467
{
1119
 
    if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
1120
 
    if( p_pic ) free( p_pic );
 
1468
    (void)p_filter;
 
1469
    if( p_pic )
 
1470
    {
 
1471
        free( p_pic->p_data_orig );
 
1472
        free( p_pic );
 
1473
    }
 
1474
}
 
1475
 
 
1476
static int SubFilterCallback( vlc_object_t *p_object, char const *psz_var,
 
1477
                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
 
1478
{
 
1479
    VLC_UNUSED(p_object); VLC_UNUSED(oldval);
 
1480
    VLC_UNUSED(newval); VLC_UNUSED(psz_var);
 
1481
 
 
1482
    spu_t *p_spu = (spu_t *)p_data;
 
1483
    vlc_mutex_lock( &p_spu->subpicture_lock );
 
1484
    filter_chain_Reset( p_spu->p_chain, NULL, NULL );
 
1485
    spu_ParseChain( p_spu );
 
1486
    vlc_mutex_unlock( &p_spu->subpicture_lock );
 
1487
    return VLC_SUCCESS;
 
1488
}
 
1489
 
 
1490
static int sub_filter_allocation_init( filter_t *p_filter, void *p_data )
 
1491
{
 
1492
    spu_t *p_spu = (spu_t *)p_data;
 
1493
 
 
1494
    p_filter->pf_sub_buffer_new = sub_new_buffer;
 
1495
    p_filter->pf_sub_buffer_del = sub_del_buffer;
 
1496
 
 
1497
    filter_owner_sys_t *p_sys = malloc( sizeof(filter_owner_sys_t) );
 
1498
    if( !p_sys ) return VLC_EGENERIC;
 
1499
 
 
1500
    p_filter->p_owner = p_sys;
 
1501
    spu_Control( p_spu, SPU_CHANNEL_REGISTER, &p_sys->i_channel );
 
1502
    p_sys->p_spu = p_spu;
 
1503
 
 
1504
    return VLC_SUCCESS;
 
1505
}
 
1506
 
 
1507
static void sub_filter_allocation_clear( filter_t *p_filter )
 
1508
{
 
1509
    filter_owner_sys_t *p_sys = p_filter->p_owner;
 
1510
    SpuClearChannel( p_sys->p_spu, p_sys->i_channel, true );
 
1511
    free( p_filter->p_owner );
1121
1512
}