video.c 43.2 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
#if LIBAVCODEC_VERSION_MAJOR < 54
    AVPaletteControl palette;
#else
80
    bool palette_sent;
81
#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
    int width = p_context->coded_width;
    int height = p_context->coded_height;
131

132
133
134
135
136
137
    if( p_sys->p_va == NULL )
    {
        int aligns[AV_NUM_DATA_POINTERS];

        avcodec_align_dimensions2(p_context, &width, &height, aligns);
    }
138
139
140
141
142
143
144
145

    if( width == 0 || height == 0)
        return NULL; /* invalid display size */

    p_dec->fmt_out.video.i_width = width;
    p_dec->fmt_out.video.i_height = height;

    if( width != p_context->width || height != p_context->height )
146
147
148
149
    {
        p_dec->fmt_out.video.i_visible_width = p_context->width;
        p_dec->fmt_out.video.i_visible_height = p_context->height;
    }
150
151
152
153
154
    else
    {
        p_dec->fmt_out.video.i_visible_width = width;
        p_dec->fmt_out.video.i_visible_height = height;
    }
155

156
    if( !p_sys->p_va && GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) )
157
    {
158
159
160
161
        /* 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;
162
    }
163
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
164
165

    /* If an aspect-ratio was specified in the input format then force it */
Laurent Aimar's avatar
Laurent Aimar committed
166
    if( p_dec->fmt_in.video.i_sar_num > 0 && p_dec->fmt_in.video.i_sar_den > 0 )
167
    {
Laurent Aimar's avatar
Laurent Aimar committed
168
169
        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;
170
171
172
    }
    else
    {
173
174
        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;
175

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

Laurent Aimar's avatar
Laurent Aimar committed
183
184
    if( p_dec->fmt_in.video.i_frame_rate > 0 &&
        p_dec->fmt_in.video.i_frame_rate_base > 0 )
185
186
187
188
    {
        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
189
            p_dec->fmt_in.video.i_frame_rate_base;
190
    }
191
    else if( p_context->time_base.num > 0 && p_context->time_base.den > 0 )
192
193
    {
        p_dec->fmt_out.video.i_frame_rate = p_context->time_base.den;
194
        p_dec->fmt_out.video.i_frame_rate_base = p_context->time_base.num * __MAX( p_context->ticks_per_frame, 1 );
195
    }
196

197
    return decoder_NewPicture( p_dec );
198
199
200
201
202
203
204
205
}

/*****************************************************************************
 * 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
206
int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
207
                      AVCodec *p_codec, int i_codec_id, const char *psz_namecodec )
208
209
{
    decoder_sys_t *p_sys;
210
    int i_val;
211
212

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

216
217
    p_codec->type = AVMEDIA_TYPE_VIDEO;
    p_context->codec_type = AVMEDIA_TYPE_VIDEO;
218
    p_context->codec_id = i_codec_id;
219
220
221
222
    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;
223
    p_sys->p_ff_pic = avcodec_alloc_frame();
224
    p_sys->b_delayed_open = true;
225
    p_sys->p_va = NULL;
Laurent Aimar's avatar
Laurent Aimar committed
226
    vlc_sem_init( &p_sys->sem_mt, 0 );
227
228

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

    /*  ***** Get configuration of ffmpeg plugin ***** */
    p_sys->p_context->workaround_bugs =
233
        var_InheritInteger( p_dec, "avcodec-workaround-bugs" );
234
    p_sys->p_context->err_recognition =
235
        var_InheritInteger( p_dec, "avcodec-error-resilience" );
236

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

Luca Barbato's avatar
Luca Barbato committed
240
241
242
243
244
    /* ***** Output always the frames ***** */
#if LIBAVCODEC_VERSION_CHECK(55, 23, 1, 40, 101)
    p_sys->p_context->flags |= CODEC_FLAG_OUTPUT_CORRUPT;
#endif

245
    i_val = var_CreateGetInteger( p_dec, "avcodec-vismv" );
246
    if( i_val ) p_sys->p_context->debug_mv = i_val;
247

248
    i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" );
249
250
251
252
    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
    if( var_CreateGetBool( p_dec, "avcodec-fast" ) )
255
        p_sys->p_context->flags2 |= CODEC_FLAG2_FAST;
256

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

260
261
262
263
264
265
266
    i_val = var_CreateGetInteger( p_dec, "avcodec-skip-frame" );
    if( i_val >= 4 ) p_sys->p_context->skip_frame = AVDISCARD_ALL;
    else if( i_val == 3 ) p_sys->p_context->skip_frame = AVDISCARD_NONKEY;
    else if( i_val == 2 ) p_sys->p_context->skip_frame = AVDISCARD_BIDIR;
    else if( i_val == 1 ) p_sys->p_context->skip_frame = AVDISCARD_NONREF;
    else if( i_val == -1 ) p_sys->p_context->skip_frame = AVDISCARD_NONE;
    else p_sys->p_context->skip_frame = AVDISCARD_DEFAULT;
267
    p_sys->i_skip_frame = p_sys->p_context->skip_frame;
268

269
270
271
272
273
274
275
    i_val = var_CreateGetInteger( p_dec, "avcodec-skip-idct" );
    if( i_val >= 4 ) p_sys->p_context->skip_idct = AVDISCARD_ALL;
    else if( i_val == 3 ) p_sys->p_context->skip_idct = AVDISCARD_NONKEY;
    else if( i_val == 2 ) p_sys->p_context->skip_idct = AVDISCARD_BIDIR;
    else if( i_val == 1 ) p_sys->p_context->skip_idct = AVDISCARD_NONREF;
    else if( i_val == -1 ) p_sys->p_context->skip_idct = AVDISCARD_NONE;
    else p_sys->p_context->skip_idct = AVDISCARD_DEFAULT;
276
    p_sys->i_skip_idct = p_sys->p_context->skip_idct;
277

278
    /* ***** libavcodec direct rendering ***** */
279
    p_sys->b_direct_rendering = false;
280
    p_sys->i_direct_rendering_used = -1;
281
    if( var_CreateGetBool( p_dec, "avcodec-dr" ) &&
282
       (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
283
        /* No idea why ... but this fixes flickering on some TSCC streams */
284
285
        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 &&
286
287
288
289
        !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() */
290
        p_sys->b_direct_rendering = true;
291
292
    }

293
    /* libavcodec doesn't properly release old pictures when frames are skipped */
294
    //if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = false;
295
296
    if( p_sys->b_direct_rendering )
    {
297
        msg_Dbg( p_dec, "trying to use direct rendering" );
298
299
        p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
    }
300
301
302
303
    else
    {
        msg_Dbg( p_dec, "direct rendering is disabled" );
    }
304

305
    p_sys->p_context->get_format = ffmpeg_GetFormat;
306
307
    /* Always use our get_buffer wrapper so we can calculate the
     * PTS correctly */
308
309
310
#if LIBAVCODEC_VERSION_MAJOR >= 55
    p_sys->p_context->get_buffer2 = lavc_GetFrame;
#else
311
    p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
312
    p_sys->p_context->reget_buffer = avcodec_default_reget_buffer;
313
    p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
314
#endif
315
316
    p_sys->p_context->opaque = p_dec;

Laurent Aimar's avatar
Laurent Aimar committed
317
#ifdef HAVE_AVCODEC_MT
318
    int i_thread_count = var_InheritInteger( p_dec, "avcodec-threads" );
Laurent Aimar's avatar
Laurent Aimar committed
319
    if( i_thread_count <= 0 )
320
    {
Laurent Aimar's avatar
Laurent Aimar committed
321
        i_thread_count = vlc_GetCPUCount();
322
323
        if( i_thread_count > 1 )
            i_thread_count++;
324
325
326

        //FIXME: take in count the decoding time
        i_thread_count = __MIN( i_thread_count, 4 );
327
    }
328
    i_thread_count = __MIN( i_thread_count, 16 );
329
330
    msg_Dbg( p_dec, "allowing %d thread(s) for decoding", i_thread_count );
    p_sys->p_context->thread_count = i_thread_count;
331
    p_sys->p_context->thread_safe_callbacks = true;
332

333
    switch( i_codec_id )
Laurent Aimar's avatar
Laurent Aimar committed
334
    {
335
336
337
338
339
340
341
342
        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 */
343
# if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0))
344
345
346
        case AV_CODEC_ID_H264:
        case AV_CODEC_ID_VC1:
        case AV_CODEC_ID_WMV3:
347
            p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
348
# endif
349
    }
350

351
352
353
354
    if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
        p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count;
#endif

355
    /* ***** misc init ***** */
356
    p_sys->i_pts = VLC_TS_INVALID;
357
358
    p_sys->b_has_b_frames = false;
    p_sys->b_first_frame = true;
359
    p_sys->b_flush = false;
360
361
362
363
    p_sys->i_late_frames = 0;

    /* Set output properties */
    p_dec->fmt_out.i_cat = VIDEO_ES;
364
365
    if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS )
    {
366
        /* we are doomed. but not really, because most codecs set their pix_fmt later on */
367
        p_dec->fmt_out.i_codec = VLC_CODEC_I420;
368
369
    }
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
370

371
372
    p_dec->fmt_out.video.orientation = p_dec->fmt_in.video.orientation;

373
#if LIBAVCODEC_VERSION_MAJOR < 54
374
    /* Setup palette */
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
    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
404
405
406
407
408
409
410
    if( p_dec->fmt_in.video.p_palette ) {
        p_sys->palette_sent = false;
        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
        p_sys->palette_sent = true;
411
#endif
412

413
414
415
    /* ***** init this codec with special data ***** */
    ffmpeg_InitCodec( p_dec );

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

439
    if( !pp_block )
440
        return NULL;
441

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

452
    p_block = *pp_block;
453
454
455
    if(!p_block && !(p_sys->p_codec->capabilities & CODEC_CAP_DELAY) )
        return NULL;

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

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

469
            p_sys->i_late_frames = 0;
470

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

476
477
478
            block_Release( p_block );
            return NULL;
        }
479

480
481
482
483
484
485
486
        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;
        }
