decoder.c 74 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
#include <vlc_block.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include <vlc_codec.h>
41
#include <vlc_spu.h>
Laurent Aimar's avatar
Laurent Aimar committed
42
#include <vlc_meta.h>
43
#include <vlc_dialog.h>
44
#include <vlc_modules.h>
zorglub's avatar
zorglub committed
45
46
47

#include "audio_output/aout_internal.h"
#include "stream_output/stream_output.h"
Laurent Aimar's avatar
Laurent Aimar committed
48
#include "input_internal.h"
49
50
#include "clock.h"
#include "decoder.h"
Christophe Mutricy's avatar
Christophe Mutricy committed
51
#include "event.h"
52
#include "resource.h"
53

54
#include "../video_output/vout_control.h"
Laurent Aimar's avatar
Laurent Aimar committed
55

56
57
static decoder_t *CreateDecoder( vlc_object_t *, input_thread_t *,
                                 es_format_t *, bool, input_resource_t *,
58
                                 sout_instance_t *p_sout );
59
static void       DeleteDecoder( decoder_t * );
60

61
static void      *DecoderThread( void * );
62
63
static void       DecoderProcess( decoder_t *, block_t * );
static void       DecoderError( decoder_t *p_dec, block_t *p_block );
Laurent Aimar's avatar
Laurent Aimar committed
64
65
static void       DecoderOutputChangePause( decoder_t *, bool b_paused, mtime_t i_date );
static void       DecoderFlush( decoder_t * );
66
67
static void       DecoderSignalBuffering( decoder_t *, bool );
static void       DecoderFlushBuffering( decoder_t * );
Sam Hocevar's avatar
   
Sam Hocevar committed
68

Laurent Aimar's avatar
Laurent Aimar committed
69
70
static void       DecoderUnsupportedCodec( decoder_t *, vlc_fourcc_t );

gbazin's avatar
   
gbazin committed
71
72
73
74
75
/* Buffers allocation callbacks for the decoders */
static aout_buffer_t *aout_new_buffer( decoder_t *, int );

static picture_t *vout_new_buffer( decoder_t * );
static void vout_del_buffer( decoder_t *, picture_t * );
gbazin's avatar
   
gbazin committed
76
77
static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * );
gbazin's avatar
   
gbazin committed
78

79
static subpicture_t *spu_new_buffer( decoder_t *, const subpicture_updater_t * );
80
81
static void spu_del_buffer( decoder_t *, subpicture_t * );

82
83
struct decoder_owner_sys_t
{
Laurent Aimar's avatar
Laurent Aimar committed
84
85
    int64_t         i_preroll_end;

86
    input_thread_t  *p_input;
87
    input_resource_t*p_resource;
88
    input_clock_t   *p_clock;
89
    int             i_last_rate;
90

91
92
    vout_thread_t   *p_spu_vout;
    int              i_spu_channel;
93
    int64_t          i_spu_order;
94

95
96
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
97

98
99
    vlc_thread_t     thread;

100
101
    /* Some decoders require already packetized data (ie. not truncated) */
    decoder_t *p_packetizer;
102
    bool b_packetizer;
103

104
105
106
107
108
    /* Current format in use by the output */
    video_format_t video;
    audio_format_t audio;
    es_format_t    sout;

109
110
111
    /* */
    bool           b_fmt_description;
    es_format_t    fmt_description;
Laurent Aimar's avatar
Laurent Aimar committed
112
    vlc_meta_t     *p_description;
113

114
115
    /* fifo */
    block_fifo_t *p_fifo;
116

117
118
    /* Lock for communication with decoder thread */
    vlc_mutex_t lock;
119
120
    vlc_cond_t  wait_request;
    vlc_cond_t  wait_acknowledge;
121

Laurent Aimar's avatar
Laurent Aimar committed
122
    /* -- These variables need locking on write(only) -- */
123
    audio_output_t *p_aout;
Laurent Aimar's avatar
Laurent Aimar committed
124
125
126
127

    vout_thread_t   *p_vout;

    /* -- Theses variables need locking on read *and* write -- */
128
129
    bool b_exit;

Laurent Aimar's avatar
Laurent Aimar committed
130
    /* Pause */
131
    bool b_paused;
132
133
134
    struct
    {
        mtime_t i_date;
135
        int     i_ignore;
136
137
138
139
140
141
    } pause;

