encoder.c 27.7 KB
Newer Older
gbazin's avatar
 
gbazin committed
1 2 3
/*****************************************************************************
 * encoder.c: video and audio encoder using the ffmpeg library
 *****************************************************************************
4
 * Copyright (C) 1999-2004 VideoLAN
gbazin's avatar
gbazin committed
5
 * $Id$
gbazin's avatar
 
gbazin committed
6 7
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8
 *          Gildas Bazin <gbazin@videolan.org>
9
 *          Christophe Massiot <massiot@via.ecp.fr>
gbazin's avatar
 
gbazin committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/aout.h>
32
#include <vlc/sout.h>
gbazin's avatar
 
gbazin committed
33 34 35
#include <vlc/decoder.h>

/* ffmpeg header */
gbazin's avatar
 
gbazin committed
36
#define HAVE_MMX
gbazin's avatar
 
gbazin committed
37 38 39 40 41 42
#ifdef HAVE_FFMPEG_AVCODEC_H
#   include <ffmpeg/avcodec.h>
#else
#   include <avcodec.h>
#endif

43 44 45 46
#if LIBAVCODEC_BUILD < 4704
#   define AV_NOPTS_VALUE 0
#endif

gbazin's avatar
 
gbazin committed
47 48 49
#include "ffmpeg.h"

#define AVCODEC_MAX_VIDEO_FRAME_SIZE (3*1024*1024)
50 51 52
#define HURRY_UP_GUARD1 (450000)
#define HURRY_UP_GUARD2 (300000)
#define HURRY_UP_GUARD3 (100000)
gbazin's avatar
 
gbazin committed
53 54 55 56

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
57 58
int  E_(OpenEncoder) ( vlc_object_t * );
void E_(CloseEncoder)( vlc_object_t * );
gbazin's avatar
 
gbazin committed
59 60 61 62

static block_t *EncodeVideo( encoder_t *, picture_t * );
static block_t *EncodeAudio( encoder_t *, aout_buffer_t * );

63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
struct thread_context_t;
static int FfmpegThread( struct thread_context_t *p_context );
static int FfmpegExecute( AVCodecContext *s,
                          int (*pf_func)(AVCodecContext *c2, void *arg2),
                          void **arg, int *ret, int count );

/*****************************************************************************
 * thread_context_t : for multithreaded encoding
 *****************************************************************************/
#if LIBAVCODEC_BUILD >= 4702
struct thread_context_t
{
    VLC_COMMON_MEMBERS

    AVCodecContext  *p_context;
    int             (* pf_func)(AVCodecContext *c, void *arg);
    void            *arg;
    int             i_ret;

    vlc_mutex_t     lock;
    vlc_cond_t      cond;
    vlc_bool_t      b_work, b_done;
};
#endif

gbazin's avatar
 
gbazin committed
88 89 90 91 92 93 94 95 96 97 98 99 100 101
/*****************************************************************************
 * encoder_sys_t : ffmpeg encoder descriptor
 *****************************************************************************/
struct encoder_sys_t
{
    /*
     * Ffmpeg properties
     */
    AVCodec         *p_codec;
    AVCodecContext  *p_context;

    /*
     * Common properties
     */
gbazin's avatar
 
gbazin committed
102 103
    char *p_buffer;
    char *p_buffer_out;
gbazin's avatar
 
gbazin committed
104

gbazin's avatar
 
gbazin committed
105
    /*
106
     * Video properties
gbazin's avatar
 
gbazin committed
107
     */
gbazin's avatar
 
gbazin committed
108 109
    mtime_t i_last_ref_pts;
    mtime_t i_buggy_pts_detect;
110
    mtime_t i_last_pts;
111
    vlc_bool_t b_inited;
gbazin's avatar
 
gbazin committed
112

gbazin's avatar
 
gbazin committed
113 114 115
    /*
     * Audio properties
     */
gbazin's avatar
 
gbazin committed
116
    int i_frame_size;
gbazin's avatar
 
gbazin committed
117 118
    int i_samples_delay;
    mtime_t i_pts;
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

    /* Encoding settings */
    int        i_key_int;
    int        i_b_frames;
    int        i_vtolerance;
    int        i_qmin;
    int        i_qmax;
    int        i_hq;
    vlc_bool_t b_strict_rc;
    int        i_rc_buffer_size;
    float      f_rc_buffer_aggressivity;
    vlc_bool_t b_pre_me;
    vlc_bool_t b_hurry_up;
    vlc_bool_t b_interlace;
    float      f_i_quant_factor;
    int        i_noise_reduction;
    vlc_bool_t b_mpeg4_matrix;
    vlc_bool_t b_trellis;
gbazin's avatar
gbazin committed
137
    int        i_quality; /* for VBR */
138 139 140 141
};

