decoder.c 71.2 KB
Newer Older
1
/*****************************************************************************
2
 * decoder.c: Functions for the management of decoders
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
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
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
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
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

36
#include <vlc_atomic.h>
37 38 39 40 41
#include <vlc_block.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include <vlc_codec.h>
42
#include <vlc_spu.h>
Laurent Aimar's avatar
Laurent Aimar committed
43
#include <vlc_meta.h>
44
#include <vlc_dialog.h>
45
#include <vlc_modules.h>
46 47 48

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

55
#include "../video_output/vout_control.h"
56

57 58 59 60 61 62 63 64 65 66
/*
 * Possibles values set in p_owner->reload atomic
 */
enum reload
{
    RELOAD_NO_REQUEST,
    RELOAD_DECODER,     /* Reload the decoder module */
    RELOAD_DECODER_AOUT /* Stop the aout and reload the decoder module */
};

67 68
struct decoder_owner_sys_t
{
69
    input_thread_t  *p_input;
70
    input_resource_t*p_resource;
71
    input_clock_t   *p_clock;
72
    int             i_last_rate;
73

74 75
    vout_thread_t   *p_spu_vout;
    int              i_spu_channel;
76
    int64_t          i_spu_order;
77

78 79
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
80

81 82
    vlc_thread_t     thread;

83 84
    void (*pf_update_stat)( decoder_owner_sys_t *, unsigned decoded, unsigned lost );

85 86
    /* Some decoders require already packetized data (ie. not truncated) */
    decoder_t *p_packetizer;
87
    bool b_packetizer;
88

89
    /* Current format in use by the output */
90
    es_format_t    fmt;
91

92 93
    /* */
    bool           b_fmt_description;
Laurent Aimar's avatar
Laurent Aimar committed
94
    vlc_meta_t     *p_description;
95
    atomic_int     reload;
96

97 98
    /* fifo */
    block_fifo_t *p_fifo;
99

100 101
    /* Lock for communication with decoder thread */
    vlc_mutex_t lock;
102 103
    vlc_cond_t  wait_request;
    vlc_cond_t  wait_acknowledge;
104
    vlc_cond_t  wait_fifo; /* TODO: merge with wait_acknowledge */
105
    vlc_cond_t  wait_timed;
106

107
    /* -- These variables need locking on write(only) -- */
108
    audio_output_t *p_aout;
109 110 111 112

    vout_thread_t   *p_vout;

    /* -- Theses variables need locking on read *and* write -- */
113 114
    /* Preroll */
    int64_t i_preroll_end;
115
    /* Pause */
116 117 118
    mtime_t pause_date;
    unsigned frames_countdown;
    bool paused;
119

120 121
    bool error;

122 123 124 125
    /* Waiting */
    bool b_waiting;
    bool b_first;
    bool b_has_data;
126

127
    /* Flushing */
128
    bool flushing;
129
    bool b_draining;
130
    atomic_bool drained;
131
    bool b_idle;
132

133
    /* CC */
134
#define MAX_CC_DECODERS 64 /* The es_out only creates one type of es */
135 136 137
    struct
    {
        bool b_supported;
138 139
        decoder_cc_desc_t desc;
        decoder_t *pp_decoder[MAX_CC_DECODERS];
140
    } cc;
141 142 143

    /* Delay */
    mtime_t i_ts_delay;
144 145
};

146 147 148 149 150 151
/* 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))
152
#define BLOCK_FLAG_CORE_PRIVATE_RELOADED (1 << BLOCK_FLAG_CORE_PRIVATE_SHIFT)
153

154 155 156 157 158 159 160 161 162
/**
 * Load a decoder module
 */
static int LoadDecoder( decoder_t *p_dec, bool b_packetizer,
                        const es_format_t *restrict p_fmt )
{
    p_dec->b_frame_drop_allowed = true;
    p_dec->i_extra_picture_buffers = 0;

163
    p_dec->pf_decode = NULL;
164 165
    p_dec->pf_get_cc = NULL;
    p_dec->pf_packetize = NULL;
166
    p_dec->pf_flush = NULL;
167 168

    es_format_Copy( &p_dec->fmt_in, p_fmt );
169
    es_format_Init( &p_dec->fmt_out, p_fmt->i_cat, 0 );
170 171 172

    /* Find a suitable decoder/packetizer module */
    if( !b_packetizer )
173
    {
Thomas Guillem's avatar
Thomas Guillem committed
174
        static const char caps[ES_CATEGORY_COUNT][16] = {
175
            [VIDEO_ES] = "video decoder",
176
            [AUDIO_ES] = "audio decoder",
177
            [SPU_ES] = "spu decoder",
178 179 180 181
        };
        p_dec->p_module = module_need( p_dec, caps[p_dec->fmt_in.i_cat],
                                       "$codec", false );
    }
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214
    else
        p_dec->p_module = module_need( p_dec, "packetizer", "$packetizer", false );

    if( !p_dec->p_module )
    {
        es_format_Clean( &p_dec->fmt_in );
        return -1;
    }
    else
        return 0;
}

/**
 * Unload a decoder module
 */
static void UnloadDecoder( decoder_t *p_dec )
{
    if( p_dec->p_module )
    {
        module_unneed( p_dec, p_dec->p_module );
        p_dec->p_module = NULL;
    }

    if( p_dec->p_description )
    {
        vlc_meta_Delete( p_dec->p_description );
        p_dec->p_description = NULL;
    }

    es_format_Clean( &p_dec->fmt_in );
    es_format_Clean( &p_dec->fmt_out );
}

