decoder.c 41.2 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
Antoine Cellerier's avatar
Antoine Cellerier 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/vlc.h>
Laurent Aimar's avatar
Laurent Aimar committed
35

Clément Stenac's avatar
Clément Stenac 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

Laurent Aimar's avatar
Laurent Aimar committed
48 49
static decoder_t * CreateDecoder( input_thread_t *, es_format_t *, int );
static void        DeleteDecoder( decoder_t * );
50

Gildas Bazin's avatar
 
Gildas Bazin committed
51
static int         DecoderThread( decoder_t * );
52
static int         DecoderDecode( decoder_t * p_dec, block_t *p_block );
Sam Hocevar's avatar
 
Sam Hocevar committed
53

Gildas Bazin's avatar
 
Gildas Bazin committed
54 55 56 57 58 59
/* 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 * );
Gildas Bazin's avatar
 
Gildas Bazin committed
60 61
static void vout_link_picture( decoder_t *, picture_t * );
static void vout_unlink_picture( decoder_t *, picture_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
62

63 64 65
static subpicture_t *spu_new_buffer( decoder_t * );
static void spu_del_buffer( decoder_t *, subpicture_t * );

66
static es_format_t null_es_format;
Gildas Bazin's avatar
 
Gildas Bazin committed
67

68 69
struct decoder_owner_sys_t
{
70
    bool      b_own_thread;
71

Laurent Aimar's avatar
Laurent Aimar committed
72 73
    int64_t         i_preroll_end;

74 75
    input_thread_t  *p_input;

76 77 78 79 80
    aout_instance_t *p_aout;
    aout_input_t    *p_aout_input;

    vout_thread_t   *p_vout;

81 82 83
    vout_thread_t   *p_spu_vout;
    int              i_spu_channel;

84 85
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
86

87 88 89
    /* Some decoders require already packetized data (ie. not truncated) */
    decoder_t *p_packetizer;

90 91 92 93 94 95 96
    /* 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;
97 98

    /* CC */
99
    bool b_cc_supported;
100
    vlc_mutex_t lock_cc;
101
    bool pb_cc_present[4];
102
    decoder_t *pp_cc[4];
103 104
};

105 106 107 108 109 110
/* */
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 );
111
    intf_UserFatal( p_dec, false, _("No suitable decoder module"), 
112 113
                    _("VLC does not support the audio or video format \"%4.4s\". "
                      "Unfortunately there is no way for you to fix this."), (char*)&codec );
114 115
}

116 117
/* decoder_GetInputAttachment:
 */
Laurent Aimar's avatar
Laurent Aimar committed
118 119
input_attachment_t *decoder_GetInputAttachment( decoder_t *p_dec,
                                                const char *psz_name )
120 121 122 123 124 125
{
    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
126 127 128 129 130 131 132 133 134
/* 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 );
}
135 136 137 138
/* decoder_GetDisplayDate:
 */
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
139
    VLC_UNUSED(p_dec);
140 141
    return i_ts;
}
142

Clément Stenac's avatar
Clément Stenac committed
143 144 145 146 147 148 149
/**
 * 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
150
decoder_t *input_DecoderNew( input_thread_t *p_input,
151
                             es_format_t *fmt, bool b_force_decoder )
152
{
153 154
    decoder_t   *p_dec = NULL;
    vlc_value_t val;
155

156 157 158
#ifndef ENABLE_SOUT
    (void)b_force_decoder;
#else
159
    /* If we are in sout mode, search for packetizer module */
Clément Stenac's avatar
Clément Stenac committed
160
    if( p_input->p->p_sout && !b_force_decoder )
161
    {
162
        /* Create the decoder configuration structure */
Laurent Aimar's avatar
Laurent Aimar committed
163
        p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_PACKETIZER );
164
        if( p_dec == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
165
        {
166
            msg_Err( p_input, "could not create packetizer" );
167
            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
168
                            _("VLC could not open the packetizer module.") );
169
            return NULL;
Gildas Bazin's avatar
 
Gildas Bazin committed
170
        }
171
    }
172
    else