    /* Buffering */
    bool b_buffering;
    struct
    {
142
        bool b_first;
143
144
145
146
147
148
149
150
151
152
153
        bool b_full;
        int  i_count;

        picture_t     *p_picture;
        picture_t     **pp_picture_next;

        subpicture_t  *p_subpic;
        subpicture_t  **pp_subpic_next;

        aout_buffer_t *p_audio;
        aout_buffer_t **pp_audio_next;
154
155
156

        block_t       *p_block;
        block_t       **pp_block_next;
157
    } buffer;
158

Laurent Aimar's avatar
Laurent Aimar committed
159
160
161
    /* Flushing */
    bool b_flushing;

162
    /* CC */
163
164
165
166
167
168
    struct
    {
        bool b_supported;
        bool pb_present[4];
        decoder_t *pp_decoder[4];
    } cc;
169
170
171

    /* Delay */
    mtime_t i_ts_delay;
172
173
};

174
175
176
177
#define DECODER_MAX_BUFFERING_COUNT (4)
#define DECODER_MAX_BUFFERING_AUDIO_DURATION (AOUT_MAX_PREPARE_TIME)
#define DECODER_MAX_BUFFERING_VIDEO_DURATION (1*CLOCK_FREQ)

178
179
180
181
182
183
184
185
/* Pictures which are DECODER_BOGUS_VIDEO_DELAY or more in advance probably have
 * a bogus PTS and won't be displayed */
#define DECODER_BOGUS_VIDEO_DELAY                ((mtime_t)(DEFAULT_PTS_DELAY * 30))

/* */
#define DECODER_SPU_VOUT_WAIT_DURATION ((int)(0.200*CLOCK_FREQ))


Laurent Aimar's avatar
Laurent Aimar committed
186
187
188
/*****************************************************************************
 * Public functions
 *****************************************************************************/
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
picture_t *decoder_NewPicture( decoder_t *p_decoder )
{
    picture_t *p_picture = p_decoder->pf_vout_buffer_new( p_decoder );
    if( !p_picture )
        msg_Warn( p_decoder, "can't get output picture" );
    return p_picture;
}
void decoder_DeletePicture( decoder_t *p_decoder, picture_t *p_picture )
{
    p_decoder->pf_vout_buffer_del( p_decoder, p_picture );
}
void decoder_LinkPicture( decoder_t *p_decoder, picture_t *p_picture )
{
    p_decoder->pf_picture_link( p_decoder, p_picture );
}
void decoder_UnlinkPicture( decoder_t *p_decoder, picture_t *p_picture )
{
    p_decoder->pf_picture_unlink( p_decoder, p_picture );
}

209
210
211
212
213
214
215
aout_buffer_t *decoder_NewAudioBuffer( decoder_t *p_decoder, int i_size )
{
    if( !p_decoder->pf_aout_buffer_new )
        return NULL;
    return p_decoder->pf_aout_buffer_new( p_decoder, i_size );
}

216
217
subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
                                     const subpicture_updater_t *p_dyn )
218
{
219
    subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder, p_dyn );
220
221
222
223
    if( !p_subpicture )
        msg_Warn( p_decoder, "can't get output subpicture" );
    return p_subpicture;
}
224

225
226
227
228
void decoder_DeleteSubpicture( decoder_t *p_decoder, subpicture_t *p_subpicture )
{
    p_decoder->pf_spu_buffer_del( p_decoder, p_subpicture );
}
229

Laurent Aimar's avatar
Laurent Aimar committed
230
231
232
233
234
235
/* decoder_GetInputAttachments:
 */
int decoder_GetInputAttachments( decoder_t *p_dec,
                                 input_attachment_t ***ppp_attachment,
                                 int *pi_attachment )
{
236
237
238
239
    if( !p_dec->pf_get_attachments )
        return VLC_EGENERIC;

    return p_dec->pf_get_attachments( p_dec, ppp_attachment, pi_attachment );
Laurent Aimar's avatar
Laurent Aimar committed
240
}
241
242
243
244
/* decoder_GetDisplayDate:
 */
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
245
    if( !p_dec->pf_get_display_date )
