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

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

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

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

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

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

    /* Video decoder specific part */
    mtime_t i_pts;

    AVFrame          *p_ff_pic;

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

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

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

70
    bool b_has_b_frames;
71 72

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

75

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

    /* */
    bool b_flush;
85 86 87

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

    vlc_sem_t sem_mt;
90 91
};

Laurent Aimar's avatar
Laurent Aimar committed
92 93 94 95 96 97 98 99
#ifdef HAVE_AVCODEC_MT
#   define wait_mt(s) vlc_sem_wait( &s->sem_mt )
#   define post_mt(s) vlc_sem_post( &s->sem_mt )
#else
#   define wait_mt(s)
#   define post_mt(s)
#endif

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

114 115 116 117 118 119 120 121 122 123 124 125 126 127
static uint32_t ffmpeg_CodecTag( vlc_fourcc_t fcc )
{
    uint8_t *p = (uint8_t*)&fcc;
    return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
}

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

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

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

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

144
    if( !p_sys->p_va && GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) )
145
    {
146 147 148 149
        /* we are doomed, but not really, because most codecs set their pix_fmt
         * much later
         * FIXME does it make sense here ? */
        p_dec->fmt_out.video.i_chroma = VLC_CODEC_I420;
150
    }
151
    p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
152 153

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

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

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

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

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

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

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

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

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

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

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

231
    i_val = var_CreateGetInteger( p_dec, "avcodec-skiploopfilter" );