173
#endif
174
    {
Gildas Bazin's avatar
 
Gildas Bazin committed
175
        /* Create the decoder configuration structure */
Laurent Aimar's avatar
Laurent Aimar committed
176
        p_dec = CreateDecoder( p_input, fmt, VLC_OBJECT_DECODER );
Gildas Bazin's avatar
 
Gildas Bazin committed
177 178 179
        if( p_dec == NULL )
        {
            msg_Err( p_input, "could not create decoder" );
180
            intf_UserFatal( p_input, false, _("Streaming / Transcoding failed"),
181
                            _("VLC could not open the decoder module.") );
Gildas Bazin's avatar
 
Gildas Bazin committed
182 183
            return NULL;
        }
184 185
    }

186
    if( !p_dec->p_module )
Sam Hocevar's avatar
 
Sam Hocevar committed
187
    {
188
        DecoderUnsupportedCodec( p_dec, fmt->i_codec );
Gildas Bazin's avatar
 
Gildas Bazin committed
189 190

        DeleteDecoder( p_dec );
191
        vlc_object_release( p_dec );
192
        return NULL;
Henri Fallon's avatar
 
Henri Fallon committed
193 194
    }

Clément Stenac's avatar
Clément Stenac committed
195
    if( p_input->p->p_sout && p_input->p->input.b_can_pace_control &&
Laurent Aimar's avatar
Laurent Aimar committed
196
        !b_force_decoder )
197 198
    {
        msg_Dbg( p_input, "stream out mode -> no decoder thread" );
199
        p_dec->p_owner->b_own_thread = false;
200 201 202 203 204 205
    }
    else
    {
        var_Get( p_input, "minimize-threads", &val );
        p_dec->p_owner->b_own_thread = !val.b_bool;
    }
206

207
    if( p_dec->p_owner->b_own_thread )
Henri Fallon's avatar
 
Henri Fallon committed
208
    {
209
        int i_priority;
Laurent Aimar's avatar
Laurent Aimar committed
210
        if( fmt->i_cat == AUDIO_ES )
211 212 213 214 215 216
            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,
217
                               i_priority, false ) )
218
        {
219
            msg_Err( p_dec, "cannot spawn decoder thread" );
220 221
            module_Unneed( p_dec, p_dec->p_module );
            DeleteDecoder( p_dec );
222
            vlc_object_release( p_dec );
223 224
            return NULL;
        }
Henri Fallon's avatar
 
Henri Fallon committed
225 226
    }

227
    return p_dec;
228 229
}

Clément Stenac's avatar
Clément Stenac committed
230 231 232 233 234 235 236
/**
 * 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
237
void input_DecoderDelete( decoder_t *p_dec )
238
{
239
    vlc_object_kill( p_dec );
240

241
    if( p_dec->p_owner->b_own_thread )
242
    {
243 244 245
        /* 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
246
        input_DecoderDecode( p_dec, p_block );
247

248
        vlc_thread_join( p_dec );
249 250 251

        /* Don't module_Unneed() here because of the dll loader that wants
         * close() in the same thread than open()/decode() */
252 253 254
    }
    else
    {
255 256 257
        /* Flush */
        input_DecoderDecode( p_dec, NULL );

258 259
        module_Unneed( p_dec, p_dec->p_module );
    }
260

261 262 263 264 265
    /* */
    if( p_dec->p_owner->b_cc_supported )
    {
        int i;
        for( i = 0; i < 4; i++ )
266
            input_DecoderSetCcState( p_dec, false, i );
267 268
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
269 270 271 272
    /* Delete decoder configuration */
    DeleteDecoder( p_dec );

    /* Delete the decoder */
273
    vlc_object_release( p_dec );
274
}
Clément Stenac's avatar
Clément Stenac committed
275 276

/**
277
 * Put a block_t in the decoder's fifo.
Clément Stenac's avatar
Clément Stenac committed
278 279 280 281
 *
 * \param p_dec the decoder object
 * \param p_block the data block
 */
