decoder.c 59.8 KB
Newer Older
1
/*****************************************************************************
Laurent Aimar's avatar
Laurent Aimar committed
2
 * decoder.c: Functions for the management of decoders
3
 *****************************************************************************
4
 * Copyright (C) 1999-2004 the VideoLAN team
5
 * $Id$
6
7
 *
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8
 *          Gildas Bazin <gbazin@videolan.org>
Laurent Aimar's avatar
Laurent Aimar committed
9
 *          Laurent Aimar <fenrir@via.ecp.fr>
10
11
12
13
14
 *
 * 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.
15
 *
16
17
18
19
20
21
22
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
25
26
27
28
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
29
30
31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
32
#include <assert.h>
33

34
#include <vlc_common.h>
Laurent Aimar's avatar
Laurent Aimar committed
35

zorglub's avatar
zorglub committed
36
37
38
39
40
41
42
43
44
45
#include <vlc_block.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include <vlc_codec.h>
#include <vlc_osd.h>

#include <vlc_interface.h>
#include "audio_output/aout_internal.h"
#include "stream_output/stream_output.h"
Laurent Aimar's avatar
Laurent Aimar committed
46
#include "input_internal.h"
47
#include "input_clock.h"
48
#include "input_decoder.h"
49

Laurent Aimar's avatar
Laurent Aimar committed
50
51
#include "../video_output/vout_internal.h"

52
53
static decoder_t *CreateDecoder( input_thread_t *, es_format_t *, int, sout_instance_t *p_sout );
static void       DeleteDecoder( decoder_t * );
54

55
static void      *DecoderThread( vlc_object_t * );
56
static int        DecoderProcess( decoder_t * p_dec, block_t *p_block );
Laurent Aimar's avatar
Laurent Aimar committed
57
static void       DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date );
Sam Hocevar's avatar
   
Sam Hocevar committed
58

gbazin's avatar
   
gbazin committed
59
60
61
62
63
64
/* Buffers allocation callbacks for the decoders */
static aout_buffer_t *aout_new_buffer( decoder_t *, int );
static void aout_del_buffer( decoder_t *, aout_buffer_t * );

static picture_t *vout_new_buffer( decoder_t * );
static void vout_del_buffer( decoder_t *, picture_t * );
gbazin's avatar
   
gbazin committed
65
66
static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * );
gbazin's avatar
   
gbazin committed
67

68
69
70
static subpicture_t *spu_new_buffer( decoder_t * );
static void spu_del_buffer( decoder_t *, subpicture_t * );

71
static es_format_t null_es_format;
gbazin's avatar
   
gbazin committed
72

73
74
struct decoder_owner_sys_t
{
75
    bool      b_own_thread;
76

Laurent Aimar's avatar
Laurent Aimar committed
77
78
    int64_t         i_preroll_end;

79
    input_thread_t  *p_input;
80
    input_clock_t   *p_clock;
81
    int             i_last_rate;
82

83
84
    vout_thread_t   *p_spu_vout;
    int              i_spu_channel;
85
    int64_t          i_spu_order;
86

87
88
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
89

90
91
92
    /* Some decoders require already packetized data (ie. not truncated) */
    decoder_t *p_packetizer;

93
94
95
96
97
98
99
    /* Current format in use by the output */
    video_format_t video;
    audio_format_t audio;
    es_format_t    sout;

    /* fifo */
    block_fifo_t *p_fifo;
100

101
102
103
104
    /* Lock for communication with decoder thread */
    vlc_mutex_t lock;
    vlc_cond_t  wait;

Laurent Aimar's avatar
Laurent Aimar committed
105
106
107
108
109
110
111
    /* -- These variables need locking on write(only) -- */
    aout_instance_t *p_aout;
    aout_input_t    *p_aout_input;

    vout_thread_t   *p_vout;

    /* -- Theses variables need locking on read *and* write -- */
112
    /* */
Laurent Aimar's avatar
Laurent Aimar committed
113
    /* Pause */
114
115
    bool b_paused;
    mtime_t i_pause_date;
116

117
    /* CC */
118
119
120
121
122
123
    struct
    {
        bool b_supported;
        bool pb_present[4];
        decoder_t *pp_decoder[4];
    } cc;
124
125
126

    /* Delay */
    mtime_t i_ts_delay;
127
128
};

129
130
131
132
133
134
/* */
static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
{
    msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
             "VLC probably does not support this sound or video format.",
             (char*)&codec );
135
    intf_UserFatal( p_dec, false, _("No suitable decoder module"), 
136
137
                    _("VLC does not support the audio or video format \"%4.4s\". "
                      "Unfortunately there is no way for you to fix this."), (char*)&codec );
