video.c 39.4 KB
Newer Older
1
2
3
/*****************************************************************************
 * video.c: video decoder using the ffmpeg library
 *****************************************************************************
4
 * Copyright (C) 1999-2001 the VideoLAN team
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Gildas Bazin <gbazin@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
24
25
26
27
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
28
29
30
31
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

32
33
34
35
36
37
38
39
#if defined(HAVE_LIBAVCODEC_AVCODEC_H) && defined(HAVE_AVCODEC_DXVA2)
# if _WIN32_WINNT < 0x600
/* dxva2 needs Vista support */
#  undef _WIN32_WINNT
#  define _WIN32_WINNT 0x600
# endif
#endif

40
#include <vlc_common.h>
zorglub's avatar
zorglub committed
41
#include <vlc_codec.h>
42
#include <vlc_avcodec.h>
Laurent Aimar's avatar
Laurent Aimar committed
43
#include <vlc_cpu.h>
44
#include <assert.h>
45
46

/* ffmpeg header */
47
48
#ifdef HAVE_LIBAVCODEC_AVCODEC_H
#   include <libavcodec/avcodec.h>
49
50
51
#   ifdef HAVE_AVCODEC_VAAPI
#       include <libavcodec/vaapi.h>
#   endif
52
53
54
#   ifdef HAVE_AVCODEC_DXVA2
#       include <libavcodec/dxva2.h>
#   endif
55
#elif defined(HAVE_FFMPEG_AVCODEC_H)
56
#   include <ffmpeg/avcodec.h>
57
58
59
60
#else
#   include <avcodec.h>
#endif

61
#include "avcodec.h"
62
#include "va.h"
63
64
65
#if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
#   define HAVE_AVCODEC_VA
#endif
66
67
68
69
70
71

/*****************************************************************************
 * decoder_sys_t : decoder descriptor
 *****************************************************************************/
struct decoder_sys_t
{
72
    AVCODEC_COMMON_MEMBERS
73
74
75
76
77
78
79

    /* Video decoder specific part */
    mtime_t i_pts;

    AVFrame          *p_ff_pic;

    /* for frame skipping algo */
80
    bool b_hurry_up;
81
82
    enum AVDiscard i_skip_frame;
    enum AVDiscard i_skip_idct;
83
84
85
86
87
88

    /* how many decoded frames are late */
    int     i_late_frames;
    mtime_t i_late_frames_start;

    /* for direct rendering */
89
    bool b_direct_rendering;
90
    int  i_direct_rendering_used;
91

92
    bool b_has_b_frames;
93
94

    /* Hack to force display of still pictures */
95
    bool b_first_frame;
96

97
98
    /* */
    AVPaletteControl palette;
99
100
101

    /* */
    bool b_flush;
102
103
104

    /* VA API */
    vlc_va_t *p_va;
Laurent Aimar's avatar
Laurent Aimar committed
105
106

    vlc_sem_t sem_mt;
107
108
};

Laurent Aimar's avatar
Laurent Aimar committed
109
110
111
112
113
114
115
116
#ifdef HAVE_AVCODEC_MT
#   define wait_mt(s) vlc_sem_wait( &s->sem_mt )
#   define post_mt(s) vlc_sem_post( &s->sem_mt )
#else
#   define wait_mt(s)
#   define post_mt(s)
#endif

117
/* FIXME (dummy palette for now) */
hartman's avatar
hartman committed
118
static const AVPaletteControl palette_control;
119
120
121
122

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
123
static void ffmpeg_InitCodec      ( decoder_t * );
124
125
static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );
static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );
126
static int  ffmpeg_ReGetFrameBuf( struct AVCodecContext *, AVFrame * );
127
128
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );

129
#ifdef HAVE_AVCODEC_VA
130
131
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *,
                                          const enum PixelFormat * );
132
#endif
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
{
    uint8_t *p = (uint8_t*)&fcc;
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}

/*****************************************************************************
 * Local Functions
 *****************************************************************************/

/* Returns a new picture buffer */
static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec,
                                            AVCodecContext *p_context )
{
148
    decoder_sys_t *p_sys = p_dec->p_sys;
149

150
151
    p_dec->fmt_out.video.i_width = p_context->width;
    p_dec->fmt_out.video.i_height = p_context->height;
152
153
154
155
156
157

    if( !p_context->width || !p_context->height )
    {
        return NULL; /* invalid display size */
    }

158
    if( !p_sys->p_va && GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) )
159
    {
160
161
162
163
        /* we are doomed, but not really, because most codecs set their pix_fmt
         * much later
         * FIXME does it make sense here ? */
        p_dec->fmt_out.video.i_chroma = VLC_CODEC_I420;
164
    }
165
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
166
167

    /* If an aspect-ratio was specified in the input format then force it */
Laurent Aimar's avatar
Laurent Aimar committed
168
    if( p_dec->fmt_in.video.i_sar_num > 0 && p_dec->fmt_in.video.i_sar_den > 0 )