static const char *ppsz_enc_options[] = {
    "keyint", "bframes", "vt", "qmin", "qmax", "hq", "strict_rc",
142 143
    "rc-buffer-size", "rc-buffer-aggressivity", "pre-me", "hurry-up",
    "interlace", "i-quant-factor", "noise-reduction", "mpeg4-matrix",
gbazin's avatar
gbazin committed
144
    "trellis", "qscale", "strict", NULL
gbazin's avatar
 
gbazin committed
145 146 147
};

/*****************************************************************************
gbazin's avatar
 
gbazin committed
148
 * OpenEncoder: probe the encoder
gbazin's avatar
 
gbazin committed
149
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
150 151
extern int16_t ff_mpeg4_default_intra_matrix[];
extern int16_t ff_mpeg4_default_non_intra_matrix[];
152

gbazin's avatar
 
gbazin committed
153
int E_(OpenEncoder)( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
154 155 156
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;
gbazin's avatar
 
gbazin committed
157
    AVCodecContext *p_context;
gbazin's avatar
 
gbazin committed
158
    AVCodec *p_codec;
gbazin's avatar
 
gbazin committed
159 160
    int i_codec_id, i_cat;
    char *psz_namecodec;
161
    vlc_value_t val;
gbazin's avatar
 
gbazin committed
162

gbazin's avatar
 
gbazin committed
163
    if( !E_(GetFfmpegCodec)( p_enc->fmt_out.i_codec, &i_cat, &i_codec_id,
gbazin's avatar
 
gbazin committed
164
                             &psz_namecodec ) )
gbazin's avatar
 
gbazin committed
165
    {
166 167 168 169 170 171 172 173
        if( E_(GetFfmpegChroma)( p_enc->fmt_out.i_codec ) < 0 )
        {
            /* handed chroma output */
            return VLC_EGENERIC;
        }
        i_cat      = VIDEO_ES;
        i_codec_id = CODEC_ID_RAWVIDEO;
        psz_namecodec = "Raw video";
gbazin's avatar
 
gbazin committed
174 175
    }

176

gbazin's avatar
 
gbazin committed
177
    if( p_enc->fmt_out.i_cat == VIDEO_ES && i_cat != VIDEO_ES )
gbazin's avatar
 
gbazin committed
178
    {
gbazin's avatar
 
gbazin committed
179
        msg_Err( p_enc, "\"%s\" is not a video encoder", psz_namecodec );
gbazin's avatar
 
gbazin committed
180 181 182
        return VLC_EGENERIC;
    }

gbazin's avatar
 
gbazin committed
183 184 185 186 187 188
    if( p_enc->fmt_out.i_cat == AUDIO_ES && i_cat != AUDIO_ES )
    {
        msg_Err( p_enc, "\"%s\" is not an audio encoder", psz_namecodec );
        return VLC_EGENERIC;
    }

gbazin's avatar
 
gbazin committed
189
    /* Initialization must be done before avcodec_find_decoder() */
gbazin's avatar
 
gbazin committed
190 191
    E_(InitLibavcodec)(p_this);

gbazin's avatar
 
gbazin committed
192 193 194 195 196 197 198
    p_codec = avcodec_find_encoder( i_codec_id );
    if( !p_codec )
    {
        msg_Err( p_enc, "cannot find encoder %s", psz_namecodec );
        return VLC_EGENERIC;
    }

gbazin's avatar
 
gbazin committed
199 200 201 202 203 204 205 206 207 208
    /* Allocate the memory needed to store the decoder's structure */
    if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
    {
        msg_Err( p_enc, "out of memory" );
        return VLC_EGENERIC;
    }
    p_enc->p_sys = p_sys;
    p_sys->p_codec = p_codec;

    p_enc->pf_encode_video = EncodeVideo;
gbazin's avatar
 
gbazin committed
209
    p_enc->pf_encode_audio = EncodeAudio;
gbazin's avatar
 
gbazin committed
210

gbazin's avatar
 
gbazin committed
211 212
    p_sys->p_buffer_out = NULL;
    p_sys->p_buffer = NULL;
213
    p_sys->b_inited = 0;
gbazin's avatar
 
gbazin committed
214 215 216 217 218

    p_sys->p_context = p_context = avcodec_alloc_context();

    /* Set CPU capabilities */
    p_context->dsp_mask = 0;
gbazin's avatar
 
gbazin committed
219
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX) )
gbazin's avatar
 
gbazin committed
220
    {
gbazin's avatar
 
gbazin committed
221
        p_context->dsp_mask |= FF_MM_MMX;
gbazin's avatar
 
gbazin committed
222
    }
gbazin's avatar
 
gbazin committed
223
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT) )
gbazin's avatar
 
gbazin committed
224
    {
gbazin's avatar
 
gbazin committed
225
        p_context->dsp_mask |= FF_MM_MMXEXT;
gbazin's avatar
 
gbazin committed
226
    }
gbazin's avatar
 
gbazin committed
227
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW) )
gbazin's avatar
 
gbazin committed
228
    {
gbazin's avatar
 
gbazin committed
229
        p_context->dsp_mask |= FF_MM_3DNOW;
gbazin's avatar
 
gbazin committed
230
    }