246
        return VLC_TS_INVALID;
247

248
    return p_dec->pf_get_display_date( p_dec, i_ts );
249
250
251
252
253
}
/* decoder_GetDisplayRate:
 */
int decoder_GetDisplayRate( decoder_t *p_dec )
{
254
    if( !p_dec->pf_get_display_rate )
Laurent Aimar's avatar
Laurent Aimar committed
255
        return INPUT_RATE_DEFAULT;
256
257

    return p_dec->pf_get_display_rate( p_dec );
258
}
259

260
261
262
263
264
/* TODO: pass p_sout through p_resource? -- Courmisch */
static decoder_t *decoder_New( vlc_object_t *p_parent, input_thread_t *p_input,
                               es_format_t *fmt, input_clock_t *p_clock,
                               input_resource_t *p_resource,
                               sout_instance_t *p_sout  )
265
{
266
    decoder_t *p_dec = NULL;
267
    const char *psz_type = p_sout ? N_("packetizer") : N_("decoder");
268
    int i_priority;
269

270
    /* Create the decoder configuration structure */
271
272
    p_dec = CreateDecoder( p_parent, p_input, fmt,
                           p_sout != NULL, p_resource, p_sout );
273
    if( p_dec == NULL )
274
    {
275
276
        msg_Err( p_parent, "could not create %s", psz_type );
        dialog_Fatal( p_parent, _("Streaming / Transcoding failed"),
277
278
279
                      _("VLC could not open the %s module."),
                      vlc_gettext( psz_type ) );
        return NULL;
280
281
    }

282
    if( !p_dec->p_module )
Sam Hocevar's avatar
   
Sam Hocevar committed
283
    {
284
        DecoderUnsupportedCodec( p_dec, fmt->i_codec );
gbazin's avatar
   
gbazin committed
285
286

        DeleteDecoder( p_dec );
287
        return NULL;
Henri Fallon's avatar
   
Henri Fallon committed
288
289
    }

290
    p_dec->p_owner->p_clock = p_clock;
291
    assert( p_dec->fmt_out.i_cat != UNKNOWN_ES );
292

293
    if( p_dec->fmt_out.i_cat == AUDIO_ES )
294
        i_priority = VLC_THREAD_PRIORITY_AUDIO;
295
    else
296
        i_priority = VLC_THREAD_PRIORITY_VIDEO;
297

298
    /* Spawn the decoder thread */
299
    if( vlc_clone( &p_dec->p_owner->thread, DecoderThread, p_dec, i_priority ) )
Henri Fallon's avatar
   
Henri Fallon committed
300
    {
301
302
303
304
        msg_Err( p_dec, "cannot spawn decoder thread" );
        module_unneed( p_dec, p_dec->p_module );
        DeleteDecoder( p_dec );
        return NULL;
Henri Fallon's avatar
   
Henri Fallon committed
305
306
    }

307
    return p_dec;
308
309
}

310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335

/**
 * Spawns a new decoder thread from the input thread
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
 * \return the spawned decoder object
 */
decoder_t *input_DecoderNew( input_thread_t *p_input,
                             es_format_t *fmt, input_clock_t *p_clock,
                             sout_instance_t *p_sout  )
{
    return decoder_New( VLC_OBJECT(p_input), p_input, fmt, p_clock,
                        p_input->p->p_resource, p_sout );
}

/**
 * Spawn a decoder thread outside of the input thread.
 */
decoder_t *input_DecoderCreate( vlc_object_t *p_parent, es_format_t *fmt,
                                input_resource_t *p_resource )
{
    return decoder_New( p_parent, NULL, fmt, NULL, p_resource, NULL );
}


zorglub's avatar
zorglub committed
336
337
338
339
340
341
342
/**
 * 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
343
void input_DecoderDelete( decoder_t *p_dec )
344
{
345
346
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

347
    vlc_cancel( p_owner->thread );
348

349
    /* Make sure we aren't paused/buffering/waiting/decoding anymore */
350
    vlc_mutex_lock( &p_owner->lock );
351
    const bool b_was_paused = p_owner->b_paused;