138
139
}

140
141
/* decoder_GetInputAttachment:
 */
Laurent Aimar's avatar
Laurent Aimar committed
142
143
input_attachment_t *decoder_GetInputAttachment( decoder_t *p_dec,
                                                const char *psz_name )
144
145
146
147
148
149
{
    input_attachment_t *p_attachment;
    if( input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENT, &p_attachment, psz_name ) )
        return NULL;
    return p_attachment;
}
Laurent Aimar's avatar
Laurent Aimar committed
150
151
152
153
154
155
156
157
158
/* decoder_GetInputAttachments:
 */
int decoder_GetInputAttachments( decoder_t *p_dec,
                                 input_attachment_t ***ppp_attachment,
                                 int *pi_attachment )
{
    return input_Control( p_dec->p_owner->p_input, INPUT_GET_ATTACHMENTS,
                          ppp_attachment, pi_attachment );
}
159
160
161
162
/* decoder_GetDisplayDate:
 */
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
163
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
164

Laurent Aimar's avatar
Laurent Aimar committed
165
166
    if( !p_owner->p_clock )
        return i_ts;
167
    return input_clock_GetTS( p_owner->p_clock, NULL, p_owner->p_input->i_pts_delay, i_ts );
168
169
170
171
172
}
/* decoder_GetDisplayRate:
 */
int decoder_GetDisplayRate( decoder_t *p_dec )
{
173
174
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Laurent Aimar's avatar
Laurent Aimar committed
175
176
    if( !p_owner->p_clock )
        return INPUT_RATE_DEFAULT;
177
    return input_clock_GetRate( p_owner->p_clock );
178
}
179

zorglub's avatar
zorglub committed
180
181
182
183
184
185
186
/**
 * Spawns a new decoder thread
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
 * \return the spawned decoder object
 */
Laurent Aimar's avatar
Laurent Aimar committed
187
decoder_t *input_DecoderNew( input_thread_t *p_input,
188
                             es_format_t *fmt, input_clock_t *p_clock, sout_instance_t *p_sout  )
189
{
190
191
    decoder_t   *p_dec = NULL;
    vlc_value_t val;
192

193
194
195
#ifndef ENABLE_SOUT
    (void)b_force_decoder;
#else
196
    /* If we are in sout mode, search for packetizer module */
197
    if( p_sout )
198
    {
199
        /* Create the decoder configuration structure */
200
        p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_PACKETIZER, p_sout );
201
        if( p_dec == NULL )
gbazin's avatar
   
gbazin committed
202
        {
203
            msg_Err( p_input, "could not create packetizer" );
204
            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
205
                            _("VLC could not open the packetizer module.") );
206
            return NULL;
gbazin's avatar
   
gbazin committed
207
        }
208
    }
209
    else
210
#endif
211
    {
gbazin's avatar
   
gbazin committed
212
        /* Create the decoder configuration structure */
213
        p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_DECODER, p_sout );
gbazin's avatar
   
gbazin committed
214
215
216
        if( p_dec == NULL )
        {
            msg_Err( p_input, "could not create decoder" );
217
            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
218
                            _("VLC could not open the decoder module.") );
gbazin's avatar
   
gbazin committed
219
220
            return NULL;
        }
221
222
    }

223
    if( !p_dec->p_module )
Sam Hocevar's avatar
   
Sam Hocevar committed
224
    {
225
        DecoderUnsupportedCodec( p_dec, fmt->i_codec );
gbazin's avatar
   
gbazin committed
226
227

        DeleteDecoder( p_dec );
228
        vlc_object_release( p_dec );
229
        return NULL;
Henri Fallon's avatar
   
Henri Fallon committed
230
231
    }

232
233
    p_dec->p_owner->p_clock = p_clock;

234
    if( p_sout && p_sout == p_input->p->p_sout && p_input->p->input.b_can_pace_control )
235
236
    {
        msg_Dbg( p_input, "stream out mode -> no decoder thread" );
237
        p_dec->p_owner->b_own_thread = false;
238
239
240
241
242
243
    }
    else
    {
        var_Get( p_input, "minimize-threads", &val );
        p_dec->p_owner->b_own_thread = !val.b_bool;
    }
244

245
    if( p_dec->p_owner->b_own_thread )
Henri Fallon's avatar
   
