video.c 43 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
    bool palette_sent;
78
79
80

    /* */
    bool b_flush;
81
82
83

    /* VA API */
    vlc_va_t *p_va;
Laurent Aimar's avatar
Laurent Aimar committed
84
85

    vlc_sem_t sem_mt;
86
87
};

Laurent Aimar's avatar
Laurent Aimar committed
88
89
90
91
92
93
94
95
#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

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

110
111
112
113
114
115
116
117
118
119
120
121
122
123
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 )
{
124
    decoder_sys_t *p_sys = p_dec->p_sys;
125
126
    int width = p_context->coded_width;
    int height = p_context->coded_height;
127

128
129
130
131
132
133
    if( p_sys->p_va == NULL )
    {
        int aligns[AV_NUM_DATA_POINTERS];

        avcodec_align_dimensions2(p_context, &width, &height, aligns);
    }
134
135


136
137
138
139
140
    if( width == 0 || height == 0 || width > 8192 || height > 8192 )
    {
        msg_Err( p_dec, "Invalid frame size %dx%d.", width, height );
        return NULL; /* invalid display size */
    }
141
142
143
144
    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 )
145
146
147
148
    {
        p_dec->fmt_out.video.i_visible_width = p_context->width;
        p_dec->fmt_out.video.i_visible_height = p_context->height;
    }
149
150
151
152
153
    else
    {
        p_dec->fmt_out.video.i_visible_width = width;
        p_dec->fmt_out.video.i_visible_height = height;
    }
154

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

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

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

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

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

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

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

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

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

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

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

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

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

247
    i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" );
248
249
250
251
    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;
252

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

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

259
260
261
262
263
264
265
    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;
266
    p_sys->i_skip_frame = p_sys->p_context->skip_frame;
267

268
269
270
271
272
273
274
    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;
275
    p_sys->i_skip_idct = p_sys->p_context->skip_idct;
276

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

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

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

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

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

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

350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
    /* Workaround: frame multithreading is not compatible with
     * DXVA2. When a frame is being copied to host memory, the frame
     * is locked and cannot be used as a reference frame
     * simultaneously and thus decoding fails for some frames. This
     * causes major image corruption. */
# if defined(_WIN32)
    char *avcodec_hw = var_InheritString( p_dec, "avcodec-hw" );
    if( avcodec_hw == NULL || strcasecmp( avcodec_hw, "none" ) )
    {
        msg_Warn( p_dec, "threaded frame decoding is not compatible with DXVA2, disabled" );
        p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
    }
    free( avcodec_hw );
# endif

365
366
367
368
    if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
        p_dec->i_extra_picture_buffers = 2 * p_sys->p_context->thread_count;
#endif

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

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

385
386
    p_dec->fmt_out.video.orientation = p_dec->fmt_in.video.orientation;

387
388
389
390
391
392
393
    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;
394

395
396
397
    /* ***** init this codec with special data ***** */
    ffmpeg_InitCodec( p_dec );

398
    /* ***** Open the codec ***** */
399
    if( ffmpeg_OpenCodec( p_dec ) < 0 )
400
401
    {
        msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
402
        av_free( p_sys->p_ff_pic );
Laurent Aimar's avatar
Laurent Aimar committed
403
        vlc_sem_destroy( &p_sys->sem_mt );
404
405
406
407
408
409
410
411
412
413
        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
414
picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
415
416
{
    decoder_sys_t *p_sys = p_dec->p_sys;
417
    AVCodecContext *p_context = p_sys->p_context;
418
419
420
    int b_drawpicture;
    block_t *p_block;

421
    if( !pp_block )
422
        return NULL;
423

424
    if( !p_context->extradata_size && p_dec->fmt_in.i_extra )
425
    {
426
        ffmpeg_InitCodec( p_dec );
427
428
429
430
431
432
        if( p_sys->b_delayed_open )
        {
            if( ffmpeg_OpenCodec( p_dec ) )
                msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
        }
    }
433

434
    p_block = *pp_block;
435
436
437
    if(!p_block && !(p_sys->p_codec->capabilities & CODEC_CAP_DELAY) )
        return NULL;

438
439
    if( p_sys->b_delayed_open )
    {
440
441
        if( p_block )
            block_Release( p_block );
442
443
        return NULL;
    }
444

445
    if( p_block)
446
    {
447
448
449
        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
        {
            p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
450

451
            p_sys->i_late_frames = 0;
452

453
454
455
456
            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
457

458
459
460
            block_Release( p_block );
            return NULL;
        }
461

462
463
464
465
466
467
468
        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;
        }
469
470
    }

471
    if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) &&
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
472
        (mdate() - p_sys->i_late_frames_start > INT64_C(5000000)) )