352
353
354
    p_owner->b_paused = false;
    p_owner->b_buffering = false;
    p_owner->b_flushing = true;
355
    p_owner->b_exit = true;
356
    vlc_cond_signal( &p_owner->wait_request );
357
    vlc_mutex_unlock( &p_owner->lock );
358

359
    vlc_join( p_owner->thread, NULL );
360
361
    p_owner->b_paused = b_was_paused;

362
    module_unneed( p_dec, p_dec->p_module );
363

364
    /* */
365
    if( p_dec->p_owner->cc.b_supported )
366
367
368
    {
        int i;
        for( i = 0; i < 4; i++ )
369
            input_DecoderSetCcState( p_dec, false, i );
370
371
    }

372
    /* Delete decoder */
gbazin's avatar
   
gbazin committed
373
    DeleteDecoder( p_dec );
374
}
zorglub's avatar
zorglub committed
375
376

/**
377
 * Put a block_t in the decoder's fifo.
378
 * Thread-safe w.r.t. the decoder. May be a cancellation point.
zorglub's avatar
zorglub committed
379
380
381
382
 *
 * \param p_dec the decoder object
 * \param p_block the data block
 */
383
void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
384
{
385
386
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

387
    if( b_do_pace )
388
    {
389
390
391
392
393
394
        /* The fifo is not consummed when buffering and so will
         * deadlock vlc.
         * There is no need to lock as b_buffering is never modify
         * inside decoder thread. */
        if( !p_owner->b_buffering )
            block_FifoPace( p_owner->p_fifo, 10, SIZE_MAX );
395
    }
396
#ifdef __arm__
397
    else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ )
398
#else
399
    else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
400
#endif
401
    {
402
        /* FIXME: ideally we would check the time amount of data
403
         * in the FIFO instead of its size. */
404
405
406
        msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
                  "consumed quickly enough), resetting fifo!" );
        block_FifoEmpty( p_owner->p_fifo );
407
    }
408
409

    block_FifoPut( p_owner->p_fifo, p_block );
410
}
411

412
bool input_DecoderIsEmpty( decoder_t * p_dec )
Laurent Aimar's avatar
   
Laurent Aimar committed
413
{
414
415
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    assert( !p_owner->b_buffering );
Laurent Aimar's avatar
Laurent Aimar committed
416

417
418
419
420
    bool b_empty = block_FifoCount( p_dec->p_owner->p_fifo ) <= 0;
    if( b_empty )
    {
        vlc_mutex_lock( &p_owner->lock );
421
        /* TODO subtitles support */
422
423
        if( p_dec->fmt_out.i_cat == VIDEO_ES && p_owner->p_vout )
            b_empty = vout_IsEmpty( p_owner->p_vout );
424
        else if( p_dec->fmt_out.i_cat == AUDIO_ES && p_owner->p_aout )
425
            b_empty = aout_DecIsEmpty( p_owner->p_aout );
426
427
428
        vlc_mutex_unlock( &p_owner->lock );
    }
    return b_empty;
Laurent Aimar's avatar
   
Laurent Aimar committed
429
430
}

431
void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
432
{
433
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
434
435
    int i;

436
    vlc_mutex_lock( &p_owner->lock );
437
    for( i = 0; i < 4; i++ )
438
        pb_present[i] =  p_owner->cc.pb_present[i];
439
    vlc_mutex_unlock( &p_owner->lock );
440
}
441
int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel )
442
443
444
445
446
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

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

447
    if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
448
449
450
451
452
453
454
455
456
457
458
459
460
461
        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] );
462
463
        p_cc = CreateDecoder( VLC_OBJECT(p_dec), p_owner->p_input, &fmt,
                              false, p_owner->p_resource, p_owner->p_sout );
464
465
466
        if( !p_cc )
        {
            msg_Err( p_dec, "could not create decoder" );
467
            dialog_Fatal( p_dec, _("Streaming / Transcoding failed"), "%s",
468
                          _("VLC could not open the decoder module.") );
469
470
471
472
473
474
475
476
            return VLC_EGENERIC;
        }
        else if( !p_cc->p_module )
        {
            DecoderUnsupportedCodec( p_dec, fcc[i_channel] );
            DeleteDecoder( p_cc );
            return VLC_EGENERIC;
        }