Henri Fallon committed
246
    {
247
        int i_priority;
Laurent Aimar's avatar
Laurent Aimar committed
248
        if( fmt->i_cat == AUDIO_ES )
249
250
251
252
253
254
            i_priority = VLC_THREAD_PRIORITY_AUDIO;
        else
            i_priority = VLC_THREAD_PRIORITY_VIDEO;

        /* Spawn the decoder thread */
        if( vlc_thread_create( p_dec, "decoder", DecoderThread,
255
                               i_priority, false ) )
256
        {
257
            msg_Err( p_dec, "cannot spawn decoder thread" );
258
            module_unneed( p_dec, p_dec->p_module );
259
            DeleteDecoder( p_dec );
260
            vlc_object_release( p_dec );
261
262
            return NULL;
        }
Henri Fallon's avatar
   
Henri Fallon committed
263
264
    }

265
    return p_dec;
266
267
}

zorglub's avatar
zorglub committed
268
269
270
271
272
273
274
/**
 * Kills a decoder thread and waits until it's finished
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
 * \return nothing
 */
Laurent Aimar's avatar
Laurent Aimar committed
275
void input_DecoderDelete( decoder_t *p_dec )
276
{
277
278
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

279
    vlc_object_kill( p_dec );
280

281
    if( p_owner->b_own_thread )
282
    {
283
284
285
286
287
288
289
290
291
        /* Make sure we aren't paused anymore */
        vlc_mutex_lock( &p_owner->lock );
        if( p_owner->b_paused )
        {
            p_owner->b_paused = false;
            vlc_cond_signal( &p_owner->wait );
        }
        vlc_mutex_unlock( &p_owner->lock );

292
293
294
        /* Make sure the thread leaves the function by
         * sending it an empty block. */
        block_t *p_block = block_New( p_dec, 0 );
Laurent Aimar's avatar
Laurent Aimar committed
295
        input_DecoderDecode( p_dec, p_block );
296

297
        vlc_thread_join( p_dec );
298

299
        /* Don't module_unneed() here because of the dll loader that wants
300
         * close() in the same thread than open()/decode() */
301
302
303
    }
    else
    {
304
305
306
        /* Flush */
        input_DecoderDecode( p_dec, NULL );

307
        module_unneed( p_dec, p_dec->p_module );
308
    }
309

310
    /* */
311
    if( p_dec->p_owner->cc.b_supported )
312
313
314
    {
        int i;
        for( i = 0; i < 4; i++ )
315
            input_DecoderSetCcState( p_dec, false, i );
316
317
    }

gbazin's avatar
   
gbazin committed
318
319
320
321
    /* Delete decoder configuration */
    DeleteDecoder( p_dec );

    /* Delete the decoder */
322
    vlc_object_release( p_dec );
323
}
zorglub's avatar
zorglub committed
324
325

/**
326
 * Put a block_t in the decoder's fifo.
zorglub's avatar
zorglub committed
327
328
329
330
 *
 * \param p_dec the decoder object
 * \param p_block the data block
 */
Laurent Aimar's avatar
Laurent Aimar committed
331
void input_DecoderDecode( decoder_t * p_dec, block_t *p_block )
332
{
333
334
335
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    if( p_owner->b_own_thread )
336
    {
337
        if( p_owner->p_input->p->b_out_pace_control )
338
339
        {
            /* FIXME !!!!! */
340
            while( !p_dec->b_die && !p_dec->b_error &&
341
                   block_FifoCount( p_owner->p_fifo ) > 10 )
342
343
344
345
            {
                msleep( 1000 );
            }
        }
346
        else if( block_FifoSize( p_owner->p_fifo ) > 50000000 /* 50 MB */ )
347
348
349
350
        {
            /* FIXME: ideally we would check the time amount of data
             * in the fifo instead of its size. */
            msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
trax's avatar
trax committed
351
                      "consumed quickly enough), resetting fifo!" );
352
            block_FifoEmpty( p_owner->p_fifo );
353
354
        }

355
        block_FifoPut( p_owner->p_fifo, p_block );
356
357
358
    }
    else
    {
359
        if( p_dec->b_error || ( p_block && p_block->i_buffer <= 0 ) )
360
        {
361
362
            if( p_block )
                block_Release( p_block );
363
364
365
        }
        else
        {
366
            DecoderProcess( p_dec, p_block );
367
368
        }
    }
369
}
370

371
bool input_DecoderIsEmpty( decoder_t * p_dec )
Laurent Aimar's avatar
   
Laurent Aimar committed
372
{
373
374
    if( p_dec->p_owner->b_own_thread &&
        block_FifoCount( p_dec->p_owner->p_fifo ) > 0 )
Laurent Aimar's avatar
   
Laurent Aimar committed
375
    {
376
        return false;
Laurent Aimar's avatar
   
Laurent Aimar committed
377
    }
378
    return true;
Laurent Aimar's avatar
   
Laurent Aimar committed
379
380
}

