video.c 41.8 KB
Newer Older
1
/*****************************************************************************
2
 * video.c: video decoder using the libavcodec library
3
 *****************************************************************************
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
4
 * Copyright (C) 1999-2001 VLC authors and VideoLAN
5
6
7
8
9
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Gildas Bazin <gbazin@videolan.org>
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
10
11
12
 * 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
13
14
15
16
 * (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
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
17
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Lesser General Public License for more details.
19
 *
Jean-Baptiste Kempf's avatar
LGPL    
Jean-Baptiste Kempf committed
20
21
22
 * 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.
23
24
25
26
27
 *****************************************************************************/

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

32
#include <vlc_common.h>
zorglub's avatar
zorglub committed
33
#include <vlc_codec.h>
34
#include <vlc_avcodec.h>
Laurent Aimar's avatar
Laurent Aimar committed
35
#include <vlc_cpu.h>
36
#include <assert.h>
37

38
#include <libavcodec/avcodec.h>
39
#include <libavutil/mem.h>
40
#include <libavutil/pixdesc.h>
41

42
#include "avcodec.h"
43
#include "va.h"
44
45
46
47
48
49

/*****************************************************************************
 * decoder_sys_t : decoder descriptor
 *****************************************************************************/
struct decoder_sys_t
{
50
    AVCODEC_COMMON_MEMBERS
51
52
53
54
55
56
57

    /* Video decoder specific part */
    mtime_t i_pts;

    AVFrame          *p_ff_pic;

    /* for frame skipping algo */
58
    bool b_hurry_up;
59
60
    enum AVDiscard i_skip_frame;
    enum AVDiscard i_skip_idct;
61
62
63
64
65
66

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

    /* for direct rendering */
67
    bool b_direct_rendering;
68
    int  i_direct_rendering_used;
69

70
    bool b_has_b_frames;
71
72

    /* Hack to force display of still pictures */
73
    bool b_first_frame;
74

75

76
    /* */
77
78
79
80
81
#if LIBAVCODEC_VERSION_MAJOR < 54
    AVPaletteControl palette;
#else
# warning FIXME
#endif
82
83
84

    /* */
    bool b_flush;
85
86
87

    /* VA API */
    vlc_va_t *p_va;
Laurent Aimar's avatar
Laurent Aimar committed
88
89

    vlc_sem_t sem_mt;
90
91
};

Laurent Aimar's avatar
Laurent Aimar committed
92
93
94
95
96
97
98
99
#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

100
101
102
/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
103
static void ffmpeg_InitCodec      ( decoder_t * );
104
static void ffmpeg_CopyPicture    ( decoder_t *, picture_t *, AVFrame * );
105
106
107
#if LIBAVCODEC_VERSION_MAJOR >= 55
static int lavc_GetFrame(struct AVCodecContext *, AVFrame *, int);
#else
108
109
static int  ffmpeg_GetFrameBuf    ( struct AVCodecContext *, AVFrame * );
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
110
#endif
111
112
113
static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *,
                                          const enum PixelFormat * );

114
115
116
117
118
119
120
121
122
123
124
125
126
127
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 )
{
128
    decoder_sys_t *p_sys = p_dec->p_sys;
129

130
131
132
133
134
135
136
137
    if( p_context->coded_width != p_context->width ||
        p_context->coded_height != p_context->height )
    {
        p_dec->fmt_out.video.i_visible_width = p_context->width;
        p_dec->fmt_out.video.i_visible_height = p_context->height;
    }
    p_dec->fmt_out.video.i_width = p_context->coded_width;
    p_dec->fmt_out.video.i_height = p_context->coded_height;
138
139
140
141
142
143

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

144
    if( !p_sys->p_va && GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) )
