decoder.c 74.8 KB
Newer Older
1
/*****************************************************************************
2
 * decoder.c: Functions for the management of decoders
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1999-2004 VLC authors and VideoLAN
5
 * $Id$
6 7
 *
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8
 *          Gildas Bazin <gbazin@videolan.org>
9
 *          Laurent Aimar <fenrir@via.ecp.fr>
10
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
11 12 13
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
14
 * (at your option) any later version.
15
 *
16 17
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
18 19
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
20
 *
Jean-Baptiste Kempf's avatar
LGPL  
Jean-Baptiste Kempf committed
21 22 23
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software 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>
35

Clément Stenac's avatar
Clément Stenac 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>
Clément Stenac's avatar
Clément Stenac committed
45 46 47

#include "audio_output/aout_internal.h"
#include "stream_output/stream_output.h"
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 );

Gildas Bazin's avatar
 
Gildas Bazin 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 * );
76
static int vout_get_buffer_size( decoder_t * );
Gildas Bazin's avatar
 
Gildas Bazin committed
77 78
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
79

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

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

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

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

96 97
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
98

99 100
    vlc_thread_t     thread;

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

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

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

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

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

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

    vout_thread_t   *p_vout;

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

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

    /* Buffering */
    bool b_buffering;
    struct
    {
143
        bool b_first;
144 145 146 147 148 149 150 151 152 153 154
        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;
155 156 157

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

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

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

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

175 176 177 178
#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)

179 180 181 182 183 184 185 186
/* 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
187 188 189
/*****************************************************************************
 * Public functions
 *****************************************************************************/
190 191 192 193 194 195 196 197 198 199 200
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 );
}
201 202 203 204
int decoder_GetPictureCount( decoder_t *p_decoder )
{
    return p_decoder->pf_vout_buffer_size( p_decoder );
}
205 206 207 208 209 210 211 212 213
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 );
}

214 215 216 217 218 219 220
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 );
}

221 222
subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
                                     const subpicture_updater_t *p_dyn )
223
{
224
    subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder, p_dyn );
225 226 227 228
    if( !p_subpicture )
        msg_Warn( p_decoder, "can't get output subpicture" );
    return p_subpicture;
}
229

230 231 232 233
void decoder_DeleteSubpicture( decoder_t *p_decoder, subpicture_t *p_subpicture )
{
    p_decoder->pf_spu_buffer_del( p_decoder, p_subpicture );
}
234

Laurent Aimar's avatar
Laurent Aimar committed
235 236 237 238 239 240
/* decoder_GetInputAttachments:
 */
int decoder_GetInputAttachments( decoder_t *p_dec,
                                 input_attachment_t ***ppp_attachment,
                                 int *pi_attachment )
{
241 242 243 244
    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
245
}
246 247 248 249
/* decoder_GetDisplayDate:
 */
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
250
    if( !p_dec->pf_get_display_date )
251
        return VLC_TS_INVALID;
252

253
    return p_dec->pf_get_display_date( p_dec, i_ts );
254 255 256 257 258
}
/* decoder_GetDisplayRate:
 */
int decoder_GetDisplayRate( decoder_t *p_dec )
{
259
    if( !p_dec->pf_get_display_rate )
Laurent Aimar's avatar
Laurent Aimar committed
260
        return INPUT_RATE_DEFAULT;
261 262

    return p_dec->pf_get_display_rate( p_dec );
263
}
264

265 266 267 268 269
/* 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  )
270
{
271
    decoder_t *p_dec = NULL;
272
    const char *psz_type = p_sout ? N_("packetizer") : N_("decoder");
273
    int i_priority;
274

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

287
    if( !p_dec->p_module )
Sam Hocevar's avatar
 
Sam Hocevar committed
288
    {
289
        DecoderUnsupportedCodec( p_dec, fmt->i_codec );
Gildas Bazin's avatar
 
Gildas Bazin committed
290 291

        DeleteDecoder( p_dec );
292
        return NULL;
Henri Fallon's avatar
 
Henri Fallon committed
293 294
    }

295
    p_dec->p_owner->p_clock = p_clock;
296
    assert( p_dec->fmt_out.i_cat != UNKNOWN_ES );
297

298
    if( p_dec->fmt_out.i_cat == AUDIO_ES )
299
        i_priority = VLC_THREAD_PRIORITY_AUDIO;
300
    else
301
        i_priority = VLC_THREAD_PRIORITY_VIDEO;
302

303
    /* Spawn the decoder thread */
304
    if( vlc_clone( &p_dec->p_owner->thread, DecoderThread, p_dec, i_priority ) )
Henri Fallon's avatar
 
Henri Fallon committed
305
    {
306 307 308 309
        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
310 311
    }

312
    return p_dec;
313 314
}

315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340

/**
 * 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 );
}


Clément Stenac's avatar
Clément Stenac committed
341 342 343 344 345 346 347
/**
 * Kills a decoder thread and waits until it's finished
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
 * \return nothing
 */
348
void input_DecoderDelete( decoder_t *p_dec )
349
{
350 351
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

352
    vlc_cancel( p_owner->thread );
353

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

364
    vlc_join( p_owner->thread, NULL );
365 366
    p_owner->b_paused = b_was_paused;

367
    module_unneed( p_dec, p_dec->p_module );
368

369
    /* */
370
    if( p_dec->p_owner->cc.b_supported )
371 372 373
    {
        int i;
        for( i = 0; i < 4; i++ )
374
            input_DecoderSetCcState( p_dec, false, i );
375 376
    }

377
    /* Delete decoder */
Gildas Bazin's avatar
 
Gildas Bazin committed
378
    DeleteDecoder( p_dec );
379
}
Clément Stenac's avatar
Clément Stenac committed
380 381

/**
382
 * Put a block_t in the decoder's fifo.
383
 * Thread-safe w.r.t. the decoder. May be a cancellation point.
Clément Stenac's avatar
Clément Stenac committed
384 385 386 387
 *
 * \param p_dec the decoder object
 * \param p_block the data block
 */
388
void input_DecoderDecode( decoder_t *p_dec, block_t *p_block, bool b_do_pace )
389
{
390 391
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

392
    if( b_do_pace )
393
    {
394 395 396 397 398 399
        /* 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 );
400
    }
401
#ifdef __arm__
402
    else if( block_FifoSize( p_owner->p_fifo ) > 50*1024*1024 /* 50 MiB */ )
403
#else
404
    else if( block_FifoSize( p_owner->p_fifo ) > 400*1024*1024 /* 400 MiB, ie ~ 50mb/s for 60s */ )
405
#endif
406
    {
407
        /* FIXME: ideally we would check the time amount of data
408
         * in the FIFO instead of its size. */
409 410 411
        msg_Warn( p_dec, "decoder/packetizer fifo full (data not "
                  "consumed quickly enough), resetting fifo!" );
        block_FifoEmpty( p_owner->p_fifo );
412
    }
413 414

    block_FifoPut( p_owner->p_fifo, p_block );
415
}
416

417
bool input_DecoderIsEmpty( decoder_t * p_dec )
Laurent Aimar's avatar
 
Laurent Aimar committed
418
{
419 420
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    assert( !p_owner->b_buffering );
Laurent Aimar's avatar
Laurent Aimar committed
421

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

436
void input_DecoderIsCcPresent( decoder_t *p_dec, bool pb_present[4] )
437
{
438
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
439 440
    int i;

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

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

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

484
        vlc_mutex_lock( &p_owner->lock );
485
        p_owner->cc.pp_decoder[i_channel] = p_cc;
486
        vlc_mutex_unlock( &p_owner->lock );
487 488 489 490 491
    }
    else
    {
        decoder_t *p_cc;

492
        vlc_mutex_lock( &p_owner->lock );
493 494
        p_cc = p_owner->cc.pp_decoder[i_channel];
        p_owner->cc.pp_decoder[i_channel] = NULL;
495
        vlc_mutex_unlock( &p_owner->lock );
496 497 498

        if( p_cc )
        {
499
            module_unneed( p_cc, p_cc->p_module );
500 501 502 503 504
            DeleteDecoder( p_cc );
        }
    }
    return VLC_SUCCESS;
}
505
int input_DecoderGetCcState( decoder_t *p_dec, bool *pb_decode, int i_channel )
506 507 508
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

509
    *pb_decode = false;
510
    if( i_channel < 0 || i_channel >= 4 || !p_owner->cc.pb_present[i_channel] )
511 512
        return VLC_EGENERIC;

513
    vlc_mutex_lock( &p_owner->lock );
514
    *pb_decode = p_owner->cc.pp_decoder[i_channel] != NULL;
515
    vlc_mutex_unlock( &p_owner->lock );
516 517 518
    return VLC_EGENERIC;
}

519 520 521 522 523 524
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 );

525
    assert( !p_owner->b_paused || !b_paused );
526

527
    p_owner->b_paused = b_paused;
528
    p_owner->pause.i_date = i_date;
529
    p_owner->pause.i_ignore = 0;
530
    vlc_cond_signal( &p_owner->wait_request );
531

Laurent Aimar's avatar
Laurent Aimar committed
532
    DecoderOutputChangePause( p_dec, b_paused, i_date );
533

534 535
    vlc_mutex_unlock( &p_owner->lock );
}
536 537 538 539 540 541 542 543 544

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

Laurent Aimar's avatar
Laurent Aimar committed
546
void input_DecoderStartBuffering( decoder_t *p_dec )
547 548 549
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Laurent Aimar's avatar
Laurent Aimar committed
550
    vlc_mutex_lock( &p_owner->lock );
551

Laurent Aimar's avatar
Laurent Aimar committed
552
    DecoderFlush( p_dec );
Laurent Aimar's avatar
Laurent Aimar committed
553

554
    p_owner->buffer.b_first = true;
555 556 557
    p_owner->buffer.b_full = false;
    p_owner->buffer.i_count = 0;

558 559
    assert( !p_owner->buffer.p_picture && !p_owner->buffer.p_subpic &&
            !p_owner->buffer.p_audio && !p_owner->buffer.p_block );
560 561 562 563 564 565 566 567 568 569

    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;

570 571 572 573
    p_owner->buffer.p_block = NULL;
    p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;


574 575
    p_owner->b_buffering = true;

576
    vlc_cond_signal( &p_owner->wait_request );
577

Laurent Aimar's avatar
Laurent Aimar committed
578 579
    vlc_mutex_unlock( &p_owner->lock );
}
Laurent Aimar's avatar
Laurent Aimar committed
580

Laurent Aimar's avatar
Laurent Aimar committed
581 582
void input_DecoderStopBuffering( decoder_t *p_dec )
{
583 584 585 586 587 588
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

    p_owner->b_buffering = false;

589
    vlc_cond_signal( &p_owner->wait_request );
590 591

    vlc_mutex_unlock( &p_owner->lock );
592 593
}