381
void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
382
{
383
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
384
385
    int i;

386
    vlc_mutex_lock( &p_owner->lock );
387
    for( i = 0; i < 4; i++ )
388
        pb_present[i] =  p_owner->cc.pb_present[i];
389
    vlc_mutex_unlock( &p_owner->lock );
390
}
391
int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel )
392
393
394
395
396
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    //msg_Warn( p_dec, "input_DecoderSetCcState: %d @%d", b_decode, i_channel );

397
    if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
398
399
400
401
402
403
404
405
406
407
408
409
410
411
        return VLC_EGENERIC;

    if( b_decode )
    {
        static const vlc_fourcc_t fcc[4] = {
            VLC_FOURCC('c', 'c', '1', ' '),
            VLC_FOURCC('c', 'c', '2', ' '),
            VLC_FOURCC('c', 'c', '3', ' '),
            VLC_FOURCC('c', 'c', '4', ' '),
        };
        decoder_t *p_cc;
        es_format_t fmt;

        es_format_Init( &fmt, SPU_ES, fcc[i_channel] );
412
        p_cc = CreateDecoder( p_owner->p_input, &fmt, VLC_OBJECT_DECODER, p_owner->p_sout );
413
414
415
        if( !p_cc )
        {
            msg_Err( p_dec, "could not create decoder" );
416
            intf_UserFatal( p_dec, false, _("Streaming / Transcoding failed"),
417
418
419
420
421
422
423
                            _("VLC could not open the decoder module.") );
            return VLC_EGENERIC;
        }
        else if( !p_cc->p_module )
        {
            DecoderUnsupportedCodec( p_dec, fcc[i_channel] );
            DeleteDecoder( p_cc );
424
            vlc_object_release( p_cc );
425
426
            return VLC_EGENERIC;
        }
427
        p_cc->p_owner->p_clock = p_owner->p_clock;
428

429
        vlc_mutex_lock( &p_owner->lock );
430
        p_owner->cc.pp_decoder[i_channel] = p_cc;
431
        vlc_mutex_unlock( &p_owner->lock );
432
433
434
435
436
    }
    else
    {
        decoder_t *p_cc;

437
        vlc_mutex_lock( &p_owner->lock );
438
439
        p_cc = p_owner->cc.pp_decoder[i_channel];
        p_owner->cc.pp_decoder[i_channel] = NULL;
440
        vlc_mutex_unlock( &p_owner->lock );
441
442
443
444

        if( p_cc )
        {
            vlc_object_kill( p_cc );
445
            module_unneed( p_cc, p_cc->p_module );
446
            DeleteDecoder( p_cc );
447
            vlc_object_release( p_cc );
448
449
450
451
        }
    }
    return VLC_SUCCESS;
}
452
int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel )
453
454
455
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

456
    *pb_decode = false;
457
    if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
458
459
        return VLC_EGENERIC;

460
    vlc_mutex_lock( &p_owner->lock );
461
    *pb_decode = p_owner->cc.pp_decoder[i_channel] != NULL;
462
    vlc_mutex_unlock( &p_owner->lock );
463
464
465
    return VLC_EGENERIC;
}

466
467
468
469
470
471
void input_DecoderChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

472
    assert( !p_owner->b_paused || !b_paused );
473
474
    p_owner->b_paused = b_paused;
    p_owner->i_pause_date = i_date;
Laurent Aimar's avatar
Laurent Aimar committed
475
476
    if( p_owner->b_own_thread )
        vlc_cond_signal( &p_owner->wait );
477

Laurent Aimar's avatar
Laurent Aimar committed
478
    DecoderOutputChangePause( p_dec, b_paused, i_date );
479
480
    vlc_mutex_unlock( &p_owner->lock );
}
481
482
483
484
485
486
487
488
489

void input_DecoderChangeDelay( decoder_t *p_dec, mtime_t i_delay )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    p_owner->i_ts_delay = i_delay;
    vlc_mutex_unlock( &p_owner->lock );
}
490
491
492
493
494
495
496
497
498
499
500
501
502

void input_DecoderFlush( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    block_t *p_null;

    /* Empty the fifo */
    if( p_owner->b_own_thread )
        block_FifoEmpty( p_owner->p_fifo );

    /* Send a special block */
    p_null = block_New( p_dec, 128 );
    p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
503
504
    p_null->i_flags |= BLOCK_FLAG_CORE_FLUSH;
    if( !p_dec->fmt_in.b_packetized )
505
506
507
508
509
510
        p_null->i_flags |= BLOCK_FLAG_CORRUPTED;
    memset( p_null->p_buffer, 0, p_null->i_buffer );

    input_DecoderDecode( p_dec, p_null );
}