215
static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
216
                          const es_format_t *restrict p_fmt, enum reload reload )
217 218 219 220 221
{
    /* Copy p_fmt since it can be destroyed by UnloadDecoder */
    es_format_t fmt_in;
    if( es_format_Copy( &fmt_in, p_fmt ) != VLC_SUCCESS )
    {
222
        p_dec->p_owner->error = true;
223 224 225 226 227
        return VLC_EGENERIC;
    }

    /* Restart the decoder module */
    UnloadDecoder( p_dec );
228
    p_dec->p_owner->error = false;
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245

    if( reload == RELOAD_DECODER_AOUT )
    {
        decoder_owner_sys_t *p_owner = p_dec->p_owner;
        assert( p_owner->fmt.i_cat == AUDIO_ES );
        audio_output_t *p_aout = p_owner->p_aout;

        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_aout = NULL;
        vlc_mutex_unlock( &p_owner->lock );
        if( p_aout )
        {
            aout_DecDelete( p_aout );
            input_resource_PutAout( p_owner->p_resource, p_aout );
        }
    }

246 247
    if( LoadDecoder( p_dec, b_packetizer, &fmt_in ) )
    {
248
        p_dec->p_owner->error = true;
249 250 251 252 253 254 255
        es_format_Clean( &fmt_in );
        return VLC_EGENERIC;
    }
    es_format_Clean( &fmt_in );
    return VLC_SUCCESS;
}

256
static void DecoderUpdateFormatLocked( decoder_t *p_dec )
257
{
258
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
259

260
    vlc_assert_locked( &p_owner->lock );
261

262 263
    es_format_Clean( &p_owner->fmt );
    es_format_Copy( &p_owner->fmt, &p_dec->fmt_out );
264

265
    /* Move p_description */
266 267 268 269 270 271 272 273 274
    if( p_dec->p_description != NULL )
    {
        if( p_owner->p_description != NULL )
            vlc_meta_Delete( p_owner->p_description );
        p_owner->p_description = p_dec->p_description;
        p_dec->p_description = NULL;
    }

    p_owner->b_fmt_description = true;
275 276
}

277 278 279 280
/*****************************************************************************
 * Buffers allocation callbacks for the decoders
 *****************************************************************************/
static vout_thread_t *aout_request_vout( void *p_private,
281 282
                                         vout_thread_t *p_vout,
                                         const video_format_t *p_fmt, bool b_recyle )
283
{
284
    decoder_t *p_dec = p_private;
285
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
286
    input_thread_t *p_input = p_owner->p_input;
287

288 289 290 291
    p_vout = input_resource_RequestVout( p_owner->p_resource, p_vout, p_fmt, 1,
                                         b_recyle );
    if( p_input != NULL )
        input_SendEventVout( p_input );
292

293
    return p_vout;
294
}
295

296 297 298 299 300 301 302 303 304 305 306 307 308 309
static bool aout_replaygain_changed( const audio_replay_gain_t *a,
                                     const audio_replay_gain_t *b )
{
    for( size_t i=0; i<AUDIO_REPLAY_GAIN_MAX; i++ )
    {
        if( a->pb_gain[i] != b->pb_gain[i] ||
            a->pb_peak[i] != b->pb_peak[i] ||
            a->pb_gain[i] != b->pb_gain[i] ||
            a->pb_peak[i] != b->pb_peak[i] )
            return true;
    }
    return false;
}

310
static int aout_update_format( decoder_t *p_dec )
311
{
312 313
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

314 315
    if( p_owner->p_aout &&
       ( !AOUT_FMTS_IDENTICAL(&p_dec->fmt_out.audio, &p_owner->fmt.audio) ||
316 317
         p_dec->fmt_out.i_codec != p_dec->fmt_out.audio.i_format ||
         p_dec->fmt_out.i_profile != p_owner->fmt.i_profile ) )
318
    {
319
        audio_output_t *p_aout = p_owner->p_aout;
320

321 322 323
        /* Parameters changed, restart the aout */
        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_aout = NULL;
324
        vlc_mutex_unlock( &p_owner->lock );
325
        aout_DecDelete( p_aout );
326

327
        input_resource_PutAout( p_owner->p_resource, p_aout );
328
    }
329

330 331 332 333 334 335 336 337 338 339 340 341
    /* Check if only replay gain has changed */
    if( aout_replaygain_changed( &p_dec->fmt_in.audio_replay_gain,
                                 &p_owner->fmt.audio_replay_gain ) )
    {
        p_dec->fmt_out.audio_replay_gain = p_dec->fmt_in.audio_replay_gain;
        if( p_owner->p_aout )
        {
            p_owner->fmt.audio_replay_gain = p_dec->fmt_in.audio_replay_gain;
            var_TriggerCallback( p_owner->p_aout, "audio-replay-gain-mode" );
        }
    }

342
    if( p_owner->p_aout == NULL )
343
    {
344
        p_dec->fmt_out.audio.i_format = p_dec->fmt_out.i_codec;
345

346 347
        audio_sample_format_t format = p_dec->fmt_out.audio;
        aout_FormatPrepare( &format );
348

349 350
        const int i_force_dolby = var_InheritInteger( p_dec, "force-dolby-surround" );
        if( i_force_dolby &&
351
            format.i_physical_channels == (AOUT_CHAN_LEFT|AOUT_CHAN_RIGHT) )
352
        {
353
            if( i_force_dolby == 1 )
354
                format.i_chan_mode |= AOUT_CHANMODE_DOLBYSTEREO;
355
            else /* i_force_dolby == 2 */
356
                format.i_chan_mode &= ~AOUT_CHANMODE_DOLBYSTEREO;
357
        }
358

359 360 361 362 363
        aout_request_vout_t request_vout = {
            .pf_request_vout = aout_request_vout,
            .p_private = p_dec,
        };
        audio_output_t *p_aout;
Laurent Aimar's avatar
Laurent Aimar committed
364

365 366
        p_aout = input_resource_GetAout( p_owner->p_resource );
        if( p_aout )
Laurent Aimar's avatar
Laurent Aimar committed
367
        {
368 369 370 371 372
            /* TODO: 3.0 HACK: we need to put i_profile inside audio_format_t
             * for 4.0 */
            if( p_dec->fmt_out.i_codec == VLC_CODEC_DTS )
                var_SetBool( p_aout, "dtshd", p_dec->fmt_out.i_profile > 0 );

373 374 375
            if( aout_DecNew( p_aout, &format,
                             &p_dec->fmt_out.audio_replay_gain,
                             &request_vout ) )
Laurent Aimar's avatar
Laurent Aimar committed
376
            {
377 378
                input_resource_PutAout( p_owner->p_resource, p_aout );
                p_aout = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
379 380
            }
        }
381

382 383
        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_aout = p_aout;
384

385
        DecoderUpdateFormatLocked( p_dec );
386
        aout_FormatPrepare( &p_owner->fmt.audio );
387
        vlc_mutex_unlock( &p_owner->lock );
388

389 390
        if( p_owner->p_input != NULL )
            input_SendEventAout( p_owner->p_input );
391

392 393 394 395 396
        if( p_aout == NULL )
        {
            msg_Err( p_dec, "failed to create audio output" );
            return -1;
        }
Laurent Aimar's avatar
Laurent Aimar committed
397

398 399 400 401
        p_dec->fmt_out.audio.i_bytes_per_frame =
            p_owner->fmt.audio.i_bytes_per_frame;
        p_dec->fmt_out.audio.i_frame_length =
            p_owner->fmt.audio.i_frame_length;
402
    }
403
    return 0;
Laurent Aimar's avatar
Laurent Aimar committed
404 405
}