232 233 234 235
    if( i_val >= 4 ) p_sys->p_context->skip_loop_filter = AVDISCARD_ALL;
    else if( i_val == 3 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONKEY;
    else if( i_val == 2 ) p_sys->p_context->skip_loop_filter = AVDISCARD_BIDIR;
    else if( i_val == 1 ) p_sys->p_context->skip_loop_filter = AVDISCARD_NONREF;
236

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

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

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

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

289
    /* ***** libavcodec direct rendering ***** */
290
    p_sys->b_direct_rendering = false;
291
    p_sys->i_direct_rendering_used = -1;
292
    if( var_CreateGetBool( p_dec, "avcodec-dr" ) &&
293
       (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
294
        /* No idea why ... but this fixes flickering on some TSCC streams */
295 296
        p_sys->i_codec_id != AV_CODEC_ID_TSCC && p_sys->i_codec_id != AV_CODEC_ID_CSCD &&
        p_sys->i_codec_id != AV_CODEC_ID_CINEPAK &&
297 298 299 300
        !p_sys->p_context->debug_mv )
    {
        /* Some codecs set pix_fmt only after the 1st frame has been decoded,
         * so we need to do another check in ffmpeg_GetFrameBuf() */
301
        p_sys->b_direct_rendering = true;
302 303
    }

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

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

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

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

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

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

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

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

382
#if LIBAVCODEC_VERSION_MAJOR < 54
383
    /* Setup palette */
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
    memset( &p_sys->palette, 0, sizeof(p_sys->palette) );
    if( p_dec->fmt_in.video.p_palette )
    {
        p_sys->palette.palette_changed = 1;

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

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

        p_dec->fmt_out.video.p_palette = malloc( sizeof(video_palette_t) );
        if( p_dec->fmt_out.video.p_palette )
            *p_dec->fmt_out.video.p_palette = *p_dec->fmt_in.video.p_palette;
    }
    else if( p_sys->i_codec_id != CODEC_ID_MSVIDEO1 && p_sys->i_codec_id != CODEC_ID_CINEPAK )
    {
        p_sys->p_context->palctrl = &p_sys->palette;
    }
#else
# warning FIXME
#endif
415

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

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

    return VLC_SUCCESS;
}

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

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

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

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

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

        p_sys->i_late_frames = 0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
        if( i_pts <= VLC_TS_INVALID )
            i_pts = p_sys->i_pts;

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

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

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

678
        if( i_display_date > 0 && i_display_date <= mdate() )
679 680 681 682 683 684 685 686 687 688
        {
            p_sys->i_late_frames++;
            if( p_sys->i_late_frames == 1 )
                p_sys->i_late_frames_start = mdate();
        }
        else
        {
            p_sys->i_late_frames = 0;
        }

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

692
        if( p_sys->p_va != NULL || p_sys->p_ff_pic->opaque == NULL )
693 694
        {
            /* Get a new picture */
695
            p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
696 697 698 699 700 701 702 703 704 705 706 707 708
            if( !p_pic )
            {
                block_Release( p_block );
                return NULL;
            }

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

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

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

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

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

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

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

    block_Release( p_block );
    return NULL;
}

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

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

767 768 769
    /* do not flush buffers if codec hasn't been opened (theora/vorbis/VC1) */
    if( p_sys->p_context->codec )
        avcodec_flush_buffers( p_sys->p_context );
770

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

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

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

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

782 783 784 785 786 787 788 789 790 791
/*****************************************************************************
 * ffmpeg_InitCodec: setup codec extra initialization data for ffmpeg
 *****************************************************************************/
static void ffmpeg_InitCodec( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    int i_size = p_dec->fmt_in.i_extra;

    if( !i_size ) return;

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

        p_sys->p_context->extradata_size = i_size + 12;
        p = p_sys->p_context->extradata  =
            malloc( p_sys->p_context->extradata_size );
ivoire's avatar
ivoire committed
799 800
        if( !p )
            return;
801 802 803 804 805 806 807

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

        /* Now remove all atoms before the SMI one */
        if( p_sys->p_context->extradata_size > 0x5a &&
808
            strncmp( (char*)&p[0x56], "SMI ", 4 ) )
809 810 811 812 813 814 815 816 817 818 819
        {
            uint8_t *psz = &p[0x52];

            while( psz < &p[p_sys->p_context->extradata_size - 8] )
            {
                int i_size = GetDWBE( psz );
                if( i_size <= 1 )
                {
                    /* FIXME handle 1 as long size */
                    break;
                }
820
                if( !strncmp( (char*)&psz[4], "SMI ", 4 ) )
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835
                {
                    memmove( &p[0x52], psz,
                             &p[p_sys->p_context->extradata_size] - psz );
                    break;
                }

                psz += i_size;
            }
        }
    }
    else
    {
        p_sys->p_context->extradata_size = i_size;
        p_sys->p_context->extradata =
            malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
ivoire's avatar
ivoire committed
836 837 838 839 840 841 842
        if( p_sys->p_context->extradata )
        {
            memcpy( p_sys->p_context->extradata,
                    p_dec->fmt_in.p_extra, i_size );
            memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
                    0, FF_INPUT_BUFFER_PADDING_SIZE );
        }
843 844 845
    }
}

846 847 848 849 850 851 852 853 854
/*****************************************************************************
 * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
 *                     picture_t structure (when not in direct rendering mode).
 *****************************************************************************/
static void ffmpeg_CopyPicture( decoder_t *p_dec,
                                picture_t *p_pic, AVFrame *p_ff_pic )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

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

866
        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
867
        {
868 869 870 871 872 873 874 875
            p_src  = p_ff_pic->data[i_plane];
            p_dst = p_pic->p[i_plane].p_pixels;
            i_src_stride = p_ff_pic->linesize[i_plane];
            i_dst_stride = p_pic->p[i_plane].i_pitch;

            i_size = __MIN( i_src_stride, i_dst_stride );
            for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines;
                 i_line++ )
876
            {
Rafaël Carré's avatar
Rafaël Carré committed
877
                memcpy( p_dst, p_src, i_size );
878 879
                p_src += i_src_stride;
                p_dst += i_dst_stride;
880 881 882 883 884
            }
        }
    }
    else
    {
885 886 887
        const char *name = av_get_pix_fmt_name( p_sys->p_context->pix_fmt );
        msg_Err( p_dec, "Unsupported decoded output format %d (%s)",
                 p_sys->p_context->pix_fmt, name ? name : "unknown" );
888
        p_dec->b_error = 1;
Steve Lhomme's avatar