169
    {
Laurent Aimar's avatar
Laurent Aimar committed
170
171
        p_dec->fmt_out.video.i_sar_num = p_dec->fmt_in.video.i_sar_num;
        p_dec->fmt_out.video.i_sar_den = p_dec->fmt_in.video.i_sar_den;
172
173
174
    }
    else
    {
175
176
        p_dec->fmt_out.video.i_sar_num = p_context->sample_aspect_ratio.num;
        p_dec->fmt_out.video.i_sar_den = p_context->sample_aspect_ratio.den;
177

Laurent Aimar's avatar
Laurent Aimar committed
178
        if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
179
        {
Laurent Aimar's avatar
Laurent Aimar committed
180
181
            p_dec->fmt_out.video.i_sar_num = 1;
            p_dec->fmt_out.video.i_sar_den = 1;
182
183
184
        }
    }

Laurent Aimar's avatar
Laurent Aimar committed
185
186
    if( p_dec->fmt_in.video.i_frame_rate > 0 &&
        p_dec->fmt_in.video.i_frame_rate_base > 0 )
187
188
189
190
    {
        p_dec->fmt_out.video.i_frame_rate =
            p_dec->fmt_in.video.i_frame_rate;
        p_dec->fmt_out.video.i_frame_rate_base =
damienf's avatar
damienf committed
191
            p_dec->fmt_in.video.i_frame_rate_base;
192
    }
193
    else if( p_context->time_base.num > 0 && p_context->time_base.den > 0 )
194
195
196
197
    {
        p_dec->fmt_out.video.i_frame_rate = p_context->time_base.den;
        p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num;
    }
198

199
    return decoder_NewPicture( p_dec );
200
201
202
203
204
205
206
207
}

/*****************************************************************************
 * InitVideo: initialize the video decoder
 *****************************************************************************
 * the ffmpeg codec will be opened, some memory allocated. The vout is not yet
 * opened (done after the first decoded frame).
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
208
int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
209
                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
210
211
{
    decoder_sys_t *p_sys;
212
    int i_val;
213
214

    /* Allocate the memory needed to store the decoder's structure */
ivoire's avatar
ivoire committed
215
    if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(decoder_sys_t) ) ) == NULL )
216
        return VLC_ENOMEM;
217

218
219
    p_codec->type = AVMEDIA_TYPE_VIDEO;
    p_context->codec_type = AVMEDIA_TYPE_VIDEO;
220
    p_context->codec_id = i_codec_id;
221
222
223
224
    p_sys->p_context = p_context;
    p_sys->p_codec = p_codec;
    p_sys->i_codec_id = i_codec_id;
    p_sys->psz_namecodec = psz_namecodec;
225
    p_sys->p_ff_pic = avcodec_alloc_frame();
226
    p_sys->b_delayed_open = true;
227
    p_sys->p_va = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
228
    vlc_sem_init( &p_sys->sem_mt, 0 );
229
230

    /* ***** Fill p_context with init values ***** */
231
    p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_original_fourcc ?: p_dec->fmt_in.i_codec );
232
233
234

    /*  ***** Get configuration of ffmpeg plugin ***** */
    p_sys->p_context->workaround_bugs =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
235
        var_InheritInteger( p_dec, "ffmpeg-workaround-bugs" );
aballier's avatar
aballier committed
236
    p_sys->p_context->error_recognition =
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
237
        var_InheritInteger( p_dec, "ffmpeg-error-resilience" );
238

239
240
    if( var_CreateGetBool( p_dec, "grayscale" ) )
        p_sys->p_context->flags |= CODEC_FLAG_GRAY;
241

242
243
    i_val = var_CreateGetInteger( p_dec, "ffmpeg-vismv" );
    if( i_val ) p_sys->p_context->debug_mv = i_val;
244

245
246
    i_val = var_CreateGetInteger( p_dec, "ffmpeg-lowres" );
    if( i_val > 0 && i_val <= 2 ) p_sys->p_context->lowres = i_val;
247