594 595 596 597 598 599
void input_DecoderWaitBuffering( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

600
    while( p_owner->b_buffering && !p_owner->buffer.b_full )
601 602
    {
        block_FifoWake( p_owner->p_fifo );
603
        vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
604 605 606 607
    }

    vlc_mutex_unlock( &p_owner->lock );
}
608

609 610 611 612 613 614 615
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 );
616
    if( p_dec->fmt_out.i_cat == VIDEO_ES )
617
    {
618 619 620 621
        if( p_owner->b_paused && p_owner->p_vout )
        {
            vout_NextPicture( p_owner->p_vout, pi_duration );
            p_owner->pause.i_ignore++;
622
            vlc_cond_signal( &p_owner->wait_request );
623 624 625 626 627 628
        }
    }
    else
    {
        /* TODO subtitle should not be flushed */
        DecoderFlush( p_dec );
629 630 631
    }
    vlc_mutex_unlock( &p_owner->lock );
}
632

Laurent Aimar's avatar
Laurent Aimar committed
633
bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_meta_t **pp_meta )
634 635 636 637 638 639 640 641 642 643
{
    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
644 645 646 647 648 649 650 651 652 653 654

        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 );
            }
        }
655 656 657 658 659 660
        p_owner->b_fmt_description = false;
    }
    vlc_mutex_unlock( &p_owner->lock );
    return b_changed;
}

661 662 663 664 665 666 667
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 );
}

668
void input_DecoderGetObjects( decoder_t *p_dec,
669
                              vout_thread_t **pp_vout, audio_output_t **pp_aout )
670 671 672 673 674
{
    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
675
        *pp_vout = p_owner->p_vout ? vlc_object_hold( p_owner->p_vout ) : NULL;
676
    if( pp_aout )
Laurent Aimar's avatar
Laurent Aimar committed
677
        *pp_aout = p_owner->p_aout ? vlc_object_hold( p_owner->p_aout ) : NULL;
678 679 680
    vlc_mutex_unlock( &p_owner->lock );
}

Laurent Aimar's avatar
Laurent Aimar committed
681 682 683
/*****************************************************************************
 * Internal functions
 *****************************************************************************/
684 685 686 687
static int DecoderGetInputAttachments( decoder_t *p_dec,
                                       input_attachment_t ***ppp_attachment,
                                       int *pi_attachment )
{
688 689 690 691 692
    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,
693 694 695 696 697 698 699 700
                          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 )
701
        i_ts = VLC_TS_INVALID;
702 703
    vlc_mutex_unlock( &p_owner->lock );

704
    if( !p_owner->p_clock || i_ts <= VLC_TS_INVALID )
705 706
        return i_ts;

707
    if( input_clock_ConvertTS( p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) )
708
        return VLC_TS_INVALID;
709 710

    return i_ts;
711 712 713 714 715 716 717 718 719
}
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
720 721 722 723

/* */
static void DecoderUnsupportedCodec( decoder_t *p_dec, vlc_fourcc_t codec )
{
724
    msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'. "
Laurent Aimar's avatar
Laurent Aimar committed
725 726
             "VLC probably does not support this sound or video format.",
             (char*)&codec );
727 728 729 730
    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
731 732 733
}


Clément Stenac's avatar
Clément Stenac committed
734 735 736 737 738
/**
 * Create a decoder object
 *
 * \param p_input the input thread
 * \param p_es the es descriptor
739
 * \param b_packetizer instead of a decoder
Clément Stenac's avatar
Clément Stenac committed
740 741
 * \return the decoder object
 */
742 743
static decoder_t * CreateDecoder( vlc_object_t *p_parent,
                                  input_thread_t *p_input,
744
                                  es_format_t *fmt, bool b_packetizer,
745
                                  input_resource_t *p_resource,
746
                                  sout_instance_t *p_sout )
Sam Hocevar's avatar
 
Sam Hocevar committed
747
{
Gildas Bazin's avatar
 
Gildas Bazin committed
748
    decoder_t *p_dec;
749
    decoder_owner_sys_t *p_owner;
750 751
    es_format_t null_es_format;

752
    p_dec = vlc_custom_create( p_parent, sizeof( *p_dec ), "decoder" );
Gildas Bazin's avatar
 
Gildas Bazin committed
753
    if( p_dec == NULL )
Sam Hocevar's avatar
 
Sam Hocevar committed
754 755
        return NULL;

756 757 758 759 760
    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;
Gildas Bazin's avatar
 
Gildas Bazin committed
761

762
    /* Initialize the decoder */
Gildas Bazin's avatar
 
Gildas Bazin committed
763 764
    p_dec->p_module = NULL;

765
    memset( &null_es_format, 0, sizeof(es_format_t) );
766 767
    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
768

769 770
    p_dec->p_description = NULL;

Gildas Bazin's avatar
 
Gildas Bazin committed
771
    /* Allocate our private structure for the decoder */
772
    p_dec->p_owner = p_owner = malloc( sizeof( decoder_owner_sys_t ) );
773
    if( unlikely(p_owner == NULL) )
774 775
    {
        vlc_object_release( p_dec );
Gildas Bazin's avatar
 
Gildas Bazin committed
776
        return NULL;
777
    }
778 779 780
    p_owner->i_preroll_end = VLC_TS_INVALID;
    p_owner->i_last_rate = INPUT_RATE_DEFAULT;
    p_owner->p_input = p_input;
781
    p_owner->p_resource = p_resource;
782 783 784 785 786 787 788 789 790
    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;
791

792
    /* decoder fifo */
793 794
    p_owner->p_fifo = block_FifoNew();
    if( unlikely(p_owner->p_fifo == NULL) )
795
    {
796
        free( p_owner );
797
        vlc_object_release( p_dec );
798
        return NULL;
799
    }
800

Gildas Bazin's avatar
 
Gildas Bazin committed
801 802 803 804
    /* 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;
805
    p_dec->pf_vout_buffer_size = vout_get_buffer_size;
Gildas Bazin's avatar
 
Gildas Bazin committed
806 807
    p_dec->pf_picture_link    = vout_link_picture;
    p_dec->pf_picture_unlink  = vout_unlink_picture;
808 809
    p_dec->pf_spu_buffer_new  = spu_new_buffer;
    p_dec->pf_spu_buffer_del  = spu_del_buffer;
810 811 812 813
    /* */
    p_dec->pf_get_attachments  = DecoderGetInputAttachments;
    p_dec->pf_get_display_date = DecoderGetDisplayDate;
    p_dec->pf_get_display_rate = DecoderGetDisplayRate;
Gildas Bazin's avatar
 
Gildas Bazin committed
814

815
    /* Find a suitable decoder/packetizer module */
816
    if( !b_packetizer )
817
        p_dec->p_module = module_need( p_dec, "decoder", "$codec", false );
818
    else
819
        p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false );
820 821

    /* Check if decoder requires already packetized data */
822
    if( !b_packetizer &&
823 824
        p_dec->b_need_packetized && !p_dec->fmt_in.b_packetized )
    {
825
        p_owner->p_packetizer =
826
            vlc_custom_create( p_parent, sizeof( decoder_t ), "packetizer" );
827
        if( p_owner->p_packetizer )
828
        {
829
            es_format_Copy( &p_owner->p_packetizer->fmt_in,
830 831
                            &p_dec->fmt_in );

832
            es_format_Copy( &p_owner->p_packetizer->fmt_out,
833 834
                            &null_es_format );

835 836
            p_owner->p_packetizer->p_module =
                module_need( p_owner->p_packetizer,
837
                             "packetizer", "$packetizer", false );
838

839
            if( !p_owner->p_packetizer->p_module )
840
            {
841 842
                es_format_Clean( &p_owner->p_packetizer->fmt_in );
                vlc_object_release( p_owner->p_packetizer );
843 844 845 846
            }
        }
    }

847 848 849
    /* Copy ourself the input replay gain */
    if( fmt->i_cat == AUDIO_ES )
    {
850
        for( unsigned i = 0; i < AUDIO_REPLAY_GAIN_MAX; i++ )
851 852 853 854 855 856 857 858 859 860 861 862 863
        {
            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];
            }
        }
    }
864 865 866

    /* */
    vlc_mutex_init( &p_owner->lock );
867 868
    vlc_cond_init( &p_owner->wait_request );
    vlc_cond_init( &p_owner->wait_acknowledge );
869

870 871
    p_owner->b_fmt_description = false;
    es_format_Init( &p_owner->fmt_description, UNKNOWN_ES, 0 );
Laurent Aimar's avatar
Laurent Aimar committed
872
    p_owner->p_description = NULL;
873

874 875
    p_owner->b_exit = false;

876
    p_owner->b_paused = false;
877
    p_owner->pause.i_date = VLC_TS_INVALID;
878
    p_owner->pause.i_ignore = 0;
879 880

    p_owner->b_buffering = false;
881
    p_owner->buffer.b_first = true;
882 883 884 885 886
    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;
887
    p_owner->buffer.p_block = NULL;
888 889 890

    p_owner->b_flushing = false;

891
    /* */
892
    p_owner->cc.b_supported = false;
893
    if( !b_packetizer )
894 895
    {
        if( p_owner->p_packetizer && p_owner->p_packetizer->pf_get_cc )
896
            p_owner->cc.b_supported = true;
897
        if( p_dec->pf_get_cc )
898
            p_owner->cc.b_supported = true;
899 900
    }

901
    for( unsigned i = 0; i < 4; i++ )
902
    {
903 904
        p_owner->cc.pb_present[i] = false;
        p_owner->cc.pp_decoder[i] = NULL;
905
    }
906
    p_owner->i_ts_delay = 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
907 908 909
    return p_dec;
}

Clément Stenac's avatar
Clément Stenac committed
910 911 912 913 914
/**
 * The decoding main loop
 *
 * \param p_dec the decoder
 */
915
static void *DecoderThread( void *p_data )
Gildas Bazin's avatar
 
Gildas Bazin committed
916
{
917
    decoder_t *p_dec = (decoder_t *)p_data;
918 919
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Gildas Bazin's avatar
 
Gildas Bazin committed
920
    /* The decoder's main loop */
921
    for( ;; )
922
    {
923
        block_t *p_block = block_FifoGet( p_owner->p_fifo );
924

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

929
        if( p_block )
930
        {
931 932
            int canc = vlc_savecancel();

933 934 935 936 937 938 939 940
            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;
            }

941
            if( p_dec->b_error )
942
                DecoderError( p_dec, p_block );
943 944
            else
                DecoderProcess( p_dec, p_block );
945 946

            vlc_restorecancel( canc );
947
        }
948
    }
949
    return NULL;
950
}
Gildas Bazin's avatar
 
Gildas Bazin committed
951

952 953 954 955 956 957 958 959 960 961 962 963 964 965
static block_t *DecoderBlockFlushNew()
{
    block_t *p_null = block_Alloc( 128 );
    if( !p_null )
        return NULL;

    p_null->i_flags |= BLOCK_FLAG_DISCONTINUITY |
                       BLOCK_FLAG_CORRUPTED |
                       BLOCK_FLAG_CORE_FLUSH;
    memset( p_null->p_buffer, 0, p_null->i_buffer );

    return p_null;
}