zorglub's avatar
zorglub committed
511
512
513
514
515
516
517
518
/**
 * Create a decoder object
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
 * \param i_object_type Object type as define in include/vlc_objects.h
 * \return the decoder object
 */
Laurent Aimar's avatar
Laurent Aimar committed
519
static decoder_t * CreateDecoder( input_thread_t *p_input,
520
                                  es_format_t *fmt, int i_object_type, sout_instance_t *p_sout )
Sam Hocevar's avatar
   
Sam Hocevar committed
521
{
gbazin's avatar
   
gbazin committed
522
    decoder_t *p_dec;
523
524
    decoder_owner_sys_t *p_owner;
    int i;
Sam Hocevar's avatar
   
Sam Hocevar committed
525

gbazin's avatar
   
gbazin committed
526
    p_dec = vlc_object_create( p_input, i_object_type );
gbazin's avatar
   
gbazin committed
527
    if( p_dec == NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
528
529
        return NULL;

530
531
532
533
534
    p_dec->pf_decode_audio = NULL;
    p_dec->pf_decode_video = NULL;
    p_dec->pf_decode_sub = NULL;
    p_dec->pf_get_cc = NULL;
    p_dec->pf_packetize = NULL;
gbazin's avatar
   
gbazin committed
535

536
    /* Initialize the decoder fifo */
gbazin's avatar
   
gbazin committed
537
538
    p_dec->p_module = NULL;

539
    memset( &null_es_format, 0, sizeof(es_format_t) );
Laurent Aimar's avatar
Laurent Aimar committed
540
541
    es_format_Copy( &p_dec->fmt_in, fmt );
    es_format_Copy( &p_dec->fmt_out, &null_es_format );
gbazin's avatar
   
gbazin committed
542
543

    /* Allocate our private structure for the decoder */
544
    p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
gbazin's avatar
   
gbazin committed
545
    if( p_dec->p_owner == NULL )
546
547
    {
        vlc_object_release( p_dec );
gbazin's avatar
   
gbazin committed
548
        return NULL;
549
    }
550
    p_dec->p_owner->b_own_thread = true;
Laurent Aimar's avatar
Laurent Aimar committed
551
    p_dec->p_owner->i_preroll_end = -1;
552
    p_dec->p_owner->i_last_rate = INPUT_RATE_DEFAULT;
553
    p_dec->p_owner->p_input = p_input;
gbazin's avatar
   
gbazin committed
554
555
556
    p_dec->p_owner->p_aout = NULL;
    p_dec->p_owner->p_aout_input = NULL;
    p_dec->p_owner->p_vout = NULL;
557
558
    p_dec->p_owner->p_spu_vout = NULL;
    p_dec->p_owner->i_spu_channel = 0;
559
    p_dec->p_owner->i_spu_order = 0;
560
    p_dec->p_owner->p_sout = p_sout;
561
    p_dec->p_owner->p_sout_input = NULL;
562
    p_dec->p_owner->p_packetizer = NULL;
563

564
    /* decoder fifo */
565
    if( ( p_dec->p_owner->p_fifo = block_FifoNew() ) == NULL )
566
567
568
    {
        free( p_dec->p_owner );
        vlc_object_release( p_dec );
569
        return NULL;
570
    }
571

gbazin's avatar
   
gbazin committed
572
573
574
575
576
    /* Set buffers allocation callbacks for the decoders */
    p_dec->pf_aout_buffer_new = aout_new_buffer;
    p_dec->pf_aout_buffer_del = aout_del_buffer;
    p_dec->pf_vout_buffer_new = vout_new_buffer;
    p_dec->pf_vout_buffer_del = vout_del_buffer;
gbazin's avatar
   
gbazin committed
577
578
    p_dec->pf_picture_link    = vout_link_picture;
    p_dec->pf_picture_unlink  = vout_unlink_picture;
579
580
    p_dec->pf_spu_buffer_new  = spu_new_buffer;
    p_dec->pf_spu_buffer_del  = spu_del_buffer;
gbazin's avatar
   
gbazin committed
581

gbazin's avatar
   
gbazin committed
582
583
    vlc_object_attach( p_dec, p_input );

584
585
    /* Find a suitable decoder/packetizer module */
    if( i_object_type == VLC_OBJECT_DECODER )
586
        p_dec->p_module = module_need( p_dec, "decoder", "$codec", 0 );
587
    else
588
        p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", 0 );
589
590
591
592
593
594
595
596
597
598
599
600

    /* Check if decoder requires already packetized data */
    if( i_object_type == VLC_OBJECT_DECODER &&
        p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
    {
        p_dec->p_owner->p_packetizer =
            vlc_object_create( p_input, VLC_OBJECT_PACKETIZER );
        if( p_dec->p_owner->p_packetizer )
        {
            es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_in,
                            &p_dec->fmt_in );

Laurent Aimar's avatar
Laurent Aimar committed
601
602
603
            es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_out,
                            &null_es_format );

604
605
606
            vlc_object_attach( p_dec->p_owner->p_packetizer, p_input );

            p_dec->p_owner->p_packetizer->p_module =
607
                module_need( p_dec->p_owner->p_packetizer,
608
609
610
611
612
613
                             "packetizer", "$packetizer", 0 );

            if( !p_dec->p_owner->p_packetizer->p_module )
            {
                es_format_Clean( &p_dec->p_owner->p_packetizer->fmt_in );
                vlc_object_detach( p_dec->p_owner->p_packetizer );
614
                vlc_object_release( p_dec->p_owner->p_packetizer );
615
616
617
618
            }
        }
    }

619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
    /* Copy ourself the input replay gain */
    if( fmt->i_cat == AUDIO_ES )
    {
        for( i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
        {
            if( !p_dec->fmt_out.audio_replay_gain.pb_peak[i] )
            {
                p_dec->fmt_out.audio_replay_gain.pb_peak[i] = fmt->audio_replay_gain.pb_peak[i];
                p_dec->fmt_out.audio_replay_gain.pf_peak[i] = fmt->audio_replay_gain.pf_peak[i];
            }
            if( !p_dec->fmt_out.audio_replay_gain.pb_gain[i] )
            {
                p_dec->fmt_out.audio_replay_gain.pb_gain[i] = fmt->audio_replay_gain.pb_gain[i];
                p_dec->fmt_out.audio_replay_gain.pf_gain[i] = fmt->audio_replay_gain.pf_gain[i];
            }
        }
    }
636
    /* */
637
    p_owner->cc.b_supported = false;
638
639
640
    if( i_object_type == VLC_OBJECT_DECODER )
    {
        if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
641
            p_owner->cc.b_supported = true;
642
        if( p_dec->pf_get_cc )
643
            p_owner->cc.b_supported = true;
644
645
    }

646
647
648
649
    vlc_mutex_init( &p_owner->lock );
    vlc_cond_init( &p_owner->wait );
    p_owner->b_paused = false;
    p_owner->i_pause_date = 0;
650
651
    for( i = 0; i < 4; i++ )
    {
652
653
        p_owner->cc.pb_present[i] = false;
        p_owner->cc.pp_decoder[i] = NULL;
654
    }
655
    p_owner->i_ts_delay = 0;
gbazin's avatar
   
gbazin committed
656
657
658
    return p_dec;
}

zorglub's avatar
zorglub committed
659
660
661
662
663
/**
 * The decoding main loop
 *
 * \param p_dec the decoder
 */
664
static void *DecoderThread( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
665
{
666
667
668
    decoder_t *p_dec = (decoder_t *)p_this;
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

669
    block_t *p_block;
670
    int canc = vlc_savecancel();
gbazin's avatar
   
gbazin committed
671
672

    /* The decoder's main loop */
673
    while( vlc_object_alive( p_dec ) && !p_dec->b_error )
gbazin's avatar
   
gbazin committed
674
    {
675
        if( ( p_block = block_FifoGet( p_owner->p_fifo ) ) == NULL )
gbazin's avatar
   
gbazin committed
676
        {
677
            p_dec->b_error = true;
gbazin's avatar
   
gbazin committed
678
679
            break;
        }
Laurent Aimar's avatar
Laurent Aimar committed
680

681
        if( DecoderProcess( p_dec, p_block ) != VLC_SUCCESS )
682
683
            break;
    }
gbazin's avatar
   
gbazin committed
684

685
    while( vlc_object_alive( p_dec ) )
686
687
    {
        /* Trash all received PES packets */
688
        p_block = block_FifoGet( p_owner->p_fifo );
689
690
        if( p_block )
            block_Release( p_block );
691
    }
gbazin's avatar
   
gbazin committed
692

693
694
    /* We do it here because of the dll loader that wants close() in the
     * same thread than open()/decode() */
695
    module_unneed( p_dec, p_dec->p_module );
696
    vlc_restorecancel( canc );
697
    return NULL;
698
}
gbazin's avatar
   
gbazin committed
699

Laurent Aimar's avatar
Laurent Aimar committed
700
701
702
703
704
705
706
707
708
709
710
711
static void DecoderWaitUnpause( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

    while( p_owner->b_paused )
        vlc_cond_wait( &p_owner->wait, &p_owner->lock );

    vlc_mutex_unlock( &p_owner->lock );
}

712
static void DecoderGetDelays( decoder_t *p_dec, mtime_t *pi_ts_delay, mtime_t *pi_es_delay )
713
714
715
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

716
717
    *pi_ts_delay = p_owner->p_input->i_pts_delay;

718
719
    vlc_mutex_lock( &p_owner->lock );

720
    *pi_es_delay = p_owner->i_ts_delay;
721
722
723
724

    vlc_mutex_unlock( &p_owner->lock );
}

Laurent Aimar's avatar
Laurent Aimar committed
725
726
727
728
static void DecoderOutputChangePause( decoder_t *p_dec, bool b_paused, mtime_t i_date )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Laurent Aimar's avatar
Laurent Aimar committed
729
730
    vlc_assert_locked( &p_owner->lock );

Laurent Aimar's avatar
Laurent Aimar committed
731
732
733
734
    /* XXX only audio and video output have to be paused.
     * - for sout it is useless
     * - for subs, it is done by the vout
     */
Laurent Aimar's avatar
Laurent Aimar committed
735
736
    if( p_dec->fmt_in.i_cat == AUDIO_ES )
    {
Laurent Aimar's avatar
Laurent Aimar committed
737
738
739
        if( p_owner->p_aout && p_owner->p_aout_input )
            aout_DecChangePause( p_owner->p_aout, p_owner->p_aout_input,
                                 b_paused, i_date );
Laurent Aimar's avatar
Laurent Aimar committed
740
741
742
743
744
745
746
    }
    else if( p_dec->fmt_in.i_cat == VIDEO_ES )
    {
        if( p_owner->p_vout )
            vout_ChangePause( p_owner->p_vout, b_paused, i_date );
    }
}
Laurent Aimar's avatar
Laurent Aimar committed
747
748
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
749
750
751
    if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
        *pi_preroll = INT64_MAX;
    else if( p->i_pts > 0 )