248
249
250
251
252
    i_val = var_CreateGetInteger( p_dec, "ffmpeg-skiploopfilter" );
    if( i_val >= 4 ) p_sys->p_context->skip_loop_filter = AVDISCARD_ALL;
    else if( i_val == 3 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONKEY;
    else if( i_val == 2 ) p_sys->p_context->skip_loop_filter = AVDISCARD_BIDIR;
    else if( i_val == 1 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONREF;
253

254
255
    if( var_CreateGetBool( p_dec, "ffmpeg-fast" ) )
        p_sys->p_context->flags2 |= CODEC_FLAG2_FAST;
256

257
    /* ***** ffmpeg frame skipping ***** */
258
    p_sys->b_hurry_up = var_CreateGetBool( p_dec, "ffmpeg-hurry-up" );
259

260
    switch( var_CreateGetInteger( p_dec, "ffmpeg-skip-frame" ) )
261
262
263
264
265
266
267
268
    {
        case -1:
            p_sys->p_context->skip_frame = AVDISCARD_NONE;
            break;
        case 0:
            p_sys->p_context->skip_frame = AVDISCARD_DEFAULT;
            break;
        case 1:
269
            p_sys->p_context->skip_frame = AVDISCARD_NONREF;
270
271
272
273
274
275
276
277
278
279
280
            break;
        case 2:
            p_sys->p_context->skip_frame = AVDISCARD_NONKEY;
            break;
        case 3:
            p_sys->p_context->skip_frame = AVDISCARD_ALL;
            break;
        default:
            p_sys->p_context->skip_frame = AVDISCARD_NONE;
            break;
    }
281
    p_sys->i_skip_frame = p_sys->p_context->skip_frame;
282

283
    switch( var_CreateGetInteger( p_dec, "ffmpeg-skip-idct" ) )
284
285
286
287
288
289
290
291
    {
        case -1:
            p_sys->p_context->skip_idct = AVDISCARD_NONE;
            break;
        case 0:
            p_sys->p_context->skip_idct = AVDISCARD_DEFAULT;
            break;
        case 1:
292
            p_sys->p_context->skip_idct = AVDISCARD_NONREF;
293
294
295
296
297
298
299
300
301
302
303
            break;
        case 2:
            p_sys->p_context->skip_idct = AVDISCARD_NONKEY;
            break;
        case 3:
            p_sys->p_context->skip_idct = AVDISCARD_ALL;
            break;
        default:
            p_sys->p_context->skip_idct = AVDISCARD_NONE;
            break;
    }
304
    p_sys->i_skip_idct = p_sys->p_context->skip_idct;
305

306
    /* ***** ffmpeg direct rendering ***** */
307
    p_sys->b_direct_rendering = false;
308
    p_sys->i_direct_rendering_used = -1;
309
310
    if( var_CreateGetBool( p_dec, "ffmpeg-dr" ) &&
       (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
311
        /* No idea why ... but this fixes flickering on some TSCC streams */
312
        p_sys->i_codec_id != CODEC_ID_TSCC && p_sys->i_codec_id != CODEC_ID_CSCD &&
313
#if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 68, 2 ) ) && (LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 100, 1 ) )
314
315
316
        /* avcodec native vp8 decode doesn't handle EMU_EDGE flag, and I
           don't have idea howto implement fallback to libvpx decoder */
        p_sys->i_codec_id != CODEC_ID_VP8 &&
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
317
#endif
318
319
320
321
        !p_sys->p_context->debug_mv )
    {
        /* Some codecs set pix_fmt only after the 1st frame has been decoded,
         * so we need to do another check in ffmpeg_GetFrameBuf() */
322
        p_sys->b_direct_rendering = true;
323
324
325
    }

    /* ffmpeg doesn't properly release old pictures when frames are skipped */
326
    //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = false;
327
328
    if( p_sys->b_direct_rendering )
    {
329
        msg_Dbg( p_dec, "trying to use direct rendering" );
330
331
        p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
    }
332
333
334
335
    else
    {
        msg_Dbg( p_dec, "direct rendering is disabled" );
    }
336
337
338
339

    /* Always use our get_buffer wrapper so we can calculate the
     * PTS correctly */
    p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
340
    p_sys->p_context->reget_buffer = ffmpeg_ReGetFrameBuf;
341
342
343
    p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
    p_sys->p_context->opaque = p_dec;

Laurent Aimar's avatar
Laurent Aimar committed
344
345
346
347
#ifdef HAVE_AVCODEC_MT
    int i_thread_count = var_InheritInteger( p_dec, "ffmpeg-threads" );
    if( i_thread_count <= 0 )
        i_thread_count = vlc_GetCPUCount();
348
349
350
351
    msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count );
    p_sys->p_context->thread_count = i_thread_count;
#endif

Laurent Aimar's avatar
Laurent Aimar committed
352
#ifdef HAVE_AVCODEC_VA
353
    const bool b_use_hw = var_CreateGetBool( p_dec, "ffmpeg-hw" );
354
355
356
357
358
    if( b_use_hw &&
        (i_codec_id == CODEC_ID_MPEG1VIDEO || i_codec_id == CODEC_ID_MPEG2VIDEO ||
         i_codec_id == CODEC_ID_MPEG4 ||
         i_codec_id == CODEC_ID_H264 ||
         i_codec_id == CODEC_ID_VC1 || i_codec_id == CODEC_ID_WMV3) )
Laurent Aimar's avatar
Laurent Aimar committed
359
    {
360
#ifdef HAVE_AVCODEC_MT
361
362
363
364
365
        if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
        {
            msg_Warn( p_dec, "threaded frame decoding is not compatible with ffmpeg-hw, disabled" );
            p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
        }
366
#endif
367
368
        p_sys->p_context->get_format = ffmpeg_GetFormat;
    }
Laurent Aimar's avatar
Laurent Aimar committed
369
370
#endif

371
    /* ***** misc init ***** */
372
    p_sys->i_pts = VLC_TS_INVALID;
373
374
    p_sys->b_has_b_frames = false;
    p_sys->b_first_frame = true;
375
    p_sys->b_flush = false;
376
377
378
379
    p_sys->i_late_frames = 0;

    /* Set output properties */
    p_dec->fmt_out.i_cat = VIDEO_ES;
380
381
    if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS )
    {
382
        /* we are doomed. but not really, because most codecs set their pix_fmt later on */
383
        p_dec->fmt_out.i_codec = VLC_CODEC_I420;
384
385
    }
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
386
387

    /* Setup palette */
388
    memset( &p_sys->palette, 0, sizeof(p_sys->palette) );
389
    if( p_dec->fmt_in.video.p_palette )
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
    {
        p_sys->palette.palette_changed = 1;

        for( int i = 0; i < __MIN( AVPALETTE_COUNT, p_dec->fmt_in.video.p_palette->i_entries ); i++ )
        {
            union {
                uint32_t u;
                uint8_t a[4];
            } c;
            c.a[0] = p_dec->fmt_in.video.p_palette->palette[i][0];
            c.a[1] = p_dec->fmt_in.video.p_palette->palette[i][1];
            c.a[2] = p_dec->fmt_in.video.p_palette->palette[i][2];
            c.a[3] = p_dec->fmt_in.video.p_palette->palette[i][3];

            p_sys->palette.palette[i] = c.u;
        }
        p_sys->p_context->palctrl = &p_sys->palette;

        p_dec->fmt_out.video.p_palette = malloc( sizeof(video_palette_t) );
        if( p_dec->fmt_out.video.p_palette )
            *p_dec->fmt_out.video.p_palette = *p_dec->fmt_in.video.p_palette;
    }
412
    else if( p_sys->i_codec_id != CODEC_ID_MSVIDEO1 && p_sys->i_codec_id != CODEC_ID_CINEPAK )
413
414
415
    {
        p_sys->p_context->palctrl = &p_sys->palette;
    }
416

417
418
419
    /* ***** init this codec with special data ***** */
    ffmpeg_InitCodec( p_dec );

420
    /* ***** Open the codec ***** */
421
    if( ffmpeg_OpenCodec( p_dec ) < 0 )
422
423
    {
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
424
        av_free( p_sys->p_ff_pic );
Laurent Aimar's avatar
Laurent Aimar committed
425
        vlc_sem_destroy( &p_sys->sem_mt );
426
427
428
429
430
431
432
433
434
435
        free( p_sys );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}

/*****************************************************************************
 * DecodeVideo: Called to decode one or more frames
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
436
picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
437
438
{
    decoder_sys_t *p_sys = p_dec->p_sys;
439
    AVCodecContext *p_context = p_sys->p_context;
440
    int b_drawpicture;
441
    int b_null_size = false;
442
443
    block_t *p_block;

444
445
    if( !pp_block || !*pp_block )
        return NULL;
446

447
    if( !p_context->extradata_size && p_dec->fmt_in.i_extra )
448
    {
449
        ffmpeg_InitCodec( p_dec );
450
451
452
453
454
455
        if( p_sys->b_delayed_open )
        {
            if( ffmpeg_OpenCodec( p_dec ) )
                msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
        }
    }
456

457
    p_block = *pp_block;
458
459
460
461
462
    if( p_sys->b_delayed_open )
    {
        block_Release( p_block );
        return NULL;
    }
463
464
465

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
466
        p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
467
468
469

        p_sys->i_late_frames = 0;

470
471
        if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY )
            avcodec_flush_buffers( p_context );
Laurent Aimar's avatar
Laurent Aimar committed
472

473
        block_Release( p_block );
474
475
476
477
478
479
480
481
482
483
484
        return NULL;
    }

    if( p_block->i_flags & BLOCK_FLAG_PREROLL )
    {
        /* Do not care about late frames when prerolling
         * TODO avoid decoding of non reference frame
         * (ie all B except for H264 where it depends only on nal_ref_idc) */
        p_sys->i_late_frames = 0;
    }