Laurent Aimar's avatar
Laurent Aimar committed
282
void input_DecoderDecode( decoder_t * p_dec, block_t *p_block )
283
{
284 285
    if( p_dec->p_owner->b_own_thread )
    {
Clément Stenac's avatar
Clément Stenac committed
286
        if( p_dec->p_owner->p_input->p->b_out_pace_control )
287 288
        {
            /* FIXME !!!!! */
289
            while( !p_dec->b_die && !p_dec->b_error &&
290
                   block_FifoCount( p_dec->p_owner->p_fifo ) > 10 )
291 292 293 294
            {
                msleep( 1000 );
            }
        }
295
        else if( block_FifoSize( p_dec->p_owner->p_fifo ) > 50000000 /* 50 MB */ )
296 297 298 299
        {
            /* 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 "
300
                      "consumed quickly enough), resetting fifo!" );
301 302 303 304
            block_FifoEmpty( p_dec->p_owner->p_fifo );
        }

        block_FifoPut( p_dec->p_owner->p_fifo, p_block );
305 306 307
    }
    else
    {
308
        if( p_dec->b_error || (p_block && p_block->i_buffer <= 0) )
309
        {
310
            if( p_block ) block_Release( p_block );
311 312 313 314 315 316
        }
        else
        {
            DecoderDecode( p_dec, p_block );
        }
    }
317
}
318

319
void input_DecoderDiscontinuity( decoder_t * p_dec, bool b_flush )
Laurent Aimar's avatar
Laurent Aimar committed
320 321 322 323
{
    block_t *p_null;

    /* Empty the fifo */
324
    if( p_dec->p_owner->b_own_thread && b_flush )
Laurent Aimar's avatar
Laurent Aimar committed
325 326 327 328 329
        block_FifoEmpty( p_dec->p_owner->p_fifo );

    /* Send a special block */
    p_null = block_New( p_dec, 128 );
    p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY;
330 331 332
    /* FIXME check for p_packetizer or b_packitized from es_format_t of input ? */
    if( p_dec->p_owner->p_packetizer && b_flush )
        p_null->i_flags |= BLOCK_FLAG_CORRUPTED;
Laurent Aimar's avatar
Laurent Aimar committed
333 334 335 336 337
    memset( p_null->p_buffer, 0, p_null->i_buffer );

    input_DecoderDecode( p_dec, p_null );
}

338
bool input_DecoderEmpty( decoder_t * p_dec )
Laurent Aimar's avatar
 
Laurent Aimar committed
339
{
340 341
    if( p_dec->p_owner->b_own_thread
     && block_FifoCount( p_dec->p_owner->p_fifo ) > 0 )
Laurent Aimar's avatar
 
Laurent Aimar committed
342
    {
343
        return false;
Laurent Aimar's avatar
 
Laurent Aimar committed
344
    }
345
    return true;
Laurent Aimar's avatar
 
Laurent Aimar committed
346 347
}

348
void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
349 350 351 352 353 354 355 356
{
    int i;

    vlc_mutex_lock( &p_dec->p_owner->lock_cc );
    for( i = 0; i < 4; i++ )
        pb_present[i] =  p_dec->p_owner->pb_cc_present[i];
    vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
}
357
int input_DecoderSetCcState( decoder_t *p_dec, bool b_decode, int i_channel )
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

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

    if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
        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] );
        p_cc = CreateDecoder( p_owner->p_input, &fmt, VLC_OBJECT_DECODER );
        if( !p_cc )
        {
            msg_Err( p_dec, "could not create decoder" );
382
            intf_UserFatal( p_dec, false, _("Streaming / Transcoding failed"),
383 384 385 386 387 388 389
                            _("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 );
390
            vlc_object_release( p_cc );
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411
            return VLC_EGENERIC;
        }

        vlc_mutex_lock( &p_owner->lock_cc );
        p_dec->p_owner->pp_cc[i_channel] = p_cc;
        vlc_mutex_unlock( &p_owner->lock_cc );
    }
    else
    {
        decoder_t *p_cc;

        vlc_mutex_lock( &p_owner->lock_cc );
        p_cc = p_dec->p_owner->pp_cc[i_channel];
        p_dec->p_owner->pp_cc[i_channel] = NULL;
        vlc_mutex_unlock( &p_dec->p_owner->lock_cc );

        if( p_cc )
        {
            vlc_object_kill( p_cc );
            module_Unneed( p_cc, p_cc->p_module );
            DeleteDecoder( p_cc );
412
            vlc_object_release( p_cc );
413 414 415 416
        }
    }
    return VLC_SUCCESS;
}
417
int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel )
418 419 420
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

