decoder.c 72.5 KB
Newer Older
1
/*****************************************************************************
Laurent Aimar's avatar
Laurent Aimar committed
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>
Laurent Aimar's avatar
Laurent Aimar committed
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
#include <stdatomic.h>
34

35
#include <vlc_common.h>
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"
Laurent Aimar's avatar
Laurent Aimar committed
48
#include "input_internal.h"
49
#include "../clock/input_clock.h"
50
#include "decoder.h"
Christophe Mutricy's avatar
Christophe Mutricy committed
51
#include "event.h"
52
#include "resource.h"
53

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

56 57 58 59 60 61 62 63 64 65
/*
 * 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 */
};

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

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

77 78
    sout_instance_t         *p_sout;
    sout_packetizer_input_t *p_sout_input;
79

80 81
    vlc_thread_t     thread;

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

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

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

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

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

99 100
    /* Lock for communication with decoder thread */
    vlc_mutex_t lock;
101 102
    vlc_cond_t  wait_request;
    vlc_cond_t  wait_acknowledge;
103
    vlc_cond_t  wait_fifo; /* TODO: merge with wait_acknowledge */
Thomas Guillem's avatar
Thomas Guillem committed
104
    vlc_cond_t  wait_timed;
105

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

    vout_thread_t   *p_vout;

    /* -- Theses variables need locking on read *and* write -- */
Thomas Guillem's avatar
Thomas Guillem committed
112 113
    /* Preroll */
    int64_t i_preroll_end;
114
    /* Pause & Rate */
115
    mtime_t pause_date;
116
    float rate;
117 118
    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

Laurent Aimar's avatar
Laurent Aimar committed
127
    /* Flushing */
128
    bool flushing;
129
    bool b_draining;
130
    atomic_bool drained;
131
    bool b_idle;
Laurent Aimar's avatar
Laurent Aimar committed
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
#define VLC_TS_OLDEST  (VLC_TS_INVALID + 1)

156 157 158 159 160 161 162 163 164
/**
 * 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;

165
    p_dec->pf_decode = NULL;
166 167
    p_dec->pf_get_cc = NULL;
    p_dec->pf_packetize = NULL;
168
    p_dec->pf_flush = NULL;
169 170

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

    /* Find a suitable decoder/packetizer module */
    if( !b_packetizer )
175
    {
Thomas Guillem's avatar
Thomas Guillem committed
176
        static const char caps[ES_CATEGORY_COUNT][16] = {
177
            [VIDEO_ES] = "video decoder",
178
            [AUDIO_ES] = "audio decoder",
179
            [SPU_ES] = "spu decoder",
180
        };
181 182
        p_dec->p_module = module_need_var( p_dec, caps[p_dec->fmt_in.i_cat],
                                           "codec" );
183
    }
184
    else
185
        p_dec->p_module = module_need_var( p_dec, "packetizer", "packetizer" );
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 215 216

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

217
static int ReloadDecoder( decoder_t *p_dec, bool b_packetizer,
218
                          const es_format_t *restrict p_fmt, enum reload reload )
219 220 221 222 223
{
    /* 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 )
    {
224
        p_dec->p_owner->error = true;
225 226 227 228 229
        return VLC_EGENERIC;
    }

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

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

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

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

262
    vlc_assert_locked( &p_owner->lock );
263

264 265
    es_format_Clean( &p_owner->fmt );
    es_format_Copy( &p_owner->fmt, &p_dec->fmt_out );
266

267
    /* Move p_description */
268 269 270 271 272 273 274 275 276
    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;
277 278
}

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

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

295
    return p_vout;
296
}
Clément Stenac's avatar
Clément Stenac committed
297

François Cartegnie's avatar
François Cartegnie committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311
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;
}

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

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

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

329
        input_resource_PutAout( p_owner->p_resource, p_aout );
330
    }
331