406
static int vout_update_format( decoder_t *p_dec )
407
{
408
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
409

410 411 412 413 414 415 416 417 418 419
    if( p_owner->p_vout == NULL
     || p_dec->fmt_out.video.i_width != p_owner->fmt.video.i_width
     || p_dec->fmt_out.video.i_height != p_owner->fmt.video.i_height
     || p_dec->fmt_out.video.i_visible_width != p_owner->fmt.video.i_visible_width
     || p_dec->fmt_out.video.i_visible_height != p_owner->fmt.video.i_visible_height
     || p_dec->fmt_out.video.i_x_offset != p_owner->fmt.video.i_x_offset
     || p_dec->fmt_out.video.i_y_offset != p_owner->fmt.video.i_y_offset
     || p_dec->fmt_out.i_codec != p_owner->fmt.video.i_chroma
     || (int64_t)p_dec->fmt_out.video.i_sar_num * p_owner->fmt.video.i_sar_den !=
        (int64_t)p_dec->fmt_out.video.i_sar_den * p_owner->fmt.video.i_sar_num ||
420 421
        p_dec->fmt_out.video.orientation != p_owner->fmt.video.orientation ||
        p_dec->fmt_out.video.multiview_mode != p_owner->fmt.video.multiview_mode )
422
    {
423
        vout_thread_t *p_vout;
424

425
        if( !p_dec->fmt_out.video.i_width ||
426 427 428
            !p_dec->fmt_out.video.i_height ||
            p_dec->fmt_out.video.i_width < p_dec->fmt_out.video.i_visible_width ||
            p_dec->fmt_out.video.i_height < p_dec->fmt_out.video.i_visible_height )
429 430 431 432
        {
            /* Can't create a new vout without display size */
            return -1;
        }
433

434 435 436 437 438 439 440
        video_format_t fmt = p_dec->fmt_out.video;
        fmt.i_chroma = p_dec->fmt_out.i_codec;

        if( vlc_fourcc_IsYUV( fmt.i_chroma ) )
        {
            const vlc_chroma_description_t *dsc = vlc_fourcc_GetChromaDescription( fmt.i_chroma );
            for( unsigned int i = 0; dsc && i < dsc->plane_count; i++ )
441
            {
442 443 444 445
                while( fmt.i_width % dsc->p[i].w.den )
                    fmt.i_width++;
                while( fmt.i_height % dsc->p[i].h.den )
                    fmt.i_height++;
446 447 448
            }
        }

449
        if( !fmt.i_visible_width || !fmt.i_visible_height )
450
        {
451 452
            if( p_dec->fmt_in.video.i_visible_width &&
                p_dec->fmt_in.video.i_visible_height )
453
            {
454 455 456 457
                fmt.i_visible_width  = p_dec->fmt_in.video.i_visible_width;
                fmt.i_visible_height = p_dec->fmt_in.video.i_visible_height;
                fmt.i_x_offset       = p_dec->fmt_in.video.i_x_offset;
                fmt.i_y_offset       = p_dec->fmt_in.video.i_y_offset;
458
            }
459
            else
460
            {
461 462 463 464
                fmt.i_visible_width  = fmt.i_width;
                fmt.i_visible_height = fmt.i_height;
                fmt.i_x_offset       = 0;
                fmt.i_y_offset       = 0;
465 466
            }
        }
467

468 469 470 471 472 473 474 475 476 477 478
        if( fmt.i_visible_height == 1088 &&
            var_CreateGetBool( p_dec, "hdtv-fix" ) )
        {
            fmt.i_visible_height = 1080;
            if( !(fmt.i_sar_num % 136))
            {
                fmt.i_sar_num *= 135;
                fmt.i_sar_den *= 136;
            }
            msg_Warn( p_dec, "Fixing broken HDTV stream (display_height=1088)");
        }
479

480 481 482 483 484
        if( !fmt.i_sar_num || !fmt.i_sar_den )
        {
            fmt.i_sar_num = 1;
            fmt.i_sar_den = 1;
        }
485

486 487
        vlc_ureduce( &fmt.i_sar_num, &fmt.i_sar_den,
                     fmt.i_sar_num, fmt.i_sar_den, 50000 );
488

489 490
        video_format_AdjustColorSpace( &fmt );

491
        vlc_mutex_lock( &p_owner->lock );
492

493 494 495
        p_vout = p_owner->p_vout;
        p_owner->p_vout = NULL;
        vlc_mutex_unlock( &p_owner->lock );
496

497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521
        unsigned dpb_size;
        switch( p_dec->fmt_in.i_codec )
        {
        case VLC_CODEC_HEVC:
        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;
        }
        p_vout = input_resource_RequestVout( p_owner->p_resource,
                                             p_vout, &fmt,
                                             dpb_size +
                                             p_dec->i_extra_picture_buffers + 1,
                                             true );
        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_vout = p_vout;
522

523
        DecoderUpdateFormatLocked( p_dec );
524
        p_owner->fmt.video.i_chroma = p_dec->fmt_out.i_codec;
525 526 527 528 529 530 531 532 533
        vlc_mutex_unlock( &p_owner->lock );

        if( p_owner->p_input != NULL )
            input_SendEventVout( p_owner->p_input );
        if( p_vout == NULL )
        {
            msg_Err( p_dec, "failed to create video output" );
            return -1;
        }
534
    }
535 536 537 538

    if ( memcmp( &p_dec->fmt_out.video.mastering,
                 &p_owner->fmt.video.mastering,
                 sizeof(p_owner->fmt.video.mastering)) ||
539 540 541 542
         p_dec->fmt_out.video.lighting.MaxCLL !=
         p_owner->fmt.video.lighting.MaxCLL ||
         p_dec->fmt_out.video.lighting.MaxFALL !=
         p_owner->fmt.video.lighting.MaxFALL)
543 544 545 546 547 548
    {
        /* the format has changed but we don't need a new vout */
        vlc_mutex_lock( &p_owner->lock );
        DecoderUpdateFormatLocked( p_dec );
        vlc_mutex_unlock( &p_owner->lock );
    }
549
    return 0;
550 551
}

