encoder.c 23.9 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
8
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Gildas Bazin <gbazin@netcourrier.com>
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
32
33
34
 *
 * 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>
#include <vlc/decoder.h>

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

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

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

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

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

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

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*****************************************************************************
 * 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
101
102
    char *p_buffer;
    char *p_buffer_out;
gbazin's avatar
   
gbazin committed
103

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

gbazin's avatar
   
gbazin committed
112
113
114
    /*
     * Audio properties
     */
gbazin's avatar
   
gbazin committed
115
    int i_frame_size;
gbazin's avatar
   
gbazin committed
116
117
    int i_samples_delay;
    mtime_t i_pts;
gbazin's avatar
   
gbazin committed
118
119
120
};

/*****************************************************************************
gbazin's avatar
   
gbazin committed
121
 * OpenEncoder: probe the encoder
gbazin's avatar
   
gbazin committed
122
 *****************************************************************************/
gbazin's avatar
   
gbazin committed
123
124
extern int16_t ff_mpeg4_default_intra_matrix[];
extern int16_t ff_mpeg4_default_non_intra_matrix[];
125

gbazin's avatar
   
gbazin committed
126
int E_(OpenEncoder)( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
127
128
129
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;
gbazin's avatar
   
gbazin committed
130
    AVCodecContext *p_context;
gbazin's avatar
   
gbazin committed
131
    AVCodec *p_codec;
gbazin's avatar
   
gbazin committed
132
133
    int i_codec_id, i_cat;
    char *psz_namecodec;
gbazin's avatar
   
gbazin committed
134

gbazin's avatar
   
gbazin committed
135
    if( !E_(GetFfmpegCodec)( p_enc->fmt_out.i_codec, &i_cat, &i_codec_id,
gbazin's avatar
   
gbazin committed
136
                             &psz_namecodec ) )
gbazin's avatar
   
gbazin committed
137
    {
138
139
140
141
142
143
144
145
        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
146
147
    }

148

gbazin's avatar
   
gbazin committed
149
    if( p_enc->fmt_out.i_cat == VIDEO_ES && i_cat != VIDEO_ES )
gbazin's avatar
   
gbazin committed
150
    {
gbazin's avatar
   
gbazin committed
151
        msg_Err( p_enc, "\"%s\" is not a video encoder", psz_namecodec );
gbazin's avatar
   
gbazin committed
152
153
154
        return VLC_EGENERIC;
    }

gbazin's avatar
   
gbazin committed
155
156
157
158
159
160
    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
161
    /* Initialization must be done before avcodec_find_decoder() */
gbazin's avatar
   
gbazin committed
162
163
    E_(InitLibavcodec)(p_this);

gbazin's avatar
   
gbazin committed
164
165
166
167
168
169
170
    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
171
172
173
174
175
176
177
178
179
180
    /* 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
181
    p_enc->pf_encode_audio = EncodeAudio;
gbazin's avatar
   
gbazin committed
182

gbazin's avatar
   
gbazin committed
183
184
    p_sys->p_buffer_out = NULL;
    p_sys->p_buffer = NULL;
185
    p_sys->b_inited = 0;
gbazin's avatar
   
gbazin committed
186
187
188
189
190

    p_sys->p_context = p_context = avcodec_alloc_context();

    /* Set CPU capabilities */
    p_context->dsp_mask = 0;
gbazin's avatar
   
gbazin committed
191
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMX) )
gbazin's avatar
   
gbazin committed
192
    {
gbazin's avatar
   
gbazin committed
193
        p_context->dsp_mask |= FF_MM_MMX;
gbazin's avatar
   
gbazin committed
194
    }
gbazin's avatar
   
gbazin committed
195
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_MMXEXT) )
gbazin's avatar
   
gbazin committed
196
    {
gbazin's avatar
   
gbazin committed
197
        p_context->dsp_mask |= FF_MM_MMXEXT;
gbazin's avatar
   
gbazin committed
198
    }
gbazin's avatar
   
gbazin committed
199
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_3DNOW) )
gbazin's avatar
   
gbazin committed
200
    {
gbazin's avatar
   
gbazin committed
201
        p_context->dsp_mask |= FF_MM_3DNOW;
gbazin's avatar
   
gbazin committed
202
    }
gbazin's avatar
   