421
    *pb_decode = false;
422 423 424 425 426 427 428 429 430
    if( i_channel < 0 || i_channel >= 4 || !p_owner->pb_cc_present[i_channel] )
        return VLC_EGENERIC;

    vlc_mutex_lock( &p_owner->lock_cc );
    *pb_decode = p_dec->p_owner->pp_cc[i_channel] != NULL;
    vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
    return VLC_EGENERIC;
}

Clément Stenac's avatar
Clément Stenac committed
431 432 433 434 435 436 437 438
/**
 * 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
439 440
static decoder_t * CreateDecoder( input_thread_t *p_input,
                                  es_format_t *fmt, int i_object_type )
Sam Hocevar's avatar
 
Sam Hocevar committed
441
{
Gildas Bazin's avatar
 
Gildas Bazin committed
442
    decoder_t *p_dec;
443 444
    decoder_owner_sys_t *p_owner;
    int i;
Sam Hocevar's avatar
 
Sam Hocevar committed
445

Gildas Bazin's avatar
 
Gildas Bazin committed
446
    p_dec = vlc_object_create( p_input, i_object_type );
Gildas Bazin's avatar
 
Gildas Bazin committed
447
    if( p_dec == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
448
    {
449
        msg_Err( p_input, "out of memory" );
Sam Hocevar's avatar
 
Sam Hocevar committed
450 451 452
        return NULL;
    }

Gildas Bazin's avatar
 
Gildas Bazin committed
453 454 455
    p_dec->pf_decode_audio = 0;
    p_dec->pf_decode_video = 0;
    p_dec->pf_decode_sub = 0;
456
    p_dec->pf_get_cc = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
457
    p_dec->pf_packetize = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
458

459
    /* Initialize the decoder fifo */
Gildas Bazin's avatar
 
Gildas Bazin committed
460 461
    p_dec->p_module = NULL;

462
    memset( &null_es_format, 0, sizeof(es_format_t) );
Laurent Aimar's avatar
Laurent Aimar committed
463 464
    es_format_Copy( &p_dec->fmt_in, fmt );
    es_format_Copy( &p_dec->fmt_out, &null_es_format );
Gildas Bazin's avatar
 
Gildas Bazin committed
465 466

    /* Allocate our private structure for the decoder */
467
    p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
Gildas Bazin's avatar
 
Gildas Bazin committed
468 469 470 471 472
    if( p_dec->p_owner == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return NULL;
    }
473
    p_dec->p_owner->b_own_thread = true;
Laurent Aimar's avatar
Laurent Aimar committed
474
    p_dec->p_owner->i_preroll_end = -1;
475
    p_dec->p_owner->p_input = p_input;
Gildas Bazin's avatar
 
Gildas Bazin committed
476 477 478
    p_dec->p_owner->p_aout = NULL;
    p_dec->p_owner->p_aout_input = NULL;
    p_dec->p_owner->p_vout = NULL;
479 480
    p_dec->p_owner->p_spu_vout = NULL;
    p_dec->p_owner->i_spu_channel = 0;
Clément Stenac's avatar
Clément Stenac committed
481
    p_dec->p_owner->p_sout = p_input->p->p_sout;
482
    p_dec->p_owner->p_sout_input = NULL;
483
    p_dec->p_owner->p_packetizer = NULL;
484

485 486 487 488 489 490
    /* decoder fifo */
    if( ( p_dec->p_owner->p_fifo = block_FifoNew( p_dec ) ) == NULL )
    {
        msg_Err( p_dec, "out of memory" );
        return NULL;
    }
491

Gildas Bazin's avatar
 