477
        p_cc->p_owner->p_clock = p_owner->p_clock;
478

479
        vlc_mutex_lock( &p_owner->lock );
480
        p_owner->cc.pp_decoder[i_channel] = p_cc;
481
        vlc_mutex_unlock( &p_owner->lock );
482
483
484
485
486
    }
    else
    {
        decoder_t *p_cc;

487
        vlc_mutex_lock( &p_owner->lock );
488
489
        p_cc = p_owner->cc.pp_decoder[i_channel];
        p_owner->cc.pp_decoder[i_channel] = NULL;
490
        vlc_mutex_unlock( &p_owner->lock );
491
492
493

        if( p_cc )
        {
494
            module_unneed( p_cc, p_cc->p_module );
495
496
497
498
499
            DeleteDecoder( p_cc );
        }
    }
    return VLC_SUCCESS;
}
500
int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel )
501
502
503
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

504
    *pb_decode = false;
505
    if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
506
507
        return VLC_EGENERIC;

508
    vlc_mutex_lock( &p_owner->lock );
509
    *pb_decode = p_owner->cc.pp_decoder[i_channel] != NULL;
510
    vlc_mutex_unlock( &p_owner->lock );
511
512
513
    return VLC_EGENERIC;
}

514
515
516
517
518
519
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 );

520
    assert( !p_owner->b_paused || !b_paused );
521

522
    p_owner->b_paused = b_paused;
523
    p_owner->pause.i_date = i_date;
524
    p_owner->pause.i_ignore = 0;
525
    vlc_cond_signal( &p_owner->wait_request );
526

Laurent Aimar's avatar
Laurent Aimar committed
527
    DecoderOutputChangePause( p_dec, b_paused, i_date );
528

529
530
    vlc_mutex_unlock( &p_owner->lock );
}
531
532
533
534
535
536
537
538
539

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 );
}
540

Laurent Aimar's avatar
Laurent Aimar committed
541
void input_DecoderStartBuffering( decoder_t *p_dec )
542
543
544
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Laurent Aimar's avatar
Laurent Aimar committed
545
    vlc_mutex_lock( &p_owner->lock );
546

Laurent Aimar's avatar
Laurent Aimar committed
547
    DecoderFlush( p_dec );
Laurent Aimar's avatar
Laurent Aimar committed
548

549
    p_owner->buffer.b_first = true;
550
551
552
    p_owner->buffer.b_full = false;
    p_owner->buffer.i_count = 0;

553
554
    assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic &&
            !p_owner->buffer.p_audio && !p_owner->buffer.p_block );
555
556
557
558
559
560
561
562
563
564

    p_owner->buffer.p_picture = NULL;
    p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;

    p_owner->buffer.p_subpic = NULL;
    p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;

    p_owner->buffer.p_audio = NULL;
    p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;

565
566
567
568
    p_owner->buffer.p_block = NULL;
    p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;


569
570
    p_owner->b_buffering = true;

571
    vlc_cond_signal( &p_owner->wait_request );
572

Laurent Aimar's avatar
Laurent Aimar committed
573
574
    vlc_mutex_unlock( &p_owner->lock );
}
Laurent Aimar's avatar
Laurent Aimar committed
575

Laurent Aimar's avatar
Laurent Aimar committed
576
577
void input_DecoderStopBuffering( decoder_t *p_dec )
{
578
579
580
581
582
583
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

    p_owner->b_buffering = false;

584
    vlc_cond_signal( &p_owner->wait_request );
585
586

    vlc_mutex_unlock( &p_owner->lock );
587
588
}

589
590
591
592
593
594
void input_DecoderWaitBuffering( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

595
    while( p_owner->b_buffering && !p_owner->buffer.b_full )
596
597
    {
        block_FifoWake( p_owner->p_fifo );
598
        vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
599
600
601
602
    }

    vlc_mutex_unlock( &p_owner->lock );
}
603

604
605
606
607
608
609
610
void input_DecoderFrameNext( decoder_t *p_dec, mtime_t *pi_duration )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    *pi_duration = 0;

    vlc_mutex_lock( &p_owner->lock );