gbazin's avatar
 
gbazin committed
231
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE) )
gbazin's avatar
 
gbazin committed
232
    {
gbazin's avatar
 
gbazin committed
233 234
        p_context->dsp_mask |= FF_MM_SSE;
        p_context->dsp_mask |= FF_MM_SSE2;
gbazin's avatar
 
gbazin committed
235 236
    }

237
    sout_CfgParse( p_enc, ENC_CFG_PREFIX, ppsz_enc_options, p_enc->p_cfg );
238 239 240 241 242 243 244 245 246 247 248 249 250

    var_Get( p_enc, ENC_CFG_PREFIX "keyint", &val );
    p_sys->i_key_int = val.i_int;

    var_Get( p_enc, ENC_CFG_PREFIX "bframes", &val );
    p_sys->i_b_frames = val.i_int;

    var_Get( p_enc, ENC_CFG_PREFIX "vt", &val );
    p_sys->i_vtolerance = val.i_int;

    var_Get( p_enc, ENC_CFG_PREFIX "interlace", &val );
    p_sys->b_interlace = val.b_bool;

251
    var_Get( p_enc, ENC_CFG_PREFIX "pre-me", &val );
252 253
    p_sys->b_pre_me = val.b_bool;

254
    var_Get( p_enc, ENC_CFG_PREFIX "hurry-up", &val );
255 256 257 258 259 260 261
    p_sys->b_hurry_up = val.b_bool;
    if( p_sys->b_hurry_up )
    {
        /* hurry up mode needs noise reduction, even small */
        p_sys->i_noise_reduction = 1;
    }

262
    var_Get( p_enc, ENC_CFG_PREFIX "strict-rc", &val );
263
    p_sys->b_strict_rc = val.b_bool;
264
    var_Get( p_enc, ENC_CFG_PREFIX "rc-buffer-size", &val );
265
    p_sys->i_rc_buffer_size = val.i_int;
266
    var_Get( p_enc, ENC_CFG_PREFIX "rc-buffer-aggressivity", &val );
267 268
    p_sys->f_rc_buffer_aggressivity = val.f_float;

269
    var_Get( p_enc, ENC_CFG_PREFIX "i-quant-factor", &val );
270 271
    p_sys->f_i_quant_factor = val.f_float;

272
    var_Get( p_enc, ENC_CFG_PREFIX "noise-reduction", &val );
273 274
    p_sys->i_noise_reduction = val.i_int;

275
    var_Get( p_enc, ENC_CFG_PREFIX "mpeg4-matrix", &val );
276 277
    p_sys->b_mpeg4_matrix = val.b_bool;

gbazin's avatar
gbazin committed
278 279 280 281
    var_Get( p_enc, ENC_CFG_PREFIX "qscale", &val );
    if( val.f_float < 0.01 || val.f_float > 255.0 ) val.f_float = 0;
    p_sys->i_quality = (int)(FF_QP2LAMBDA * val.f_float + 0.5);

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
    var_Get( p_enc, ENC_CFG_PREFIX "hq", &val );
    if( val.psz_string && *val.psz_string )
    {
        if( !strcmp( val.psz_string, "rd" ) )
            p_sys->i_hq = FF_MB_DECISION_RD;
        else if( !strcmp( val.psz_string, "bits" ) )
            p_sys->i_hq = FF_MB_DECISION_BITS;
        else if( !strcmp( val.psz_string, "simple" ) )
            p_sys->i_hq = FF_MB_DECISION_SIMPLE;
        else
            p_sys->i_hq = FF_MB_DECISION_RD;
    }
    if( val.psz_string ) free( val.psz_string );

    var_Get( p_enc, ENC_CFG_PREFIX "qmin", &val );
    p_sys->i_qmin = val.i_int;
    var_Get( p_enc, ENC_CFG_PREFIX "qmax", &val );
    p_sys->i_qmax = val.i_int;
    var_Get( p_enc, ENC_CFG_PREFIX "trellis", &val );
    p_sys->b_trellis = val.b_bool;

gbazin's avatar
gbazin committed
303 304 305 306
    var_Get( p_enc, ENC_CFG_PREFIX "strict", &val );
    if( val.i_int < - 1 || val.i_int > 1 ) val.i_int = 0;
    p_context->strict_std_compliance = val.i_int;

gbazin's avatar
 