485
    if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) &&
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
486
        (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) )
487
    {
488
        if( p_sys->i_pts > VLC_TS_INVALID )
489
490
491
        {
            msg_Err( p_dec, "more than 5 seconds of late video -> "
                     "dropping frame (computer too slow ?)" );
492
            p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
493
494
495
496
497
498
499
500
        }
        block_Release( p_block );
        p_sys->i_late_frames--;
        return NULL;
    }

    /* A good idea could be to decode all I pictures and see for the other */
    if( !p_dec->b_pace_control &&
501
502
        p_sys->b_hurry_up &&
        (p_sys->i_late_frames > 4) )
503
504
    {
        b_drawpicture = 0;
505
        if( p_sys->i_late_frames < 12 )
506
        {
507
            p_context->skip_frame =
508
509
                    (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
                    AVDISCARD_NONREF : p_sys->i_skip_frame;
510
511
512
513
514
515
516
517
518
519
520
521
        }
        else
        {
            /* picture too late, won't decode
             * but break picture until a new I, and for mpeg4 ...*/
            p_sys->i_late_frames--; /* needed else it will never be decrease */
            block_Release( p_block );
            return NULL;
        }
    }
    else
    {
522
        if( p_sys->b_hurry_up )
523
            p_context->skip_frame = p_sys->i_skip_frame;
Laurent Aimar's avatar
Laurent Aimar committed
524
        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
525
526
527
528
529
            b_drawpicture = 1;
        else
            b_drawpicture = 0;
    }

530
    if( p_context->width <= 0 || p_context->height <= 0 )
531
    {
532
        if( p_sys->b_hurry_up )
533
            p_context->skip_frame = p_sys->i_skip_frame;
534
        b_null_size = true;
535
    }
Laurent Aimar's avatar
Laurent Aimar committed
536
537
    else if( !b_drawpicture )
    {
538
539
540
        /* It creates broken picture
         * FIXME either our parser or ffmpeg is broken */
#if 0
541
        if( p_sys->b_hurry_up )
542
            p_context->skip_frame = __MAX( p_context->skip_frame,
543
                                                  AVDISCARD_NONREF );
544
#endif
Laurent Aimar's avatar
Laurent Aimar committed
545
    }
546
547

    /*
548
     * Do the actual decoding now */
549
550
551
552
553

    /* Don't forget that ffmpeg requires a little more bytes
     * that the real frame size */
    if( p_block->i_buffer > 0 )
    {
554
555
        p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;

556
557
558
        p_block = block_Realloc( p_block, 0,
                            p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
        if( !p_block )
ivoire's avatar
ivoire committed
559
            return NULL;
560
        p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
561
        *pp_block = p_block;
562
        memset( p_block->p_buffer + p_block->i_buffer, 0,
563
564
565
                FF_INPUT_BUFFER_PADDING_SIZE );
    }

566
    while( p_block->i_buffer > 0 || p_sys->b_flush )
567
568
569
    {
        int i_used, b_gotpicture;
        picture_t *p_pic;
570
        AVPacket pkt;
571

572
573
574
575
576
577
578
        /* Set the PTS/DTS in the context reordered_opaque field */
        if( p_block->i_pts > VLC_TS_INVALID  )
            p_context->reordered_opaque = (p_block->i_pts << 1) | 0;
        else if( p_block->i_dts > VLC_TS_INVALID )
            p_context->reordered_opaque = (p_block->i_dts << 1) | 1;
        else
            p_context->reordered_opaque = INT64_MIN;
579
        p_sys->p_ff_pic->reordered_opaque = p_context->reordered_opaque;
580
581
582
583
584

        /* Make sure we don't reuse the same timestamps twice */
        p_block->i_pts =
        p_block->i_dts = VLC_TS_INVALID;

Laurent Aimar's avatar
Laurent Aimar committed
585
        post_mt( p_sys );
586

587
588
589
590
591
        av_init_packet( &pkt );
        pkt.data = p_block->p_buffer;
        pkt.size = p_block->i_buffer;
        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                       &b_gotpicture, &pkt );
592

593
594
        if( b_null_size && !p_sys->b_flush &&
            p_context->width > 0 && p_context->height > 0 )
595
596
        {
            /* Reparse it to not drop the I frame */
597
            b_null_size = false;
598
            if( p_sys->b_hurry_up )
599
                p_context->skip_frame = p_sys->i_skip_frame;
600
601
            i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                           &b_gotpicture, &pkt );
602
        }
Laurent Aimar's avatar
Laurent Aimar committed
603
        wait_mt( p_sys );
604

605
606
607
        if( p_sys->b_flush )
            p_sys->b_first_frame = true;

608
        if( p_block->i_buffer <= 0 )
609
610
            p_sys->b_flush = false;

611
612
        if( i_used < 0 )
        {
Laurent Aimar's avatar
Laurent Aimar committed
613
            if( b_drawpicture )
614
615
                msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
                          p_block->i_buffer );
616
617
618
            block_Release( p_block );
            return NULL;
        }
