video.c 42.1 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
    int aligns[AV_NUM_DATA_POINTERS];
    int width = p_context->coded_width;
    int height = p_context->coded_height;
132

133 134 135 136 137 138 139 140 141
    avcodec_align_dimensions2(p_context, &width, &height, aligns);

    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 )
142 143 144 145
    {
        p_dec->fmt_out.video.i_visible_width = p_context->width;
        p_dec->fmt_out.video.i_visible_height = p_context->height;
    }
146

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

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

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

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

188
    return decoder_NewPicture( p_dec );
189 190 191 192 193 194 195 196
}

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

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

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

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

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

228 229
    if( var_CreateGetBool( p_dec, "grayscale" ) )
        p_sys->p_context->flags |= CODEC_FLAG_GRAY;
230

231
    i_val = var_CreateGetInteger( p_dec, "avcodec-vismv" );
232
    if( i_val ) p_sys->p_context->debug_mv = i_val;
233

234
    i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" );
235 236 237 238
    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;
239

240
    if( var_CreateGetBool( p_dec, "avcodec-fast" ) )
241
        p_sys->p_context->flags2 |= CODEC_FLAG2_FAST;
242

243
    /* ***** libavcodec frame skipping ***** */
244
    p_sys->b_hurry_up = var_CreateGetBool( p_dec, "avcodec-hurry-up" );
245

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

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

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

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

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

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

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

347
    switch( i_codec_id )
Laurent Aimar's avatar
Laurent Aimar committed
348
    {
349 350 351 352 353 354 355 356
        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 */
357
# if (LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55, 1, 0))
358 359 360
        case AV_CODEC_ID_H264:
        case AV_CODEC_ID_VC1:
        case AV_CODEC_ID_WMV3:
361
            p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
362
# endif
363
    }
364

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
#if LIBAVCODEC_VERSION_MAJOR < 54
386
    /* Setup palette */
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 415 416 417
    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
418

419 420 421
    /* ***** init this codec with special data ***** */
    ffmpeg_InitCodec( p_dec );

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

446 447
    if( !pp_block || !*pp_block )
        return NULL;
448

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

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

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

        p_sys->i_late_frames = 0;

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

477
        block_Release( p_block );
478 479 480 481 482 483 484 485 486 487 488
        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;
    }

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

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

    /*
552
     * Do the actual decoding now */
553

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

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

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

Laurent Aimar's avatar
Laurent Aimar committed
576
        post_mt( p_sys );
577

578 579 580
        av_init_packet( &pkt );
        pkt.data = p_block->p_buffer;
        pkt.size = p_block->i_buffer;
581 582 583 584 585 586 587
        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;

588 589
        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
                                       &b_gotpicture, &pkt );
590

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

603 604 605
        if( p_sys->b_flush )
            p_sys->b_first_frame = true;

606
        if( p_block->i_buffer <= 0 )
607 608
            p_sys->b_flush = false;

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

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

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

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

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

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 672 673 674
        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);
            }
        }
675

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

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

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

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

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

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

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

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

            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
        {
750
            decoder_DeletePicture( p_dec, p_pic );
751 752 753 754 755 756 757 758 759 760
        }
    }

    block_Release( p_block );
    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 800 801
    {
        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
802 803
        if( !p )
            return;
804 805 806 807 808 809 810

        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 &&
811
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
812 813 814 815 816 817 818 819 820 821 822
        {
            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;
                }
823
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
824 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 =
            malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
839 840 841 842 843 844 845
        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 );
        }
846 847 848
    }
}

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

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

869
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
870
        {
871 872 873 874 875 876 877 878
            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++ )
879
            {
Rafaël Carré's avatar
Rafaël Carré committed
880
                memcpy( p_dst, p_src, i_size );
881 882
                p_src += i_src_stride;
                p_dst += i_dst_stride;
883 884 885 886 887
            }
        }
    }
    else
    {