611
    if( p_dec->fmt_out.i_cat == VIDEO_ES )
612
    {
613
614
615
616
        if( p_owner->b_paused && p_owner->p_vout )
        {
            vout_NextPicture( p_owner->p_vout, pi_duration );
            p_owner->pause.i_ignore++;
617
            vlc_cond_signal( &p_owner->wait_request );
618
619
620
621
622
623
        }
    }
    else
    {
        /* TODO subtitle should not be flushed */
        DecoderFlush( p_dec );
624
625
626
    }
    vlc_mutex_unlock( &p_owner->lock );
}
627

Laurent Aimar's avatar
Laurent Aimar committed
628
bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_meta_t **pp_meta )
629
630
631
632
633
634
635
636
637
638
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    bool b_changed;

    vlc_mutex_lock( &p_owner->lock );
    b_changed = p_owner->b_fmt_description;
    if( b_changed )
    {
        if( p_fmt )
            es_format_Copy( p_fmt, &p_owner->fmt_description );
Laurent Aimar's avatar
Laurent Aimar committed
639
640
641
642
643
644
645
646
647
648
649

        if( pp_meta )
        {
            *pp_meta = NULL;
            if( p_owner->p_description )
            {
                *pp_meta = vlc_meta_New();
                if( *pp_meta )
                    vlc_meta_Merge( *pp_meta, p_owner->p_description );
            }
        }
650
651
652
653
654
655
        p_owner->b_fmt_description = false;
    }
    vlc_mutex_unlock( &p_owner->lock );
    return b_changed;
}

656
657
658
659
660
661
662
size_t input_DecoderGetFifoSize( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    return block_FifoSize( p_owner->p_fifo );
}

663
void input_DecoderGetObjects( decoder_t *p_dec,
664
                              vout_thread_t **pp_vout, audio_output_t **pp_aout )
665
666
667
668
669
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    if( pp_vout )
Laurent Aimar's avatar
Laurent Aimar committed
670
        *pp_vout = p_owner->p_vout ? vlc_object_hold( p_owner->p_vout ) : NULL;
671
    if( pp_aout )
Laurent Aimar's avatar
Laurent Aimar committed
672
        *pp_aout = p_owner->p_aout ? vlc_object_hold( p_owner->p_aout ) : NULL;
673
674
675
    vlc_mutex_unlock( &p_owner->lock );
}

Laurent Aimar's avatar
Laurent Aimar committed
676
677
678
/*****************************************************************************
 * Internal functions
 *****************************************************************************/
679
680
681
682
static int DecoderGetInputAttachments( decoder_t *p_dec,
                                       input_attachment_t ***ppp_attachment,
                                       int *pi_attachment )
{
683
684
685
686
687
    input_thread_t *p_input = p_dec->p_owner->p_input;

    if( unlikely(p_input == NULL) )
        return VLC_ENOOBJ;
    return input_Control( p_input, INPUT_GET_ATTACHMENTS,
688
689
690
691
692
693
694
695
                          ppp_attachment, pi_attachment );
}
static mtime_t DecoderGetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    if( p_owner->b_buffering || p_owner->b_paused )
696
        i_ts = VLC_TS_INVALID;
697
698
    vlc_mutex_unlock( &p_owner->lock );

699
    if( !p_owner->p_clock || i_ts <= VLC_TS_INVALID )
700
701
        return i_ts;

702
    if( input_clock_ConvertTS( p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) )
703
        return VLC_TS_INVALID;
704
705

    return i_ts;
706
707
708
709
710
711
712
713
714
}
static int DecoderGetDisplayRate( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    if( !p_owner->p_clock )
        return INPUT_RATE_DEFAULT;
    return input_clock_GetRate( p_owner->p_clock );
}
Laurent Aimar's avatar
Laurent Aimar committed
715
716
717
718

/* */
static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
{
ivoire's avatar
ivoire committed
719
    msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'. "
Laurent Aimar's avatar
Laurent Aimar committed
720
721
             "VLC probably does not support this sound or video format.",
             (char*)&codec );
722
723
724
725
    dialog_Fatal( p_dec, _("No suitable decoder module"),
                 _("VLC does not support the audio or video format \"%4.4s\". "
                  "Unfortunately there is no way for you to fix this."),
                  (char*)&codec );