Laurent Aimar's avatar
Laurent Aimar committed
619
620
        else if( i_used > p_block->i_buffer ||
                 p_context->thread_count > 1 )
621
        {
622
            i_used = p_block->i_buffer;
623
624
625
        }

        /* Consumed bytes */
626
627
        p_block->i_buffer -= i_used;
        p_block->p_buffer += i_used;
628
629
630
631
632
633
634
635

        /* Nothing to display */
        if( !b_gotpicture )
        {
            if( i_used == 0 ) break;
            continue;
        }

636
637
638
639
640
641
        /* Sanity check (seems to be needed for some streams) */
        if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
        {
            p_sys->b_has_b_frames = true;
        }

642
643
644
645
646
647
648
649
650
651
652
653
654
        /* Compute the PTS */
        mtime_t i_pts = VLC_TS_INVALID;
        if( p_sys->p_ff_pic->reordered_opaque != INT64_MIN )
        {
            mtime_t i_ts = p_sys->p_ff_pic->reordered_opaque >> 1;
            bool    b_dts = p_sys->p_ff_pic->reordered_opaque & 1;
            if( b_dts )
            {
                if( !p_context->has_b_frames ||
                    !p_sys->b_has_b_frames ||
                    !p_sys->p_ff_pic->reference ||
                    p_sys->i_pts <= VLC_TS_INVALID )
                    i_pts = i_ts;
655
656
657
658
659
660
661
662
663

                /* Guess what ? The rules are different for Real Video :( */
                if( (p_dec->fmt_in.i_codec == VLC_CODEC_RV30 ||
                     p_dec->fmt_in.i_codec == VLC_CODEC_RV40) &&
                    p_sys->b_has_b_frames )
                {
                    i_pts = VLC_TS_INVALID;
                    if(p_sys->p_ff_pic->reference) i_pts = i_ts;
                }
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
            }
            else
            {
                i_pts = i_ts;
            }
        }
        if( i_pts <= VLC_TS_INVALID )
            i_pts = p_sys->i_pts;

        /* Interpolate the next PTS */
        if( i_pts > VLC_TS_INVALID )
            p_sys->i_pts = i_pts;
        if( p_sys->i_pts > VLC_TS_INVALID )
        {
            /* interpolate the next PTS */
            if( p_dec->fmt_in.video.i_frame_rate > 0 &&
                p_dec->fmt_in.video.i_frame_rate_base > 0 )
            {
                p_sys->i_pts += INT64_C(1000000) *
                    (2 + p_sys->p_ff_pic->repeat_pict) *
                    p_dec->fmt_in.video.i_frame_rate_base /
                    (2 * p_dec->fmt_in.video.i_frame_rate);
            }
            else if( p_context->time_base.den > 0 )
            {
                int i_tick = p_context->ticks_per_frame;
                if( i_tick <= 0 )
                    i_tick = 1;

                p_sys->i_pts += INT64_C(1000000) *
                    (2 + p_sys->p_ff_pic->repeat_pict) *
                    i_tick * p_context->time_base.num /
                    (2 * p_context->time_base.den);
            }
        }