gbazin committed
307 308
    if( p_enc->fmt_in.i_cat == VIDEO_ES )
    {
309 310
        int i_aspect_num, i_aspect_den;

311 312 313 314 315 316 317 318
        if( !p_enc->fmt_in.video.i_width || !p_enc->fmt_in.video.i_height )
        {
            msg_Warn( p_enc, "invalid size %ix%i", p_enc->fmt_in.video.i_width,
                      p_enc->fmt_in.video.i_height );
            free( p_sys );
            return VLC_EGENERIC;
        }

gbazin's avatar
 
gbazin committed
319 320
        p_context->width = p_enc->fmt_in.video.i_width;
        p_context->height = p_enc->fmt_in.video.i_height;
gbazin's avatar
 
gbazin committed
321

gbazin's avatar
 
gbazin committed
322 323
        p_context->frame_rate = p_enc->fmt_in.video.i_frame_rate;
        p_context->frame_rate_base= p_enc->fmt_in.video.i_frame_rate_base;
gbazin's avatar
 
gbazin committed
324

325 326 327 328 329 330 331 332
        /* Defaults from ffmpeg.c */
        p_context->qblur = 0.5;
        p_context->qcompress = 0.5;
        p_context->b_quant_offset = 1.25;
        p_context->b_quant_factor = 1.25;
        p_context->i_quant_offset = 0.0;
        p_context->i_quant_factor = -0.8;

333 334
        if( p_sys->i_key_int > 0 )
            p_context->gop_size = p_sys->i_key_int;
335
        p_context->max_b_frames =
336
            __MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES );
337 338
        p_context->b_frame_strategy = 0;

gbazin's avatar
 
gbazin committed
339
#if LIBAVCODEC_BUILD >= 4687
340 341 342
        av_reduce( &i_aspect_num, &i_aspect_den,
                   p_enc->fmt_in.video.i_aspect,
                   VOUT_ASPECT_FACTOR, 1 << 30 /* something big */ );
343
        av_reduce( &p_context->sample_aspect_ratio.num,
gbazin's avatar
gbazin committed
344
                   &p_context->sample_aspect_ratio.den,
345
                   i_aspect_num *
gbazin's avatar
gbazin committed
346
                   (int64_t)p_context->height / p_context->width,
347
                   i_aspect_den, 1 << 30 /* something big */ );
gbazin's avatar
 
gbazin committed
348
#else
gbazin's avatar
 
gbazin committed
349 350
        p_context->aspect_ratio = ((float)p_enc->fmt_in.video.i_aspect) /
            VOUT_ASPECT_FACTOR;
gbazin's avatar
 
gbazin committed
351
#endif
gbazin's avatar
 
gbazin committed
352

gbazin's avatar
 
gbazin committed
353 354
        p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE );

355
        p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
Christophe Massiot's avatar
Christophe Massiot committed
356

357
        if ( p_sys->b_strict_rc )
Christophe Massiot's avatar
Christophe Massiot committed
358 359
        {
            p_context->rc_max_rate = p_enc->fmt_out.i_bitrate;
360 361
            p_context->rc_buffer_size = p_sys->i_rc_buffer_size;
            p_context->rc_buffer_aggressivity = p_sys->f_rc_buffer_aggressivity;
362 363
        }

364 365
        if ( p_sys->f_i_quant_factor != 0.0 )
            p_context->i_quant_factor = p_sys->f_i_quant_factor;
366

gbazin's avatar
 
gbazin committed
367
#if LIBAVCODEC_BUILD >= 4690
368
        p_context->noise_reduction = p_sys->i_noise_reduction;
gbazin's avatar
 
gbazin committed
369
#endif
370

371
        if ( p_sys->b_mpeg4_matrix )
372 373 374
        {
            p_context->intra_matrix = ff_mpeg4_default_intra_matrix;
            p_context->inter_matrix = ff_mpeg4_default_non_intra_matrix;
Christophe Massiot's avatar
Christophe Massiot committed
375 376
        }

377
        if ( p_sys->b_pre_me )
Christophe Massiot's avatar
Christophe Massiot committed
378 379 380 381
        {
            p_context->pre_me = 1;
            p_context->me_pre_cmp = FF_CMP_CHROMA;
        }
382

383
        if ( p_sys->b_interlace )
384 385 386 387 388 389 390
        {
            p_context->flags |= CODEC_FLAG_INTERLACED_DCT;
#if LIBAVCODEC_BUILD >= 4698
            p_context->flags |= CODEC_FLAG_INTERLACED_ME;
#endif
        }

391
        if ( p_sys->b_trellis )
392 393
            p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;

gbazin's avatar
 
gbazin committed
394
#if LIBAVCODEC_BUILD >= 4702
395 396
        if ( p_enc->i_threads >= 1 )
            p_context->thread_count = p_enc->i_threads;
gbazin's avatar
 
gbazin committed
397
#endif
398

399 400
        if( p_sys->i_vtolerance > 0 )
            p_context->bit_rate_tolerance = p_sys->i_vtolerance;
401

402 403 404 405
        if( p_sys->i_qmin > 0 )
            p_context->mb_qmin = p_context->qmin = p_sys->i_qmin;
        if( p_sys->i_qmax > 0 )
            p_context->mb_qmax = p_context->qmax = p_sys->i_qmax;
406 407
        p_context->max_qdiff = 3;

408
        p_context->mb_decision = p_sys->i_hq;
gbazin's avatar
gbazin committed
409 410 411 412 413 414 415 416

        if( p_sys->i_quality )
        {
            p_context->flags |= CODEC_FLAG_QSCALE;
#if LIBAVCODEC_BUILD >= 4668
            p_context->global_quality = p_sys->i_quality;
#endif
        }