François Cartegnie's avatar
François Cartegnie committed
332 333 334 335 336 337 338 339 340 341 342 343
    /* 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" );
        }
    }

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

348 349
        audio_sample_format_t format = p_dec->fmt_out.audio;
        aout_FormatPrepare( &format );
350

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

361 362 363 364 365
        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
366

367 368
        p_aout = input_resource_GetAout( p_owner->p_resource );
        if( p_aout )
Laurent Aimar's avatar
Laurent Aimar committed
369
        {
370 371 372 373 374
            /* 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 );

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

384 385
        vlc_mutex_lock( &p_owner->lock );
        p_owner->p_aout = p_aout;
386

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

391 392
        if( p_owner->p_input != NULL )
            input_SendEventAout( p_owner->p_input );
393

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

400 401 402 403
        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;
404
    }
405
    return 0;
Laurent Aimar's avatar
Laurent Aimar committed
406 407
}

408
static int vout_update_format( decoder_t *p_dec )
Sam Hocevar's avatar
 
Sam Hocevar committed
409
{
410
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
411

412 413 414 415 416 417 418 419 420 421
    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 ||
422 423
        p_dec->fmt_out.video.orientation != p_owner->fmt.video.orientation ||
        p_dec->fmt_out.video.multiview_mode != p_owner->fmt.video.multiview_mode )
424
    {
425
        vout_thread_t *p_vout;
Laurent Aimar's avatar
Laurent Aimar committed
426

427
        if( !p_dec->fmt_out.video.i_width ||
428 429 430
            !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 )
431 432 433 434
        {
            /* Can't create a new vout without display size */
            return -1;
        }
435

436 437 438 439 440 441 442
        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++ )
443
            {
444 445 446 447
                while( fmt.i_width % dsc->p[i].w.den )
                    fmt.i_width++;
                while( fmt.i_height % dsc->p[i].h.den )
                    fmt.i_height++;
448 449 450
            }
        }

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

470 471 472 473 474 475 476 477 478 479 480
        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)");
        }
481

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

488 489
        vlc_ureduce( &fmt.i_sar_num, &fmt.i_sar_den,
                     fmt.i_sar_num, fmt.i_sar_den, 50000 );
490

491 492
        video_format_AdjustColorSpace( &fmt );

493
        vlc_mutex_lock( &p_owner->lock );
494

495 496 497
        p_vout = p_owner->p_vout;
        p_owner->p_vout = NULL;
        vlc_mutex_unlock( &p_owner->lock );
498

499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
        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;
524

525
        DecoderUpdateFormatLocked( p_dec );
526
        p_owner->fmt.video.i_chroma = p_dec->fmt_out.i_codec;
527 528 529 530 531 532 533 534 535
        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;
        }
536
    }
537 538 539 540

    if ( memcmp( &p_dec->fmt_out.video.mastering,
                 &p_owner->fmt.video.mastering,
                 sizeof(p_owner->fmt.video.mastering)) ||
541 542 543 544
         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)
