es_out.c 24.8 KB
Newer Older
1
2
3
/*****************************************************************************
 * es_out.c: Es Out handler for input.
 *****************************************************************************
zorglub's avatar
zorglub committed
4
 * Copyright (C) 2003-2004 VideoLAN
5
 * $Id: es_out.c,v 1.17 2004/01/18 04:53:57 fenrir Exp $
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>

#include <vlc/vlc.h>
#include <vlc/input.h>
#include <vlc/decoder.h>

zorglub's avatar
zorglub committed
33
#include "vlc_playlist.h"
34
35
36
37
38
#include "codecs.h"

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
39
40
41
42
43
44
struct es_out_id_t
{
    int             i_channel;
    es_descriptor_t *p_es;
};

45
46
47
struct es_out_sys_t
{
    input_thread_t *p_input;
48
    vlc_bool_t      b_pcr_set;
49

50
    /* all es */
51
52
    int         i_id;

53
54
    int         i_es;
    es_out_id_t **es;
55

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    /* mode gestion */
    vlc_bool_t  b_active;
    int         i_mode;

    /* es count */
    int         i_audio;
    int         i_video;
    int         i_sub;

    /* es to select */
    int         i_audio_last;
    int         i_sub_last;

    /* current main es */
    es_out_id_t *p_es_audio;
    es_out_id_t *p_es_video;
    es_out_id_t *p_es_sub;
73
74
75
76
77
78
79
80
81
82
83
84
85
};

static es_out_id_t *EsOutAdd    ( es_out_t *, es_format_t * );
static int          EsOutSend   ( es_out_t *, es_out_id_t *, block_t * );
static void         EsOutDel    ( es_out_t *, es_out_id_t * );
static int          EsOutControl( es_out_t *, int i_query, va_list );


/*****************************************************************************
 * input_EsOutNew:
 *****************************************************************************/
es_out_t *input_EsOutNew( input_thread_t *p_input )
{
86
87
88
    es_out_t     *out = malloc( sizeof( es_out_t ) );
    es_out_sys_t *p_sys = malloc( sizeof( es_out_sys_t ) );
    vlc_value_t  val;
89
90
91
92
93

    out->pf_add     = EsOutAdd;
    out->pf_send    = EsOutSend;
    out->pf_del     = EsOutDel;
    out->pf_control = EsOutControl;
94
95
96
    out->p_sys      = p_sys;

    p_sys->p_input = p_input;
97
    p_sys->b_pcr_set = VLC_FALSE;
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

    p_sys->b_active = VLC_FALSE;
    p_sys->i_mode   = ES_OUT_MODE_AUTO;

    p_sys->i_id    = 1;

    p_sys->i_es    = 0;
    p_sys->es      = NULL;

    p_sys->i_audio = 0;
    p_sys->i_video = 0;
    p_sys->i_sub   = 0;

    var_Get( p_input, "audio-channel", &val );
    p_sys->i_audio_last = val.i_int;

    var_Get( p_input, "spu-channel", &val );
    p_sys->i_sub_last = val.i_int;

    p_sys->p_es_audio = NULL;
    p_sys->p_es_video = NULL;
    p_sys->p_es_sub   = NULL;
120
121
122
123
124
125
126
127
128
129
130
131

    return out;
}

/*****************************************************************************
 * input_EsOutDelete:
 *****************************************************************************/
void input_EsOutDelete( es_out_t *out )
{
    es_out_sys_t *p_sys = out->p_sys;
    int i;

132
    for( i = 0; i < p_sys->i_es; i++ )
133
    {
134
        free( p_sys->es[i] );
135
    }
136
    if( p_sys->es )
137
    {
138
        free( p_sys->es );
139
140
141
142
143
    }
    free( p_sys );
    free( out );
}

144
145
146
147
148
149
150
151
152
153
154
/*****************************************************************************
 * EsOutSelect: Select an ES given the current mode
 * XXX: you need to take a the lock before (stream.stream_lock)
 *****************************************************************************/