Laurent Aimar's avatar
Laurent Aimar committed
966 967 968 969
static void DecoderFlush( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

970
    vlc_assert_locked( &p_owner->lock );
Laurent Aimar's avatar
Laurent Aimar committed
971

972 973
    /* Empty the fifo */
    block_FifoEmpty( p_owner->p_fifo );
Laurent Aimar's avatar
Laurent Aimar committed
974

975 976
    /* Monitor for flush end */
    p_owner->b_flushing = true;
977
    vlc_cond_signal( &p_owner->wait_request );
Laurent Aimar's avatar
Laurent Aimar committed
978 979

    /* Send a special block */
980
    block_t *p_null = DecoderBlockFlushNew();
Laurent Aimar's avatar
Laurent Aimar committed
981 982
    if( !p_null )
        return;
983
    input_DecoderDecode( p_dec, p_null, false );
Laurent Aimar's avatar
Laurent Aimar committed
984 985

    /* */
986
    while( p_owner->b_flushing )
987
        vlc_cond_wait( &p_owner->wait_acknowledge, &p_owner->lock );
Laurent Aimar's avatar
Laurent Aimar committed
988 989
}

990 991 992 993 994 995 996 997 998 999
static void DecoderSignalBuffering( decoder_t *p_dec, bool b_full )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );

    if( p_owner->b_buffering )
    {
        if( b_full )
            p_owner->buffer.b_full = true;
1000
        vlc_cond_signal( &p_owner->wait_acknowledge );
1001 1002 1003 1004 1005
    }

    vlc_mutex_unlock( &p_owner->lock );
}

Laurent Aimar's avatar
Laurent Aimar committed
1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
static bool DecoderIsFlushing( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    bool b_flushing;

    vlc_mutex_lock( &p_owner->lock );

    b_flushing = p_owner->b_flushing;

    vlc_mutex_unlock( &p_owner->lock );

    return b_flushing;
}

1020 1021 1022 1023 1024 1025 1026 1027
static void DecoderWaitUnblock( decoder_t *p_dec, bool *pb_reject )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_assert_locked( &p_owner->lock );

    while( !p_owner->b_flushing )
    {
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042
        if( p_owner->b_paused )
        {
            if( p_owner->b_buffering && !p_owner->buffer.b_full )
                break;
            if( p_owner->pause.i_ignore > 0 )
            {
                p_owner->pause.i_ignore--;
                break;
            }
        }
        else
        {
            if( !p_owner->b_buffering || !p_owner->buffer.b_full )
                break;
        }
1043
        vlc_cond_wait( &p_owner->wait_request, &p_owner->lock );
1044 1045 1046 1047 1048 1049
    }

    if( pb_reject )
        *pb_reject = p_owner->b_flushing;
}

Laurent Aimar's avatar
Laurent Aimar committed
1050 1051 1052 1053
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
1054 1055
    vlc_assert_locked( &p_owner->lock );

Laurent Aimar's avatar
Laurent Aimar committed
1056 1057 1058 1059
    /* XXX only audio and video output have to be paused.
     * - for sout it is useless
     * - for subs, it is done by the vout
     */
1060
    if( p_dec->fmt_out.i_cat == AUDIO_ES )
Laurent Aimar's avatar
Laurent Aimar committed
1061
    {
1062
        if( p_owner->p_aout )
1063
            aout_DecChangePause( p_owner->p_aout, b_paused, i_date );
Laurent Aimar's avatar
Laurent Aimar committed
1064
    }
1065
    else if( p_dec->fmt_out.i_cat == VIDEO_ES )
Laurent Aimar's avatar
Laurent Aimar committed
1066 1067 1068 1069 1070
    {
        if( p_owner->p_vout )
            vout_ChangePause( p_owner->p_vout, b_paused, i_date );
    }
}
Laurent Aimar's avatar
Laurent Aimar committed
1071 1072
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
1073 1074
    if( p->i_flags & (BLOCK_FLAG_PREROLL|BLOCK_FLAG_DISCONTINUITY) )
        *pi_preroll = INT64_MAX;
1075
    else if( p->i_dts > VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
1076
        *pi_preroll = __MIN( *pi_preroll, p->i_dts );
1077
    else if( p->i_pts > VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
1078
        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
Laurent Aimar's avatar
Laurent Aimar committed
1079
}
1080

1081
static mtime_t DecoderTeletextFixTs( mtime_t i_ts )
1082 1083 1084 1085
{
    mtime_t current_date = mdate();

    /* FIXME I don't really like that, es_out SHOULD do it using the video pts */
1086
    if( i_ts <= VLC_TS_INVALID || i_ts > current_date + 10000000 || i_ts < current_date )
1087 1088 1089
    {
        /* ETSI EN 300 472 Annex A : do not take into account the PTS
         * for teletext streams. */
1090
        return current_date + 400000;
1091 1092 1093 1094
    }
    return i_ts;
}

Laurent Aimar's avatar
Laurent Aimar committed
1095
static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
1096
                          mtime_t *pi_duration, int *pi_rate, mtime_t i_ts_bound, bool b_telx )
1097
{
Laurent Aimar's avatar
Laurent Aimar committed
1098 1099
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    input_clock_t   *p_clock = p_owner->p_clock;
1100

Laurent Aimar's avatar
Laurent Aimar committed
1101
    vlc_assert_locked( &p_owner->lock );
1102

Laurent Aimar's avatar
Laurent Aimar committed
1103
    const mtime_t i_es_delay = p_owner->i_ts_delay;
1104

Laurent Aimar's avatar
Laurent Aimar committed
1105 1106 1107
    if( p_clock )
    {
        const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
1108
        int i_rate;
1109

1110
        if( *pi_ts0 > VLC_TS_INVALID )
1111
        {
1112
            *pi_ts0 += i_es_delay;
1113
            if( pi_ts1 && *pi_ts1 > VLC_TS_INVALID )
1114
                *pi_ts1 += i_es_delay;
1115
            if( input_clock_ConvertTS( p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound ) )
1116
                *pi_ts0 = VLC_TS_INVALID;
1117 1118 1119 1120
        }
        else
        {
            i_rate = input_clock_GetRate( p_clock );
1121
        }
1122

Laurent Aimar's avatar
Laurent Aimar committed
1123 1124 1125
        /* Do not create ephemere data because of rounding errors */
        if( !b_ephemere && pi_ts1 && *pi_ts0 == *pi_ts1 )
            *pi_ts1 += 1;
1126

Laurent Aimar's avatar
Laurent Aimar committed
1127 1128 1129
        if( pi_duration )
            *pi_duration = ( *pi_duration * i_rate +
                                    INPUT_RATE_DEFAULT-1 ) / INPUT_RATE_DEFAULT;
1130

Laurent Aimar's avatar
Laurent Aimar committed
1131 1132
        if( pi_rate )
            *pi_rate = i_rate;
1133

Laurent Aimar's avatar
Laurent Aimar committed
1134 1135
        if( b_telx )
        {
1136
            *pi_ts0 = DecoderTeletextFixTs( *pi_ts0 );
1137
            if( pi_ts1 && *pi_ts1 <= VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
1138 1139 1140
                *pi_ts1 = *pi_ts0;
        }
    }
1141
}
1142

1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
static bool DecoderIsExitRequested( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    bool b_exit = p_owner->b_exit;
    vlc_mutex_unlock( &p_owner->lock );

    return b_exit;
}

1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168
/**
 * If *pb_reject, it does nothing, otherwise it waits for the given
 * deadline or a flush request (in which case it set *pi_reject to true.
 */
static void DecoderWaitDate( decoder_t *p_dec,
                             bool *pb_reject, mtime_t i_deadline )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    if( *pb_reject || i_deadline < 0 )
        return;

    for( ;; )
    {
        vlc_mutex_lock( &p_owner->lock );
1169
        if( p_owner->b_flushing || p_owner->b_exit )
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
        {
            *pb_reject = true;
            vlc_mutex_unlock( &p_owner->lock );
            break;
        }
        int i_ret = vlc_cond_timedwait( &p_owner->wait_request, &p_owner->lock,
                                        i_deadline );
        vlc_mutex_unlock( &p_owner->lock );
        if( i_ret )
            break;
    }
}

1183
static void DecoderPlayAudio( decoder_t *p_dec, aout_buffer_t *p_audio,
1184 1185 1186
                              int *pi_played_sum, int *pi_lost_sum )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1187
    audio_output_t *p_aout = p_owner->p_aout;
1188

1189
    /* */
1190
    if( p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/*
1191 1192 1193 1194 1195 1196 1197 1198
    {
        msg_Warn( p_dec, "non-dated audio buffer received" );
        *pi_lost_sum += 1;
        aout_BufferFree( p_audio );
        return;
    }

    /* */
1199
    vlc_mutex_lock( &p_owner->lock );
1200

1201 1202 1203
    if( p_owner->b_buffering || p_owner->buffer.p_audio )
    {
        p_audio->p_next = NULL;
1204

1205 1206
        *p_owner->buffer.pp_audio_next = p_audio;
        p_owner->buffer.pp_audio_next = &p_audio->p_next;
1207

1208 1209
        p_owner->buffer.i_count++;
        if( p_owner->buffer.i_count > DECODER_MAX_BUFFERING_COUNT ||
1210
            p_audio->i_pts - p_owner->buffer.p_audio->i_pts > DECODER_MAX_BUFFERING_AUDIO_DURATION )
1211 1212
        {
            p_owner->buffer.b_full = true;
1213
            vlc_cond_signal( &p_owner->wait_acknowledge );
1214 1215
        }
    }
1216

1217 1218 1219 1220 1221
    for( ;; )
    {
        bool b_has_more = false;
        bool b_reject;
        DecoderWaitUnblock( p_dec, &b_reject );
1222

1223 1224 1225 1226 1227
        if( p_owner->b_buffering )
        {
            vlc_mutex_unlock( &p_owner->lock );
            return;
        }
1228

1229 1230 1231 1232
        /* */
        if( p_owner->buffer.p_audio )
        {
            p_audio = p_owner->buffer.p_audio;
1233

1234
            p_owner->buffer.p_audio = p_audio->p_next;
Laurent Aimar's avatar
Laurent Aimar committed
1235
            p_owner->buffer.i_count--;
1236

1237 1238 1239 1240 1241 1242
            b_has_more = p_owner->buffer.p_audio != NULL;
            if( !b_has_more )
                p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
        }

        /* */
1243
        const bool b_dated = p_audio->i_pts > VLC_TS_INVALID;
1244 1245
        int i_rate = INPUT_RATE_DEFAULT;

1246
        DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
1247
                      &i_rate, AOUT_MAX_ADVANCE_TIME, false );
1248 1249 1250

        vlc_mutex_unlock( &p_owner->lock );

1251
        if( !p_aout ||
1252
            p_audio->i_pts <= VLC_TS_INVALID ||
1253 1254 1255 1256
            i_rate < INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE ||
            i_rate > INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE )
            b_reject = true;

1257
        DecoderWaitDate( p_dec, &b_reject,
1258
                         p_audio->i_pts - AOUT_MAX_PREPARE_TIME );
1259

1260 1261
        if( !b_reject )
        {
1262
            if( !aout_DecPlay( p_aout, p_audio, i_rate ) )
1263
                *pi_played_sum += 1;
1264
            *pi_lost_sum += aout_DecGetResetLost( p_aout );
1265
        }
1266
        else
1267
        {
1268
            if( b_dated )
1269
                msg_Warn( p_dec, "received buffer in the future" );
1270
            else
1271
                msg_Warn( p_dec, "non-dated audio buffer received" );
1272

1273 1274
            *pi_lost_sum += 1;
            aout_BufferFree( p_audio );
1275
        }
1276 1277 1278

        if( !b_has_more )
            break;
1279

1280
        vlc_mutex_lock( &p_owner->lock );
1281 1282 1283 1284 1285
        if( !p_owner->buffer.p_audio )
        {
            vlc_mutex_unlock( &p_owner->lock );
            break;
        }
1286
    }