699

700
        /* Update frame late count (except when doing preroll) */
701
702
        mtime_t i_display_date = 0;
        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
703
            i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
704

705
        if( i_display_date > 0 && i_display_date <= mdate() )
706
707
708
709
710
711
712
713
714
715
        {
            p_sys->i_late_frames++;
            if( p_sys->i_late_frames == 1 )
                p_sys->i_late_frames_start = mdate();
        }
        else
        {
            p_sys->i_late_frames = 0;
        }

716
        if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) )
717
718
719
720
721
            continue;

        if( !p_sys->p_ff_pic->opaque )
        {
            /* Get a new picture */
722
            p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
723
724
725
726
727
728
729
730
731
732
733
734
735
            if( !p_pic )
            {
                block_Release( p_block );
                return NULL;
            }

            /* Fill p_picture_t from AVVideoFrame and do chroma conversion
             * if needed */
            ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic );
        }
        else
        {
            p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
736
            decoder_LinkPicture( p_dec, p_pic );
737
738
        }

Laurent Aimar's avatar
Laurent Aimar committed
739
        if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
740
741
        {
            /* Fetch again the aspect ratio in case it changed */
742
            p_dec->fmt_out.video.i_sar_num
743
                = p_context->sample_aspect_ratio.num;
744
            p_dec->fmt_out.video.i_sar_den
745
                = p_context->sample_aspect_ratio.den;
746

Laurent Aimar's avatar
Laurent Aimar committed
747
            if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
748
            {
Laurent Aimar's avatar
Laurent Aimar committed
749
750
                p_dec->fmt_out.video.i_sar_num = 1;
                p_dec->fmt_out.video.i_sar_den = 1;
751
752
753
            }
        }

754
        /* Send decoded frame to vout */
755
        if( i_pts > VLC_TS_INVALID)
756
        {
757
            p_pic->date = i_pts;
758
759
760
761

            if( p_sys->b_first_frame )
            {
                /* Hack to force display of still pictures */
762
763
                p_sys->b_first_frame = false;
                p_pic->b_force = true;
764
765
766
767
768
769
            }

            p_pic->i_nb_fields = 2 + p_sys->p_ff_pic->repeat_pict;
            p_pic->b_progressive = !p_sys->p_ff_pic->interlaced_frame;
            p_pic->b_top_field_first = p_sys->p_ff_pic->top_field_first;

770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
            p_pic->i_qstride = p_sys->p_ff_pic->qstride;
            int i_mb_h = ( p_pic->format.i_height + 15 ) / 16;
            p_pic->p_q = malloc( p_pic->i_qstride * i_mb_h );
            memcpy( p_pic->p_q, p_sys->p_ff_pic->qscale_table,
                    p_pic->i_qstride * i_mb_h );
            switch( p_sys->p_ff_pic->qscale_type )
            {
                case FF_QSCALE_TYPE_MPEG1:
                    p_pic->i_qtype = QTYPE_MPEG1;
                    break;
                case FF_QSCALE_TYPE_MPEG2:
                    p_pic->i_qtype = QTYPE_MPEG2;
                    break;
                case FF_QSCALE_TYPE_H264:
                    p_pic->i_qtype = QTYPE_H264;
                    break;
            }

788
789
790
791
            return p_pic;
        }
        else
        {
792
            decoder_DeletePicture( p_dec, p_pic );
793
794
795
796
797
798
799
800
801
802
        }
    }

    block_Release( p_block );
    return NULL;
}

/*****************************************************************************
 * EndVideo: decoder destruction
 *****************************************************************************
803
 * This function is called when the thread ends after a successful
804
805
 * initialization.
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
806
void EndVideoDec( decoder_t *p_dec )
807
808
809
{
    decoder_sys_t *p_sys = p_dec->p_sys;

Laurent Aimar's avatar
Laurent Aimar committed
810
811
    post_mt( p_sys );

812
813
814
    /* do not flush buffers if codec hasn't been opened (theora/vorbis/VC1) */
    if( p_sys->p_context->codec )
        avcodec_flush_buffers( p_sys->p_context );
815

Laurent Aimar's avatar
Laurent Aimar committed
816
817
    wait_mt( p_sys );

818
    if( p_sys->p_ff_pic ) av_free( p_sys->p_ff_pic );
819
820

    if( p_sys->p_va )