487
488
    }

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

    /* A good idea could be to decode all I pictures and see for the other */
    if( !p_dec->b_pace_control &&
506
507
        p_sys->b_hurry_up &&
        (p_sys->i_late_frames > 4) )
508
509
    {
        b_drawpicture = 0;
510
        if( p_sys->i_late_frames < 12 )
511
        {
512
            p_context->skip_frame =
513
514
                    (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
                    AVDISCARD_NONREF : p_sys->i_skip_frame;
515
516
517
518
519
520
        }
        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 */
521
522
            if( p_block )
                block_Release( p_block );
523
            msg_Warn( p_dec, "More than 4 late frames, dropping frame" );
524
525
526
527
528
            return NULL;
        }
    }
    else
    {
529
        if( p_sys->b_hurry_up )
530
            p_context->skip_frame = p_sys->i_skip_frame;
531
        if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
532
533
534
535
536
            b_drawpicture = 1;
        else
            b_drawpicture = 0;
    }

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

    /*
554
     * Do the actual decoding now */
555

556
    /* Don't forget that libavcodec requires a little more bytes
557
     * that the real frame size */
558
    if( p_block && p_block->i_buffer > 0 )
559
    {
560
561
        p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;

562
563
564
        p_block = block_Realloc( p_block, 0,
                            p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
        if( !p_block )
ivoire's avatar
ivoire committed
565
            return NULL;
566
        p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
567
        *pp_block = p_block;
568
        memset( p_block->p_buffer + p_block->i_buffer, 0,
569
570
571
                FF_INPUT_BUFFER_PADDING_SIZE );
    }

572
    while( !p_block || p_block->i_buffer > 0 || p_sys->b_flush )
573
574
575
    {
        int i_used, b_gotpicture;
        picture_t *p_pic;
576
        AVPacket pkt;
577

Laurent Aimar's avatar
Laurent Aimar committed
578
        post_mt( p_sys );
579

580
        av_init_packet( &pkt );
581
582
583
584
585
586
587
588
589
590
591
592
593
        if( p_block )
        {
            pkt.data = p_block->p_buffer;
            pkt.size = p_block->i_buffer;
            pkt.pts = p_block->i_pts;
            pkt.dts = p_block->i_dts;
        }
        else
        {
            /* Return delayed frames if codec has CODEC_CAP_DELAY */
            pkt.data = NULL;
            pkt.size = 0;
        }
594

595
596
597
598
599
600
601
602
603
604
605
#if LIBAVCODEC_VERSION_MAJOR >= 54
        if( !p_sys->palette_sent )
        {
            uint8_t *pal = av_packet_new_side_data(&pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE);
            if (pal) {
                memcpy(pal, p_dec->fmt_in.video.p_palette->palette, AVPALETTE_SIZE);
                p_sys->palette_sent = true;
            }
        }
#endif

606
        /* Make sure we don't reuse the same timestamps twice */
607
608
609
610
611
        if( p_block )
        {
            p_block->i_pts =
            p_block->i_dts = VLC_TS_INVALID;
        }
612

613
614
        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                       &b_gotpicture, &pkt );
615

Laurent Aimar's avatar
Laurent Aimar committed
616
        wait_mt( p_sys );
617

618
619
620
        if( p_sys->b_flush )
            p_sys->b_first_frame = true;

621
        if( p_block )
622
        {
623
624
            if( p_block->i_buffer <= 0 )
                p_sys->b_flush = false;
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
            if( i_used < 0 )
            {
                if( b_drawpicture )
                    msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
                            p_block->i_buffer );
                block_Release( p_block );
                return NULL;
            }
            else if( (unsigned)i_used > p_block->i_buffer ||
                    p_context->thread_count > 1 )
            {
                i_used = p_block->i_buffer;
            }

            /* Consumed bytes */
            p_block->i_buffer -= i_used;
            p_block->p_buffer += i_used;
        }