145
    {
146
147
148
149
        /* 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;
150
    }
151
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
152
153

    /* If an aspect-ratio was specified in the input format then force it */
Laurent Aimar's avatar
Laurent Aimar committed
154
    if( p_dec->fmt_in.video.i_sar_num > 0 && p_dec->fmt_in.video.i_sar_den > 0 )
155
    {
Laurent Aimar's avatar
Laurent Aimar committed
156
157
        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;
158
159
160
    }
    else
    {
161
162
        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;
163

Laurent Aimar's avatar
Laurent Aimar committed
164
        if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
165
        {
Laurent Aimar's avatar
Laurent Aimar committed
166
167
            p_dec->fmt_out.video.i_sar_num = 1;
            p_dec->fmt_out.video.i_sar_den = 1;
168
169
170
        }
    }

Laurent Aimar's avatar
Laurent Aimar committed
171
172
    if( p_dec->fmt_in.video.i_frame_rate > 0 &&
        p_dec->fmt_in.video.i_frame_rate_base > 0 )
173
174
175
176
    {
        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
177
            p_dec->fmt_in.video.i_frame_rate_base;
178
    }
179
    else if( p_context->time_base.num > 0 && p_context->time_base.den > 0 )
180
181
    {
        p_dec->fmt_out.video.i_frame_rate = p_context->time_base.den;
182
        p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num * __MAX( p_context->ticks_per_frame, 1 );
183
    }
184

185
    return decoder_NewPicture( p_dec );
186
187
188
189
190
191
192
193
}

/*****************************************************************************
 * 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
194
int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
195
                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
196
197
{
    decoder_sys_t *p_sys;
198
    int i_val;
199
200

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

204
205
    p_codec->type = AVMEDIA_TYPE_VIDEO;
    p_context->codec_type = AVMEDIA_TYPE_VIDEO;
206
    p_context->codec_id = i_codec_id;
207
208
209
210
    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;
211
    p_sys->p_ff_pic = avcodec_alloc_frame();
212
    p_sys->b_delayed_open = true;
213
    p_sys->p_va = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
214
    vlc_sem_init( &p_sys->sem_mt, 0 );
215
216

    /* ***** Fill p_context with init values ***** */
217
    p_sys->p_context->codec_tag = ffmpeg_CodecTag( p_dec->fmt_in.i_original_fourcc ?: p_dec->fmt_in.i_codec );
218
219
220

    /*  ***** Get configuration of ffmpeg plugin ***** */
    p_sys->p_context->workaround_bugs =
221
        var_InheritInteger( p_dec, "avcodec-workaround-bugs" );
222
    p_sys->p_context->err_recognition =
223
        var_InheritInteger( p_dec, "avcodec-error-resilience" );
224

225
226
    if( var_CreateGetBool( p_dec, "grayscale" ) )
        p_sys->p_context->flags |= CODEC_FLAG_GRAY;
227

228
    i_val = var_CreateGetInteger( p_dec, "avcodec-vismv" );
229
    if( i_val ) p_sys->p_context->debug_mv = i_val;
230

231
    i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" );
232
233
234
235
    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;
236

237
    if( var_CreateGetBool( p_dec, "avcodec-fast" ) )
238
        p_sys->p_context->flags2 |= CODEC_FLAG2_FAST;
239

240
    /* ***** libavcodec frame skipping ***** */
241
    p_sys->b_hurry_up = var_CreateGetBool( p_dec, "avcodec-hurry-up" );
242

243
    switch( var_CreateGetInteger( p_dec, "avcodec-skip-frame" ) )
244
245
246
247
248
249
250
251
    {
        case -1:
            p_sys->p_context->skip_frame = AVDISCARD_NONE;
            break;
        case 0:
            p_sys->p_context->skip_frame = AVDISCARD_DEFAULT;
            break;
        case 1:
252
            p_sys->p_context->skip_frame = AVDISCARD_NONREF;
253
254
255
256
257
258
259
260
261
262
263
            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;
    }
264
    p_sys->i_skip_frame = p_sys->p_context->skip_frame;
265

266
    switch( var_CreateGetInteger( p_dec, "avcodec-skip-idct" ) )
267
268
269
270
271
272
273
274
    {
        case -1:
            p_sys->p_context->skip_idct = AVDISCARD_NONE;
            break;
        case 0:
            p_sys->p_context->skip_idct = AVDISCARD_DEFAULT;
            break;
        case 1:
275
            p_sys->p_context->skip_idct = AVDISCARD_NONREF;
276
277
278
279
280
281
282
283
284
285
286
            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;
    }