gbazin's avatar
 
gbazin committed
417 418 419 420 421 422 423 424 425
    }
    else if( p_enc->fmt_in.i_cat == AUDIO_ES )
    {
        p_enc->fmt_in.i_codec  = AOUT_FMT_S16_NE;
        p_context->sample_rate = p_enc->fmt_in.audio.i_rate;
        p_context->channels    = p_enc->fmt_in.audio.i_channels;
    }

    /* Misc parameters */
gbazin's avatar
 
gbazin committed
426
    p_context->bit_rate = p_enc->fmt_out.i_bitrate;
gbazin's avatar
 
gbazin committed
427

gbazin's avatar
 
gbazin committed
428
    if( i_codec_id == CODEC_ID_RAWVIDEO )
gbazin's avatar
 
gbazin committed
429
    {
430 431
        /* XXX: hack: Force same codec (will be handled by transcode) */
        p_enc->fmt_in.i_codec = p_enc->fmt_out.i_codec;
gbazin's avatar
 
gbazin committed
432
        p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->fmt_in.i_codec );
gbazin's avatar
 
gbazin committed
433 434 435 436 437 438 439
    }

    /* Make sure we get extradata filled by the encoder */
    p_context->extradata_size = 0;
    p_context->extradata = NULL;
    p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;

gbazin's avatar
 
gbazin committed
440
    if( avcodec_open( p_context, p_codec ) )
gbazin's avatar
 
gbazin committed
441
    {
gbazin's avatar
 
gbazin committed
442 443 444 445 446 447 448
        if( p_enc->fmt_in.i_cat == AUDIO_ES && p_context->channels > 2 )
        {
            p_context->channels = 2;
            p_enc->fmt_in.audio.i_channels = 2; // FIXME
            if( avcodec_open( p_context, p_codec ) )
            {
                msg_Err( p_enc, "cannot open encoder" );
449
                free( p_sys );
gbazin's avatar
 
gbazin committed
450 451 452 453 454 455 456
                return VLC_EGENERIC;
            }
            msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
        }
        else
        {
            msg_Err( p_enc, "cannot open encoder" );
457
            free( p_sys );
gbazin's avatar
 
gbazin committed
458 459
            return VLC_EGENERIC;
        }
gbazin's avatar
 
gbazin committed
460 461
    }

gbazin's avatar
 
gbazin committed
462 463
    p_enc->fmt_out.i_extra = p_context->extradata_size;
    p_enc->fmt_out.p_extra = p_context->extradata;
gbazin's avatar
 
gbazin committed
464 465
    p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;

gbazin's avatar
 
gbazin committed
466 467
    if( p_enc->fmt_in.i_cat == AUDIO_ES )
    {
468
        p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
gbazin's avatar
 
gbazin committed
469 470 471 472
        p_sys->i_frame_size = p_context->frame_size * 2 * p_context->channels;
        p_sys->p_buffer = malloc( p_sys->i_frame_size );
    }

gbazin's avatar
 
gbazin committed
473 474
    p_sys->i_last_ref_pts = 0;
    p_sys->i_buggy_pts_detect = 0;
gbazin's avatar
 
gbazin committed
475 476
    p_sys->i_samples_delay = 0;
    p_sys->i_pts = 0;
477
    p_sys->i_last_pts = 0;
gbazin's avatar
 
gbazin committed
478

gbazin's avatar
 
gbazin committed
479 480
    msg_Dbg( p_enc, "found encoder %s", psz_namecodec );

gbazin's avatar
 
gbazin committed
481 482 483
    return VLC_SUCCESS;
}

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557
/****************************************************************************
 * Ffmpeg threading system
 ****************************************************************************/
#if LIBAVCODEC_BUILD >= 4702
static int FfmpegThread( struct thread_context_t *p_context )
{
    while ( !p_context->b_die && !p_context->b_error )
    {
        vlc_mutex_lock( &p_context->lock );
        while ( !p_context->b_work && !p_context->b_die && !p_context->b_error )
        {
            vlc_cond_wait( &p_context->cond, &p_context->lock );
        }
        p_context->b_work = 0;
        vlc_mutex_unlock( &p_context->lock );
        if ( p_context->b_die || p_context->b_error )
            break;

        if ( p_context->pf_func )
        {
            p_context->i_ret = p_context->pf_func( p_context->p_context,
                                                   p_context->arg );
        }

        vlc_mutex_lock( &p_context->lock );
        p_context->b_done = 1;
        vlc_cond_signal( &p_context->cond );
        vlc_mutex_unlock( &p_context->lock );
    }

    return 0;
}