static void EsOutSelect( es_out_t *out, es_out_id_t *es, vlc_bool_t b_force )
{
    es_out_sys_t      *p_sys = out->p_sys;
    input_thread_t    *p_input = p_sys->p_input;

    int i_cat = es->p_es->i_cat;

155
156
    if( !p_sys->b_active ||
        ( !b_force && es->p_es->fmt.i_priority < 0 ) )
157
158
159
160
161
162
    {
        return;
    }

    if( p_sys->i_mode == ES_OUT_MODE_ALL || b_force )
    {
163
164
165
166
        if( !es->p_es->p_dec )
        {
            input_SelectES( p_input, es->p_es );
        }
167
168
169
170
171
    }
    else if( p_sys->i_mode == ES_OUT_MODE_AUTO )
    {
        int i_wanted  = -1;

172
173
174
175
176
177
        if( es->p_es->p_pgrm != NULL &&
            es->p_es->p_pgrm != p_input->stream.p_selected_program )
        {
            return;
        }

178
179
        if( i_cat == AUDIO_ES )
        {
gbazin's avatar
   
gbazin committed
180
181
182
            if( p_sys->p_es_audio &&
                p_sys->p_es_audio->p_es->fmt.i_priority >=
                    es->p_es->fmt.i_priority )
183
184
185
            {
                return;
            }
gbazin's avatar
   
gbazin committed
186
187
            i_wanted  = p_sys->i_audio_last >= 0 ?
                            p_sys->i_audio_last : es->i_channel;
188
189
190
        }
        else if( i_cat == SPU_ES )
        {
gbazin's avatar
   
gbazin committed
191
192
193
            if( p_sys->p_es_sub &&
                p_sys->p_es_sub->p_es->fmt.i_priority >=
                    es->p_es->fmt.i_priority )
194
195
196
197
198
199
200
201
202
203
            {
                return;
            }
            i_wanted  = p_sys->i_sub_last;
        }
        else if( i_cat == VIDEO_ES )
        {
            i_wanted  = es->i_channel;
        }

Laurent Aimar's avatar
Laurent Aimar committed
204
        if( i_wanted == es->i_channel && es->p_es->p_dec == NULL )
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
        {
            input_SelectES( p_input, es->p_es );
        }
    }

    /* FIXME TODO handle priority here */
    if( es->p_es->p_dec )
    {
        if( i_cat == AUDIO_ES )
        {
            if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
                p_sys->p_es_audio && p_sys->p_es_audio->p_es->p_dec )
            {
                input_UnselectES( p_input, p_sys->p_es_audio->p_es );
            }
            p_sys->p_es_audio = es;
        }
        else if( i_cat == SPU_ES )
        {
            if( p_sys->i_mode == ES_OUT_MODE_AUTO &&
                p_sys->p_es_sub && p_sys->p_es_sub->p_es->p_dec )
            {
                input_UnselectES( p_input, p_sys->p_es_sub->p_es );
            }
            p_sys->p_es_sub = es;
        }
        else if( i_cat == VIDEO_ES )
        {
            p_sys->p_es_video = es;
        }
    }
}

238
239
240
241
242
243
/*****************************************************************************
 * EsOutAdd:
 *****************************************************************************/