287
    p_sys->i_skip_idct = p_sys->p_context->skip_idct;
288

289
    /* ***** libavcodec direct rendering ***** */
290
    p_sys->b_direct_rendering = false;
291
    p_sys->i_direct_rendering_used = -1;
292
    if( var_CreateGetBool( p_dec, "avcodec-dr" ) &&
293
       (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
294
        /* No idea why ... but this fixes flickering on some TSCC streams */
295
296
        p_sys->i_codec_id != AV_CODEC_ID_TSCC && p_sys->i_codec_id != AV_CODEC_ID_CSCD &&
        p_sys->i_codec_id != AV_CODEC_ID_CINEPAK &&
297
298
299
300
        !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() */
301
        p_sys->b_direct_rendering = true;
302
303
    }

304
    /* libavcodec doesn't properly release old pictures when frames are skipped */
305
    //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = false;
306
307
    if( p_sys->b_direct_rendering )
    {
308
        msg_Dbg( p_dec, "trying to use direct rendering" );
309
310
        p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
    }
311
312
313
314
    else
    {
        msg_Dbg( p_dec, "direct rendering is disabled" );
    }
315

316
    p_sys->p_context->get_format = ffmpeg_GetFormat;
317
318
    /* Always use our get_buffer wrapper so we can calculate the
     * PTS correctly */
319
320
321
#if LIBAVCODEC_VERSION_MAJOR >= 55
    p_sys->p_context->get_buffer2 = lavc_GetFrame;
#else
322
    p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
323
    p_sys->p_context->reget_buffer = avcodec_default_reget_buffer;
324
    p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
325
#endif
326
327
    p_sys->p_context->opaque = p_dec;

Laurent Aimar's avatar
Laurent Aimar committed
328
#ifdef HAVE_AVCODEC_MT
329
    int i_thread_count = var_InheritInteger( p_dec, "avcodec-threads" );
Laurent Aimar's avatar
Laurent Aimar committed
330
    if( i_thread_count <= 0 )
331
    {
Laurent Aimar's avatar
Laurent Aimar committed
332
        i_thread_count = vlc_GetCPUCount();
333
334
        if( i_thread_count > 1 )
            i_thread_count++;
335
336
337

        //FIXME: take in count the decoding time
        i_thread_count = __MIN( i_thread_count, 4 );
338
    }
339
    i_thread_count = __MIN( i_thread_count, 16 );
340
341
    msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count );
    p_sys->p_context->thread_count = i_thread_count;
342
    p_sys->p_context->thread_safe_callbacks = true;
343

344
    switch( i_codec_id )
Laurent Aimar's avatar
Laurent Aimar committed
345
    {
346
347
348
349
350
351
352
353
        case AV_CODEC_ID_MPEG4:
        case AV_CODEC_ID_H263:
            p_sys->p_context->thread_type = 0;
            break;
        case AV_CODEC_ID_MPEG1VIDEO:
        case AV_CODEC_ID_MPEG2VIDEO:
            p_sys->p_context->thread_type &= ~FF_THREAD_SLICE;
            /* fall through */
354
# if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0))
355
356
357
        case AV_CODEC_ID_H264:
        case AV_CODEC_ID_VC1:
        case AV_CODEC_ID_WMV3:
358
            p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
359
# endif
360
    }
361

362
363
364
365
    if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
        p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count;
#endif

366
    /* ***** misc init ***** */
367
    p_sys->i_pts = VLC_TS_INVALID;
368
369
    p_sys->b_has_b_frames = false;
    p_sys->b_first_frame = true;
370
    p_sys->b_flush = false;
371
372
373
374
    p_sys->i_late_frames = 0;

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