821
    {
822
        vlc_va_Delete( p_sys->p_va );
823
824
        p_sys->p_va = NULL;
    }
Laurent Aimar's avatar
Laurent Aimar committed
825
    vlc_sem_destroy( &p_sys->sem_mt );
826
827
}

828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
/*****************************************************************************
 * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg
 *****************************************************************************/
static void ffmpeg_InitCodec( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_size = p_dec->fmt_in.i_extra;

    if( !i_size ) return;

    if( p_sys->i_codec_id == CODEC_ID_SVQ3 )
    {
        uint8_t *p;

        p_sys->p_context->extradata_size = i_size + 12;
        p = p_sys->p_context->extradata  =
            malloc( p_sys->p_context->extradata_size );
ivoire's avatar
ivoire committed
845
846
        if( !p )
            return;
847
848
849
850
851
852
853

        memcpy( &p[0],  "SVQ3", 4 );
        memset( &p[4], 0, 8 );
        memcpy( &p[12], p_dec->fmt_in.p_extra, i_size );

        /* Now remove all atoms before the SMI one */
        if( p_sys->p_context->extradata_size > 0x5a &&
854
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
855
856
857
858
859
860
861
862
863
864
865
        {
            uint8_t *psz = &p[0x52];

            while( psz < &p[p_sys->p_context->extradata_size - 8] )
            {
                int i_size = GetDWBE( psz );
                if( i_size <= 1 )
                {
                    /* FIXME handle 1 as long size */
                    break;
                }
866
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
                {
                    memmove( &p[0x52], psz,
                             &p[p_sys->p_context->extradata_size] - psz );
                    break;
                }

                psz += i_size;
            }
        }
    }
    else
    {
        p_sys->p_context->extradata_size = i_size;
        p_sys->p_context->extradata =
            malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
882
883
884
885
886
887
888
        if( p_sys->p_context->extradata )
        {
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
            memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
889
890
891
    }
}

892
893
894
895
896
897
898
899
900
/*****************************************************************************
 * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
 *                     picture_t structure (when not in direct rendering mode).
 *****************************************************************************/
static void ffmpeg_CopyPicture( decoder_t *p_dec,
                                picture_t *p_pic, AVFrame *p_ff_pic )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

901
902
    if( p_sys->p_va )
    {
903
        vlc_va_Extract( p_sys->p_va, p_pic, p_ff_pic );
904
905
    }
    else if( TestFfmpegChroma( p_sys->p_context->pix_fmt, -1 ) == VLC_SUCCESS )
906
907
908
909
910
    {
        int i_plane, i_size, i_line;
        uint8_t *p_dst, *p_src;
        int i_src_stride, i_dst_stride;

911
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
912
        {
913
914
915
916
917
918
919
920
            p_src  = p_ff_pic->data[i_plane];
            p_dst = p_pic->p[i_plane].p_pixels;
            i_src_stride = p_ff_pic->linesize[i_plane];
            i_dst_stride = p_pic->p[i_plane].i_pitch;

            i_size = __MIN( i_src_stride, i_dst_stride );
            for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;
                 i_line++ )
921
            {
922
923
924
                vlc_memcpy( p_dst, p_src, i_size );
                p_src += i_src_stride;
                p_dst += i_dst_stride;
925
926
927
928
929
            }
        }
    }
    else
    {
930
931
932
        msg_Err( p_dec, "don't know how to convert chroma %i",
                 p_sys->p_context->pix_fmt );
        p_dec->b_error = 1;
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
    }
}

/*****************************************************************************
 * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
 *****************************************************************************
 * It is used for direct rendering as well as to get the right PTS for each
 * decoded picture (even in indirect rendering mode).
 *****************************************************************************/
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
                               AVFrame *p_ff_pic )
{
    decoder_t *p_dec = (decoder_t *)p_context->opaque;
    decoder_sys_t *p_sys = p_dec->p_sys;
    picture_t *p_pic;

949
    /* */
950
    p_ff_pic->reordered_opaque = p_context->reordered_opaque;
951
952
953
954
    p_ff_pic->opaque = NULL;

    if( p_sys->p_va )
    {
955
#ifdef HAVE_AVCODEC_VA
956
        /* hwaccel_context is not present in old ffmpeg version */
957
        if( vlc_va_Setup( p_sys->p_va,
958
959
                          &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
                          p_context->width, p_context->height ) )
960
        {
961
            msg_Err( p_dec, "vlc_va_Setup failed" );
962
963
            return -1;
        }
964
965
966
#else
        assert(0);
#endif
967
968
969
970
971

        /* */
        p_ff_pic->type = FF_BUFFER_TYPE_USER;
        /* FIXME what is that, should give good value */
        p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
972

973
        if( vlc_va_Get( p_sys->p_va, p_ff_pic ) )
974
975
976
977
978
979
        {
            msg_Err( p_dec, "VaGrabSurface failed" );
            return -1;
        }
        return 0;
    }
980
    else if( !p_sys->b_direct_rendering )
981
    {
982
        /* Not much to do in indirect rendering mode. */
983
984
985
        return avcodec_default_get_buffer( p_context, p_ff_pic );
    }

Laurent Aimar's avatar
Laurent Aimar committed
986
    wait_mt( p_sys );
987
    /* Some codecs set pix_fmt only after the 1st frame has been decoded,
988
989
     * so we need to check for direct rendering again. */

990
991
992
    int i_width = p_context->width;
    int i_height = p_context->height;
    avcodec_align_dimensions( p_context, &i_width, &i_height );
993

994
    if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS ||
995
        p_context->pix_fmt == PIX_FMT_PAL8 )