gbazin committed
203
    if( !(p_enc->p_libvlc->i_cpu & CPU_CAPABILITY_SSE) )
gbazin's avatar
   
gbazin committed
204
    {
gbazin's avatar
   
gbazin committed
205
206
        p_context->dsp_mask |= FF_MM_SSE;
        p_context->dsp_mask |= FF_MM_SSE2;
gbazin's avatar
   
gbazin committed
207
208
    }

gbazin's avatar
   
gbazin committed
209
210
    if( p_enc->fmt_in.i_cat == VIDEO_ES )
    {
211
212
213
214
215
216
217
218
        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
219
220
        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
221

gbazin's avatar
   
gbazin committed
222
223
        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
224

225
226
227
228
229
230
231
232
233
234
235
236
237
        /* 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;

        p_context->gop_size = p_enc->i_key_int > 0 ? p_enc->i_key_int : 50;
        p_context->max_b_frames =
            __MIN( p_enc->i_b_frames, FF_MAX_B_FRAMES );
        p_context->b_frame_strategy = 0;

gbazin's avatar
   
gbazin committed
238
#if LIBAVCODEC_BUILD >= 4687
gbazin's avatar
   
gbazin committed
239
        p_context->sample_aspect_ratio =
gbazin's avatar
   
gbazin committed
240
241
242
            (AVRational){ p_enc->fmt_in.video.i_aspect *
                          (int64_t)p_context->height / p_context->width,
                          VOUT_ASPECT_FACTOR };
gbazin's avatar
   
gbazin committed
243
#else
gbazin's avatar
   
gbazin committed
244
245
        p_context->aspect_ratio = ((float)p_enc->fmt_in.video.i_aspect) /
            VOUT_ASPECT_FACTOR;
gbazin's avatar
   
gbazin committed
246
#endif
gbazin's avatar
   
gbazin committed
247

gbazin's avatar
   
gbazin committed
248
249
        p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE );

250
        p_enc->fmt_in.i_codec = VLC_FOURCC('I','4','2','0');
Christophe Massiot's avatar
Christophe Massiot committed
251
252
253
254

        if ( p_enc->b_strict_rc )
        {
            p_context->rc_max_rate = p_enc->fmt_out.i_bitrate;
255
256
257
258
259
260
261
262
263
            p_context->rc_buffer_size = p_enc->i_rc_buffer_size;
            p_context->rc_buffer_aggressivity = p_enc->f_rc_buffer_aggressivity;
        }

        if ( p_enc->f_i_quant_factor != 0.0 )
        {
            p_context->i_quant_factor = p_enc->f_i_quant_factor;
        }

gbazin's avatar
   
gbazin committed
264
#if LIBAVCODEC_BUILD >= 4690
265
        p_context->noise_reduction = p_enc->i_noise_reduction;
gbazin's avatar
   
gbazin committed
266
#endif
267
268
269
270
271

        if ( p_enc->b_mpeg4_matrix )
        {
            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
272
273
274
275
276
277
278
        }

        if ( p_enc->b_pre_me )
        {
            p_context->pre_me = 1;
            p_context->me_pre_cmp = FF_CMP_CHROMA;
        }
279
280
281
282
283
284
285
286
287
288
289
290
291
292

        if ( p_enc->b_interlace )
        {
            p_context->flags |= CODEC_FLAG_INTERLACED_DCT;
#if LIBAVCODEC_BUILD >= 4698
            p_context->flags |= CODEC_FLAG_INTERLACED_ME;
#endif
        }

        if ( p_enc->b_trellis )
        {
            p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
        }

gbazin's avatar
   
gbazin committed
293
#if LIBAVCODEC_BUILD >= 4702
294
295
296
297
        if ( p_enc->i_threads >= 1 )
        {
            p_context->thread_count = p_enc->i_threads;
        }
gbazin's avatar
   
gbazin committed
298
#endif
299
300
301
302
303
304
305
306
307
308
309

        if( p_enc->i_vtolerance > 0 )
        {
            p_context->bit_rate_tolerance = p_enc->i_vtolerance;
        }

        p_context->mb_qmin = p_context->qmin = p_enc->i_qmin;
        p_context->mb_qmax = p_context->qmax = p_enc->i_qmax;
        p_context->max_qdiff = 3;

        p_context->mb_decision = p_enc->i_hq;
gbazin's avatar
   
gbazin committed
310
311
312
313
314
315
316
317
318
    }
    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
319
    p_context->bit_rate = p_enc->fmt_out.i_bitrate;
gbazin's avatar
   
gbazin committed
320

gbazin's avatar
   
gbazin committed
321
    if( i_codec_id == CODEC_ID_RAWVIDEO )
gbazin's avatar
   
gbazin committed
322
    {
323
324
        /* 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
325
        p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->fmt_in.i_codec );
gbazin's avatar
   
gbazin committed
326
327
328
329
330
331
332
    }

    /* 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
333
    if( avcodec_open( p_context, p_codec ) )
gbazin's avatar
   
gbazin committed
334
    {
gbazin's avatar
   
gbazin committed
335
336
337
338
339
340
341
        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" );
342
                free( p_sys );
gbazin's avatar
   
gbazin committed
343
344
345
346
347
348
349
                return VLC_EGENERIC;
            }
            msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
        }
        else
        {
            msg_Err( p_enc, "cannot open encoder" );
350
            free( p_sys );
gbazin's avatar
   
gbazin committed
351
352
            return VLC_EGENERIC;
        }
gbazin's avatar
   
gbazin committed
353
354
    }

gbazin's avatar
   
gbazin committed
355
356
    p_enc->fmt_out.i_extra = p_context->extradata_size;
    p_enc->fmt_out.p_extra = p_context->extradata;
gbazin's avatar
   
gbazin committed
357
358
    p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;

gbazin's avatar
   
gbazin committed
359
360
    if( p_enc->fmt_in.i_cat == AUDIO_ES )
    {
361
        p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
gbazin's avatar
   
gbazin committed
362
363
364
365
        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
366
367
    p_sys->i_last_ref_pts = 0;
    p_sys->i_buggy_pts_detect = 0;
gbazin's avatar
   
gbazin committed
368
369
    p_sys->i_samples_delay = 0;
    p_sys->i_pts = 0;
370
    p_sys->i_last_pts = 0;
gbazin's avatar
   
gbazin committed
371

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

gbazin's avatar
   
gbazin committed
374
375
376
    return VLC_SUCCESS;
}

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/****************************************************************************
 * 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
451
452
453
454
455
456
457
458
/****************************************************************************
 * 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;
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490

#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
491

Laurent Aimar's avatar
Laurent Aimar committed
492
    memset( &frame, 0, sizeof( AVFrame ) );
gbazin's avatar
   
gbazin committed
493
494
495
496
497
498
    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;
    }

499
500
501
502
503
504
505
506
507
508
    /* 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

509
#if LIBAVCODEC_BUILD < 4702
gbazin's avatar
   
gbazin committed
510
    /* Set the pts of the frame being encoded (segfaults with mpeg4!)*/
511
512
513
    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' ) )
514
515
516
#else
    if( 1 )
#endif
Christophe Massiot's avatar
Christophe Massiot committed
517
    {
518
        frame.pts = p_pict->date ? p_pict->date : AV_NOPTS_VALUE;
519

520
        if ( p_enc->b_hurry_up && frame.pts != AV_NOPTS_VALUE )
Christophe Massiot's avatar
Christophe Massiot committed
521
        {
522
523
            mtime_t current_date = mdate();

524
            if ( current_date + HURRY_UP_GUARD3 > frame.pts )
525
526
527
528
529
530
531
532
533
            {
                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
            {
                p_sys->p_context->mb_decision = p_enc->i_hq;

534
                if ( current_date + HURRY_UP_GUARD2 > frame.pts )
535
536
                {
                    p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
537
538
539
#if LIBAVCODEC_BUILD >= 4690
                    p_sys->p_context->noise_reduction = p_enc->i_noise_reduction
                         + (HURRY_UP_GUARD2 + current_date - frame.pts) / 500;
540
541
542
543
544
545
546
#endif
                    msg_Dbg( p_enc, "hurry up mode 2" );
                }
                else
                {
                    if ( p_enc->b_trellis )
                        p_sys->p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
547
548
549
#if LIBAVCODEC_BUILD >= 4690
                    p_sys->p_context->noise_reduction =
                                    p_enc->i_noise_reduction;
550
551
552
553
#endif
                }
            }

554
            if ( current_date + HURRY_UP_GUARD1 > frame.pts )
555
            {
556
557
                frame.pict_type = FF_P_TYPE;
                /* msg_Dbg( p_enc, "hurry up mode 1 %lld", current_date + HURRY_UP_GUARD1 - frame.pts ); */
558
            }
Christophe Massiot's avatar
Christophe Massiot committed
559
560
        }
    }
gbazin's avatar
   
gbazin committed
561
    else
Christophe Massiot's avatar
Christophe Massiot committed
562
    {
563
        frame.pts = AV_NOPTS_VALUE;
Christophe Massiot's avatar
Christophe Massiot committed
564
    }
gbazin's avatar
   
gbazin committed
565

gbazin's avatar
gbazin committed
566
    if ( frame.pts != AV_NOPTS_VALUE && frame.pts != 0 )
567
568
569
    {
        if ( p_sys->i_last_pts == frame.pts )
        {
gbazin's avatar
gbazin committed
570
571
            msg_Warn( p_enc, "almost fed libavcodec with two frames with the "
                      "same PTS (" I64Fd ")", frame.pts );
572
573
574
575
576
577
578
            return NULL;
        }
        else
        {
            p_sys->i_last_pts = frame.pts;
        }
    }
gbazin's avatar
   
gbazin committed
579
580
581

    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
582

gbazin's avatar
   
gbazin committed
583
584
585
586
587
    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 );

588
        if( p_sys->p_context->coded_frame->pts != AV_NOPTS_VALUE &&
gbazin's avatar
gbazin committed
589
            p_sys->p_context->coded_frame->pts != 0 &&
gbazin's avatar
   
gbazin committed
590
591
592
593
594
            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
595
596
597
            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
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
            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
625
626
627
            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
628
629
630
            p_block->i_dts = p_block->i_pts = p_pict->date;
        }

631
632
633
634
635
636
637
638
639
640
641
642
643
        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
644
645
646
647
648
649
650
651
652
653
654
655
656
        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
657

gbazin's avatar
   
gbazin committed
658
659
660
661
662
663
    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
664
                (mtime_t)p_enc->fmt_in.audio.i_rate;
gbazin's avatar
   
gbazin committed
665
666
667
668
669
670
671
672
673
674
675

    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
676
            int i_delay_size = i_samples_delay * 2 *
gbazin's avatar
   
gbazin committed
677
678
679
680
681
682
                                 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
683
            i_samples += i_samples_delay;
gbazin's avatar
   
gbazin committed
684
685
686
687
688
689
690
691
692
693
            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
694
695
696
697
698

#if 0
        msg_Warn( p_enc, "avcodec_encode_audio: %d", i_out );
#endif
        if( i_out < 0 ) break;
gbazin's avatar
   
gbazin committed
699
700
701

        p_buffer += p_sys->i_frame_size;
        p_sys->i_samples_delay -= p_sys->p_context->frame_size;
gbazin's avatar
   
gbazin committed
702
703
704
        i_samples -= p_sys->p_context->frame_size;

        if( i_out == 0 ) continue;
gbazin's avatar
   
gbazin committed
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720

        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
721
    if( i_samples )
gbazin's avatar
   
gbazin committed
722
    {
gbazin's avatar
   
gbazin committed
723
724
        memcpy( p_sys->p_buffer + i_samples_delay * 2 *
                p_sys->p_context->channels, p_buffer,
gbazin's avatar
   
gbazin committed
725
726
727
728
729
730
731
                i_samples * 2 * p_sys->p_context->channels );
    }

    return p_chain;
}

/*****************************************************************************
gbazin's avatar
   
gbazin committed
732
 * CloseEncoder: ffmpeg encoder destruction
gbazin's avatar
   
gbazin committed
733
 *****************************************************************************/
gbazin's avatar
   
gbazin committed
734
void E_(CloseEncoder)( vlc_object_t *p_this )
gbazin's avatar
   
gbazin committed
735
736
737
738
{
    encoder_t *p_enc = (encoder_t *)p_this;
    encoder_sys_t *p_sys = p_enc->p_sys;

739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
#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] );
        }

755
        free( pp_contexts );
756
757
758
    }
#endif

gbazin's avatar
   
gbazin committed
759
    avcodec_close( p_sys->p_context );
760
    av_free( p_sys->p_context );
gbazin's avatar
   
gbazin committed
761
762
763
764

    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
765
766
    free( p_sys );
}