382
#if LIBAVCODEC_VERSION_MAJOR < 54
383
    /* Setup palette */
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
    memset( &p_sys->palette, 0, sizeof(p_sys->palette) );
    if( p_dec->fmt_in.video.p_palette )
    {
        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;
    }
    else if( p_sys->i_codec_id != CODEC_ID_MSVIDEO1 && p_sys->i_codec_id != CODEC_ID_CINEPAK )
    {
        p_sys->p_context->palctrl = &p_sys->palette;
    }
#else
# warning FIXME
#endif
415

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

419
    /* ***** Open the codec ***** */
420
    if( ffmpeg_OpenCodec( p_dec ) < 0 )
421
422
    {
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
423
        av_free( p_sys->p_ff_pic );
Laurent Aimar's avatar
Laurent Aimar committed
424
        vlc_sem_destroy( &p_sys->sem_mt );
425
426
427
428
429
430
431
432
433
434
        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
435
picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
436
437
{
    decoder_sys_t *p_sys = p_dec->p_sys;
438
    AVCodecContext *p_context = p_sys->p_context;
439
    int b_drawpicture;
440
    int b_null_size = false;
441
442
    block_t *p_block;

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

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

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

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

        p_sys->i_late_frames = 0;

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

474
        block_Release( p_block );
475
476
477
478
479
480
481
482
483
484
485
        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;
    }

486
    if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) &&
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
487
        (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) )
488
    {
489
        if( p_sys->i_pts > VLC_TS_INVALID )
490
491
492
        {
            msg_Err( p_dec, "more than 5 seconds of late video -> "
                     "dropping frame (computer too slow ?)" );
493
            p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
494
495
496
497
498
499
500
501
        }
        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 &&
502
503
        p_sys->b_hurry_up &&
        (p_sys->i_late_frames > 4) )
504
505
    {
        b_drawpicture = 0;
506
        if( p_sys->i_late_frames < 12 )
507
        {
508
            p_context->skip_frame =
509
510
                    (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
                    AVDISCARD_NONREF : p_sys->i_skip_frame;
511
512
513
514
515
516
517
518
519
520
521
522
        }
        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
    {
523
        if( p_sys->b_hurry_up )
524
            p_context->skip_frame = p_sys->i_skip_frame;
Laurent Aimar's avatar
Laurent Aimar committed
525
        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
526
527
528
529
530
            b_drawpicture = 1;
        else
            b_drawpicture = 0;
    }

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

    /*
549
     * Do the actual decoding now */
550

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

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

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

Laurent Aimar's avatar
Laurent Aimar committed
573
        post_mt( p_sys );
574

575
576
577
        av_init_packet( &pkt );
        pkt.data = p_block->p_buffer;
        pkt.size = p_block->i_buffer;
578
579
580
581
582
583
584
        pkt.pts = p_block->i_pts;
        pkt.dts = p_block->i_dts;

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

585
586
        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                       &b_gotpicture, &pkt );
587

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

600
601
602
        if( p_sys->b_flush )
            p_sys->b_first_frame = true;

603
        if( p_block->i_buffer <= 0 )
604
605
            p_sys->b_flush = false;

606
607
        if( i_used < 0 )
        {
Laurent Aimar's avatar
Laurent Aimar committed
608
            if( b_drawpicture )
609
610
                msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
                          p_block->i_buffer );
611
612
613
            block_Release( p_block );
            return NULL;
        }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
614
        else if( (unsigned)i_used > p_block->i_buffer ||
Laurent Aimar's avatar
Laurent Aimar committed
615
                 p_context->thread_count > 1 )
616
        {
617
            i_used = p_block->i_buffer;
618
619
620
        }

        /* Consumed bytes */
621
622
        p_block->i_buffer -= i_used;
        p_block->p_buffer += i_used;
623
624
625
626
627
628
629
630

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

631
        /* Sanity check (seems to be needed for some streams) */
632
        if( p_sys->p_ff_pic->pict_type == AV_PICTURE_TYPE_B)
633
634
635
636
        {
            p_sys->b_has_b_frames = true;
        }

637
        /* Compute the PTS */
638
639
640
641
642
        mtime_t i_pts =
                    p_sys->p_ff_pic->pkt_pts;
        if (i_pts <= VLC_TS_INVALID)
            i_pts = p_sys->p_ff_pic->pkt_dts;