static es_out_id_t *EsOutAdd( es_out_t *out, es_format_t *fmt )
{
    es_out_sys_t      *p_sys = out->p_sys;
zorglub's avatar
zorglub committed
244
    playlist_t        *p_playlist = NULL;
245
    input_thread_t    *p_input = p_sys->p_input;
246
    es_out_id_t       *es = malloc( sizeof( es_out_id_t ) );
247
    pgrm_descriptor_t *p_prgm = NULL;
248
    char              psz_cat[sizeof( "Stream " ) + 10];
249
250
251
252
253
254
255
256
257
258
259
260
261
    input_info_category_t *p_cat;

    vlc_mutex_lock( &p_input->stream.stream_lock );
    if( fmt->i_group >= 0 )
    {
        /* search program */
        p_prgm = input_FindProgram( p_input, fmt->i_group );

        if( p_prgm == NULL )
        {
            /* create it */
            p_prgm = input_AddProgram( p_input, fmt->i_group, 0 );

262
263
264
265
266
267
            /* XXX welcome to kludge, add a dummy es, if you want to understand
             * why have a look at input_SetProgram. Basicaly, it assume the first
             * es to be the PMT, how that is stupide, nevertheless it is needed for
             * the old ts demuxer */
            input_AddES( p_input, p_prgm, 0, UNKNOWN_ES, NULL, 0 );

268
269
270
271
272
273
274
275
            /* Select the first by default */
            if( p_input->stream.p_selected_program == NULL )
            {
                p_input->stream.p_selected_program = p_prgm;
            }
        }
    }

276
    es->p_es = input_AddES( p_input,
277
                            p_prgm,
278
                            out->p_sys->i_id,
279
                            fmt->i_cat,
Laurent Aimar's avatar
Laurent Aimar committed
280
                            fmt->psz_language, 0 );
281
282
    es->p_es->i_stream_id = out->p_sys->i_id;
    es->p_es->i_fourcc = fmt->i_codec;
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

    switch( fmt->i_cat )
    {
        case AUDIO_ES:
        {
            WAVEFORMATEX *p_wf =
                malloc( sizeof( WAVEFORMATEX ) + fmt->i_extra);

            p_wf->wFormatTag        = WAVE_FORMAT_UNKNOWN;
            p_wf->nChannels         = fmt->audio.i_channels;
            p_wf->nSamplesPerSec    = fmt->audio.i_rate;
            p_wf->nAvgBytesPerSec   = fmt->i_bitrate / 8;
            p_wf->nBlockAlign       = fmt->audio.i_blockalign;
            p_wf->wBitsPerSample    = fmt->audio.i_bitspersample;
            p_wf->cbSize            = fmt->i_extra;
            if( fmt->i_extra > 0 )
            {
                memcpy( &p_wf[1], fmt->p_extra, fmt->i_extra );
            }
302
303
304
            es->p_es->p_waveformatex = p_wf;

            es->i_channel = p_sys->i_audio;
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
            break;
        }
        case VIDEO_ES:
        {
            BITMAPINFOHEADER *p_bih = malloc( sizeof( BITMAPINFOHEADER ) +
                                              fmt->i_extra );
            p_bih->biSize           = sizeof(BITMAPINFOHEADER) + fmt->i_extra;
            p_bih->biWidth          = fmt->video.i_width;
            p_bih->biHeight         = fmt->video.i_height;
            p_bih->biPlanes         = 1;
            p_bih->biBitCount       = 24;
            p_bih->biCompression    = fmt->i_codec;
            p_bih->biSizeImage      = fmt->video.i_width *
                                          fmt->video.i_height;
            p_bih->biXPelsPerMeter  = 0;
            p_bih->biYPelsPerMeter  = 0;
            p_bih->biClrUsed        = 0;
            p_bih->biClrImportant   = 0;

            if( fmt->i_extra > 0 )
            {
                memcpy( &p_bih[1], fmt->p_extra, fmt->i_extra );
            }
328
329
330
            es->p_es->p_bitmapinfoheader = p_bih;

            es->i_channel = p_sys->i_video;
331
332
333
334
335
336
337
338
            break;
        }
        case SPU_ES:
        {
            subtitle_data_t *p_sub = malloc( sizeof( subtitle_data_t ) );
            memset( p_sub, 0, sizeof( subtitle_data_t ) );
            if( fmt->i_extra > 0 )
            {
339
                p_sub->psz_header = malloc( fmt->i_extra  + 1 );
340
                memcpy( p_sub->psz_header, fmt->p_extra , fmt->i_extra );
341
342
                /* just to be sure */
                ((uint8_t*)fmt->p_extra)[fmt->i_extra] = '\0';
343
344
            }
            /* FIXME beuuuuuurk */
345
346
347
            es->p_es->p_demux_data = p_sub;

            es->i_channel = p_sys->i_sub;
348
349
            break;
        }
350

351
        default:
352
            es->i_channel = 0;
353
354
355
            break;
    }

356
    sprintf( psz_cat, _("Stream %d"), out->p_sys->i_id - 1 );
zorglub's avatar
zorglub committed
357
358
359
360
    /* Get a category and the playlist */
    if( ( p_cat = input_InfoCategory( p_input, psz_cat ) ) &&
        ( p_playlist = (playlist_t *)vlc_object_find( p_input,
                       VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ) ) )
361
362
363
364
365
    {
        /* Add information */
        switch( fmt->i_cat )
        {
            case AUDIO_ES:
gbazin's avatar
   
gbazin committed
366
367
                if( fmt->psz_description )
                {
Sam Hocevar's avatar
Sam Hocevar committed
368
                    input_AddInfo( p_cat, _("Description"), "%s",
gbazin's avatar
   
gbazin committed
369
                                   fmt->psz_description );
zorglub's avatar
zorglub committed
370
371
372
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                     _("Description"), "%s",
                                     fmt->psz_description );
gbazin's avatar
   
gbazin committed
373
                }
374
375
                input_AddInfo( p_cat, _("Codec"), "%.4s",
                               (char*)&fmt->i_codec );
zorglub's avatar
zorglub committed
376
377
378
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                  _("Codec"),"%.4s",(char*)&fmt->i_codec );

379
                input_AddInfo( p_cat, _("Type"), _("Audio") );
zorglub's avatar
zorglub committed
380
381
382
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                 _("Type"), _("Audio") );