Gildas Bazin committed
492 493 494 495 496
    /* 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;
Gildas Bazin's avatar
 
Gildas Bazin committed
497 498
    p_dec->pf_picture_link    = vout_link_picture;
    p_dec->pf_picture_unlink  = vout_unlink_picture;
499 500
    p_dec->pf_spu_buffer_new  = spu_new_buffer;
    p_dec->pf_spu_buffer_del  = spu_del_buffer;
Gildas Bazin's avatar
 
Gildas Bazin committed
501

Gildas Bazin's avatar
 
Gildas Bazin committed
502 503
    vlc_object_attach( p_dec, p_input );

504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520
    /* Find a suitable decoder/packetizer module */
    if( i_object_type == VLC_OBJECT_DECODER )
        p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );
    else
        p_dec->p_module = module_Need( p_dec, "packetizer", "$packetizer", 0 );

    /* 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
521 522 523
            es_format_Copy( &p_dec->p_owner->p_packetizer->fmt_out,
                            &null_es_format );

524 525 526 527 528 529 530 531 532 533
            vlc_object_attach( p_dec->p_owner->p_packetizer, p_input );

            p_dec->p_owner->p_packetizer->p_module =
                module_Need( p_dec->p_owner->p_packetizer,
                             "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 );
534
                vlc_object_release( p_dec->p_owner->p_packetizer );
535 536 537 538
            }
        }
    }

539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555
    /* 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];
            }
        }
    }
556
    /* */
557
    p_owner->b_cc_supported = false;
558 559 560
    if( i_object_type == VLC_OBJECT_DECODER )
    {
        if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
561
            p_owner->b_cc_supported = true;
562
        if( p_dec->pf_get_cc )
563
            p_owner->b_cc_supported = true;
564 565 566 567 568
    }

    vlc_mutex_init( p_dec, &p_owner->lock_cc );
    for( i = 0; i < 4; i++ )
    {
569
        p_owner->pb_cc_present[i] = false;
570 571
        p_owner->pp_cc[i] = NULL;
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
572 573 574
    return p_dec;
}

Clément Stenac's avatar
Clément Stenac committed
575 576 577 578 579 580
/**
 * The decoding main loop
 *
 * \param p_dec the decoder
 * \return 0
 */
Gildas Bazin's avatar
 