1287 1288
}

Laurent Aimar's avatar
Laurent Aimar committed
1289 1290
static void DecoderDecodeAudio( decoder_t *p_dec, block_t *p_block )
{
1291
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1292
    aout_buffer_t   *p_aout_buf;
1293 1294 1295
    int i_decoded = 0;
    int i_lost = 0;
    int i_played = 0;
Laurent Aimar's avatar
Laurent Aimar committed
1296 1297 1298

    while( (p_aout_buf = p_dec->pf_decode_audio( p_dec, &p_block )) )
    {
1299
        audio_output_t *p_aout = p_owner->p_aout;
1300

1301
        if( DecoderIsExitRequested( p_dec ) )
1302 1303
        {
            /* It prevent freezing VLC in case of broken decoder */
1304
            aout_DecDeleteBuffer( p_aout, p_aout_buf );
1305 1306 1307 1308
            if( p_block )
                block_Release( p_block );
            break;
        }
1309
        i_decoded++;
Laurent Aimar's avatar
Laurent Aimar committed
1310

1311
        if( p_owner->i_preroll_end > VLC_TS_INVALID &&
1312
            p_aout_buf->i_pts < p_owner->i_preroll_end )
Laurent Aimar's avatar
Laurent Aimar committed
1313
        {
1314
            aout_DecDeleteBuffer( p_aout, p_aout_buf );
1315
            continue;
Laurent Aimar's avatar
Laurent Aimar committed
1316
        }
1317

1318
        if( p_owner->i_preroll_end > VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
1319
        {
1320
            msg_Dbg( p_dec, "End of audio preroll" );
1321 1322
            if( p_owner->p_aout )
                aout_DecFlush( p_owner->p_aout );
Laurent Aimar's avatar
Laurent Aimar committed
1323
            /* */
1324
            p_owner->i_preroll_end = VLC_TS_INVALID;
Laurent Aimar's avatar
Laurent Aimar committed
1325
        }
1326

1327
        DecoderPlayAudio( p_dec, p_aout_buf, &i_played, &i_lost );
1328 1329 1330
    }

    /* Update ugly stat */
1331 1332 1333
    input_thread_t  *p_input = p_owner->p_input;

    if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_played > 0) )
1334 1335
    {
        vlc_mutex_lock( &p_input->p->counters.counters_lock);
1336

1337 1338 1339 1340 1341 1342
        stats_UpdateInteger( p_dec, p_input->p->counters.p_lost_abuffers,
                             i_lost, NULL );
        stats_UpdateInteger( p_dec, p_input->p->counters.p_played_abuffers,
                             i_played, NULL );
        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_audio,
                             i_decoded, NULL );
1343

1344
        vlc_mutex_unlock( &p_input->p->counters.counters_lock);
Laurent Aimar's avatar
Laurent Aimar committed
1345 1346
    }
}
1347 1348
static void DecoderGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
{
1349
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1350
    block_t *p_cc;
1351
    bool pb_present[4];
1352
    bool b_processed = false;
1353 1354 1355 1356 1357 1358
    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 */
1359
    if( !p_owner->cc.b_supported )
1360 1361 1362 1363 1364 1365
        return;

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

1366
    vlc_mutex_lock( &p_owner->lock );
1367 1368
    for( i = 0, i_cc_decoder = 0; i < 4; i++ )
    {
1369 1370
        p_owner->cc.pb_present[i] |= pb_present[i];
        if( p_owner->cc.pp_decoder[i] )
1371 1372 1373 1374 1375
            i_cc_decoder++;
    }

    for( i = 0; i < 4; i++ )
    {
1376
        if( !p_owner->cc.pp_decoder[i] )
1377 1378 1379
            continue;

        if( i_cc_decoder > 1 )
1380
            DecoderProcess( p_owner->cc.pp_decoder[i], block_Duplicate( p_cc ) );
1381
        else
1382
            DecoderProcess( p_owner->cc.pp_decoder[i], p_cc );
1383
        i_cc_decoder--;
1384
        b_processed = true;
1385
    }
1386
    vlc_mutex_unlock( &p_owner->lock );
1387 1388 1389

    if( !b_processed )
        block_Release( p_cc );
1390
}
1391

1392 1393 1394 1395 1396
static void DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
                              int *pi_played_sum, int *pi_lost_sum )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    vout_thread_t  *p_vout = p_owner->p_vout;
1397
    bool b_first_buffered;
1398

1399
    if( p_picture->date <= VLC_TS_INVALID )
1400
    {
1401
        msg_Warn( p_dec, "non-dated video buffer received" );
1402
        *pi_lost_sum += 1;
Laurent Aimar's avatar
Laurent Aimar committed
1403
        vout_ReleasePicture( p_vout, p_picture );
1404 1405 1406 1407
        return;
    }

    /* */
1408 1409
    vlc_mutex_lock( &p_owner->lock );

1410
    if( ( p_owner->b_buffering && !p_owner->buffer.b_first ) || p_owner->buffer.p_picture )
1411 1412
    {
        p_picture->p_next = NULL;
1413

1414 1415
        *p_owner->buffer.pp_picture_next = p_picture;
        p_owner->buffer.pp_picture_next = &p_picture->p_next;
1416

1417 1418 1419 1420 1421
        p_owner->buffer.i_count++;
        if( p_owner->buffer.i_count > DECODER_MAX_BUFFERING_COUNT ||
            p_picture->date - p_owner->buffer.p_picture->date > DECODER_MAX_BUFFERING_VIDEO_DURATION )
        {
            p_owner->buffer.b_full = true;
1422
            vlc_cond_signal( &p_owner->wait_acknowledge );
1423 1424
        }
    }
1425
    b_first_buffered = p_owner->buffer.p_picture != NULL;
Laurent Aimar's avatar
Laurent Aimar committed
1426

1427
    for( ;; b_first_buffered = false )
1428 1429
    {
        bool b_has_more = false;
1430

1431
        bool b_reject;
1432

1433
        DecoderWaitUnblock( p_dec, &b_reject );
1434

1435
        if( p_owner->b_buffering && !p_owner->buffer.b_first )
1436 1437 1438 1439
        {
            vlc_mutex_unlock( &p_owner->lock );
            return;
        }
1440
        bool b_buffering_first = p_owner->b_buffering;
1441

1442 1443
        /* */
        if( p_owner->buffer.p_picture )
1444
        {
1445 1446 1447
            p_picture = p_owner->buffer.p_picture;

            p_owner->buffer.p_picture = p_picture->p_next;
Laurent Aimar's avatar
Laurent Aimar committed
1448
            p_owner->buffer.i_count--;
1449 1450 1451 1452

            b_has_more = p_owner->buffer.p_picture != NULL;
            if( !b_has_more )
                p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
1453 1454
        }

1455
        /* */
1456 1457 1458 1459 1460 1461 1462 1463
        if( b_buffering_first )
        {
            assert( p_owner->buffer.b_first );
            assert( !p_owner->buffer.i_count );
            msg_Dbg( p_dec, "Received first picture" );
            p_owner->buffer.b_first = false;
            p_picture->b_force = true;
        }
Laurent Aimar's avatar
Laurent Aimar committed
1464

1465
        const bool b_dated = p_picture->date > VLC_TS_INVALID;
Laurent Aimar's avatar
Laurent Aimar committed
1466
        int i_rate = INPUT_RATE_DEFAULT;
1467
        DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
1468
                      &i_rate, DECODER_BOGUS_VIDEO_DELAY, false );
1469 1470 1471 1472

        vlc_mutex_unlock( &p_owner->lock );

        /* */
1473
        if( !p_picture->b_force && p_picture->date <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify video_output/*
1474 1475 1476
            b_reject = true;

        if( !b_reject )
1477
        {
1478
            if( i_rate != p_owner->i_last_rate || b_first_buffered )
1479 1480
            {
                /* Be sure to not display old picture after our own */
1481
                vout_Flush( p_vout, p_picture->date );
1482 1483
                p_owner->i_last_rate = i_rate;
            }
Laurent Aimar's avatar
Laurent Aimar committed
1484
            vout_PutPicture( p_vout, p_picture );
1485 1486 1487
        }
        else
        {
1488
            if( b_dated )
1489
                msg_Warn( p_dec, "early picture skipped" );
1490
            else
1491
                msg_Warn( p_dec, "non-dated video buffer received" );
1492

1493
            *pi_lost_sum += 1;
Laurent Aimar's avatar
Laurent Aimar committed
1494
            vout_ReleasePicture( p_vout, p_picture );
1495
        }
1496 1497 1498
        int i_tmp_display;
        int i_tmp_lost;
        vout_GetResetStatistic( p_vout, &i_tmp_display, &i_tmp_lost );
1499

1500 1501 1502
        *pi_played_sum += i_tmp_display;
        *pi_lost_sum += i_tmp_lost;

1503
        if( !b_has_more || b_buffering_first )
1504
            break;
1505

1506
        vlc_mutex_lock( &p_owner->lock );
1507 1508 1509 1510 1511
        if( !p_owner->buffer.p_picture )
        {
            vlc_mutex_unlock( &p_owner->lock );
            break;
        }
1512
    }
1513 1514
}