552
static picture_t *vout_new_buffer( decoder_t *p_dec )
553
{
554
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
555
    assert( p_owner->p_vout );
556

557
    return vout_GetPicture( p_owner->p_vout );
558
}
559

560 561 562 563 564 565 566
static subpicture_t *spu_new_buffer( decoder_t *p_dec,
                                     const subpicture_updater_t *p_updater )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    vout_thread_t *p_vout = NULL;
    subpicture_t *p_subpic;
    int i_attempts = 30;
567

568 569
    while( i_attempts-- )
    {
570
        if( p_owner->error )
571
            break;
572

573 574 575
        p_vout = input_resource_HoldVout( p_owner->p_resource );
        if( p_vout )
            break;
576

577 578
        msleep( DECODER_SPU_VOUT_WAIT_DURATION );
    }
579

580 581 582 583
    if( !p_vout )
    {
        msg_Warn( p_dec, "no vout found, dropping subpicture" );
        return NULL;
584
    }
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603

    if( p_owner->p_spu_vout != p_vout )
    {
        p_owner->i_spu_channel = vout_RegisterSubpictureChannel( p_vout );
        p_owner->i_spu_order = 0;
        p_owner->p_spu_vout = p_vout;
    }

    p_subpic = subpicture_New( p_updater );
    if( p_subpic )
    {
        p_subpic->i_channel = p_owner->i_spu_channel;
        p_subpic->i_order = p_owner->i_spu_order++;
        p_subpic->b_subtitle = true;
    }

    vlc_object_release( p_vout );

    return p_subpic;
604
}
605

606 607 608
static int DecoderGetInputAttachments( decoder_t *p_dec,
                                       input_attachment_t ***ppp_attachment,
                                       int *pi_attachment )
609
{
610 611 612 613 614 615 616 617 618 619 620 621 622
    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,
                          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 );
623
    if( p_owner->b_waiting )
624 625
        i_ts = VLC_TS_INVALID;
    vlc_mutex_unlock( &p_owner->lock );
626

627 628
    if( !p_owner->p_clock || i_ts <= VLC_TS_INVALID )
        return i_ts;
629

630 631 632 633 634 635
    if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_owner->p_clock, NULL, &i_ts, NULL, INT64_MAX ) ) {
        msg_Err(p_dec, "Could not get display date for timestamp %"PRId64"", i_ts);
        return VLC_TS_INVALID;
    }

    return i_ts;
636 637
}

638
static int DecoderGetDisplayRate( decoder_t *p_dec )
Laurent Aimar's avatar
Laurent Aimar committed
639 640 641
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

642 643 644 645
    if( !p_owner->p_clock )
        return INPUT_RATE_DEFAULT;
    return input_clock_GetRate( p_owner->p_clock );
}
Laurent Aimar's avatar
Laurent Aimar committed
646