383
384
385
386
                if( fmt->audio.i_channels > 0 )
                {
                    input_AddInfo( p_cat, _("Channels"), "%d",
                                   fmt->audio.i_channels );
zorglub's avatar
zorglub committed
387
388
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                      _("Channels"), "%d",                                                            fmt->audio.i_channels );
389
                }
gbazin's avatar
   
gbazin committed
390
391
                if( fmt->psz_language )
                {
Sam Hocevar's avatar
Sam Hocevar committed
392
                    input_AddInfo( p_cat, _("Language"), "%s",
gbazin's avatar
   
gbazin committed
393
                                   fmt->psz_language );
zorglub's avatar
zorglub committed
394
395
396
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                     _("Language"), "%s",
                                     fmt->psz_language );
gbazin's avatar
   
gbazin committed
397
                }
398
399
                if( fmt->audio.i_rate > 0 )
                {
zorglub's avatar
zorglub committed
400
                    input_AddInfo( p_cat, _("Sample rate"), _("%d Hz"),
401
                                   fmt->audio.i_rate );
zorglub's avatar
zorglub committed
402
403
404
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                     _("Sample rate"), _("%d Hz"),
                                      fmt->audio.i_rate );
405
406
407
                }
                if( fmt->i_bitrate > 0 )
                {
zorglub's avatar
zorglub committed
408
                    input_AddInfo( p_cat, _("Bitrate"), _("%d bps"),
409
                                   fmt->i_bitrate );
zorglub's avatar
zorglub committed
410
411
412
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                    _("Bitrate"), _("%d bps"),
                                     fmt->i_bitrate );
413
414
415
                }
                if( fmt->audio.i_bitspersample )
                {
Sam Hocevar's avatar
Sam Hocevar committed
416
                    input_AddInfo( p_cat, _("Bits per sample"), "%d",
417
                                   fmt->audio.i_bitspersample );
zorglub's avatar
zorglub committed
418
419
420
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                     _("Bits per sample"), "%d",
                                     fmt->audio.i_bitspersample );
421
422
423
                }
                break;
            case VIDEO_ES:
gbazin's avatar
   
gbazin committed
424
425
                if( fmt->psz_description )
                {
Sam Hocevar's avatar
Sam Hocevar committed
426
                    input_AddInfo( p_cat, _("Description"), "%s",
gbazin's avatar
   
gbazin committed
427
                                   fmt->psz_description );
zorglub's avatar
zorglub committed
428
429
430
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                     _("Description"), "%s",
                                     fmt->psz_description );
gbazin's avatar
   
gbazin committed
431
                }
432
                input_AddInfo( p_cat, _("Type"), _("Video") );