Laurent Aimar's avatar
Laurent Aimar committed
752
753
754
755
        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
    else if( p->i_dts > 0 )
        *pi_preroll = __MIN( *pi_preroll, p->i_dts );
}
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771

static mtime_t DecoderTeletextFixTs( mtime_t i_ts, mtime_t i_ts_delay )
{
    mtime_t current_date = mdate();

    /* FIXME I don't really like that, es_out SHOULD do it using the video pts */
    if( !i_ts || i_ts > current_date + 10000000 || i_ts < current_date )
    {
        /* ETSI EN 300 472 Annex A : do not take into account the PTS
         * for teletext streams. */
        return current_date + 400000 + i_ts_delay;
    }
    return i_ts;
}

static void DecoderSoutBufferFixTs( block_t *p_block,
772
773
                                    input_clock_t *p_clock,
                                    mtime_t i_ts_delay, mtime_t i_es_delay,
774
775
                                    bool b_teletext )
{
776
777
    assert( p_clock );

778
779
    if( !p_block->i_dts && !p_block->i_pts )
        p_block->i_rate = input_clock_GetRate( p_clock );
780
781

    if( p_block->i_dts > 0 )
782
        p_block->i_dts = input_clock_GetTS( p_clock, &p_block->i_rate,
783
                                            i_ts_delay, p_block->i_dts + i_es_delay);
784
785

    if( p_block->i_pts > 0 )
786
        p_block->i_pts = input_clock_GetTS( p_clock, &p_block->i_rate,
787
                                            i_ts_delay, p_block->i_pts + i_es_delay );
788
789
790
791
792
793
794
795

    if( p_block->i_length > 0 )
        p_block->i_length = ( p_block->i_length * p_block->i_rate +
                                INPUT_RATE_DEFAULT-1 ) / INPUT_RATE_DEFAULT;

    if( b_teletext )
        p_block->i_pts = DecoderTeletextFixTs( p_block->i_pts, i_ts_delay );
}
796
static void DecoderAoutBufferFixTs( aout_buffer_t *p_buffer, int *pi_rate,
797
798
                                    input_clock_t *p_clock,
                                    mtime_t i_ts_delay, mtime_t i_es_delay )