643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
        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);
            }
        }
672

673
        /* Update frame late count (except when doing preroll) */
674
675
        mtime_t i_display_date = 0;
        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
676
            i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
677

678
        if( i_display_date > 0 && i_display_date <= mdate() )
679
680
681
682
683
684
685
686
687
688
        {
            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;
        }

689
        if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) )
690
691
            continue;

692
        if( p_sys->p_va != NULL || p_sys->p_ff_pic->opaque == NULL )
693
694
        {
            /* Get a new picture */
695
            p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
696
697
698
699
700
701
702
703
704
705
706
707
708
            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;
709
            decoder_LinkPicture( p_dec, p_pic );
710
711
        }

Laurent Aimar's avatar
Laurent Aimar committed
712
        if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
713
714
        {
            /* Fetch again the aspect ratio in case it changed */
715
            p_dec->fmt_out.video.i_sar_num
716
                = p_context->sample_aspect_ratio.num;
717
            p_dec->fmt_out.video.i_sar_den
718
                = p_context->sample_aspect_ratio.den;
719

Laurent Aimar's avatar
Laurent Aimar committed
720
            if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
721
            {
Laurent Aimar's avatar
Laurent Aimar committed
722
723
                p_dec->fmt_out.video.i_sar_num = 1;
                p_dec->fmt_out.video.i_sar_den = 1;
724
725
726
            }
        }

727
        /* Send decoded frame to vout */
728
        if( i_pts > VLC_TS_INVALID)
729
        {
730
            p_pic->date = i_pts;
731
732
733
734

            if( p_sys->b_first_frame )
            {
                /* Hack to force display of still pictures */
735
736
                p_sys->b_first_frame = false;
                p_pic->b_force = true;
737
738
739
740
741
742
743
744
745
746
            }

            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;

            return p_pic;
        }
        else
        {
747
            decoder_DeletePicture( p_dec, p_pic );
748
749
750
751
752
753
754
755
756
757
        }
    }

    block_Release( p_block );
    return NULL;
}

/*****************************************************************************
 * EndVideo: decoder destruction
 *****************************************************************************
758
 * This function is called when the thread ends after a successful
759
760
 * initialization.
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
761
void EndVideoDec( decoder_t *p_dec )
762
763
764
{
    decoder_sys_t *p_sys = p_dec->p_sys;

Laurent Aimar's avatar
Laurent Aimar committed
765
766
    post_mt( p_sys );

767
768
769
    /* 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 );
770

Laurent Aimar's avatar
Laurent Aimar committed
771
772
    wait_mt( p_sys );

773
774
    if( p_sys->p_ff_pic )
        av_free( p_sys->p_ff_pic );
775
776

    if( p_sys->p_va )
777
        vlc_va_Delete( p_sys->p_va );
778

Laurent Aimar's avatar
Laurent Aimar committed
779
    vlc_sem_destroy( &p_sys->sem_mt );
780
781
}

782
783
784
785
786
787
788
789
790
791
/*****************************************************************************
 * 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;

792
    if( p_sys->i_codec_id == AV_CODEC_ID_SVQ3 )
793
794
795
796
797
798
    {
        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
799
800
        if( !p )
            return;
801
802
803
804
805
806
807

        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 &&
808
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
809
810
811
812
813
814
815
816
817
818
819
        {
            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;
                }
820
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
                {
                    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
836
837
838
839
840
841
842
        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 );
        }
843
844
845
    }
}

846
847
848
849
850
851
852
853
854
/*****************************************************************************
 * 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;

855
856
    if( p_sys->p_va )
    {
857
858
        vlc_va_Extract( p_sys->p_va, p_pic, p_ff_pic->opaque,
                        p_ff_pic->data[3] );
859
    }
860
    else if( FindVlcChroma( p_sys->p_context->pix_fmt ) )
861
862
863
864
865
    {
        int i_plane, i_size, i_line;
        uint8_t *p_dst, *p_src;
        int i_src_stride, i_dst_stride;

866
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
867
        {
868
869
870
871
872
873
874
875
            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++ )
876
            {
Rafaël Carré's avatar
Rafaël Carré committed
877
                memcpy( p_dst, p_src, i_size );
878
879
                p_src += i_src_stride;
                p_dst += i_dst_stride;
880
881
882
883
884
            }
        }
    }
    else
    {
885
886
887
        const char *name = av_get_pix_fmt_name( p_sys->p_context->pix_fmt );
        msg_Err( p_dec, "Unsupported decoded output format %d (%s)",
                 p_sys->p_context->pix_fmt, name ? name : "unknown" );
888
        p_dec->b_error = 1;
889
890
891
    }
}

892
#if LIBAVCODEC_VERSION_MAJOR >= 55
893
894
static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
                            int flags)
895
896
897
898
899
900
901
902
903
904
905
{
    decoder_t *dec = ctx->opaque;
    decoder_sys_t *sys = dec->p_sys;
    vlc_va_t *va = sys->p_va;

    if (vlc_va_Setup(va, &ctx->hwaccel_context, &dec->fmt_out.video.i_chroma,
                     ctx->coded_width, ctx->coded_height))
    {
        msg_Err(dec, "hardware acceleration setup failed");
        return -1;
    }
906
    if (vlc_va_Get(va, &frame->opaque, &frame->data[0]))
907
908
909
910
    {
        msg_Err(dec, "hardware acceleration picture allocation failed");
        return -1;
    }
911
912
913
    /* data[0] must be non-NULL for libavcodec internal checks.
     * data[3] actually contains the format-specific surface handle. */
    frame->data[3] = frame->data[0];