647 648 649 650
/*****************************************************************************
 * Public functions
 *****************************************************************************/
block_t *decoder_NewAudioBuffer( decoder_t *dec, int samples )
651
{
652 653 654
    assert( dec->fmt_out.audio.i_frame_length > 0
         && dec->fmt_out.audio.i_bytes_per_frame  > 0 );

655 656 657 658
    size_t length = samples * dec->fmt_out.audio.i_bytes_per_frame
                            / dec->fmt_out.audio.i_frame_length;
    block_t *block = block_Alloc( length );
    if( likely(block != NULL) )
659
    {
660 661
        block->i_nb_samples = samples;
        block->i_pts = block->i_length = 0;
662
    }
663
    return block;
664 665
}

666 667
subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
                                     const subpicture_updater_t *p_dyn )
668
{
669 670 671 672 673
    subpicture_t *p_subpicture = p_decoder->pf_spu_buffer_new( p_decoder, p_dyn );
    if( !p_subpicture )
        msg_Warn( p_decoder, "can't get output subpicture" );
    return p_subpicture;
}
674

675
static void RequestReload( decoder_t * p_dec )
676 677 678 679 680 681 682
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    /* Don't override reload if it's RELOAD_DECODER_AOUT */
    int expected = RELOAD_NO_REQUEST;
    atomic_compare_exchange_strong( &p_owner->reload, &expected, RELOAD_DECODER );
}

683 684 685 686 687 688 689 690
/* decoder_GetInputAttachments:
 */
int decoder_GetInputAttachments( decoder_t *p_dec,
                                 input_attachment_t ***ppp_attachment,
                                 int *pi_attachment )
{
    if( !p_dec->pf_get_attachments )
        return VLC_EGENERIC;
691

692 693 694 695 696 697 698 699
    return p_dec->pf_get_attachments( p_dec, ppp_attachment, pi_attachment );
}
/* decoder_GetDisplayDate:
 */
mtime_t decoder_GetDisplayDate( decoder_t *p_dec, mtime_t i_ts )
{
    if( !p_dec->pf_get_display_date )
        return VLC_TS_INVALID;
700

701 702 703 704 705 706 707 708
    return p_dec->pf_get_display_date( p_dec, i_ts );
}
/* decoder_GetDisplayRate:
 */
int decoder_GetDisplayRate( decoder_t *p_dec )
{
    if( !p_dec->pf_get_display_rate )
        return INPUT_RATE_DEFAULT;
709

710
    return p_dec->pf_get_display_rate( p_dec );
711 712
}

713 714 715 716 717 718 719 720 721 722
void decoder_AbortPictures( decoder_t *p_dec, bool b_abort )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_mutex_lock( &p_owner->lock );
    if( p_owner->p_vout != NULL )
        vout_Cancel( p_owner->p_vout, b_abort );
    vlc_mutex_unlock( &p_owner->lock );
}

723
static void DecoderWaitUnblock( decoder_t *p_dec )
724 725 726 727 728
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    vlc_assert_locked( &p_owner->lock );

729
    for( ;; )
730
    {
731 732
        if( !p_owner->b_waiting || !p_owner->b_has_data )
            break;
733
        vlc_cond_wait( &p_owner->wait_request, &p_owner->lock );
734 735 736
    }
}

737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
/* DecoderTimedWait: Interruptible wait
 * Returns VLC_SUCCESS if wait was not interrupted, and VLC_EGENERIC otherwise */
static int DecoderTimedWait( decoder_t *p_dec, mtime_t deadline )
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;

    if (deadline - mdate() <= 0)
        return VLC_SUCCESS;

    vlc_fifo_Lock( p_owner->p_fifo );
    while( !p_owner->flushing
        && vlc_fifo_TimedWaitCond( p_owner->p_fifo, &p_owner->wait_timed,
                                   deadline ) == 0 );
    int ret = p_owner->flushing ? VLC_EGENERIC : VLC_SUCCESS;
    vlc_fifo_Unlock( p_owner->p_fifo );
    return ret;
}

Laurent Aimar's avatar
Laurent Aimar committed
755 756
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
757 758 759 760 761
    if( p->i_flags & BLOCK_FLAG_PREROLL )
        *pi_preroll = INT64_MAX;
    /* Check if we can use the packet for end of preroll */
    else if( (p->i_flags & BLOCK_FLAG_DISCONTINUITY) &&
             (p->i_buffer == 0 || (p->i_flags & BLOCK_FLAG_CORRUPTED)) )
762
        *pi_preroll = INT64_MAX;
763
    else if( p->i_dts > VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
764
        *pi_preroll = __MIN( *pi_preroll, p->i_dts );
765
    else if( p->i_pts > VLC_TS_INVALID )
766
        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
Laurent Aimar's avatar
Laurent Aimar committed
767
}
768

Laurent Aimar's avatar
Laurent Aimar committed
769
static void DecoderFixTs( decoder_t *p_dec, mtime_t *pi_ts0, mtime_t *pi_ts1,
770
                          mtime_t *pi_duration, int *pi_rate, mtime_t i_ts_bound )