Gildas Bazin committed
581 582
static int DecoderThread( decoder_t * p_dec )
{
583
    block_t *p_block;
Gildas Bazin's avatar
 
Gildas Bazin committed
584 585

    /* The decoder's main loop */
586
    while( !p_dec->b_die && !p_dec->b_error )
Gildas Bazin's avatar
 
Gildas Bazin committed
587
    {
588
        if( ( p_block = block_FifoGet( p_dec->p_owner->p_fifo ) ) == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
589
        {
590
            p_dec->b_error = 1;
Gildas Bazin's avatar
 
Gildas Bazin committed
591 592
            break;
        }
593
        if( DecoderDecode( p_dec, p_block ) != VLC_SUCCESS )
594 595 596 597
        {
            break;
        }
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
598

599 600 601 602
    while( !p_dec->b_die )
    {
        /* Trash all received PES packets */
        p_block = block_FifoGet( p_dec->p_owner->p_fifo );
603
        if( p_block ) block_Release( p_block );
604
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
605

606 607
    /* We do it here because of the dll loader that wants close() in the
     * same thread than open()/decode() */
608
    module_Unneed( p_dec, p_dec->p_module );
Gildas Bazin's avatar
 
Gildas Bazin committed
609

610 611
    return 0;
}
Gildas Bazin's avatar
 
Gildas Bazin committed
612

Laurent Aimar's avatar
Laurent Aimar committed
613 614
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
615 616 617
    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
618 619 620 621 622 623 624
        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
    else if( p->i_dts > 0 )
        *pi_preroll = __MIN( *pi_preroll, p->i_dts );
}
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{
    input_thread_t *p_input = p_dec->p_owner->p_input;
625
    const int i_rate = p_block->i_rate;
Laurent Aimar's avatar
Laurent Aimar committed
626 627 628 629 630 631 632 633
    aout_buffer_t *p_aout_buf;

    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
    {
        vlc_mutex_lock( &p_input->p->counters.counters_lock );
        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio, 1, NULL );
        vlc_mutex_unlock( &p_input->p->counters.counters_lock );

634
        if( p_aout_buf->start_date < p_dec->p_owner->i_preroll_end )
Laurent Aimar's avatar
Laurent Aimar committed
635 636 637
        {
            aout_DecDeleteBuffer( p_dec->p_owner->p_aout,
                                  p_dec->p_owner->p_aout_input, p_aout_buf );
638
            continue;
Laurent Aimar's avatar
Laurent Aimar committed
639
        }
640 641

        if( p_dec->p_owner->i_preroll_end > 0 )
Laurent Aimar's avatar
Laurent Aimar committed
642
        {
643 644
            /* FIXME TODO flush audio output (don't know how to do that) */
            msg_Dbg( p_dec, "End of audio preroll" );
Laurent Aimar's avatar
Laurent Aimar committed
645 646
            p_dec->p_owner->i_preroll_end = -1;
        }
647 648
        aout_DecPlay( p_dec->p_owner->p_aout,
                      p_dec->p_owner->p_aout_input,
649
                      p_aout_buf, i_rate );
Laurent Aimar's avatar
Laurent Aimar committed
650 651
    }
}
652 653 654
static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
{
    block_t *p_cc;
655
    bool pb_present[4];
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
    int i;
    int i_cc_decoder;

    assert( p_dec_cc->pf_get_cc != NULL );

    /* Do not try retreiving CC if not wanted (sout) or cannot be retreived */
    if( !p_dec->p_owner->b_cc_supported )
        return;

    p_cc = p_dec_cc->pf_get_cc( p_dec_cc, pb_present );
    if( !p_cc )
        return;

    vlc_mutex_lock( &p_dec->p_owner->lock_cc );
    for( i = 0, i_cc_decoder = 0; i < 4; i++ )
    {
        p_dec->p_owner->pb_cc_present[i] |= pb_present[i];
        if( p_dec->p_owner->pp_cc[i] )
            i_cc_decoder++;
    }

    for( i = 0; i < 4; i++ )
    {
        if( !p_dec->p_owner->pp_cc[i] )
            continue;

        if( i_cc_decoder > 1 )
            DecoderDecode( p_dec->p_owner->pp_cc[i], block_Duplicate( p_cc ) );
        else
            DecoderDecode( p_dec->p_owner->pp_cc[i], p_cc );
        i_cc_decoder--;
    }
    vlc_mutex_unlock( &p_dec->p_owner->lock_cc );
}
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 717 718
static void VoutDisplayedPicture( vout_thread_t *p_vout, picture_t *p_pic )
{
    vlc_mutex_lock( &p_vout->picture_lock );

    if( p_pic->i_status == READY_PICTURE )
    {
        /* Grr cannot destroy ready picture by myself so be sure vout won't like it */
        p_pic->date = 1;
    }
    else if( p_pic->i_refcount > 0 )
    {
        p_pic->i_status = DISPLAYED_PICTURE;
    }
    else
    {
        p_pic->i_status = DESTROYED_PICTURE;
        p_vout->i_heap_size--;
    }

    vlc_mutex_unlock( &p_vout->picture_lock );
}
static void VoutFlushPicture( vout_thread_t *p_vout )
{
    int i;
    vlc_mutex_lock( &p_vout->picture_lock );
    for( i = 0; i < p_vout->render.i_pictures; i++ )
    {
        picture_t *p_pic = p_vout->render.pp_picture[i];

719 720
        if( p_pic->i_status == READY_PICTURE ||
            p_pic->i_status == DISPLAYED_PICTURE )
721 722 723 724 725 726 727 728
        {
            /* We cannot change picture status if it is in READY_PICTURE state,
             * Just make sure they won't be displayed */
            p_pic->date = 1;
        }
    }
    vlc_mutex_unlock( &p_vout->picture_lock );
}
Laurent Aimar's avatar
Laurent Aimar committed
729 730 731 732 733 734 735 736 737 738 739
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{
    input_thread_t *p_input = p_dec->p_owner->p_input;
    picture_t *p_pic;

    while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
    {
        vlc_mutex_lock( &p_input->p->counters.counters_lock );
        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video, 1, NULL );
        vlc_mutex_unlock( &p_input->p->counters.counters_lock );

740
        if( p_pic->date < p_dec->p_owner->i_preroll_end )
Laurent Aimar's avatar
Laurent Aimar committed
741
        {
742 743
            VoutDisplayedPicture( p_dec->p_owner->p_vout, p_pic );
            continue;
Laurent Aimar's avatar
Laurent Aimar committed
744
        }
745 746

        if( p_dec->p_owner->i_preroll_end > 0 )
Laurent Aimar's avatar
Laurent Aimar committed
747
        {
748 749 750 751
            msg_Dbg( p_dec, "End of video preroll" );
            if( p_dec->p_owner->p_vout )
                VoutFlushPicture( p_dec->p_owner->p_vout );
            /* */
Laurent Aimar's avatar
Laurent Aimar committed
752 753
            p_dec->p_owner->i_preroll_end = -1;
        }
754

755 756 757
        if( ( !p_dec->p_owner->p_packetizer || !p_dec->p_owner->p_packetizer->pf_get_cc ) && p_dec->pf_get_cc )
            DecoderGetCc( p_dec, p_dec );

758 759 760
        vout_DatePicture( p_dec->p_owner->p_vout, p_pic,
                          p_pic->date );
        vout_DisplayPicture( p_dec->p_owner->p_vout, p_pic );
Laurent Aimar's avatar
Laurent Aimar committed
761 762 763
    }
}