914

915
916
    frame->buf[0] = av_buffer_create(frame->data[0], 0, va->release,
                                     frame->opaque, 0);
917
918
    if (unlikely(frame->buf[0] == NULL))
    {
919
        vlc_va_Release(va, frame->opaque, frame->data[0]);
920
921
        return -1;
    }
922
923
    assert(frame->data[0] != NULL);
    (void) flags;
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
    return 0;
}

typedef struct
{
    decoder_t *decoder;
    picture_t *picture;
} lavc_pic_ref_t;

static void lavc_dr_ReleaseFrame(void *opaque, uint8_t *data)
{
    lavc_pic_ref_t *ref = opaque;

    decoder_UnlinkPicture(ref->decoder, ref->picture);
    free(ref);
    (void) data;
}

static picture_t *lavc_dr_GetFrame(struct AVCodecContext *ctx,
943
                                   AVFrame *frame, int flags)
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
{
    decoder_t *dec = (decoder_t *)ctx->opaque;

    if (GetVlcChroma(&dec->fmt_out.video, ctx->pix_fmt) != VLC_SUCCESS)
        return NULL;
    dec->fmt_out.i_codec = dec->fmt_out.video.i_chroma;
    if (ctx->pix_fmt == PIX_FMT_PAL8)
        return NULL;

    int width = frame->width;
    int height = frame->height;
    int aligns[AV_NUM_DATA_POINTERS];

    avcodec_align_dimensions2(ctx, &width, &height, aligns);

    picture_t *pic = ffmpeg_NewPictBuf(dec, ctx);
    if (pic == NULL)
        return NULL;

    /* Check that the picture is suitable for libavcodec */
964
965
966
967
968
969
970
971
972
973
974
    if (pic->p[0].i_pitch < width * pic->p[0].i_pixel_pitch)
    {
        msg_Dbg(dec, "plane 0: pitch too small (%d/%d*%d)",
                pic->p[0].i_pitch, width, pic->p[0].i_pixel_pitch);
        goto no_dr;
    }

    if (pic->p[0].i_lines < height)
    {
        msg_Dbg(dec, "plane 0: lines too few (%d/%d)",
                pic->p[0].i_lines, height);
975
        goto no_dr;
976
    }
977
978
979

    for (int i = 0; i < pic->i_planes; i++)
    {
980
        if (pic->p[i].i_pitch % aligns[i])
981
982
983
        {
            msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)",
                    i, pic->p[i].i_pitch, aligns[i]);
984
            goto no_dr;
985
        }