Laurent Aimar's avatar
Laurent Aimar committed
1515 1516
static void DecoderDecodeVideo( decoder_t *p_dec, block_t *p_block )
{
1517
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1518
    picture_t      *p_pic;
1519 1520 1521
    int i_lost = 0;
    int i_decoded = 0;
    int i_displayed = 0;
Laurent Aimar's avatar
Laurent Aimar committed
1522 1523 1524

    while( (p_pic = p_dec->pf_decode_video( p_dec, &p_block )) )
    {
1525
        vout_thread_t  *p_vout = p_owner->p_vout;
1526
        if( DecoderIsExitRequested( p_dec ) )
1527 1528
        {
            /* It prevent freezing VLC in case of broken decoder */
Laurent Aimar's avatar
Laurent Aimar committed
1529
            vout_ReleasePicture( p_vout, p_pic );
1530 1531 1532 1533 1534
            if( p_block )
                block_Release( p_block );
            break;
        }

1535
        i_decoded++;
Laurent Aimar's avatar
Laurent Aimar committed
1536

1537
        if( p_owner->i_preroll_end > VLC_TS_INVALID && p_pic->date < p_owner->i_preroll_end )
Laurent Aimar's avatar
Laurent Aimar committed
1538
        {
Laurent Aimar's avatar
Laurent Aimar committed
1539
            vout_ReleasePicture( p_vout, p_pic );
1540
            continue;
Laurent Aimar's avatar
Laurent Aimar committed
1541
        }
1542

1543
        if( p_owner->i_preroll_end > VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
1544
        {
1545
            msg_Dbg( p_dec, "End of video preroll" );
1546
            if( p_vout )
1547
                vout_Flush( p_vout, VLC_TS_INVALID+1 );
1548
            /* */
1549
            p_owner->i_preroll_end = VLC_TS_INVALID;
Laurent Aimar's avatar
Laurent Aimar committed
1550
        }
1551

1552
        if( p_dec->pf_get_cc &&
1553
            ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
1554 1555
            DecoderGetCc( p_dec, p_dec );

1556
        DecoderPlayVideo( p_dec, p_pic, &i_displayed, &i_lost );
1557
    }
1558 1559 1560 1561 1562

    /* Update ugly stat */
    input_thread_t *p_input = p_owner->p_input;

    if( p_input != NULL && (i_decoded > 0 || i_lost > 0 || i_displayed > 0) )
1563 1564
    {
        vlc_mutex_lock( &p_input->p->counters.counters_lock );
1565

1566 1567 1568 1569 1570 1571 1572
        stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_video,
                             i_decoded, NULL );
        stats_UpdateInteger( p_dec, p_input->p->counters.p_lost_pictures,
                             i_lost , NULL);

        stats_UpdateInteger( p_dec, p_input->p->counters.p_displayed_pictures,
                             i_displayed, NULL);
1573

1574
        vlc_mutex_unlock( &p_input->p->counters.counters_lock );
Laurent Aimar's avatar
Laurent Aimar committed
1575 1576 1577
    }
}

1578 1579 1580 1581 1582 1583
static void DecoderPlaySpu( decoder_t *p_dec, subpicture_t *p_subpic,
                            bool b_telx )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    vout_thread_t *p_vout = p_owner->p_spu_vout;

1584
    /* */
1585
    if( p_subpic->i_start <= VLC_TS_INVALID && !b_telx )
1586 1587 1588 1589 1590 1591 1592
    {
        msg_Warn( p_dec, "non-dated spu buffer received" );
        subpicture_Delete( p_subpic );
        return;
    }

    /* */
1593 1594
    vlc_mutex_lock( &p_owner->lock );

1595 1596 1597
    if( p_owner->b_buffering || p_owner->buffer.p_subpic )
    {
        p_subpic->p_next = NULL;
1598

1599 1600
        *p_owner->buffer.pp_subpic_next = p_subpic;
        p_owner->buffer.pp_subpic_next = &p_subpic->p_next;
1601

1602 1603 1604 1605 1606
        p_owner->buffer.i_count++;
        /* XXX it is important to be full after the first one */
        if( p_owner->buffer.i_count > 0 )
        {
            p_owner->buffer.b_full = true;
1607
            vlc_cond_signal( &p_owner->wait_acknowledge );
1608 1609
        }
    }
1610

1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628
    for( ;; )
    {
        bool b_has_more = false;
        bool b_reject;
        DecoderWaitUnblock( p_dec, &b_reject );

        if( p_owner->b_buffering )
        {
            vlc_mutex_unlock( &p_owner->lock );
            return;
        }

        /* */
        if( p_owner->buffer.p_subpic )
        {
            p_subpic = p_owner->buffer.p_subpic;

            p_owner->buffer.p_subpic = p_subpic->p_next;
Laurent Aimar's avatar
Laurent Aimar committed
1629
            p_owner->buffer.i_count--;
1630 1631 1632 1633 1634 1635 1636 1637

            b_has_more = p_owner->buffer.p_subpic != NULL;
            if( !b_has_more )
                p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
        }

        /* */
        DecoderFixTs( p_dec, &p_subpic->i_start, &p_subpic->i_stop, NULL,
1638
                      NULL, INT64_MAX, b_telx );
1639 1640 1641

        vlc_mutex_unlock( &p_owner->lock );

1642 1643 1644 1645 1646 1647
        if( p_subpic->i_start <= VLC_TS_INVALID )
            b_reject = true;

        DecoderWaitDate( p_dec, &b_reject,
                         p_subpic->i_start - SPU_MAX_PREPARE_TIME );

1648
        if( !b_reject )
1649
            vout_PutSubpicture( p_vout, p_subpic );
1650 1651 1652 1653 1654 1655
        else
            subpicture_Delete( p_subpic );

        if( !b_has_more )
            break;
        vlc_mutex_lock( &p_owner->lock );
1656 1657 1658 1659 1660
        if( !p_owner->buffer.p_subpic )
        {
            vlc_mutex_unlock( &p_owner->lock );
            break;
        }
1661
    }
1662 1663
}

1664
#ifdef ENABLE_SOUT
1665 1666 1667 1668 1669
static void DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block,
                             bool b_telx )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

Laurent Aimar's avatar
Laurent Aimar committed
1670
    assert( p_owner->p_clock );
1671
    assert( !p_sout_block->p_next );
Laurent Aimar's avatar
Laurent Aimar committed
1672

1673 1674
    vlc_mutex_lock( &p_owner->lock );

1675 1676 1677
    if( p_owner->b_buffering || p_owner->buffer.p_block )
    {
        block_ChainLastAppend( &p_owner->buffer.pp_block_next, p_sout_block );
1678

1679 1680 1681 1682 1683
        p_owner->buffer.i_count++;
        /* XXX it is important to be full after the first one */
        if( p_owner->buffer.i_count > 0 )
        {
            p_owner->buffer.b_full = true;
1684
            vlc_cond_signal( &p_owner->wait_acknowledge );
1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698
        }
    }

    for( ;; )
    {
        bool b_has_more = false;
        bool b_reject;
        DecoderWaitUnblock( p_dec, &b_reject );

        if( p_owner->b_buffering )
        {
            vlc_mutex_unlock( &p_owner->lock );
            return;
        }
1699

1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
        /* */
        if( p_owner->buffer.p_block )
        {
            p_sout_block = p_owner->buffer.p_block;

            p_owner->buffer.p_block = p_sout_block->p_next;
            p_owner->buffer.i_count--;

            b_has_more = p_owner->buffer.p_block != NULL;
            if( !b_has_more )
                p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
        }
1712
        p_sout_block->p_next = NULL;
1713 1714

        DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
1715
                      &p_sout_block->i_length, NULL, INT64_MAX, b_telx );
1716 1717 1718 1719

        vlc_mutex_unlock( &p_owner->lock );

        if( !b_reject )
1720
            sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block ); // FIXME --VLC_TS_INVALID inspect stream_output/*
1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732
        else
            block_Release( p_sout_block );

        if( !b_has_more )
            break;
        vlc_mutex_lock( &p_owner->lock );
        if( !p_owner->buffer.p_block )
        {
            vlc_mutex_unlock( &p_owner->lock );
            break;
        }
    }
1733
}
1734
#endif
1735

1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750
/* */
static void DecoderFlushBuffering( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_assert_locked( &p_owner->lock );

    while( p_owner->buffer.p_picture )
    {
        picture_t *p_picture = p_owner->buffer.p_picture;

        p_owner->buffer.p_picture = p_picture->p_next;
        p_owner->buffer.i_count--;

        if( p_owner->p_vout )
1751
        {
Laurent Aimar's avatar
Laurent Aimar committed
1752
            vout_ReleasePicture( p_owner->p_vout, p_picture );
1753
        }
1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781

        if( !p_owner->buffer.p_picture )
            p_owner->buffer.pp_picture_next = &p_owner->buffer.p_picture;
    }
    while( p_owner->buffer.p_audio )
    {
        aout_buffer_t *p_audio = p_owner->buffer.p_audio;

        p_owner->buffer.p_audio = p_audio->p_next;
        p_owner->buffer.i_count--;

        aout_BufferFree( p_audio );

        if( !p_owner->buffer.p_audio )
            p_owner->buffer.pp_audio_next = &p_owner->buffer.p_audio;
    }
    while( p_owner->buffer.p_subpic )
    {
        subpicture_t *p_subpic = p_owner->buffer.p_subpic;

        p_owner->buffer.p_subpic = p_subpic->p_next;
        p_owner->buffer.i_count--;

        subpicture_Delete( p_subpic );

        if( !p_owner->buffer.p_subpic )
            p_owner->buffer.pp_subpic_next = &p_owner->buffer.p_subpic;
    }
1782 1783 1784 1785 1786 1787 1788 1789
    if( p_owner->buffer.p_block )
    {
        block_ChainRelease( p_owner->buffer.p_block );

        p_owner->buffer.i_count = 0;
        p_owner->buffer.p_block = NULL;
        p_owner->buffer.pp_block_next = &p_owner->buffer.p_block;
    }
1790 1791
}

1792
#ifdef ENABLE_SOUT
1793
/* This function process a block for sout
1794
 */
1795
static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
1796
{
1797
    decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
1798
    const bool b_telx = p_dec->fmt_in.i_codec == VLC_CODEC_TELETEXT;
1799
    block_t *p_sout_block;
1800

1801 1802
    while( ( p_sout_block =
                 p_dec->pf_packetize( p_dec, p_block ? &p_block : NULL ) ) )
1803
    {
1804
        if( !p_owner->p_sout_input )
1805
        {
1806 1807 1808 1809 1810
            es_format_Copy( &p_owner->sout, &p_dec->fmt_out );

            p_owner->sout.i_group = p_dec->fmt_in.i_group;
            p_owner->sout.i_id = p_dec->fmt_in.i_id;
            if( p_dec->fmt_in.psz_language )
1811
            {
1812
                free( p_owner->sout.psz_language );
1813 1814 1815
                p_owner->sout.psz_language =
                    strdup( p_dec->fmt_in.psz_language );
            }
1816

1817 1818 1819
            p_owner->p_sout_input =
                sout_InputNew( p_owner->p_sout,
                               &p_owner->sout );
Gildas Bazin's avatar
 
Gildas Bazin committed
1820

1821 1822 1823 1824 1825
            if( p_owner->p_sout_input == NULL )
            {
                msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
                         (char *)&p_owner->sout.i_codec );
                p_dec->b_error = true;
1826

1827
                while( p_sout_block )
Gildas Bazin's avatar
 
Gildas Bazin committed
1828
                {
1829 1830 1831
                    block_t *p_next = p_sout_block->p_next;
                    block_Release( p_sout_block );
                    p_sout_block = p_next;
1832
                }
1833
                break;
1834
            }
1835
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
1836

1837 1838 1839
        while( p_sout_block )
        {
            block_t *p_next = p_sout_block->p_next;
Gildas Bazin's avatar
 
Gildas Bazin committed
1840

1841
            p_sout_block->p_next = NULL;
1842

1843
            DecoderPlaySout( p_dec, p_sout_block, b_telx );
Gildas Bazin's avatar
 
Gildas Bazin committed
1844

1845 1846
            p_sout_block = p_next;
        }
1847
    }
1848
}
1849
#endif
1850 1851 1852