799
{
800
801
802
803
    /* sout display module does not set clock */
    if( !p_clock )
        return;

804
805
806
    if( !p_buffer->start_date && !p_buffer->end_date )
        *pi_rate = input_clock_GetRate( p_clock );

807
    if( p_buffer->start_date > 0 )
808
809
810
        p_buffer->start_date =
            input_clock_GetTS( p_clock, pi_rate,
                               i_ts_delay, p_buffer->start_date + i_es_delay );
811

812
    if( p_buffer->end_date > 0 )
813
814
815
        p_buffer->end_date =
            input_clock_GetTS( p_clock, pi_rate,
                               i_ts_delay, p_buffer->end_date + i_es_delay );
816
}
817
818
819
static void DecoderVoutBufferFixTs( picture_t *p_picture, int *pi_rate,
                                    input_clock_t *p_clock,
                                    mtime_t i_ts_delay, mtime_t i_es_delay )
820
{
821
822
823
824
    /* sout display module does not set clock */
    if( !p_clock )
        return;

825
    if( p_picture->date > 0 )
826
827
828
        p_picture->date =
            input_clock_GetTS( p_clock, pi_rate,
                               i_ts_delay, p_picture->date + i_es_delay );
829
830
}
static void DecoderSpuBufferFixTs( subpicture_t *p_subpic,
831
832
                                   input_clock_t *p_clock,
                                   mtime_t i_ts_delay, mtime_t i_es_delay,
833
834
835
836
                                   bool b_teletext )
{
    bool b_ephemere = p_subpic->i_start == p_subpic->i_stop;

837
838
839
840
    /* sout display module does not set clock */
    if( !p_clock )
        return;

841
    if( p_subpic->i_start > 0 )
842
843
844
        p_subpic->i_start =
            input_clock_GetTS( p_clock, NULL,
                               i_ts_delay, p_subpic->i_start + i_es_delay );
845

846
    if( p_subpic->i_stop > 0 )
847
848
849
        p_subpic->i_stop =
            input_clock_GetTS( p_clock, NULL,
                               i_ts_delay, p_subpic->i_stop + i_es_delay );
850
851
852
853
854
855
856
857
858

    /* Do not create ephemere picture because of rounding errors */
    if( !b_ephemere && p_subpic->i_start == p_subpic->i_stop )
        p_subpic->i_stop++;

    if( b_teletext )
        p_subpic->i_start = DecoderTeletextFixTs( p_subpic->i_start, i_ts_delay );
}