644
645
646
647
648
649
650
651

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

652
        /* Sanity check (seems to be needed for some streams) */
653
        if( p_sys->p_ff_pic->pict_type == AV_PICTURE_TYPE_B)
654
655
656
657
        {
            p_sys->b_has_b_frames = true;
        }

658
        /* Compute the PTS */
659
660
661
662
663
        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;

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

694
        /* Update frame late count (except when doing preroll) */
695
        mtime_t i_display_date = 0;
696
        if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
697
            i_display_date = decoder_GetDisplayDate( p_dec, i_pts );
698

699
        if( i_display_date > 0 && i_display_date <= mdate() )
700
701
702
703
704
705
706
707
708
709
        {
            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;
        }

710
        if( !b_drawpicture || ( !p_sys->p_va && !p_sys->p_ff_pic->linesize[0] ) )
711
712
            continue;

713
        if( p_sys->p_va != NULL || p_sys->p_ff_pic->opaque == NULL )
714
715
        {
            /* Get a new picture */
716
            p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
717
718
            if( !p_pic )
            {
719
720
                if( p_block )
                    block_Release( p_block );
721
722
723
724
725
726
727
728
729
730
                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;
731
            decoder_LinkPicture( p_dec, p_pic );
732
733
        }

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

Laurent Aimar's avatar
Laurent Aimar committed
742
            if( !p_dec->fmt_out.video.i_sar_num || !p_dec->fmt_out.video.i_sar_den )
743
            {
Laurent Aimar's avatar
Laurent Aimar committed
744
745
                p_dec->fmt_out.video.i_sar_num = 1;
                p_dec->fmt_out.video.i_sar_den = 1;
746
747
748
            }
        }