static int FfmpegExecute( AVCodecContext *s,
                          int (*pf_func)(AVCodecContext *c2, void *arg2),
                          void **arg, int *ret, int count )
{
    struct thread_context_t ** pp_contexts =
                         (struct thread_context_t **)s->thread_opaque;
    int i;

    /* Note, we can be certain that this is not called with the same
     * AVCodecContext by different threads at the same time */
    for ( i = 0; i < count; i++ )
    {
        vlc_mutex_lock( &pp_contexts[i]->lock );
        pp_contexts[i]->arg = arg[i];
        pp_contexts[i]->pf_func = pf_func;
        pp_contexts[i]->i_ret = 12345;
        pp_contexts[i]->b_work = 1;
        vlc_cond_signal( &pp_contexts[i]->cond );
        vlc_mutex_unlock( &pp_contexts[i]->lock );
    }
    for ( i = 0; i < count; i++ )
    {
        vlc_mutex_lock( &pp_contexts[i]->lock );
        while ( !pp_contexts[i]->b_done )
        {
            vlc_cond_wait( &pp_contexts[i]->cond, &pp_contexts[i]->lock );
        }
        pp_contexts[i]->b_done = 0;
        pp_contexts[i]->pf_func = NULL;
        vlc_mutex_unlock( &pp_contexts[i]->lock );

        if ( ret )
        {
            ret[i] = pp_contexts[i]->i_ret;
        }
    }

    return 0;
}
#endif

gbazin's avatar
 
gbazin committed
558 559 560 561 562 563 564 565
/****************************************************************************
 * EncodeVideo: the whole thing
 ****************************************************************************/
static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    AVFrame frame;
    int i_out, i_plane;
566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597

#if LIBAVCODEC_BUILD >= 4702
    if ( !p_sys->b_inited && p_enc->i_threads >= 1 )
    {
        struct thread_context_t ** pp_contexts;
        int i;

        p_sys->b_inited = 1;
        pp_contexts = malloc( sizeof(struct thread_context_t *)
                                 * p_enc->i_threads );
        p_sys->p_context->thread_opaque = (void *)pp_contexts;

        for ( i = 0; i < p_enc->i_threads; i++ )
        {
            pp_contexts[i] = vlc_object_create( p_enc,
                                     sizeof(struct thread_context_t) );
            pp_contexts[i]->p_context = p_sys->p_context;
            vlc_mutex_init( p_enc, &pp_contexts[i]->lock );
            vlc_cond_init( p_enc, &pp_contexts[i]->cond );
            pp_contexts[i]->b_work = 0;
            pp_contexts[i]->b_done = 0;
            if ( vlc_thread_create( pp_contexts[i], "encoder", FfmpegThread,
                                    VLC_THREAD_PRIORITY_VIDEO, VLC_FALSE ) )
            {
                msg_Err( p_enc, "cannot spawn encoder thread, expect to die soon" );
                return NULL;
            }
        }

        p_sys->p_context->execute = FfmpegExecute;
    }
#endif
gbazin's avatar
 
gbazin committed
598

Laurent Aimar's avatar
Laurent Aimar committed
599
    memset( &frame, 0, sizeof( AVFrame ) );
gbazin's avatar
 
gbazin committed
600 601 602 603 604 605
    for( i_plane = 0; i_plane < p_pict->i_planes; i_plane++ )
    {
        frame.data[i_plane] = p_pict->p[i_plane].p_pixels;
        frame.linesize[i_plane] = p_pict->p[i_plane].i_pitch;
    }

606 607 608 609 610 611 612 613 614 615
    /* Let ffmpeg select the frame type */
    frame.pict_type = 0;

    frame.repeat_pict = p_pict->i_nb_fields;

#if LIBAVCODEC_BUILD >= 4685
    frame.interlaced_frame = !p_pict->b_progressive;
    frame.top_field_first = p_pict->b_top_field_first;
#endif

616
#if LIBAVCODEC_BUILD < 4702
gbazin's avatar
 
gbazin committed
617
    /* Set the pts of the frame being encoded (segfaults with mpeg4!)*/
618 619 620
    if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', 'g', 'v' ) ||
        p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', '1', 'v' ) ||
        p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', '2', 'v' ) )
621 622 623
#else
    if( 1 )
#endif
Christophe Massiot's avatar
Christophe Massiot committed
624
    {
625
        frame.pts = p_pict->date ? p_pict->date : AV_NOPTS_VALUE;
626

627
        if ( p_sys->b_hurry_up && frame.pts != AV_NOPTS_VALUE )
Christophe Massiot's avatar
Christophe Massiot committed
628
        {
629 630
            mtime_t current_date = mdate();

631
            if ( current_date + HURRY_UP_GUARD3 > frame.pts )
632 633 634 635 636 637 638
            {
                p_sys->p_context->mb_decision = FF_MB_DECISION_SIMPLE;
                p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
                msg_Dbg( p_enc, "hurry up mode 3" );
            }
            else
            {
639
                p_sys->p_context->mb_decision = p_sys->i_hq;
640

641
                if ( current_date + HURRY_UP_GUARD2 > frame.pts )
642 643
                {
                    p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
644
#if LIBAVCODEC_BUILD >= 4690
645
                    p_sys->p_context->noise_reduction = p_sys->i_noise_reduction
646
                         + (HURRY_UP_GUARD2 + current_date - frame.pts) / 500;
647 648 649 650 651
#endif
                    msg_Dbg( p_enc, "hurry up mode 2" );
                }
                else
                {
652
                    if ( p_sys->b_trellis )
653
                        p_sys->p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
654 655
#if LIBAVCODEC_BUILD >= 4690
                    p_sys->p_context->noise_reduction =
656
                        p_sys->i_noise_reduction;
657 658 659 660
#endif
                }
            }

661
            if ( current_date + HURRY_UP_GUARD1 > frame.pts )
662
            {
663 664
                frame.pict_type = FF_P_TYPE;
                /* msg_Dbg( p_enc, "hurry up mode 1 %lld", current_date + HURRY_UP_GUARD1 - frame.pts ); */
665
            }
Christophe Massiot's avatar
Christophe Massiot committed
666 667
        }
    }