473
    {
474
        if( p_sys->i_pts > VLC_TS_INVALID )
475
        {
476
            p_sys->i_pts = VLC_TS_INVALID; /* To make sure we recover properly */
477
        }
478
479
        if( p_block )
            block_Release( p_block );
480
        p_sys->i_late_frames--;
481
482
        msg_Err( p_dec, "more than 5 seconds of late video -> "
                 "dropping frame (computer too slow ?)" );
483
484
485
486
487
        return NULL;
    }

    /* A good idea could be to decode all I pictures and see for the other */
    if( !p_dec->b_pace_control &&
488
489
        p_sys->b_hurry_up &&
        (p_sys->i_late_frames > 4) )
490
491
    {
        b_drawpicture = 0;
492
        if( p_sys->i_late_frames < 12 )
493
        {
494
            p_context->skip_frame =
495
496
                    (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
                    AVDISCARD_NONREF : p_sys->i_skip_frame;
497
498
499
500
501
502
        }
        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 */
503
504
            if( p_block )
                block_Release( p_block );
505
            msg_Warn( p_dec, "More than 4 late frames, dropping frame" );
506
507
508
509
510
            return NULL;
        }
    }
    else
    {
511
        if( p_sys->b_hurry_up )
512
            p_context->skip_frame = p_sys->i_skip_frame;
513
        if( !p_block || !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
514
515
516
517
518
            b_drawpicture = 1;
        else
            b_drawpicture = 0;
    }

519
    if( p_context->width <= 0 || p_context->height <= 0 )
520
    {
521
        if( p_sys->b_hurry_up )
522
            p_context->skip_frame = p_sys->i_skip_frame;
523
    }
Laurent Aimar's avatar
Laurent Aimar committed
524
525
    else if( !b_drawpicture )
    {
526
527
528
        /* It creates broken picture
         * FIXME either our parser or ffmpeg is broken */
#if 0
529
        if( p_sys->b_hurry_up )
530
            p_context->skip_frame = __MAX( p_context->skip_frame,
531
                                                  AVDISCARD_NONREF );
532
#endif
Laurent Aimar's avatar
Laurent Aimar committed
533
    }
534
535

    /*
536
     * Do the actual decoding now */
537

538
    /* Don't forget that libavcodec requires a little more bytes
539
     * that the real frame size */
540
    if( p_block && p_block->i_buffer > 0 )
541
    {
542
543
        p_sys->b_flush = ( p_block->i_flags & BLOCK_FLAG_END_OF_SEQUENCE ) != 0;

544
545
546
        p_block = block_Realloc( p_block, 0,
                            p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
        if( !p_block )
ivoire's avatar
ivoire committed
547
            return NULL;
548
        p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
549
        *pp_block = p_block;
550
        memset( p_block->p_buffer + p_block->i_buffer, 0,
551
552
553
                FF_INPUT_BUFFER_PADDING_SIZE );
    }

554
    while( !p_block || p_block->i_buffer > 0 || p_sys->b_flush )
555
556
557
    {
        int i_used, b_gotpicture;
        picture_t *p_pic;
558
        AVPacket pkt;
559

Laurent Aimar's avatar
Laurent Aimar committed
560
        post_mt( p_sys );
561

562
        av_init_packet( &pkt );
563
564
565
566
567
568
569
570
571
572
573
574
575
        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;
        }
576

577
578
579
580
581
582
583
584
585
        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;
            }
        }

586
        /* Make sure we don't reuse the same timestamps twice */
587
588
589
590
591
        if( p_block )
        {
            p_block->i_pts =
            p_block->i_dts = VLC_TS_INVALID;
        }
592

593
594
        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                       &b_gotpicture, &pkt );
595

Laurent Aimar's avatar
Laurent Aimar committed
596
        wait_mt( p_sys );
597

598
599
600
        if( p_sys->b_flush )
            p_sys->b_first_frame = true;

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

606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
            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;
        }
624
625
626
627
628
629
630
631

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

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

638
        /* Compute the PTS */
639
640
641
642
643
        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;

644
645
646
647
648
649
650
651
652
653
654
655
        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 )
            {
656
                p_sys->i_pts += CLOCK_FREQ *
657
658
659
660
661
662
663
664
665
666
                    (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;

667
                p_sys->i_pts += CLOCK_FREQ *
668
669
670
671
672
                    (2 + p_sys->p_ff_pic->repeat_pict) *
                    i_tick * p_context->time_base.num /
                    (2 * p_context->time_base.den);
            }
        }