545 546 547 548 549 550
    {
        /* 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 );
    }
551
    return 0;
Gildas Bazin's avatar
 
Gildas Bazin committed
552 553
}

554
static picture_t *vout_new_buffer( decoder_t *p_dec )
Gildas Bazin's avatar
 
Gildas Bazin committed
555
{
556
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
557
    assert( p_owner->p_vout );
558

559
    return vout_GetPicture( p_owner->p_vout );
560
}
561

562 563 564 565 566 567 568
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;
569

570 571
    while( i_attempts-- )
    {
572
        if( p_owner->error )
573
            break;
574

575 576 577
        p_vout = input_resource_HoldVout( p_owner->p_resource );
        if( p_vout )
            break;
578

579 580
        msleep( DECODER_SPU_VOUT_WAIT_DURATION );
    }
581

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

    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;
606
}
Gildas Bazin's avatar
 
Gildas Bazin committed
607

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

Steve Lhomme's avatar
Steve Lhomme committed
629
    if( !p_owner->p_clock || i_ts == VLC_TS_INVALID )
630
        return i_ts;
631

632 633 634 635 636 637
    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;
638 639
}

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

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

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

657 658 659 660
    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) )
661
    {
662 663
        block->i_nb_samples = samples;
        block->i_pts = block->i_length = 0;
664
    }
665
    return block;
666 667
}

668 669
subpicture_t *decoder_NewSubpicture( decoder_t *p_decoder,
                                     const subpicture_updater_t *p_dyn )
Laurent Aimar's avatar
Laurent Aimar committed
670
{
671 672 673 674 675
    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;
}
Laurent Aimar's avatar
Laurent Aimar committed
676

677
static void RequestReload( decoder_t * p_dec )
678 679 680 681 682 683 684
{
    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 );
}

685 686 687 688 689 690 691 692
/* 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;
Laurent Aimar's avatar
Laurent Aimar committed
693

694 695 696 697 698 699 700 701
    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;
Laurent Aimar's avatar
Laurent Aimar committed
702

703 704 705 706 707 708 709 710
    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;
Laurent Aimar's avatar
Laurent Aimar committed
711

712
    return p_dec->pf_get_display_rate( p_dec );
Laurent Aimar's avatar
Laurent Aimar committed
713 714
}

715 716 717 718 719 720 721 722 723 724
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 );
}

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

    vlc_assert_locked( &p_owner->lock );

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

Thomas Guillem's avatar
Thomas Guillem committed
739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756
/* 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
757 758
static inline void DecoderUpdatePreroll( int64_t *pi_preroll, const block_t *p )
{
759 760 761 762 763
    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)) )
764
        *pi_preroll = INT64_MAX;
Steve Lhomme's avatar
Steve Lhomme committed
765
    else if( p->i_dts != VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
766
        *pi_preroll = __MIN( *pi_preroll, p->i_dts );
Steve Lhomme's avatar
Steve Lhomme committed
767
    else if( p->i_pts != VLC_TS_INVALID )
Laurent Aimar's avatar
Laurent Aimar committed
768
        *pi_preroll = __MIN( *pi_preroll, p->i_pts );
Laurent Aimar's avatar
Laurent Aimar committed
769
}
770

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

Laurent Aimar's avatar
Laurent Aimar committed
777
    vlc_assert_locked( &p_owner->lock );
778

Laurent Aimar's avatar
Laurent Aimar committed
779
    const mtime_t i_es_delay = p_owner->i_ts_delay;
780

781 782
    if( !p_clock )
        return;
783

784 785
    const bool b_ephemere = pi_ts1 && *pi_ts0 == *pi_ts1;
    int i_rate;
786

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

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

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

    if( pi_rate )
        *pi_rate = i_rate;
819
}
820

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

826 827
    assert( p_owner->p_clock );
    assert( !p_sout_block->p_next );
828

829
    vlc_mutex_lock( &p_owner->lock );
830

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

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

841
    vlc_mutex_unlock( &p_owner->lock );
842

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

847 848 849
/* 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
850
{
851
    decoder_owner_sys_t *p_owner = p_dec->p_owner;
852
    block_t *p_sout_block;
853
    block_t **pp_block = p_block ? &p_block : NULL;
Laurent Aimar's avatar
Laurent Aimar committed
854

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

863 864 865 866 867 868 869 870
            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 );
            }
871
            vlc_mutex_unlock( &p_owner->lock );
872 873 874 875 876 877 878 879

            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 );
880
                p_owner->error = true;
881

882 883 884
                if(p_block)
                    block_Release(p_block);

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

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

894 895 896 897
            p_sout_block->p_next = NULL;

            if( DecoderPlaySout( p_dec, p_sout_block ) == VLC_EGENERIC )
            {
898 899
                msg_Err( p_dec, "cannot continue streaming due to errors with codec %4.4s",
                                (char *)&p_owner->fmt.i_codec );
900

901
                p_owner->error = true;
902

903
                /* Cleanup */