Laurent Aimar's avatar
Laurent Aimar committed
859
860
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{
861
862
863
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    input_thread_t  *p_input = p_owner->p_input;
    input_clock_t   *p_clock = p_owner->p_clock;
864
    aout_buffer_t   *p_aout_buf;
865
866
867
    int i_decoded = 0;
    int i_lost = 0;
    int i_played = 0;
Laurent Aimar's avatar
Laurent Aimar committed
868
869
870

    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
    {
871
872
        aout_instance_t *p_aout = p_owner->p_aout;
        aout_input_t    *p_aout_input = p_owner->p_aout_input;
873
        int i_lost = 0;
874
        int i_played;
875

876
877
878
        if( p_dec->b_die )
        {
            /* It prevent freezing VLC in case of broken decoder */
879
            aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf );
880
881
882
883
            if( p_block )
                block_Release( p_block );
            break;
        }
884
        i_decoded++;
Laurent Aimar's avatar
Laurent Aimar committed
885

886
        if( p_aout_buf->start_date < p_owner->i_preroll_end )
Laurent Aimar's avatar
Laurent Aimar committed
887
        {
888
            aout_DecDeleteBuffer( p_aout, p_aout_input, p_aout_buf );
889
            continue;
Laurent Aimar's avatar
Laurent Aimar committed
890
        }
891

892
        if( p_owner->i_preroll_end > 0 )
Laurent Aimar's avatar
Laurent Aimar committed
893
        {
894
895
            /* FIXME TODO flush audio output (don't know how to do that) */
            msg_Dbg( p_dec, "End of audio preroll" );
896
            p_owner->i_preroll_end = -1;
Laurent Aimar's avatar
Laurent Aimar committed
897
        }
898

Laurent Aimar's avatar
Laurent Aimar committed
899
900
        DecoderWaitUnpause( p_dec );

901
        int i_rate = INPUT_RATE_DEFAULT;
902
903
904
        mtime_t i_ts_delay;
        mtime_t i_es_delay;
        DecoderGetDelays( p_dec, &i_ts_delay, &i_es_delay );
905

906
        DecoderAoutBufferFixTs( p_aout_buf, &i_rate, p_clock, i_ts_delay, i_es_delay );
907

908
        if( !p_clock && p_block && p_block->i_rate > 0 )
909
910
911
            i_rate = p_block->i_rate;

        /* FIXME TODO take care of audio-delay for mdate check */
912
913
        const mtime_t i_max_date = mdate() + i_ts_delay +
            i_es_delay * i_rate / INPUT_RATE_DEFAULT + AOUT_MAX_ADVANCE_TIME;
914
915
916
917

        if( p_aout_buf->start_date > 0 &&
            p_aout_buf->start_date <= i_max_date &&
            i_rate >= INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE &&
918
            i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
919
920
921
922
923
924
925
926
927