/* This function process a video block
 */
1853
static void DecoderProcessVideo( decoder_t *p_dec, block_t *p_block, bool b_flush )
1854 1855 1856 1857
{
    decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;

    if( p_owner->p_packetizer )
1858
    {
1859 1860
        block_t *p_packetized_block;
        decoder_t *p_packetizer = p_owner->p_packetizer;
1861

1862 1863
        while( (p_packetized_block =
                p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
1864
        {
1865
            if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
1866
            {
1867 1868 1869 1870 1871
                es_format_Clean( &p_dec->fmt_in );
                es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
            }
            if( p_packetizer->pf_get_cc )
                DecoderGetCc( p_dec, p_packetizer );
1872

1873 1874 1875 1876
            while( p_packetized_block )
            {
                block_t *p_next = p_packetized_block->p_next;
                p_packetized_block->p_next = NULL;
1877

1878
                DecoderDecodeVideo( p_dec, p_packetized_block );
1879

1880
                p_packetized_block = p_next;
1881 1882
            }
        }
1883 1884 1885 1886 1887 1888 1889 1890
        /* The packetizer does not output a block that tell the decoder to flush
         * do it ourself */
        if( b_flush )
        {
            block_t *p_null = DecoderBlockFlushNew();
            if( p_null )
                DecoderDecodeVideo( p_dec, p_null );
        }
Gildas Bazin's avatar
 
Gildas Bazin committed
1891
    }
1892
    else if( p_block )
1893
    {
1894 1895
        DecoderDecodeVideo( p_dec, p_block );
    }
Laurent Aimar's avatar
Laurent Aimar committed
1896 1897

    if( b_flush && p_owner->p_vout )
1898
        vout_Flush( p_owner->p_vout, VLC_TS_INVALID+1 );
1899
}
1900

1901 1902
/* This function process a audio block
 */
1903
static void DecoderProcessAudio( decoder_t *p_dec, block_t *p_block, bool b_flush )
1904 1905
{
    decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
1906

1907 1908 1909 1910 1911 1912 1913 1914 1915
    if( p_owner->p_packetizer )
    {
        block_t *p_packetized_block;
        decoder_t *p_packetizer = p_owner->p_packetizer;

        while( (p_packetized_block =
                p_packetizer->pf_packetize( p_packetizer, p_block ? &p_block : NULL )) )
        {
            if( p_packetizer->fmt_out.i_extra && !p_dec->fmt_in.i_extra )
1916
            {
1917 1918 1919
                es_format_Clean( &p_dec->fmt_in );
                es_format_Copy( &p_dec->fmt_in, &p_packetizer->fmt_out );
            }
1920

1921 1922 1923 1924
            while( p_packetized_block )
            {
                block_t *p_next = p_packetized_block->p_next;
                p_packetized_block->p_next = NULL;
1925

1926
                DecoderDecodeAudio( p_dec, p_packetized_block );
1927

1928
                p_packetized_block = p_next;
1929 1930
            }
        }
1931 1932 1933 1934 1935 1936 1937 1938
        /* The packetizer does not output a block that tell the decoder to flush
         * do it ourself */
        if( b_flush )
        {
            block_t *p_null = DecoderBlockFlushNew();
            if( p_null )
                DecoderDecodeAudio( p_dec, p_null );
        }
1939
    }
1940
    else if( p_block )
1941
    {
1942 1943
        DecoderDecodeAudio( p_dec, p_block );
    }
Laurent Aimar's avatar
Laurent Aimar committed
1944

1945
    if( b_flush && p_owner->p_aout )
1946
        aout_DecFlush( p_owner->p_aout );
1947
}
1948

1949 1950
/* This function process a subtitle block
 */
1951
static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush )
1952
{
1953
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1954
    const bool b_telx = p_dec->fmt_in.i_codec == VLC_CODEC_TELETEXT;
1955

1956 1957 1958
    input_thread_t *p_input = p_owner->p_input;
    vout_thread_t *p_vout;
    subpicture_t *p_spu;
Laurent Aimar's avatar
Laurent Aimar committed
1959

1960 1961
    while( (p_spu = p_dec->pf_decode_sub( p_dec, p_block ? &p_block : NULL ) ) )
    {
1962 1963 1964 1965 1966 1967 1968
        if( p_input != NULL )
        {
            vlc_mutex_lock( &p_input->p->counters.counters_lock );
            stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1,
                                 NULL );
            vlc_mutex_unlock( &p_input->p->counters.counters_lock );
        }
1969

1970
        p_vout = input_resource_HoldVout( p_owner->p_resource );
1971 1972 1973
        if( p_vout && p_owner->p_spu_vout == p_vout )
        {
            /* Preroll does not work very well with subtitle */
1974
            if( p_spu->i_start > VLC_TS_INVALID &&
1975
                p_spu->i_start < p_owner->i_preroll_end &&
1976
                ( p_spu->i_stop <= VLC_TS_INVALID || p_spu->i_stop < p_owner->i_preroll_end ) )
1977 1978
            {
                subpicture_Delete( p_spu );
Laurent Aimar's avatar
Laurent Aimar committed
1979
            }
1980
            else
1981
            {
1982
                DecoderPlaySpu( p_dec, p_spu, b_telx );
1983 1984
            }
        }
1985 1986
        else
        {
Laurent Aimar's avatar
Laurent Aimar committed
1987
            subpicture_Delete( p_spu );
1988 1989 1990 1991
        }
        if( p_vout )
            vlc_object_release( p_vout );
    }
1992 1993 1994

    if( b_flush && p_owner->p_spu_vout )
    {
1995
        p_vout = input_resource_HoldVout( p_owner->p_resource );
1996 1997

        if( p_vout && p_owner->p_spu_vout == p_vout )
1998
            vout_FlushSubpictureChannel( p_vout, p_owner->i_spu_channel );
1999 2000 2001 2002

        if( p_vout )
            vlc_object_release( p_vout );
    }
2003 2004
}

2005 2006 2007 2008 2009 2010 2011 2012
/* */
static void DecoderProcessOnFlush( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    DecoderFlushBuffering( p_dec );

2013 2014 2015 2016 2017 2018
    if( p_owner->b_flushing )
    {
        p_owner->b_flushing = false;
        vlc_cond_signal( &p_owner->wait_acknowledge );
    }
    vlc_mutex_unlock( &p_owner->lock );
2019
}
2020

2021 2022 2023 2024 2025 2026 2027
/**
 * Decode a block
 *
 * \param p_dec the decoder object
 * \param p_block the block to decode
 * \return VLC_SUCCESS or an error code
 */
2028
static void DecoderProcess( decoder_t *p_dec, block_t *p_block )
2029
{
2030
    decoder_owner_sys_t *p_owner = (decoder_owner_sys_t *)p_dec->p_owner;
Laurent Aimar's avatar
Laurent Aimar committed
2031
    const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);
2032

2033 2034
    if( p_block && p_block->i_buffer <= 0 )
    {
Laurent Aimar's avatar
Laurent Aimar committed
2035
        assert( !b_flush_request );
2036
        block_Release( p_block );
2037
        return;
2038 2039 2040
    }

#ifdef ENABLE_SOUT
2041
    if( p_owner->b_packetizer )
2042
    {
Laurent Aimar's avatar
Laurent Aimar committed
2043 2044 2045
        if( p_block )
            p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;

2046 2047 2048 2049 2050
        DecoderProcessSout( p_dec, p_block );
    }
    else
#endif
    {
2051 2052 2053 2054
        bool b_flush = false;

        if( p_block )
        {
Laurent Aimar's avatar
Laurent Aimar committed
2055
            const bool b_flushing = p_owner->i_preroll_end == INT64_MAX;
2056 2057
            DecoderUpdatePreroll( &p_owner->i_preroll_end, p_block );

Laurent Aimar's avatar
Laurent Aimar committed
2058
            b_flush = !b_flushing && b_flush_request;
2059 2060 2061 2062

            p_block->i_flags &= ~BLOCK_FLAG_CORE_PRIVATE_MASK;
        }

2063
        if( p_dec->fmt_out.i_cat == AUDIO_ES )
2064 2065 2066
        {
            DecoderProcessAudio( p_dec, p_block, b_flush );
        }
2067
        else if( p_dec->fmt_out.i_cat == VIDEO_ES )
2068 2069 2070
        {
            DecoderProcessVideo( p_dec, p_block, b_flush );
        }
2071
        else if( p_dec->fmt_out.i_cat == SPU_ES )
2072 2073 2074 2075 2076 2077 2078 2079
        {
            DecoderProcessSpu( p_dec, p_block, b_flush );
        }
        else
        {
            msg_Err( p_dec, "unknown ES format" );
            p_dec->b_error = true;
        }
2080
    }
2081

Laurent Aimar's avatar
Laurent Aimar committed
2082 2083
    /* */
    if( b_flush_request )
2084 2085
        DecoderProcessOnFlush( p_dec );
}
2086

2087 2088 2089 2090 2091 2092 2093
static void DecoderError( decoder_t *p_dec, block_t *p_block )
{
    const bool b_flush_request = p_block && (p_block->i_flags & BLOCK_FLAG_CORE_FLUSH);

    /* */
    if( p_block )
        block_Release( p_block );
Laurent Aimar's avatar
Laurent Aimar committed
2094

2095 2096
    if( b_flush_request )
        DecoderProcessOnFlush( p_dec );
Sam Hocevar's avatar
 
Sam Hocevar committed
2097 2098
}

2099

Clément Stenac's avatar
Clément Stenac committed
2100 2101 2102 2103 2104 2105
/**
 * Destroys a decoder object
 *
 * \param p_dec the decoder object
 * \return nothing
 */
Gildas Bazin's avatar
 
Gildas Bazin committed
2106
static void DeleteDecoder( decoder_t * p_dec )
Sam Hocevar's avatar
 