zorglub's avatar
zorglub committed
433
434
435
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                _("Type"), _("Video") );

436
437
                input_AddInfo( p_cat, _("Codec"), "%.4s",
                               (char*)&fmt->i_codec );
zorglub's avatar
zorglub committed
438
439
440
441
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                 _("Codec"), "%.4s",
                                 (char*)&fmt->i_codec );

442
443
444
445
                if( fmt->video.i_width > 0 && fmt->video.i_height > 0 )
                {
                    input_AddInfo( p_cat, _("Resolution"), "%dx%d",
                                   fmt->video.i_width, fmt->video.i_height );
zorglub's avatar
zorglub committed
446
447
448
                    playlist_AddInfo( p_playlist, -1, psz_cat,
                                    _("Resolution"), "%dx%d",
                                    fmt->video.i_width, fmt->video.i_height );
449
450
451
452
                }
                if( fmt->video.i_visible_width > 0 &&
                    fmt->video.i_visible_height > 0 )
                {
Sam Hocevar's avatar
Sam Hocevar committed
453
                    input_AddInfo( p_cat, _("Display resolution"), "%dx%d",
454
455
                                   fmt->video.i_visible_width,
                                   fmt->video.i_visible_height);
zorglub's avatar
zorglub committed
456
457
458
459
                     playlist_AddInfo( p_playlist, -1, psz_cat,
                                       _("Display resolution"), "%dx%d",
                                       fmt->video.i_visible_width,
                                       fmt->video.i_visible_height);
460
461
462
463
                }
                break;
            case SPU_ES:
                input_AddInfo( p_cat, _("Type"), _("Subtitle") );
zorglub's avatar
zorglub committed
464
465
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                   _("Type"), _("Subtitle") );
466
467
                input_AddInfo( p_cat, _("Codec"), "%.4s",
                               (char*)&fmt->i_codec );
zorglub's avatar
zorglub committed
468
469
470
                playlist_AddInfo( p_playlist, -1, psz_cat,
                                 _("Codec"), "%.4s",
                                 (char*)&fmt->i_codec );
471
472
473
474
475
                break;
            default:

                break;
        }
zorglub's avatar
zorglub committed
476
        if( p_playlist ) vlc_object_release( p_playlist );
477
478
    }

479
480
481
    /* Apply mode
     * XXX change that when we do group too */
    if( 1 )
482
    {
483
        EsOutSelect( out, es, VLC_FALSE );
484
    }
485
486
487
488
489
490
491
492

    vlc_mutex_unlock( &p_input->stream.stream_lock );

    es->p_es->fmt = *fmt;

    TAB_APPEND( out->p_sys->i_es, out->p_sys->es, es );
    p_sys->i_id++;  /* always incremented */
    switch( fmt->i_cat )
493
    {
494
495
496
497
498
499
500
501
502
        case AUDIO_ES:
            p_sys->i_audio++;
            break;
        case SPU_ES:
            p_sys->i_sub++;
            break;
        case VIDEO_ES:
            p_sys->i_video++;
            break;
503
    }
504
505

    return es;
506
507
508
}

/*****************************************************************************
509
 * EsOutSend:
510
 *****************************************************************************/