996
        goto no_dr;
997

998
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
999
1000

    /* Get a new picture */
1001
    p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
1002
    if( !p_pic )
1003
        goto no_dr;
1004
1005
1006
1007
1008
1009
    bool b_compatible = true;
    if( p_pic->p[0].i_pitch / p_pic->p[0].i_pixel_pitch < i_width ||
        p_pic->p[0].i_lines < i_height )
        b_compatible = false;
    for( int i = 0; i < p_pic->i_planes && b_compatible; i++ )
    {
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
        unsigned i_align;
        switch( p_sys->i_codec_id )
        {
        case CODEC_ID_SVQ1:
        case CODEC_ID_VP5:
        case CODEC_ID_VP6:
        case CODEC_ID_VP6F:
        case CODEC_ID_VP6A:
            i_align = 16;
            break;
        default:
            i_align = i == 0 ? 16 : 8;
            break;
        }
1024
1025
1026
1027
1028
        if( p_pic->p[i].i_pitch % i_align )
            b_compatible = false;
        if( (intptr_t)p_pic->p[i].p_pixels % i_align )
            b_compatible = false;
    }
1029
1030
1031
1032
1033
1034
    if( p_context->pix_fmt == PIX_FMT_YUV422P && b_compatible )
    {
        if( 2 * p_pic->p[1].i_pitch != p_pic->p[0].i_pitch ||
            2 * p_pic->p[2].i_pitch != p_pic->p[0].i_pitch )
            b_compatible = false;
    }
1035
1036
1037
    if( !b_compatible )
    {
        decoder_DeletePicture( p_dec, p_pic );
1038
1039
1040
1041
1042
1043
1044
        goto no_dr;
    }

    if( p_sys->i_direct_rendering_used != 1 )
    {
        msg_Dbg( p_dec, "using direct rendering" );
        p_sys->i_direct_rendering_used = 1;
1045
    }
1046

1047
    p_context->draw_horiz_band = NULL;
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

    p_ff_pic->opaque = (void*)p_pic;
    p_ff_pic->type = FF_BUFFER_TYPE_USER;
    p_ff_pic->data[0] = p_pic->p[0].p_pixels;
    p_ff_pic->data[1] = p_pic->p[1].p_pixels;
    p_ff_pic->data[2] = p_pic->p[2].p_pixels;
    p_ff_pic->data[3] = NULL; /* alpha channel but I'm not sure */

    p_ff_pic->linesize[0] = p_pic->p[0].i_pitch;
    p_ff_pic->linesize[1] = p_pic->p[1].i_pitch;
    p_ff_pic->linesize[2] = p_pic->p[2].i_pitch;
    p_ff_pic->linesize[3] = 0;

    /* FIXME what is that, should give good value */
    p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg

Laurent Aimar's avatar
Laurent Aimar committed
1064
    post_mt( p_sys );
1065
    return 0;
1066
1067
1068
1069
1070
1071
1072

no_dr:
    if( p_sys->i_direct_rendering_used != 0 )
    {
        msg_Warn( p_dec, "disabling direct rendering" );
        p_sys->i_direct_rendering_used = 0;
    }
Laurent Aimar's avatar
Laurent Aimar committed
1073
    post_mt( p_sys );
1074
    return avcodec_default_get_buffer( p_context, p_ff_pic );
1075
}
1076
1077
static int  ffmpeg_ReGetFrameBuf( struct AVCodecContext *p_context, AVFrame *p_ff_pic )
{
1078
    p_ff_pic->reordered_opaque = p_context->reordered_opaque;
1079
1080

    /* We always use default reget function, it works perfectly fine */
1081
    return avcodec_default_reget_buffer( p_context, p_ff_pic );
1082
}
1083
1084
1085
1086
1087

static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
                                    AVFrame *p_ff_pic )
{
    decoder_t *p_dec = (decoder_t *)p_context->opaque;
1088
1089
1090
1091
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( p_sys->p_va )
    {
1092
        vlc_va_Release( p_sys->p_va, p_ff_pic );
1093
1094
    }
    else if( !p_ff_pic->opaque )
1095
    {
1096
1097
1098
1099
1100
1101
        /* We can end up here without the AVFrame being allocated by
         * avcodec_default_get_buffer() if VA is used and the frame is
         * released when the decoder is closed
         */
        if( p_ff_pic->type == FF_BUFFER_TYPE_INTERNAL )
            avcodec_default_release_buffer( p_context, p_ff_pic );
1102
    }
1103
1104
1105
    else
    {
        picture_t *p_pic = (picture_t*)p_ff_pic->opaque;
1106

1107
1108
        decoder_UnlinkPicture( p_dec, p_pic );
    }
1109
1110
    for( int i = 0; i < 4; i++ )
        p_ff_pic->data[i] = NULL;
1111
}