771
{
Laurent Aimar's avatar
Laurent Aimar committed
772 773
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    input_clock_t   *p_clock = p_owner->p_clock;
774

Laurent Aimar's avatar
Laurent Aimar committed
775
    vlc_assert_locked( &p_owner->lock );
776

Laurent Aimar's avatar
Laurent Aimar committed
777
    const mtime_t i_es_delay = p_owner->i_ts_delay;
778

779 780
    if( !p_clock )
        return;
781

782 783
    const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
    int i_rate;
784

785 786 787 788 789
    if( *pi_ts0 > VLC_TS_INVALID )
    {
        *pi_ts0 += i_es_delay;
        if( pi_ts1 && *pi_ts1 > VLC_TS_INVALID )
            *pi_ts1 += i_es_delay;
790 791
        if( i_ts_bound != INT64_MAX )
            i_ts_bound += i_es_delay;
792
        if( input_clock_ConvertTS( VLC_OBJECT(p_dec), p_clock, &i_rate, pi_ts0, pi_ts1, i_ts_bound ) ) {
793
            const char *psz_name = module_get_name( p_dec->p_module, false );
794 795
            if( pi_ts1 != NULL )
                msg_Err(p_dec, "Could not convert timestamps %"PRId64
796
                        ", %"PRId64" for %s", *pi_ts0, *pi_ts1, psz_name );
797
            else
798
                msg_Err(p_dec, "Could not convert timestamp %"PRId64" for %s", *pi_ts0, psz_name );
799
            *pi_ts0 = VLC_TS_INVALID;
800
        }
801 802 803 804 805
    }
    else
    {
        i_rate = input_clock_GetRate( p_clock );
    }
806

807 808 809
    /* Do not create ephemere data because of rounding errors */
    if( !b_ephemere && pi_ts1 && *pi_ts0 == *pi_ts1 )
        *pi_ts1 += 1;
810

811 812 813 814 815 816
    if( pi_duration )
        *pi_duration = ( *pi_duration * i_rate + INPUT_RATE_DEFAULT-1 )
            / INPUT_RATE_DEFAULT;

    if( pi_rate )
        *pi_rate = i_rate;
817
}
818

819 820
#ifdef ENABLE_SOUT
static int DecoderPlaySout( decoder_t *p_dec, block_t *p_sout_block )
821 822
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
823

824 825
    assert( p_owner->p_clock );
    assert( !p_sout_block->p_next );
826

827
    vlc_mutex_lock( &p_owner->lock );
828

829
    if( p_owner->b_waiting )
830
    {
831
        p_owner->b_has_data = true;
832
        vlc_cond_signal( &p_owner->wait_acknowledge );
833
    }
834

835
    DecoderWaitUnblock( p_dec );
836 837
    DecoderFixTs( p_dec, &p_sout_block->i_dts, &p_sout_block->i_pts,
                  &p_sout_block->i_length, NULL, INT64_MAX );
838

839
    vlc_mutex_unlock( &p_owner->lock );
840

841 842
    /* FIXME --VLC_TS_INVALID inspect stream_output*/
    return sout_InputSendBuffer( p_owner->p_sout_input, p_sout_block );
843 844
}

845 846 847
/* This function process a block for sout
 */
static void DecoderProcessSout( decoder_t *p_dec, block_t *p_block )
Laurent Aimar's avatar
Laurent Aimar committed
848
{
849
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
850
    block_t *p_sout_block;
851
    block_t **pp_block = p_block ? &p_block : NULL;
Laurent Aimar's avatar
Laurent Aimar committed
852

853
    while( ( p_sout_block =
854
                 p_dec->pf_packetize( p_dec, pp_block ) ) )
Laurent Aimar's avatar
Laurent Aimar committed
855
    {
856
        if( p_owner->p_sout_input == NULL )
857
        {
858 859
            vlc_mutex_lock( &p_owner->lock );
            DecoderUpdateFormatLocked( p_dec );
Laurent Aimar's avatar
Laurent Aimar committed
860

861 862 863 864 865 866 867 868
            p_owner->fmt.i_group = p_dec->fmt_in.i_group;
            p_owner->fmt.i_id = p_dec->fmt_in.i_id;
            if( p_dec->fmt_in.psz_language )
            {
                free( p_owner->fmt.psz_language );
                p_owner->fmt.psz_language =
                    strdup( p_dec->fmt_in.psz_language );
            }
869
            vlc_mutex_unlock( &p_owner->lock );
870 871 872 873 874 875 876 877

            p_owner->p_sout_input =
                sout_InputNew( p_owner->p_sout, &p_owner->fmt );

            if( p_owner->p_sout_input == NULL )
            {
                msg_Err( p_dec, "cannot create packetizer output (%4.4s)",
                         (char *)&p_owner->fmt.i_codec );
878
                p_owner->error = true;
879

880 881 882
                if(p_block)
                    block_Release(p_block);

883 884 885
                block_ChainRelease(p_sout_block);
                break;
            }
Laurent Aimar's avatar
Laurent Aimar committed
886
        }
887

888
        while( p_sout_block )
Laurent Aimar's avatar
Laurent Aimar committed
889
        {
890
            block_t *p_next = p_sout_block->p_next;
891

892 893 894 895 896 897
            p_sout_block->p_next = NULL;

            if( DecoderPlaySout( p_dec, p_sout_block ) == VLC_EGENERIC )
            {
                msg_Err( p_dec, "cannot continue streaming due to errors" );

898
                p_owner->error = true;
899

900
                /* Cleanup */
901 902 903 904

                if( p_block )
                    block_Release( p_block );

905 906 907
                block_ChainRelease( p_next );
                return;
            }
908

909 910
            p_sout_block = p_next;
        }
Laurent Aimar's avatar
Laurent Aimar committed
911 912
    }
}
913 914
#endif

915
static void DecoderPlayCc( decoder_t *p_dec, block_t *p_cc,
916
                           const decoder_cc_desc_t *p_desc )