Sam Hocevar committed
2107
{
2108 2109
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

2110
    msg_Dbg( p_dec, "killing decoder fourcc `%4.4s', %u PES in FIFO",
2111
             (char*)&p_dec->fmt_in.i_codec,
2112
             (unsigned)block_FifoCount( p_owner->p_fifo ) );
2113

Sam Hocevar's avatar
 
Sam Hocevar committed
2114
    /* Free all packets still in the decoder fifo. */
2115 2116
    block_FifoEmpty( p_owner->p_fifo );
    block_FifoRelease( p_owner->p_fifo );
Sam Hocevar's avatar
 
Sam Hocevar committed
2117

2118 2119 2120 2121 2122
    /* */
    vlc_mutex_lock( &p_owner->lock );
    DecoderFlushBuffering( p_dec );
    vlc_mutex_unlock( &p_owner->lock );

2123
    /* Cleanup */
2124
    if( p_owner->p_aout )
2125
    {
2126 2127
        /* TODO: REVISIT gap-less audio */
        aout_DecFlush( p_owner->p_aout );
2128
        aout_DecDelete( p_owner->p_aout );
2129
        input_resource_RequestAout( p_owner->p_resource, p_owner->p_aout );
2130 2131
        if( p_owner->p_input != NULL )
            input_SendEventAout( p_owner->p_input );
2132
    }
2133
    if( p_owner->p_vout )
Gildas Bazin's avatar
 
Gildas Bazin committed
2134
    {
2135 2136
        /* Hack to make sure all the the pictures are freed by the decoder
         * and that the vout is not paused anymore */
2137
        vout_Reset( p_owner->p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
2138

2139
        /* */
2140
        bool b_recycle = vout_CanVoutBeRecycled( p_owner->p_vout );
2141
        input_resource_RequestVout( p_owner->p_resource, p_owner->p_vout, NULL,
2142
                                    0, b_recycle );
2143 2144
        if( p_owner->p_input != NULL )
            input_SendEventVout( p_owner->p_input );
Gildas Bazin's avatar
 
Gildas Bazin committed
2145 2146
    }

2147
#ifdef ENABLE_SOUT
2148
    if( p_owner->p_sout_input )
Gildas Bazin's avatar
 
Gildas Bazin committed
2149
    {
2150 2151
        sout_InputDelete( p_owner->p_sout_input );
        es_format_Clean( &p_owner->sout );
Gildas Bazin's avatar
 
Gildas Bazin committed
2152
    }
2153
#endif
Gildas Bazin's avatar
 
Gildas Bazin committed
2154

2155
    if( p_dec->fmt_out.i_cat == SPU_ES )
2156 2157 2158
    {
        vout_thread_t *p_vout;

2159
        p_vout = input_resource_HoldVout( p_owner->p_resource );
2160
        if( p_vout )
2161
        {
2162
            if( p_owner->p_spu_vout == p_vout )
2163
                vout_FlushSubpictureChannel( p_vout, p_owner->i_spu_channel );
2164 2165 2166 2167
            vlc_object_release( p_vout );
        }
    }

2168 2169
    es_format_Clean( &p_dec->fmt_in );
    es_format_Clean( &p_dec->fmt_out );
2170 2171 2172
    if( p_dec->p_description )
        vlc_meta_Delete( p_dec->p_description );
    es_format_Clean( &p_owner->fmt_description );
Laurent Aimar's avatar
Laurent Aimar committed
2173 2174
    if( p_owner->p_description )
        vlc_meta_Delete( p_owner->p_description );
2175

2176
    if( p_owner->p_packetizer )
2177
    {
2178 2179 2180 2181
        module_unneed( p_owner->p_packetizer,
                       p_owner->p_packetizer->p_module );
        es_format_Clean( &p_owner->p_packetizer->fmt_in );
        es_format_Clean( &p_owner->p_packetizer->fmt_out );
2182 2183
        if( p_owner->p_packetizer->p_description )
            vlc_meta_Delete( p_owner->p_packetizer->p_description );
2184
        vlc_object_release( p_owner->p_packetizer );
2185
    }
Gildas Bazin's avatar
 
Gildas Bazin committed
2186

2187 2188
    vlc_cond_destroy( &p_owner->wait_acknowledge );
    vlc_cond_destroy( &p_owner->wait_request );
2189
    vlc_mutex_destroy( &p_owner->lock );
2190

2191
    vlc_object_release( p_dec );
2192

2193
    free( p_owner );
Gildas Bazin's avatar
 
Gildas Bazin committed
2194 2195 2196 2197 2198
}

/*****************************************************************************
 * Buffers allocation callbacks for the decoders
 *****************************************************************************/
2199 2200 2201 2202 2203 2204 2205
static void DecoderUpdateFormatLocked( decoder_t *p_dec )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_assert_locked( &p_owner->lock );

    p_owner->b_fmt_description = true;
Laurent Aimar's avatar
Laurent Aimar committed
2206 2207 2208

    /* Copy es_format */
    es_format_Clean( &p_owner->fmt_description );
2209
    es_format_Copy( &p_owner->fmt_description, &p_dec->fmt_out );
Laurent Aimar's avatar
Laurent Aimar committed
2210 2211 2212 2213 2214 2215

    /* Move p_description */
    if( p_owner->p_description && p_dec->p_description )
        vlc_meta_Delete( p_owner->p_description );
    p_owner->p_description = p_dec->p_description;
    p_dec->p_description = NULL;
2216
}
2217
static vout_thread_t *aout_request_vout( void *p_private,
2218
                                         vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recyle )
2219 2220
{
    decoder_t *p_dec = p_private;
2221 2222
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    input_thread_t *p_input = p_owner->p_input;
2223

2224 2225
    p_vout = input_resource_RequestVout( p_owner->p_resource, p_vout, p_fmt, 1,
                                         b_recyle );
2226 2227
    if( p_input != NULL )
        input_SendEventVout( p_input );
2228 2229 2230 2231

    return p_vout;
}

Gildas Bazin's avatar
 