749
        /* Send decoded frame to vout */
750
        if( i_pts > VLC_TS_INVALID)
751
        {
752
            p_pic->date = i_pts;
753
754
755
756

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

            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
        {
769
            decoder_DeletePicture( p_dec, p_pic );
770
771
772
        }
    }

773
774
    if( p_block )
        block_Release( p_block );
775
776
777
778
779
780
    return NULL;
}

/*****************************************************************************
 * EndVideo: decoder destruction
 *****************************************************************************
781
 * This function is called when the thread ends after a successful
782
783
 * initialization.
 *****************************************************************************/
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
784
void EndVideoDec( decoder_t *p_dec )
785
786
787
{
    decoder_sys_t *p_sys = p_dec->p_sys;

Laurent Aimar's avatar
Laurent Aimar committed
788
789
    post_mt( p_sys );

790
791
792
    /* 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 );
793

Laurent Aimar's avatar
Laurent Aimar committed
794
795
    wait_mt( p_sys );

796
797
    if( p_sys->p_ff_pic )
        av_free( p_sys->p_ff_pic );
798
799

    if( p_sys->p_va )
800
        vlc_va_Delete( p_sys->p_va );
801

Laurent Aimar's avatar
Laurent Aimar committed
802
    vlc_sem_destroy( &p_sys->sem_mt );
803
804
}

805
806
807
808
809
810
811
812
813
814
/*****************************************************************************
 * 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;

815
    if( p_sys->i_codec_id == AV_CODEC_ID_SVQ3 )
816
817
818
819
    {
        uint8_t *p;

        p_sys->p_context->extradata_size = i_size + 12;
820
821
822
        p = p_sys->p_context->extradata =
            av_malloc( p_sys->p_context->extradata_size +
                       FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
823
824
        if( !p )
            return;
825
826
827
828
829
830
831

        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 &&
832
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
833
834
835
836
837
838
839
840
841
842
843
        {
            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;
                }
844
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
845
846
847
848
849
850
851
852
853
854
855
856
857
858
                {
                    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 =
859
            av_malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
860
861
862
863
        if( p_sys->p_context->extradata )
        {
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
864
            memset( p_sys->p_context->extradata + i_size,
ivoire's avatar
ivoire committed
865
866
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
867
868
869
    }
}

870
871
872
873
874
875
876
877
878
/*****************************************************************************
 * 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;

879
880
    if( p_sys->p_va )
    {
881
882
        vlc_va_Extract( p_sys->p_va, p_pic, p_ff_pic->opaque,
                        p_ff_pic->data[3] );
883
    }
884
    else if( FindVlcChroma( p_sys->p_context->pix_fmt ) )
885
886
887
888
889
    {
        int i_plane, i_size, i_line;
        uint8_t *p_dst, *p_src;
        int i_src_stride, i_dst_stride;

890
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
891
        {
892
893
894
895
896
897
898
899
            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++ )
900
            {
Rafaël Carré's avatar
Rafaël Carré committed
901
                memcpy( p_dst, p_src, i_size );
902
903
                p_src += i_src_stride;
                p_dst += i_dst_stride;
904
905
906
907
908
            }
        }
    }
    else
    {
909
910
911
        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" );
912
        p_dec->b_error = 1;
913
914
915
    }
}

916
#if LIBAVCODEC_VERSION_MAJOR >= 55
917
918
static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
                            int flags)
919
920
921
922
923
924
925
926
927
928
929
{
    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;
    }
930
    if (vlc_va_Get(va, &frame->opaque, &frame->data[0]))
931
932
933
934
    {
        msg_Err(dec, "hardware acceleration picture allocation failed");
        return -1;
    }
935
936
937
    /* 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];
938

939
940
    frame->buf[0] = av_buffer_create(frame->data[0], 0, va->release,
                                     frame->opaque, 0);
941
942
    if (unlikely(frame->buf[0] == NULL))
    {
943
        vlc_va_Release(va, frame->opaque, frame->data[0]);
944
945
        return -1;
    }
946
947
    assert(frame->data[0] != NULL);
    (void) flags;
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
    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,
967
                                   AVFrame *frame, int flags)
968
969
{
    decoder_t *dec = (decoder_t *)ctx->opaque;
970
    decoder_sys_t *sys = dec->p_sys;
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

    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 */
989
990
    if (pic->p[0].i_pitch < width * pic->p[0].i_pixel_pitch)
    {
991
992
993
        if (sys->i_direct_rendering_used != 0)
            msg_Dbg(dec, "plane 0: pitch too small (%d/%d*%d)",
                    pic->p[0].i_pitch, width, pic->p[0].i_pixel_pitch);
994
995
996
997
998
        goto no_dr;
    }

    if (pic->p[0].i_lines < height)
    {
999
1000
1001
        if (sys->i_direct_rendering_used != 0)
            msg_Dbg(dec, "plane 0: lines too few (%d/%d)",
                    pic->p[0].i_lines, height);
1002
        goto no_dr;
1003
    }
1004
1005
1006

    for (int i = 0; i < pic->i_planes; i++)
    {
1007
        if (pic->p[i].i_pitch % aligns[i])
1008
        {
1009
1010
1011
            if (sys->i_direct_rendering_used != 0)
                msg_Dbg(dec, "plane %d: pitch not aligned (%d%%%d)",
                        i, pic->p[i].i_pitch, aligns[i]);
1012
            goto no_dr;
1013
        }
1014
        if (((uintptr_t)pic->p[i].p_pixels) % aligns[i])
1015
        {
1016
1017
            if (sys->i_direct_rendering_used != 0)
                msg_Warn(dec, "plane %d not aligned", i);
1018
            goto no_dr;
1019
        }
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
    }

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