gbazin's avatar
 
gbazin committed
668
    else
Christophe Massiot's avatar
Christophe Massiot committed
669
    {
670
        frame.pts = AV_NOPTS_VALUE;
Christophe Massiot's avatar
Christophe Massiot committed
671
    }
gbazin's avatar
 
gbazin committed
672

gbazin's avatar
gbazin committed
673
    if ( frame.pts != AV_NOPTS_VALUE && frame.pts != 0 )
674 675 676
    {
        if ( p_sys->i_last_pts == frame.pts )
        {
gbazin's avatar
gbazin committed
677 678
            msg_Warn( p_enc, "almost fed libavcodec with two frames with the "
                      "same PTS (" I64Fd ")", frame.pts );
679 680 681 682 683 684 685
            return NULL;
        }
        else
        {
            p_sys->i_last_pts = frame.pts;
        }
    }
gbazin's avatar
 
gbazin committed
686

gbazin's avatar
gbazin committed
687 688
    frame.quality = p_sys->i_quality;

gbazin's avatar
 
gbazin committed
689 690
    i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out,
                                  AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame );
Christophe Massiot's avatar
Christophe Massiot committed
691

gbazin's avatar
 
gbazin committed
692 693 694 695 696
    if( i_out > 0 )
    {
        block_t *p_block = block_New( p_enc, i_out );
        memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );

697
        if( p_sys->p_context->coded_frame->pts != AV_NOPTS_VALUE &&
gbazin's avatar
gbazin committed
698
            p_sys->p_context->coded_frame->pts != 0 &&
gbazin's avatar
 
gbazin committed
699 700 701 702 703
            p_sys->i_buggy_pts_detect != p_sys->p_context->coded_frame->pts )
        {
            p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts;

            /* FIXME, 3-2 pulldown is not handled correctly */
gbazin's avatar
 
gbazin committed
704 705 706
            p_block->i_length = I64C(1000000) *
                p_enc->fmt_in.video.i_frame_rate_base /
                p_enc->fmt_in.video.i_frame_rate;
gbazin's avatar
 
gbazin committed
707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733
            p_block->i_pts    = p_sys->p_context->coded_frame->pts;

            if( !p_sys->p_context->delay ||
                ( p_sys->p_context->coded_frame->pict_type != FF_I_TYPE &&
                  p_sys->p_context->coded_frame->pict_type != FF_P_TYPE ) )
            {
                p_block->i_dts = p_block->i_pts;
            }
            else
            {
                if( p_sys->i_last_ref_pts )
                {
                    p_block->i_dts = p_sys->i_last_ref_pts;
                }
                else
                {
                    /* Let's put something sensible */
                    p_block->i_dts = p_block->i_pts;
                }

                p_sys->i_last_ref_pts = p_block->i_pts;
            }
        }
        else
        {
            /* Buggy libavcodec which doesn't update coded_frame->pts
             * correctly */
gbazin's avatar
 
gbazin committed
734 735 736
            p_block->i_length = I64C(1000000) *
                p_enc->fmt_in.video.i_frame_rate_base /
                p_enc->fmt_in.video.i_frame_rate;
gbazin's avatar
 
gbazin committed
737 738 739
            p_block->i_dts = p_block->i_pts = p_pict->date;
        }

740 741 742 743 744 745 746 747 748 749 750 751 752
        switch ( p_sys->p_context->coded_frame->pict_type )
        {
        case FF_I_TYPE:
            p_block->i_flags |= BLOCK_FLAG_TYPE_I;
            break;
        case FF_P_TYPE:
            p_block->i_flags |= BLOCK_FLAG_TYPE_P;
            break;
        case FF_B_TYPE:
            p_block->i_flags |= BLOCK_FLAG_TYPE_B;
            break;
        }

gbazin's avatar
 
gbazin committed
753 754 755 756 757 758 759 760 761 762 763 764 765
        return p_block;
    }

    return NULL;
}

/****************************************************************************
 * EncodeAudio: the whole thing
 ****************************************************************************/