Gildas Bazin committed
2232 2233
static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
{
2234
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
Gildas Bazin's avatar
 
Gildas Bazin committed
2235 2236
    aout_buffer_t *p_buffer;

2237
    if( p_owner->p_aout &&
2238
        ( p_dec->fmt_out.audio.i_rate != p_owner->audio.i_rate ||
Gildas Bazin's avatar
 
Gildas Bazin committed
2239
          p_dec->fmt_out.audio.i_original_channels !=
2240
              p_owner->audio.i_original_channels ||
Gildas Bazin's avatar
 
Gildas Bazin committed
2241
          p_dec->fmt_out.audio.i_bytes_per_frame !=
2242
              p_owner->audio.i_bytes_per_frame ) )
Gildas Bazin's avatar
 
Gildas Bazin committed
2243
    {
2244
        audio_output_t *p_aout = p_owner->p_aout;
Laurent Aimar's avatar
Laurent Aimar committed
2245

Gildas Bazin's avatar
 
Gildas Bazin committed
2246
        /* Parameters changed, restart the aout */
Laurent Aimar's avatar
Laurent Aimar committed
2247 2248
        vlc_mutex_lock( &p_owner->lock );

2249 2250
        DecoderFlushBuffering( p_dec );

2251
        aout_DecDelete( p_owner->p_aout );
2252
        p_owner->p_aout = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
2253 2254

        vlc_mutex_unlock( &p_owner->lock );
2255
        input_resource_RequestAout( p_owner->p_resource, p_aout );
Gildas Bazin's avatar
 
Gildas Bazin committed
2256 2257
    }

2258
    if( p_owner->p_aout == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
2259
    {
2260
        const int i_force_dolby = var_InheritInteger( p_dec, "force-dolby-surround" );
2261
        audio_sample_format_t format;
2262
        audio_output_t *p_aout;
2263
        aout_request_vout_t request_vout;
2264

Gildas Bazin's avatar
 
Gildas Bazin committed
2265
        p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
2266
        p_owner->audio = p_dec->fmt_out.audio;
2267

2268
        memcpy( &format, &p_owner->audio, sizeof( audio_sample_format_t ) );
2269 2270 2271
        if( i_force_dolby &&
            (format.i_original_channels&AOUT_CHAN_PHYSMASK) ==
                (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
2272
        {
2273
            if( i_force_dolby == 1 )
2274 2275 2276 2277
            {
                format.i_original_channels = format.i_original_channels |
                                             AOUT_CHAN_DOLBYSTEREO;
            }
2278
            else /* i_force_dolby == 2 */
2279 2280 2281 2282 2283 2284
            {
                format.i_original_channels = format.i_original_channels &
                                             ~AOUT_CHAN_DOLBYSTEREO;
            }
        }

2285 2286 2287
        request_vout.pf_request_vout = aout_request_vout;
        request_vout.p_private = p_dec;

2288 2289
        assert( p_owner->p_aout == NULL );
        p_aout = input_resource_RequestAout( p_owner->p_resource, NULL );
2290
        if( p_aout )
2291
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
2292
            aout_FormatPrepare( &format );
2293 2294 2295
            if( aout_DecNew( p_aout, &format,
                             &p_dec->fmt_out.audio_replay_gain,
                             &request_vout ) )
2296 2297 2298 2299 2300
            {
                input_resource_RequestAout( p_owner->p_resource, p_aout );
                p_aout = NULL;
            }
        }
Laurent Aimar's avatar
Laurent Aimar committed
2301 2302

        vlc_mutex_lock( &p_owner->lock );
2303

Laurent Aimar's avatar
Laurent Aimar committed
2304
        p_owner->p_aout = p_aout;
2305
        DecoderUpdateFormatLocked( p_dec );
2306 2307
        if( unlikely(p_owner->b_paused) ) /* fake pause if needed */
            aout_DecChangePause( p_aout, true, mdate() );
2308

Laurent Aimar's avatar
Laurent Aimar committed
2309 2310
        vlc_mutex_unlock( &p_owner->lock );

2311 2312
        if( p_owner->p_input != NULL )
            input_SendEventAout( p_owner->p_input );
2313

2314
        if( p_aout == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
2315 2316
        {
            msg_Err( p_dec, "failed to create audio output" );
2317
            p_dec->b_error = true;
Gildas Bazin's avatar
 
Gildas Bazin committed
2318 2319 2320
            return NULL;
        }
        p_dec->fmt_out.audio.i_bytes_per_frame =
2321
            p_owner->audio.i_bytes_per_frame;
Gildas Bazin's avatar
 
Gildas Bazin committed
2322 2323
    }

2324
    p_buffer = aout_DecNewBuffer( p_owner->p_aout, i_samples );
Gildas Bazin's avatar
 
Gildas Bazin committed
2325 2326 2327 2328 2329 2330

    return p_buffer;
}

static picture_t *vout_new_buffer( decoder_t *p_dec )
{
2331
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
Gildas Bazin's avatar
 
Gildas Bazin committed
2332

2333 2334 2335
    if( p_owner->p_vout == NULL ||
        p_dec->fmt_out.video.i_width != p_owner->video.i_width ||
        p_dec->fmt_out.video.i_height != p_owner->video.i_height ||
2336 2337 2338 2339 2340
        p_dec->fmt_out.video.i_visible_width != p_owner->video.i_visible_width ||
        p_dec->fmt_out.video.i_visible_height != p_owner->video.i_visible_height ||
        p_dec->fmt_out.video.i_x_offset != p_owner->video.i_x_offset  ||
        p_dec->fmt_out.video.i_y_offset != p_owner->video.i_y_offset  ||
        p_dec->fmt_out.i_codec != p_owner->video.i_chroma ||
2341 2342
        (int64_t)p_dec->fmt_out.video.i_sar_num * p_owner->video.i_sar_den !=
        (int64_t)p_dec->fmt_out.video.i_sar_den * p_owner->video.i_sar_num )
Gildas Bazin's avatar
 
Gildas Bazin committed
2343
    {
Laurent Aimar's avatar
Laurent Aimar committed
2344 2345
        vout_thread_t *p_vout;

Gildas Bazin's avatar
 
Gildas Bazin committed
2346 2347 2348 2349
        if( !p_dec->fmt_out.video.i_width ||
            !p_dec->fmt_out.video.i_height )
        {
            /* Can't create a new vout without display size */
2350
            msg_Err( p_dec, "Cannot create a new vout without display size" );
Gildas Bazin's avatar
 
Gildas Bazin committed
2351 2352 2353
            return NULL;
        }

2354 2355 2356 2357
        video_format_t fmt = p_dec->fmt_out.video;
        fmt.i_chroma = p_dec->fmt_out.i_codec;
        p_owner->video = fmt;

2358 2359
        if( vlc_fourcc_IsYUV( fmt.i_chroma ) )
        {
Rémi Duraffort's avatar
Rémi Duraffort committed
2360
            const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( fmt.i_chroma );
2361
            for( unsigned int i = 0; dsc && i < dsc->plane_count; i++ )
2362 2363 2364 2365 2366 2367 2368 2369
            {
                while( fmt.i_width % dsc->p[i].w.den )
                    fmt.i_width++;
                while( fmt.i_height % dsc->p[i].h.den )
                    fmt.i_height++;
            }
        }

2370
        if( !fmt.i_visible_width || !fmt.i_visible_height )
2371
        {
2372 2373 2374
            if( p_dec->fmt_in.video.i_visible_width &&
                p_dec->fmt_in.video.i_visible_height )
            {
2375 2376
                fmt.i_visible_width  = p_dec->fmt_in.video.i_visible_width;
                fmt.i_visible_height = p_dec->fmt_in.video.i_visible_height;
2377 2378
                fmt.i_x_offset       = p_dec->fmt_in.video.i_x_offset;
                fmt.i_y_offset       = p_dec->fmt_in.video.i_y_offset;
2379 2380 2381
            }
            else
            {
2382 2383
                fmt.i_visible_width  = fmt.i_width;
                fmt.i_visible_height = fmt.i_height;
2384 2385
                fmt.i_x_offset       = 0;
                fmt.i_y_offset       = 0;
2386
            }
2387 2388
        }

2389
        if( fmt.i_visible_height == 1088 &&
2390
            var_CreateGetBool( p_dec, "hdtv-fix" ) )
2391
        {
2392 2393
            fmt.i_visible_height = 1080;
            if( !(fmt.i_sar_num % 136))
2394
            {
2395 2396
                fmt.i_sar_num *= 135;
                fmt.i_sar_den *= 136;
2397
            }
2398
            msg_Warn( p_dec, "Fixing broken HDTV stream (display_height=1088)");
2399 2400
        }

2401
        if( !fmt.i_sar_num || !fmt.i_sar_den )
2402
        {
2403 2404
            fmt.i_sar_num = 1;
            fmt.i_sar_den = 1;
2405 2406
        }

2407 2408
        vlc_ureduce( &fmt.i_sar_num, &fmt.i_sar_den,
                     fmt.i_sar_num, fmt.i_sar_den, 50000 );
Gildas Bazin's avatar
 
Gildas Bazin committed
2409

2410
        vlc_mutex_lock( &p_owner->lock );
2411 2412 2413

        DecoderFlushBuffering( p_dec );

2414 2415 2416 2417
        p_vout = p_owner->p_vout;
        p_owner->p_vout = NULL;
        vlc_mutex_unlock( &p_owner->lock );

2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434
        unsigned dpb_size;
        switch( p_dec->fmt_in.i_codec )
        {
        case VLC_CODEC_H264:
        case VLC_CODEC_DIRAC: /* FIXME valid ? */
            dpb_size = 18;
            break;
        case VLC_CODEC_VP5:
        case VLC_CODEC_VP6:
        case VLC_CODEC_VP6F:
        case VLC_CODEC_VP8:
            dpb_size = 3;
            break;
        default:
            dpb_size = 2;
            break;
        }
2435

2436
        p_vout = input_resource_RequestVout( p_owner->p_resource,
2437
                                             p_vout, &fmt,
2438 2439 2440
                                             dpb_size +
                                             p_dec->i_extra_picture_buffers +
                                             1 + DECODER_MAX_BUFFERING_COUNT,
2441
                                             true );
Laurent Aimar's avatar
Laurent Aimar committed
2442 2443
        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_vout = p_vout;
2444 2445 2446

        DecoderUpdateFormatLocked( p_dec );

Laurent Aimar's avatar
Laurent Aimar committed
2447 2448
        vlc_mutex_unlock( &p_owner->lock );

2449 2450
        if( p_owner->p_input != NULL )
            input_SendEventVout( p_owner->p_input );
Laurent Aimar's avatar
Laurent Aimar committed
2451
        if( p_vout == NULL )
Gildas Bazin's avatar
 
Gildas Bazin committed
2452 2453
        {
            msg_Err( p_dec, "failed to create video output" );
2454
            p_dec->b_error = true;
Gildas Bazin's avatar
 
Gildas Bazin committed
2455 2456 2457 2458
            return NULL;
        }
    }

2459 2460
    /* Get a new picture
     */
Laurent Aimar's avatar
Laurent Aimar committed
2461
    for( ;; )
Gildas Bazin's avatar
 
Gildas Bazin committed
2462
    {
2463
        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
Gildas Bazin's avatar
 
Gildas Bazin committed
2464
            return NULL;
2465

Laurent Aimar's avatar
Laurent Aimar committed
2466
        picture_t *p_picture = vout_GetPicture( p_owner->p_vout );
2467 2468
        if( p_picture )
            return p_picture;
Gildas Bazin's avatar
 
Gildas Bazin committed
2469

Laurent Aimar's avatar
Laurent Aimar committed
2470 2471 2472
        if( DecoderIsFlushing( p_dec ) )
            return NULL;

2473 2474 2475
        /* */
        DecoderSignalBuffering( p_dec, true );

Gildas Bazin's avatar
 
Gildas Bazin committed
2476
        /* Check the decoder doesn't leak pictures */
2477
        vout_FixLeaks( p_owner->p_vout );
Gildas Bazin's avatar
 
Gildas Bazin committed
2478

2479
        /* FIXME add a vout_WaitPictureAvailable (timedwait) */
Gildas Bazin's avatar
 
Gildas Bazin committed
2480 2481 2482 2483 2484 2485
        msleep( VOUT_OUTMEM_SLEEP );
    }
}

static void vout_del_buffer( decoder_t *p_dec, picture_t *p_pic )
{
Laurent Aimar's avatar
Laurent Aimar committed
2486
    vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic );
Gildas Bazin's avatar
 
Gildas Bazin committed
2487
}
Gildas Bazin's avatar
 
Gildas Bazin committed
2488

2489 2490 2491 2492 2493
static int vout_get_buffer_size( decoder_t *p_dec )
{
    return vout_GetPictureCount( p_dec->p_owner->p_vout );
}

Gildas Bazin's avatar
 
Gildas Bazin committed
2494 2495
static void vout_link_picture( decoder_t *p_dec, picture_t *p_pic )
{
Laurent Aimar's avatar
Laurent Aimar committed
2496
    vout_HoldPicture( p_dec->p_owner->p_vout, p_pic );
Gildas Bazin's avatar
 
Gildas Bazin committed
2497 2498 2499 2500
}

static void vout_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
{
Laurent Aimar's avatar
Laurent Aimar committed
2501
    vout_ReleasePicture( p_dec->p_owner->p_vout, p_pic );
Gildas Bazin's avatar
 
Gildas Bazin committed
2502
}
2503

2504 2505
static subpicture_t *spu_new_buffer( decoder_t *p_dec,
                                     const subpicture_updater_t *p_updater )
2506
{
2507
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
2508
    vout_thread_t *p_vout = NULL;
2509
    subpicture_t *p_subpic;
2510
    int i_attempts = 30;
2511

2512 2513
    while( i_attempts-- )
    {
2514
        if( DecoderIsExitRequested( p_dec ) || p_dec->b_error )
2515
            break;
2516

2517
        p_vout = input_resource_HoldVout( p_owner->p_resource );
2518 2519
        if( p_vout )
            break;
2520

2521
        msleep( DECODER_SPU_VOUT_WAIT_DURATION );
2522 2523 2524 2525 2526 2527 2528
    }

    if( !p_vout )
    {
        msg_Warn( p_dec, "no vout found, dropping subpicture" );
        return NULL;
    }
2529

2530
    if( p_owner->p_spu_vout != p_vout )
2531
    {
2532 2533 2534 2535 2536 2537
        vlc_mutex_lock( &p_owner->lock );

        DecoderFlushBuffering( p_dec );

        vlc_mutex_unlock( &p_owner->lock );

2538
        p_owner->i_spu_channel = vout_RegisterSubpictureChannel( p_vout );
2539 2540
        p_owner->i_spu_order = 0;
        p_owner->p_spu_vout = p_vout;
2541 2542
    }

2543
    p_subpic = subpicture_New( p_updater );
2544 2545
    if( p_subpic )
    {
2546 2547
        p_subpic->i_channel = p_owner->i_spu_channel;
        p_subpic->i_order = p_owner->i_spu_order++;
2548
        p_subpic->b_subtitle = true;
2549
    }
2550 2551 2552

    vlc_object_release( p_vout );

2553
    return p_subpic;
2554 2555
}

2556
static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
2557
{
2558
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
2559 2560
    vout_thread_t *p_vout = NULL;

2561
    p_vout = input_resource_HoldVout( p_owner->p_resource );
2562
    if( !p_vout || p_owner->p_spu_vout != p_vout )
2563 2564 2565 2566 2567 2568 2569
    {
        if( p_vout )
            vlc_object_release( p_vout );
        msg_Warn( p_dec, "no vout found, leaking subpicture" );
        return;
    }

2570
    subpicture_Delete( p_subpic );
2571 2572

    vlc_object_release( p_vout );
2573
}
2574