764 765 766 767 768 769 770
/**
 * Decode a block
 *
 * \param p_dec the decoder object
 * \param p_block the block to decode
 * \return VLC_SUCCESS or an error code
 */
771 772
static int DecoderDecode( decoder_t *p_dec, block_t *p_block )
{
Laurent Aimar's avatar
Laurent Aimar committed
773
    decoder_owner_sys_t *p_sys = (decoder_owner_sys_t *)p_dec->p_owner;
774
    const int i_rate = p_block ? p_block->i_rate : INPUT_RATE_DEFAULT;
775

776
    if( p_block && p_block->i_buffer <= 0 )
777 778 779 780 781
    {
        block_Release( p_block );
        return VLC_SUCCESS;
    }

782
#ifdef ENABLE_SOUT
783 784 785 786
    if( p_dec->i_object_type == VLC_OBJECT_PACKETIZER )
    {
        block_t *p_sout_block;

787 788
        while( ( p_sout_block =
                     p_dec->pf_packetize( p_dec, p_block ? &p_block : 0 ) ) )
789
        {
790
            if( !p_dec->p_owner->p_sout_input )
791 792
            {
                es_format_Copy( &p_dec->p_owner->sout, &p_dec->fmt_out );
Laurent Aimar's avatar
Laurent Aimar committed
793

794
                p_dec->p_owner->sout.i_group = p_dec->fmt_in.i_group;
Laurent Aimar's avatar
Laurent Aimar committed
795
                p_dec->p_owner->sout.i_id = p_dec->fmt_in.i_id;
796 797
                if( p_dec->fmt_in.psz_language )
                {
798 799
                    if( p_dec->p_owner->sout.psz_language )
                        free( p_dec->p_owner->sout.psz_language );
800 801
                    p_dec->p_owner->sout.psz_language =
                        strdup( p_dec->fmt_in.psz_language );
802
                }
Gildas Bazin's avatar
 
Gildas Bazin committed
803

804
                p_dec->p_owner->p_sout_input =
805 806
                    sout_InputNew( p_dec->p_owner->p_sout,
                                   &p_dec->p_owner->sout );
807

808
                if( p_dec->p_owner->p_sout_input == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
809
                {
810 811
                    msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
                             (char *)&p_dec->p_owner->sout.i_codec );
812
                    p_dec->b_error = true;
Gildas Bazin's avatar
 
Gildas Bazin committed
813

814
                    while( p_sout_block )
815
                    {
816
                        block_t *p_next = p_sout_block->p_next;
817 818
                        block_Release( p_sout_block );
                        p_sout_block = p_next;
819
                    }
820 821 822
                    break;
                }
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
823

824 825
            while( p_sout_block )
            {
826
                block_t *p_next = p_sout_block->p_next;
Gildas Bazin's avatar
 
Gildas Bazin committed
827

828
                p_sout_block->p_next = NULL;
829
                p_sout_block->i_rate = i_rate;
Gildas Bazin's avatar
 
Gildas Bazin committed
830

831
                sout_InputSendBuffer( p_dec->p_owner->p_sout_input,
832
                                      p_sout_block );
Gildas Bazin's avatar
 
Gildas Bazin committed
833

834
                p_sout_block = p_next;
Gildas Bazin's avatar
 
Gildas Bazin committed
835
            }
836

837
            /* For now it's enough, as only sout impact on this flag */
838
            if( p_dec->p_owner->p_sout->i_out_pace_nocontrol > 0 &&
Clément Stenac's avatar
Clément Stenac committed
839
                p_dec->p_owner->p_input->p->b_out_pace_control )
840
            {
841
                msg_Dbg( p_dec, "switching to sync mode" );
842
                p_dec->p_owner->p_input->p->b_out_pace_control = false;
843 844
            }
            else if( p_dec->p_owner->p_sout->i_out_pace_nocontrol <= 0 &&
Clément Stenac's avatar
Clément Stenac committed
845
                     !p_dec->p_owner->p_input->p->b_out_pace_control )
846
            {
847
                msg_Dbg( p_dec, "switching to async mode" );
848
                p_dec->p_owner->p_input->p->b_out_pace_control = true;
849
            }
Gildas Bazin's avatar
 
Gildas Bazin committed
850
        }
851
    }
852 853 854
    else
#endif
    if( p_dec->fmt_in.i_cat == AUDIO_ES )
855
    {
856 857
        if( p_block )
            DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );
858

859 860 861 862 863 864
        if( p_dec->p_owner->p_packetizer )
        {
            block_t *p_packetized_block;
            decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;

            while( (p_packetized_block =
865
                    p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
866
            {
867 868
                if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
                {
869 870
                    es_format_Clean( &p_dec->fmt_in );
                    es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
871 872
                }

873
                while( p_packetized_block )
874
                {
875 876
                    block_t *p_next = p_packetized_block->p_next;
                    p_packetized_block->p_next = NULL;
877
                    p_packetized_block->i_rate = i_rate;
878

Laurent Aimar's avatar
Laurent Aimar committed
879
                    DecoderDecodeAudio( p_dec, p_packetized_block );
880 881

                    p_packetized_block = p_next;
882 883 884
                }
            }
        }
885
        else if( p_block )
886
        {
Laurent Aimar's avatar
Laurent Aimar committed
887
            DecoderDecodeAudio( p_dec, p_block );
888
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
889
    }
890
    else if( p_dec->fmt_in.i_cat == VIDEO_ES )
891
    {
892 893
        if( p_block )
            DecoderUpdatePreroll( &p_dec->p_owner->i_preroll_end, p_block );
894

895 896 897 898 899 900
        if( p_dec->p_owner->p_packetizer )
        {
            block_t *p_packetized_block;
            decoder_t *p_packetizer = p_dec->p_owner->p_packetizer;

            while( (p_packetized_block =
901
                    p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
902
            {
903 904
                if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
                {
905 906
                    es_format_Clean( &p_dec->fmt_in );
                    es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
907
                }
908 909
                if( p_packetizer->pf_get_cc )
                    DecoderGetCc( p_dec, p_packetizer );
910

911
                while( p_packetized_block )
912
                {
913 914
                    block_t *p_next = p_packetized_block->p_next;
                    p_packetized_block->p_next = NULL;
915
                    p_packetized_block->i_rate = i_rate;
916

Laurent Aimar's avatar
Laurent Aimar committed
917
                    DecoderDecodeVideo( p_dec, p_packetized_block );
918 919

                    p_packetized_block = p_next;
920 921 922
                }
            }
        }
923
        else if( p_block )
924
        {
Laurent Aimar's avatar
Laurent Aimar committed
925
            DecoderDecodeVideo( p_dec, p_block );