511
static int EsOutSend( es_out_t *out, es_out_id_t *es, block_t *p_block )
512
{
513
514
    es_out_sys_t *p_sys = out->p_sys;

515
    if( p_sys->b_pcr_set )
516
    {
517
518
519
520
521
522
523
        pgrm_descriptor_t *p_pgrm = es->p_es->p_pgrm;
        input_thread_t    *p_input = p_sys->p_input;

        if( p_pgrm == NULL )
        {
            p_pgrm = p_sys->p_input->stream.p_selected_program;
        }
524

525
        if( p_block->i_dts > 0 && p_pgrm )
526
        {
gbazin's avatar
   
gbazin committed
527
            p_block->i_dts =
528
                input_ClockGetTS( p_input, p_pgrm, p_block->i_dts * 9 / 100 );
529
        }
530
        if( p_block->i_pts > 0 && p_pgrm )
531
        {
gbazin's avatar
   
gbazin committed
532
            p_block->i_pts =
533
                input_ClockGetTS( p_input, p_pgrm, p_block->i_pts * 9 / 100 );
534
535
        }
    }
gbazin's avatar
   
gbazin committed
536

537
    vlc_mutex_lock( &out->p_sys->p_input->stream.stream_lock );
gbazin's avatar
   
gbazin committed
538
539
540
    p_block->i_rate = out->p_sys->p_input->stream.control.i_rate;
    if( es->p_es->p_dec &&
        (es->p_es->i_cat!=AUDIO_ES || !p_sys->p_input->stream.control.b_mute) )
541
    {
542
        input_DecodeBlock( es->p_es->p_dec, p_block );
543
544
545
    }
    else
    {
546
        block_Release( p_block );
547
    }
548
    vlc_mutex_unlock( &out->p_sys->p_input->stream.stream_lock );
gbazin's avatar
   
gbazin committed
549

550
551
552
553
554
555
    return VLC_SUCCESS;
}

/*****************************************************************************
 * EsOutDel:
 *****************************************************************************/
556
static void EsOutDel( es_out_t *out, es_out_id_t *es )
557
558
559
{
    es_out_sys_t *p_sys = out->p_sys;

560
561
562
563
564
565
566
567
568
569
570
571
572
573
    TAB_REMOVE( p_sys->i_es, p_sys->es, es );

    switch( es->p_es->i_cat )
    {
        case AUDIO_ES:
            p_sys->i_audio--;
            break;
        case SPU_ES:
            p_sys->i_sub--;
            break;
        case VIDEO_ES:
            p_sys->i_video--;
            break;
    }
574

575
    /* We don't try to reselect */
576
    vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
577
    if( es->p_es->p_dec )
578
    {
579
        input_UnselectES( p_sys->p_input, es->p_es );
580
    }
581
582

    if( es->p_es->p_waveformatex )
583
    {
584
585
        free( es->p_es->p_waveformatex );
        es->p_es->p_waveformatex = NULL;
586
    }
587
    if( es->p_es->p_bitmapinfoheader )
588
    {
589
590
        free( es->p_es->p_bitmapinfoheader );
        es->p_es->p_bitmapinfoheader = NULL;
591
    }
592
593
    input_DelES( p_sys->p_input, es->p_es );

gbazin's avatar
   
gbazin committed
594
595
596
597
    if( p_sys->p_es_audio == es ) p_sys->p_es_audio = NULL;
    if( p_sys->p_es_video == es ) p_sys->p_es_video = NULL;
    if( p_sys->p_es_sub   == es ) p_sys->p_es_sub   = NULL;

598
599
    vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );

600
    free( es );
601
602
603
604
605
606
607
608
609
}

/*****************************************************************************
 * EsOutControl:
 *****************************************************************************/