986
        if (((uintptr_t)pic->p[i].p_pixels) % aligns[i])
987
988
        {
            msg_Warn(dec, "plane %d not aligned", i);
989
            goto no_dr;
990
        }
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
    }

    /* Allocate buffer references */
    for (int i = 0; i < pic->i_planes; i++)
    {
        lavc_pic_ref_t *ref = malloc(sizeof (*ref));
        if (ref == NULL)
            goto error;
        ref->decoder = dec;
        ref->picture = pic;
        decoder_LinkPicture(dec, pic);

        uint8_t *data = pic->p[i].p_pixels;
        int size = pic->p[i].i_pitch * pic->p[i].i_lines;

        frame->buf[i] = av_buffer_create(data, size, lavc_dr_ReleaseFrame,
                                         ref, 0);
        if (unlikely(frame->buf[i] == NULL))
        {
            lavc_dr_ReleaseFrame(ref, data);
            goto error;
        }
    }
    decoder_UnlinkPicture(dec, pic);
    (void) flags;
    return pic;
error:
    for (unsigned i = 0; frame->buf[i] != NULL; i++)
        av_buffer_unref(&frame->buf[i]);
no_dr:
    decoder_DeletePicture(dec, pic);
    return NULL;
}

/**
 * Callback used by libavcodec 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 lavc_GetFrame(struct AVCodecContext *ctx, AVFrame *frame, int flags)
{
    decoder_t *dec = ctx->opaque;
    decoder_sys_t *sys = dec->p_sys;
    picture_t *pic;

1037
1038
1039
1040
1041
1042
1043
    for (unsigned i = 0; i < AV_NUM_DATA_POINTERS; i++)
    {
        frame->data[i] = NULL;
        frame->linesize[i] = 0;
        frame->buf[i] = NULL;
    }

1044
    if (sys->p_va != NULL)
1045
        return lavc_va_GetFrame(ctx, frame, flags);
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082

    frame->opaque = NULL;
    if (!sys->b_direct_rendering)
        return avcodec_default_get_buffer2(ctx, frame, flags);

    /* Some codecs set pix_fmt only after the 1st frame has been decoded,
     * so we need to check for direct rendering again. */
    wait_mt(sys);
    pic = lavc_dr_GetFrame(ctx, frame, flags);
    if (pic == NULL)
    {
        if (sys->i_direct_rendering_used != 0)
        {
            msg_Warn(dec, "disabling direct rendering");
            sys->i_direct_rendering_used = 0;
        }
        post_mt(sys);
        return avcodec_default_get_buffer2(ctx, frame, flags);
    }

    if (sys->i_direct_rendering_used != 1)
    {
        msg_Dbg(dec, "enabling direct rendering");
        sys->i_direct_rendering_used = 1;
    }
    post_mt(sys);

    frame->opaque = pic;
    static_assert(PICTURE_PLANE_MAX <= AV_NUM_DATA_POINTERS, "Oops!");
    for (unsigned i = 0; i < PICTURE_PLANE_MAX; i++)
    {
        frame->data[i] = pic->p[i].p_pixels;
        frame->linesize[i] = pic->p[i].i_pitch;
    }
    return 0;
}
#else
1083
1084
1085
1086
1087
1088
1089
1090
1091
static int ffmpeg_va_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;
    vlc_va_t *p_va = p_sys->p_va;

    /* hwaccel_context is not present in old ffmpeg version */
    if( vlc_va_Setup( p_va,
                &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
1092
                p_context->coded_width, p_context->coded_height ) )
1093
1094
1095
1096
1097
    {
        msg_Err( p_dec, "vlc_va_Setup failed" );
        return -1;
    }

1098
    if( vlc_va_Get( p_va, &p_ff_pic->opaque, &p_ff_pic->data[0] ) )
1099
    {
1100
        msg_Err( p_dec, "vlc_va_Get failed" );
1101
1102
1103
        return -1;
    }

1104
    p_ff_pic->data[3] = p_ff_pic->data[0];