Laurent Aimar's avatar
Laurent Aimar committed
726
727
728
}


zorglub's avatar
zorglub committed
729
730
731
732
733
/**
 * Create a decoder object
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
734
 * \param b_packetizer instead of a decoder
zorglub's avatar
zorglub committed
735
736
 * \return the decoder object
 */
737
738
static decoder_t * CreateDecoder( vlc_object_t *p_parent,
                                  input_thread_t *p_input,
739
                                  es_format_t *fmt, bool b_packetizer,
740
                                  input_resource_t *p_resource,
741
                                  sout_instance_t *p_sout )
Sam Hocevar's avatar
   
Sam Hocevar committed
742
{
gbazin's avatar
   
gbazin committed
743
    decoder_t *p_dec;
744
    decoder_owner_sys_t *p_owner;
745
746
    es_format_t null_es_format;

747
    p_dec = vlc_custom_create( p_parent, sizeof( *p_dec ), "decoder" );
gbazin's avatar
   
gbazin committed
748
    if( p_dec == NULL )
Sam Hocevar's avatar
   
Sam Hocevar committed
749
750
        return NULL;

751
752
753
754
755
    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
756

757
    /* Initialize the decoder */
gbazin's avatar
   
gbazin committed
758
759
    p_dec->p_module = NULL;

760
    memset( &null_es_format, 0, sizeof(es_format_t) );
Laurent Aimar's avatar
Laurent Aimar committed
761
762
    es_format_Copy( &p_dec->fmt_in, fmt );
    es_format_Copy( &p_dec->fmt_out, &null_es_format );
gbazin's avatar
   
gbazin committed
763

764
765
    p_dec->p_description = NULL;

gbazin's avatar
   
gbazin committed
766
    /* Allocate our private structure for the decoder */
767
    p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
768
    if( unlikely(p_owner == NULL) )
769
770
    {
        vlc_object_release( p_dec );
gbazin's avatar
   
gbazin committed
771
        return NULL;
772
    }
773
774
775
    p_owner->i_preroll_end = VLC_TS_INVALID;
    p_owner->i_last_rate = INPUT_RATE_DEFAULT;
    p_owner->p_input = p_input;
776
    p_owner->p_resource = p_resource;
777
778
779
780
781
782
783
784
785
    p_owner->p_aout = NULL;
    p_owner->p_vout = NULL;
    p_owner->p_spu_vout = NULL;
    p_owner->i_spu_channel = 0;
    p_owner->i_spu_order = 0;
    p_owner->p_sout = p_sout;
    p_owner->p_sout_input = NULL;
    p_owner->p_packetizer = NULL;
    p_owner->b_packetizer = b_packetizer;
786

787
    /* decoder fifo */
788
789
    p_owner->p_fifo = block_FifoNew();
    if( unlikely(p_owner->p_fifo == NULL) )
790
    {
791
        free( p_owner );
792
        vlc_object_release( p_dec );
793
        return NULL;
794
    }
795

gbazin's avatar
   
gbazin committed
796
797
798
799
    /* Set buffers allocation callbacks for the decoders */
    p_dec->pf_aout_buffer_new = aout_new_buffer;
    p_dec->pf_vout_buffer_new = vout_new_buffer;
    p_dec->pf_vout_buffer_del = vout_del_buffer;
gbazin's avatar
   
gbazin committed
800
801
    p_dec->pf_picture_link    = vout_link_picture;
    p_dec->pf_picture_unlink  = vout_unlink_picture;
802
803
    p_dec->pf_spu_buffer_new  = spu_new_buffer;
    p_dec->pf_spu_buffer_del  = spu_del_buffer;
804
805
806
807
    /* */
    p_dec->pf_get_attachments  = DecoderGetInputAttachments;
    p_dec->pf_get_display_date = DecoderGetDisplayDate;
    p_dec->pf_get_display_rate = DecoderGetDisplayRate;
gbazin's avatar
   
gbazin committed
808

809
    /* Find a suitable decoder/packetizer module */
810
    if( !b_packetizer )
811
        p_dec->p_module = module_need( p_dec, "decoder", "$codec", false );
812
    else
813
        p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false );