917
{
918
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
919

920
    vlc_mutex_lock( &p_owner->lock );
921

922 923
    p_owner->cc.desc = *p_desc;

924 925 926 927
    /* Fanout data to all decoders. We do not know if es_out
       selected 608 or 708. */
    uint64_t i_bitmap = p_owner->cc.desc.i_608_channels |
                        p_owner->cc.desc.i_708_channels;
928 929

    for( int i=0; i_bitmap > 0; i_bitmap >>= 1, i++ )
930
    {
931 932
        decoder_t *p_ccdec = p_owner->cc.pp_decoder[i];
        if( !p_ccdec )
933 934
            continue;

935 936 937 938 939 940 941 942 943
        if( i_bitmap > 1 )
        {
            block_FifoPut( p_ccdec->p_owner->p_fifo, block_Duplicate(p_cc) );
        }
        else
        {
            block_FifoPut( p_ccdec->p_owner->p_fifo, p_cc );
            p_cc = NULL; /* was last dec */
        }
944
    }
945

946
    vlc_mutex_unlock( &p_owner->lock );
947

948
    if( p_cc ) /* can have bitmap set but no created decs */
949
        block_Release( p_cc );
950
}
951

952
static void PacketizerGetCc( decoder_t *p_dec, decoder_t *p_dec_cc )
953 954 955
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    block_t *p_cc;
956
    decoder_cc_desc_t desc;
957 958 959 960 961

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

962 963
    assert( p_dec_cc->pf_get_cc != NULL );

964
    p_cc = p_dec_cc->pf_get_cc( p_dec_cc, &desc );
965 966
    if( !p_cc )
        return;
967
    DecoderPlayCc( p_dec, p_cc, &desc );
968 969 970
}

static int DecoderQueueCc( decoder_t *p_videodec, block_t *p_cc,
971
                           const decoder_cc_desc_t *p_desc )
972 973 974 975 976 977 978
{
    decoder_owner_sys_t *p_owner = p_videodec->p_owner;

    if( unlikely( p_cc != NULL ) )
    {
        if( p_owner->cc.b_supported &&
           ( !p_owner->p_packetizer || !p_owner->p_packetizer->pf_get_cc ) )
979
            DecoderPlayCc( p_videodec, p_cc, p_desc );
980 981 982 983
        else
            block_Release( p_cc );
    }
    return 0;
984 985
}

986
static int DecoderPlayVideo( decoder_t *p_dec, picture_t *p_picture,
987
                             unsigned *restrict pi_lost_sum )
988 989 990
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
    vout_thread_t  *p_vout = p_owner->p_vout;
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
    bool prerolled;

    vlc_mutex_lock( &p_owner->lock );
    if( p_owner->i_preroll_end > p_picture->date )
    {
        vlc_mutex_unlock( &p_owner->lock );
        picture_Release( p_picture );
        return -1;
    }

    prerolled = p_owner->i_preroll_end > INT64_MIN;
    p_owner->i_preroll_end = INT64_MIN;
    vlc_mutex_unlock( &p_owner->lock );

    if( unlikely(prerolled) )
    {
        msg_Dbg( p_dec, "end of video preroll" );

        if( p_vout )
            vout_Flush( p_vout, VLC_TS_INVALID+1 );
    }

1013
    if( p_picture->date <= VLC_TS_INVALID )
1014
    {
1015
        msg_Warn( p_dec, "non-dated video buffer received" );
1016
        goto discard;
1017 1018 1019
    }

    /* */
1020 1021
    vlc_mutex_lock( &p_owner->lock );

1022
    if( p_owner->b_waiting && !p_owner->b_first )
1023
    {
1024
        p_owner->b_has_data = true;
1025
        vlc_cond_signal( &p_owner->wait_acknowledge );
1026
    }
1027
    bool b_first_after_wait = p_owner->b_waiting && p_owner->b_has_data;
Laurent Aimar's avatar
Laurent Aimar committed
1028

1029
    DecoderWaitUnblock( p_dec );
1030

1031
    if( p_owner->b_waiting )
1032
    {
1033
        assert( p_owner->b_first );
1034
        msg_Dbg( p_dec, "Received first picture" );
1035
        p_owner->b_first = false;
1036 1037
        p_picture->b_force = true;
    }
Laurent Aimar's avatar
Laurent Aimar committed
1038

1039 1040 1041 1042
    const bool b_dated = p_picture->date > VLC_TS_INVALID;
    int i_rate = INPUT_RATE_DEFAULT;
    DecoderFixTs( p_dec, &p_picture->date, NULL, NULL,
                  &i_rate, DECODER_BOGUS_VIDEO_DELAY );
1043

1044
    vlc_mutex_unlock( &p_owner->lock );
1045

1046
    /* FIXME: The *input* FIFO should not be locked here. This will not work
1047
     * properly if/when pictures are queued asynchronously. */
1048
    vlc_fifo_Lock( p_owner->p_fifo );
1049 1050
    if( unlikely(p_owner->paused) && likely(p_owner->frames_countdown > 0) )
        p_owner->frames_countdown--;
1051 1052
    vlc_fifo_Unlock( p_owner->p_fifo );

1053
    /* */
1054 1055 1056
    if( p_vout == NULL )
        goto discard;

1057 1058
    if( p_picture->b_force || p_picture->date > VLC_TS_INVALID )
        /* FIXME: VLC_TS_INVALID -- verify video_output */