static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block, *p_chain = NULL;
gbazin's avatar
 
gbazin committed
766

gbazin's avatar
 
gbazin committed
767 768 769 770 771 772
    char *p_buffer = p_aout_buf->p_buffer;
    int i_samples = p_aout_buf->i_nb_samples;
    int i_samples_delay = p_sys->i_samples_delay;

    p_sys->i_pts = p_aout_buf->start_date -
                (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
gbazin's avatar
 
gbazin committed
773
                (mtime_t)p_enc->fmt_in.audio.i_rate;
gbazin's avatar
 
gbazin committed
774 775 776 777 778 779 780 781 782 783 784

    p_sys->i_samples_delay += i_samples;

    while( p_sys->i_samples_delay >= p_sys->p_context->frame_size )
    {
        int16_t *p_samples;
        int i_out;

        if( i_samples_delay )
        {
            /* Take care of the left-over from last time */
gbazin's avatar
 
gbazin committed
785
            int i_delay_size = i_samples_delay * 2 *
gbazin's avatar
 
gbazin committed
786 787 788 789 790 791
                                 p_sys->p_context->channels;
            int i_size = p_sys->i_frame_size - i_delay_size;

            p_samples = (int16_t *)p_sys->p_buffer;
            memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
            p_buffer -= i_delay_size;
gbazin's avatar
 
gbazin committed
792
            i_samples += i_samples_delay;
gbazin's avatar
 
gbazin committed
793 794 795 796 797 798 799 800 801 802
            i_samples_delay = 0;
        }
        else
        {
            p_samples = (int16_t *)p_buffer;
        }

        i_out = avcodec_encode_audio( p_sys->p_context, p_sys->p_buffer_out,
                                      2 * AVCODEC_MAX_AUDIO_FRAME_SIZE,
                                      p_samples );
gbazin's avatar
 
gbazin committed
803 804 805 806 807

#if 0
        msg_Warn( p_enc, "avcodec_encode_audio: %d", i_out );
#endif
        if( i_out < 0 ) break;
gbazin's avatar
 
gbazin committed
808 809 810

        p_buffer += p_sys->i_frame_size;
        p_sys->i_samples_delay -= p_sys->p_context->frame_size;
gbazin's avatar
 
gbazin committed
811 812 813
        i_samples -= p_sys->p_context->frame_size;

        if( i_out == 0 ) continue;
gbazin's avatar
 
gbazin committed
814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829

        p_block = block_New( p_enc, i_out );
        memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );

        p_block->i_length = (mtime_t)1000000 *
            (mtime_t)p_sys->p_context->frame_size /
            (mtime_t)p_sys->p_context->sample_rate;

        p_block->i_dts = p_block->i_pts = p_sys->i_pts;

        /* Update pts */
        p_sys->i_pts += p_block->i_length;
        block_ChainAppend( &p_chain, p_block );
    }

    /* Backup the remaining raw samples */
gbazin's avatar
 
gbazin committed
830
    if( i_samples )
gbazin's avatar
 
gbazin committed
831
    {
gbazin's avatar
 
gbazin committed
832 833
        memcpy( p_sys->p_buffer + i_samples_delay * 2 *
                p_sys->p_context->channels, p_buffer,
gbazin's avatar
 
gbazin committed
834 835 836 837 838 839 840
                i_samples * 2 * p_sys->p_context->channels );
    }

    return p_chain;
}

/*****************************************************************************
gbazin's avatar
 
gbazin committed
841
 * CloseEncoder: ffmpeg encoder destruction
gbazin's avatar
 
gbazin committed
842
 *****************************************************************************/
gbazin's avatar
 
gbazin committed
843
void E_(CloseEncoder)( vlc_object_t *p_this )
gbazin's avatar
 
gbazin committed
844 845 846 847
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;

848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
#if LIBAVCODEC_BUILD >= 4702
    if ( p_sys->b_inited && p_enc->i_threads >= 1 )
    {
        int i;
        struct thread_context_t ** pp_contexts =
                (struct thread_context_t **)p_sys->p_context->thread_opaque;
        for ( i = 0; i < p_enc->i_threads; i++ )
        {
            pp_contexts[i]->b_die = 1;
            vlc_cond_signal( &pp_contexts[i]->cond );
            vlc_thread_join( pp_contexts[i] );
            vlc_mutex_destroy( &pp_contexts[i]->lock );
            vlc_cond_destroy( &pp_contexts[i]->cond );
            vlc_object_destroy( pp_contexts[i] );
        }

864
        free( pp_contexts );
865 866 867
    }
#endif

gbazin's avatar
 
gbazin committed
868
    avcodec_close( p_sys->p_context );
869
    av_free( p_sys->p_context );
gbazin's avatar
 
gbazin committed
870 871 872 873

    if( p_sys->p_buffer ) free( p_sys->p_buffer );
    if( p_sys->p_buffer_out ) free( p_sys->p_buffer_out );

gbazin's avatar
 
gbazin committed
874 875
    free( p_sys );
}