673

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

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

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

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

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

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

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

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

            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
        {
749
            decoder_DeletePicture( p_dec, p_pic );
750
751
752
        }
    }

753
754
    if( p_block )
        block_Release( p_block );
755
756
757
758
759
760
    return NULL;
}

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

Laurent Aimar's avatar
Laurent Aimar committed
768
769
    post_mt( p_sys );

770
771
772
    /* 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 );
773

Laurent Aimar's avatar
Laurent Aimar committed
774
775
    wait_mt( p_sys );

776
777
    if( p_sys->p_ff_pic )
        av_free( p_sys->p_ff_pic );
778
779

    if( p_sys->p_va )
780
        vlc_va_Delete( p_sys->p_va );
781

Laurent Aimar's avatar
Laurent Aimar committed
782
    vlc_sem_destroy( &p_sys->sem_mt );
783
784
}

785
786
787
788
789
790
791
792
793
794
/*****************************************************************************
 * 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;

795
    if( p_sys->i_codec_id == AV_CODEC_ID_SVQ3 )
796
797
798
799
    {
        uint8_t *p;

        p_sys->p_context->extradata_size = i_size + 12;
800
801
802
        p = p_sys->p_context->extradata =
            av_malloc( p_sys->p_context->extradata_size +
                       FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
803
804
        if( !p )
            return;
805
806
807
808
809
810
811

        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 &&
812
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
813
814
815
816
817
818
819
820
821
822
823
        {
            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;
                }
824
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
825
826
827
828
829
830
831
832
833
834
835
836
837
838
                {
                    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 =
839
            av_malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
840
841
842
843
        if( p_sys->p_context->extradata )
        {
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
844
            memset( p_sys->p_context->extradata + i_size,
ivoire's avatar
ivoire committed
845
846
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
847
848
849
    }
}

850
851
852
853
854
855
856
857
858
/*****************************************************************************
 * 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;

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

870
871
872
873
        if( p_sys->p_context->pix_fmt == PIX_FMT_PAL8 )
        {
            if( !p_pic->format.p_palette )
                p_pic->format.p_palette = calloc( 1, sizeof(video_palette_t) );
874

875
876
            if( p_pic->format.p_palette )
            {
877
                p_pic->format.p_palette->i_entries = AVPALETTE_COUNT;
878
879
880
881
                memcpy( p_pic->format.p_palette->palette, p_ff_pic->data[1], AVPALETTE_SIZE );
            }
        }

882
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
883
        {
884
885
886
887
888
889
890
891
            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++ )
892
            {
Rafaël Carré's avatar
Rafaël Carré committed
893
                memcpy( p_dst, p_src, i_size );
894
895
                p_src += i_src_stride;
                p_dst += i_dst_stride;
896
897
898
899
900
            }
        }
    }
    else
    {
901
902
903
        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" );
904
        p_dec->b_error = 1;
905
906
907
    }
}

908
#if LIBAVCODEC_VERSION_MAJOR >= 55
909
910
static int lavc_va_GetFrame(struct AVCodecContext *ctx, AVFrame *frame,
                            int flags)
911
912
913
914
915
916
917
918
919
920
921
{
    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;
    }
922
    if (vlc_va_Get(va, &frame->opaque, &frame->data[0]))
923
924
925
926
    {
        msg_Err(dec, "hardware acceleration picture allocation failed");
        return -1;
    }
927
928
929
    /* 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];
930

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

    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 */
981
982
    if (pic->p[0].i_pitch < width * pic->p[0].i_pixel_pitch)
    {
983
984
985
        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);
986
987
988
989
990
        goto no_dr;
    }

    if (pic->p[0].i_lines < height)
    {
991
992
993
        if (sys->i_direct_rendering_used != 0)
            msg_Dbg(dec, "plane 0: lines too few (%d/%d)",
                    pic->p[0].i_lines, height);
994
        goto no_dr;
995
    }
996
997
998

    for (int i = 0; i < pic->i_planes; i++)
    {
999
        if (pic->p[i].i_pitch % aligns[i])
1000
        {
1001
1002
1003
            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]);
1004
            goto no_dr;
1005
        }
1006
        if (((uintptr_t)pic->p[i].p_pixels) % aligns[i])
1007
        {
1008
1009
            if (sys->i_direct_rendering_used != 0)
                msg_Warn(dec, "plane %d not aligned", i);
1010
            goto no_dr;
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
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
<