static int EsOutControl( es_out_t *out, int i_query, va_list args )
{
    es_out_sys_t *p_sys = out->p_sys;
    vlc_bool_t  b, *pb;
610
611
612
613
    int         i, *pi;

    es_out_id_t *es;

614
615
    switch( i_query )
    {
616
        case ES_OUT_SET_ES_STATE:
617
            vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
618
            es = (es_out_id_t*) va_arg( args, es_out_id_t * );
619
            b = (vlc_bool_t) va_arg( args, vlc_bool_t );
620
            if( b && es->p_es->p_dec == NULL )
621
            {
622
                input_SelectES( p_sys->p_input, es->p_es );
623
                vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
624
                return es->p_es->p_dec ? VLC_SUCCESS : VLC_EGENERIC;
625
            }
626
            else if( !b && es->p_es->p_dec )
627
            {
628
                input_UnselectES( p_sys->p_input, es->p_es );
629
630
631
                vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
                return VLC_SUCCESS;
            }
Laurent Aimar's avatar
Laurent Aimar committed
632
633
634
            vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
            return VLC_SUCCESS;

635
636
        case ES_OUT_GET_ES_STATE:
            es = (es_out_id_t*) va_arg( args, es_out_id_t * );
637
638
            pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );

639
640
641
642
            *pb = es->p_es->p_dec ? VLC_TRUE : VLC_FALSE;
            return VLC_SUCCESS;

        case ES_OUT_SET_ACTIVE:
643
        {
644
645
            b = (vlc_bool_t) va_arg( args, vlc_bool_t );
            p_sys->b_active = b;
646
647
648
649
650
651
652

            if( b )
            {
                vlc_value_t val;
                val.b_bool = VLC_TRUE;
                var_Set( p_sys->p_input, "intf-change", val );
            }
653
            return VLC_SUCCESS;
654
        }
655
656
657
658
659
660
661
662

        case ES_OUT_GET_ACTIVE:
            pb = (vlc_bool_t*) va_arg( args, vlc_bool_t * );
            *pb = p_sys->b_active;
            return VLC_SUCCESS;

        case ES_OUT_SET_MODE:
            i = (int) va_arg( args, int );
gbazin's avatar
   
gbazin committed
663
664
            if( i == ES_OUT_MODE_NONE || i == ES_OUT_MODE_ALL ||
                i == ES_OUT_MODE_AUTO )
665
            {
666
667
                vlc_value_t val;

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
                p_sys->i_mode = i;

                /* Reapply policy mode */
                vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
                for( i = 0; i < p_sys->i_es; i++ )
                {
                    if( p_sys->es[i]->p_es->p_dec )
                    {
                        input_UnselectES( p_sys->p_input, p_sys->es[i]->p_es );
                    }
                }
                for( i = 0; i < p_sys->i_es; i++ )
                {
                    EsOutSelect( out, p_sys->es[i], VLC_FALSE );
                }
                vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
684
685
686
687

                val.b_bool = VLC_TRUE;
                var_Set( p_sys->p_input, "intf-change", val );

688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
                return VLC_SUCCESS;
            }
            return VLC_EGENERIC;

        case ES_OUT_GET_MODE:
            pi = (int*) va_arg( args, int* );
            *pi = p_sys->i_mode;
            return VLC_SUCCESS;

        case ES_OUT_SET_ES:
            es = (es_out_id_t*) va_arg( args, es_out_id_t * );
            if( es == NULL )
            {
                for( i = 0; i < p_sys->i_es; i++ )
                {
                    vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
                    if( p_sys->es[i]->p_es->p_dec )
                    {
                        input_UnselectES( p_sys->p_input, p_sys->es[i]->p_es );
                    }
                    vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
                }
            }
            else
            {
                vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
                EsOutSelect( out, es, VLC_TRUE );
                vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
            }
717
718
            return VLC_SUCCESS;

719
        case ES_OUT_SET_PCR:
720
        case ES_OUT_SET_GROUP_PCR:
721
722
        {
            pgrm_descriptor_t *p_prgm = NULL;
723
            int64_t           i_pcr;
724

725
726
727
728
729
730
731
732
733
            if( i_query == ES_OUT_SET_PCR )
            {
                p_prgm = p_sys->p_input->stream.p_selected_program;
            }
            else
            {
                int i_group = (int)va_arg( args, int );
                p_prgm = input_FindProgram( p_sys->p_input, i_group );
            }
734
735
736
            i_pcr   = (int64_t)va_arg( args, int64_t );

            /* search program */
737
            if( p_prgm )
738
            {
739
                input_ClockManageRef( p_sys->p_input, p_prgm, i_pcr * 9 / 100);
740
741
742
743
744
745
            }
            p_sys->b_pcr_set = VLC_TRUE;
            return VLC_SUCCESS;
        }

        case ES_OUT_RESET_PCR:
746
            for( i = 0; i < p_sys->p_input->stream.i_pgrm_number; i++ )
747
            {
748
                p_sys->p_input->stream.pp_programs[i]->i_synchro_state = SYNCHRO_REINIT;
749
750
751
752
            }
            p_sys->b_pcr_set = VLC_TRUE;
            return VLC_SUCCESS;

753
754
755
756
757
        default:
            msg_Err( p_sys->p_input, "unknown query in es_out_Control" );
            return VLC_EGENERIC;
    }
}