814
815

    /* Check if decoder requires already packetized data */
816
    if( !b_packetizer &&
817
818
        p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
    {
819
        p_owner->p_packetizer =
820
            vlc_custom_create( p_parent, sizeof( decoder_t ), "packetizer" );
821
        if( p_owner->p_packetizer )
822
        {
823
            es_format_Copy( &p_owner->p_packetizer->fmt_in,
824
825
                            &p_dec->fmt_in );

826
            es_format_Copy( &p_owner->p_packetizer->fmt_out,
Laurent Aimar's avatar
Laurent Aimar committed
827
828
                            &null_es_format );

829
830
            p_owner->p_packetizer->p_module =
                module_need( p_owner->p_packetizer,
831
                             "packetizer", "$packetizer", false );
832

833
            if( !p_owner->p_packetizer->p_module )
834
            {
835
836
                es_format_Clean( &p_owner->p_packetizer->fmt_in );
                vlc_object_release( p_owner->p_packetizer );
837
838
839
840
            }
        }
    }

841
842
843
    /* Copy ourself the input replay gain */
    if( fmt->i_cat == AUDIO_ES )
    {
844
        for( unsigned i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
845
846
847
848
849
850
851
852
853
854
855
856
857
        {
            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];
            }
        }
    }
858
859
860

    /* */
    vlc_mutex_init( &p_owner->lock );
861
862
    vlc_cond_init( &p_owner->wait_request );
    vlc_cond_init( &p_owner->wait_acknowledge );
863

864
865
    p_owner->b_fmt_description = false;
    es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
Laurent Aimar's avatar
Laurent Aimar committed
866
    p_owner->p_description = NULL;
867

868
869
    p_owner->b_exit = false;

870
    p_owner->b_paused = false;
871
    p_owner->pause.i_date = VLC_TS_INVALID;
872
    p_owner->pause.i_ignore = 0;
873
874

    p_owner->b_buffering = false;
875
    p_owner->buffer.b_first = true;
876
877
878
879
880
    p_owner->buffer.b_full = false;
    p_owner->buffer.i_count = 0;
    p_owner->buffer.p_picture = NULL;
    p_owner->buffer.p_subpic = NULL;
    p_owner->buffer.p_audio = NULL;
881
    p_owner->buffer.p_block = NULL;
882
883
884

    p_owner->b_flushing = false;

885
    /* */
886
    p_owner->cc.b_supported = false;
887
    if( !b_packetizer )
888
889
    {
        if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
890
            p_owner->cc.b_supported = true;
891
        if( p_dec->pf_get_cc )
892
            p_owner->cc.b_supported = true;
893
894
    }

895
    for( unsigned i = 0; i < 4; i++ )
896
    {
897
898
        p_owner->cc.pb_present[i] = false;
        p_owner->cc.pp_decoder[i] = NULL;
899
    }
900
    p_owner->i_ts_delay = 0;
gbazin's avatar
   
gbazin committed
901
902
903
    return p_dec;
}

zorglub's avatar
zorglub committed
904
905
906
907
908
/**
 * The decoding main loop
 *
 * \param p_dec the decoder
 */
909
static void *DecoderThread( void *p_data )
gbazin's avatar
   
gbazin committed
910
{
911
    decoder_t *p_dec = (decoder_t *)p_data;
912
913
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

gbazin's avatar
   
gbazin committed
914
    /* The decoder's main loop */
915
    for( ;; )
916
    {
917
        block_t *p_block = block_FifoGet( p_owner->p_fifo );
918

919
920
        /* Make sure there is no cancellation point other than this one^^.
         * If you need one, be sure to push cleanup of p_block. */
921
922
        DecoderSignalBuffering( p_dec, p_block == NULL );

923
        if( p_block )
924
        {
925
926
            int canc = vlc_savecancel();

927
928
929
930
931
932
933
934
            if( p_block->i_flags & BLOCK_FLAG_CORE_EOS )
            {
                /* calling DecoderProcess() with NULL block will make
                 * decoders/packetizers flush their buffers */
                block_Release( p_block );
                p_block = NULL;
            }

935
            if( p_dec->b_error )