1059 1060
    {
        if( i_rate != p_owner->i_last_rate || b_first_after_wait )
1061
        {
1062 1063 1064
            /* Be sure to not display old picture after our own */
            vout_Flush( p_vout, p_picture->date );
            p_owner->i_last_rate = i_rate;
1065
        }
1066 1067 1068 1069 1070 1071
        vout_PutPicture( p_vout, p_picture );
    }
    else
    {
        if( b_dated )
            msg_Warn( p_dec, "early picture skipped" );
1072
        else
1073
            msg_Warn( p_dec, "non-dated video buffer received" );
1074
        goto discard;
1075
    }
1076

1077 1078 1079 1080
    return 0;
discard:
    *pi_lost_sum += 1;
    picture_Release( p_picture );
1081 1082
    return 0;
}
1083

1084 1085
static void DecoderUpdateStatVideo( decoder_owner_sys_t *p_owner,
                                    unsigned decoded, unsigned lost )
1086
{
1087
    input_thread_t *p_input = p_owner->p_input;
1088
    unsigned displayed = 0;
1089

1090
    /* Update ugly stat */
1091 1092 1093 1094
    if( p_input == NULL )
        return;

    if( p_owner->p_vout != NULL )
1095
    {
1096
        unsigned vout_lost = 0;
1097 1098 1099

        vout_GetResetStatistic( p_owner->p_vout, &displayed, &vout_lost );
        lost += vout_lost;
Laurent Aimar's avatar
Laurent Aimar committed
1100
    }
1101

1102 1103 1104 1105 1106
    vlc_mutex_lock( &input_priv(p_input)->counters.counters_lock );
    stats_Update( input_priv(p_input)->counters.p_decoded_video, decoded, NULL );
    stats_Update( input_priv(p_input)->counters.p_lost_pictures, lost , NULL);
    stats_Update( input_priv(p_input)->counters.p_displayed_pictures, displayed, NULL);
    vlc_mutex_unlock( &input_priv(p_input)->counters.counters_lock );
Laurent Aimar's avatar
Laurent Aimar committed
1107 1108
}

1109
static int DecoderQueueVideo( decoder_t *p_dec, picture_t *p_pic )
1110 1111
{
    assert( p_pic );
1112
    unsigned i_lost = 0;
1113
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1114

1115
    int ret = DecoderPlayVideo( p_dec, p_pic, &i_lost );
1116

1117
    p_owner->pf_update_stat( p_owner, 1, i_lost );
1118
    return ret;
1119 1120
}

1121
static int DecoderPlayAudio( decoder_t *p_dec, block_t *p_audio,
1122
                             unsigned *restrict pi_lost_sum )
1123 1124
{
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147
    bool prerolled;

    assert( p_audio != NULL );

    vlc_mutex_lock( &p_owner->lock );
    if( p_owner->i_preroll_end > p_audio->i_pts )
    {
        vlc_mutex_unlock( &p_owner->lock );
        block_Release( p_audio );
        return -1;
    }

    prerolled = p_owner->i_preroll_end > INT64_MIN;
    p_owner->i_preroll_end = INT64_MIN;
    vlc_mutex_unlock( &p_owner->lock );

    if( unlikely(prerolled) )
    {
        msg_Dbg( p_dec, "end of audio preroll" );

        if( p_owner->p_aout )
            aout_DecFlush( p_owner->p_aout, false );
    }
1148 1149

    /* */
1150
    if( p_audio->i_pts <= VLC_TS_INVALID ) // FIXME --VLC_TS_INVALID verify audio_output/*
1151 1152 1153 1154
    {
        msg_Warn( p_dec, "non-dated audio buffer received" );
        *pi_lost_sum += 1;
        block_Release( p_audio );
1155
        return 0;
1156 1157 1158 1159
    }

    /* */
    vlc_mutex_lock( &p_owner->lock );
1160
    if( p_owner->b_waiting )
1161 1162 1163 1164 1165
    {
        p_owner->b_has_data = true;
        vlc_cond_signal( &p_owner->wait_acknowledge );
    }

1166 1167
    /* */
    int i_rate = INPUT_RATE_DEFAULT;
1168

1169
    DecoderWaitUnblock( p_dec );
1170 1171
    DecoderFixTs( p_dec, &p_audio->i_pts, NULL, &p_audio->i_length,
                  &i_rate, AOUT_MAX_ADVANCE_TIME );
1172
    vlc_mutex_unlock( &p_owner->lock );
1173

1174
    audio_output_t *p_aout = p_owner->p_aout;
1175

1176 1177 1178 1179 1180
    if( p_aout != NULL && p_audio->i_pts > VLC_TS_INVALID
     && i_rate >= INPUT_RATE_DEFAULT/AOUT_MAX_INPUT_RATE
     && i_rate <= INPUT_RATE_DEFAULT*AOUT_MAX_INPUT_RATE
     && !DecoderTimedWait( p_dec, p_audio->i_pts - AOUT_MAX_PREPARE_TIME ) )
    {
1181 1182 1183 1184
        int status = aout_DecPlay( p_aout, p_audio, i_rate );
        if( status == AOUT_DEC_CHANGED )
        {
            /* Only reload the decoder */
1185
            RequestReload( p_dec );
1186 1187 1188 1189 1190 1191 1192 1193
        }
        else if( status == AOUT_DEC_FAILED )
        {
            /* If we reload because the aout failed, we should release it. That
             * way, a next call to aout_update_format() won't re-use the
             * previous (failing) aout but will try to create a new one. */
            atomic_store( &p_owner->reload, RELOAD_DECODER_AOUT );
        }
1194 1195
    }
    else
1196 1197 1198 1199
    {
        msg_Dbg( p_dec, "discarded audio buffer" );
        *pi_lost_sum += 1;
        block_Release( p_audio );