Commit 9e4b5e02 authored by Christophe Massiot's avatar Christophe Massiot

* modules/codec/ffmpeg/encoder.c:

  - use AV_NOPTS_VALUE instead of 0 when it's available
  - reworked the hurry-up mode to start with disabling the B frames first
  - reworked the hurry-up mode to remove my thread mess
  - check that we don't feed ffmpeg with twice the same PTS (crashes ffmpeg)
  - correctly flag the picture types

* modules/stream_out/transcode.c:
  - use AV_NOPTS_VALUE instead of 0 when it's available
  - copy block_t::i_flags to sout_buffer_t::i_flags (temporary)
parent 7a649fb2
/***************************************************************************** /*****************************************************************************
* encoder.c: video and audio encoder using the ffmpeg library * encoder.c: video and audio encoder using the ffmpeg library
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2004 VideoLAN
* $Id: encoder.c,v 1.23 2004/02/21 22:41:49 gbazin Exp $ * $Id: encoder.c,v 1.24 2004/03/03 11:29:26 massiot Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com> * Gildas Bazin <gbazin@netcourrier.com>
* Christophe Massiot <massiot@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
...@@ -38,12 +39,16 @@ ...@@ -38,12 +39,16 @@
# include <avcodec.h> # include <avcodec.h>
#endif #endif
#if LIBAVCODEC_BUILD < 4704
# define AV_NOPTS_VALUE 0
#endif
#include "ffmpeg.h" #include "ffmpeg.h"
#define AVCODEC_MAX_VIDEO_FRAME_SIZE (3*1024*1024) #define AVCODEC_MAX_VIDEO_FRAME_SIZE (3*1024*1024)
#define HURRY_UP_GUARD1 (1000000) #define HURRY_UP_GUARD1 (450000)
#define HURRY_UP_GUARD2 (1000000) #define HURRY_UP_GUARD2 (300000)
#define HURRY_UP_GUARD3 (200000) #define HURRY_UP_GUARD3 (100000)
/***************************************************************************** /*****************************************************************************
* Local prototypes * Local prototypes
...@@ -101,6 +106,7 @@ struct encoder_sys_t ...@@ -101,6 +106,7 @@ struct encoder_sys_t
*/ */
mtime_t i_last_ref_pts; mtime_t i_last_ref_pts;
mtime_t i_buggy_pts_detect; mtime_t i_buggy_pts_detect;
mtime_t i_last_pts;
vlc_bool_t b_inited; vlc_bool_t b_inited;
/* /*
...@@ -368,6 +374,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this ) ...@@ -368,6 +374,7 @@ int E_(OpenEncoder)( vlc_object_t *p_this )
p_sys->i_buggy_pts_detect = 0; p_sys->i_buggy_pts_detect = 0;
p_sys->i_samples_delay = 0; p_sys->i_samples_delay = 0;
p_sys->i_pts = 0; p_sys->i_pts = 0;
p_sys->i_last_pts = 0;
msg_Dbg( p_enc, "found encoder %s", psz_namecodec ); msg_Dbg( p_enc, "found encoder %s", psz_namecodec );
...@@ -496,57 +503,43 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -496,57 +503,43 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
frame.linesize[i_plane] = p_pict->p[i_plane].i_pitch; frame.linesize[i_plane] = p_pict->p[i_plane].i_pitch;
} }
/* 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
/* Set the pts of the frame being encoded (segfaults with mpeg4!)*/ /* Set the pts of the frame being encoded (segfaults with mpeg4!)*/
if( p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', 'g', 'v' ) || 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', '1', 'v' ) ||
p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', '2', 'v' ) ) p_enc->fmt_out.i_codec == VLC_FOURCC( 'm', 'p', '2', 'v' ) )
{ {
frame.pts = p_pict->date; frame.pts = p_pict->date ? p_pict->date : AV_NOPTS_VALUE;
if ( p_enc->b_hurry_up ) if ( p_enc->b_hurry_up && frame.pts != AV_NOPTS_VALUE )
{ {
mtime_t current_date = mdate(); mtime_t current_date = mdate();
#if LIBAVCODEC_BUILD >= 4702
struct thread_context_t ** pp_contexts =
(struct thread_context_t **)p_sys->p_context->thread_opaque;
#endif
if ( frame.pts && current_date + HURRY_UP_GUARD3 > frame.pts ) if ( current_date + HURRY_UP_GUARD3 > frame.pts )
{ {
p_sys->p_context->mb_decision = FF_MB_DECISION_SIMPLE; p_sys->p_context->mb_decision = FF_MB_DECISION_SIMPLE;
p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT; p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
#if LIBAVCODEC_BUILD >= 4702
if ( p_enc->i_threads >= 2 )
{
int i;
for ( i = 0; i < p_enc->i_threads; i++ )
{
vlc_thread_set_priority( pp_contexts[i],
VLC_THREAD_PRIORITY_VIDEO + 4 );
}
}
#endif
msg_Dbg( p_enc, "hurry up mode 3" ); msg_Dbg( p_enc, "hurry up mode 3" );
} }
else else
{ {
p_sys->p_context->mb_decision = p_enc->i_hq; p_sys->p_context->mb_decision = p_enc->i_hq;
if ( frame.pts && current_date + HURRY_UP_GUARD2 > frame.pts ) if ( current_date + HURRY_UP_GUARD2 > frame.pts )
{ {
p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT; p_sys->p_context->flags &= ~CODEC_FLAG_TRELLIS_QUANT;
#if LIBAVCODEC_BUILD >= 4702 #if LIBAVCODEC_BUILD >= 4690
if ( p_enc->i_threads >= 2 ) p_sys->p_context->noise_reduction = p_enc->i_noise_reduction
{ + (HURRY_UP_GUARD2 + current_date - frame.pts) / 500;
int i;
for ( i = 0; i < p_enc->i_threads; i++ )
{
vlc_thread_set_priority( pp_contexts[i],
VLC_THREAD_PRIORITY_VIDEO + 2 );
}
}
#endif #endif
msg_Dbg( p_enc, "hurry up mode 2" ); msg_Dbg( p_enc, "hurry up mode 2" );
} }
...@@ -554,48 +547,39 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -554,48 +547,39 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
{ {
if ( p_enc->b_trellis ) if ( p_enc->b_trellis )
p_sys->p_context->flags |= CODEC_FLAG_TRELLIS_QUANT; p_sys->p_context->flags |= CODEC_FLAG_TRELLIS_QUANT;
#if LIBAVCODEC_BUILD >= 4690
#if LIBAVCODEC_BUILD >= 4702 p_sys->p_context->noise_reduction =
if ( p_enc->i_threads >= 2 ) p_enc->i_noise_reduction;
{
int i;
for ( i = 0; i < p_enc->i_threads; i++ )
{
vlc_thread_set_priority( pp_contexts[i],
VLC_THREAD_PRIORITY_VIDEO );
}
}
#endif #endif
} }
} }
#if LIBAVCODEC_BUILD >= 4690 if ( current_date + HURRY_UP_GUARD1 > frame.pts )
if ( frame.pts && current_date + HURRY_UP_GUARD1 > frame.pts )
{ {
p_sys->p_context->noise_reduction = p_enc->i_noise_reduction frame.pict_type = FF_P_TYPE;
+ (HURRY_UP_GUARD1 + current_date - frame.pts) / 1500; /* msg_Dbg( p_enc, "hurry up mode 1 %lld", current_date + HURRY_UP_GUARD1 - frame.pts ); */
}
}
} }
else else
{ {
p_sys->p_context->noise_reduction = p_enc->i_noise_reduction; frame.pts = AV_NOPTS_VALUE;
}
#endif
} }
if ( frame.pts != AV_NOPTS_VALUE )
{
if ( p_sys->i_last_pts == frame.pts )
{
msg_Warn( p_enc,
"almost fed libavcodec with two frames with the same PTS (" I64Fd ")",
frame.pts );
return NULL;
} }
else else
{ {
frame.pts = 0; p_sys->i_last_pts = frame.pts;
}
} }
/* 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
i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out, i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out,
AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame ); AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame );
...@@ -605,7 +589,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -605,7 +589,7 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
block_t *p_block = block_New( p_enc, i_out ); block_t *p_block = block_New( p_enc, i_out );
memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out ); memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
if( p_sys->p_context->coded_frame->pts != 0 && if( p_sys->p_context->coded_frame->pts != AV_NOPTS_VALUE &&
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 )
{ {
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;
...@@ -647,6 +631,19 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict ) ...@@ -647,6 +631,19 @@ static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
p_block->i_dts = p_block->i_pts = p_pict->date; p_block->i_dts = p_block->i_pts = p_pict->date;
} }
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;
}
return p_block; return p_block;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* transcode.c: transcoding stream output module * transcode.c: transcoding stream output module
***************************************************************************** *****************************************************************************
* Copyright (C) 2003-2004 VideoLAN * Copyright (C) 2003-2004 VideoLAN
* $Id: transcode.c,v 1.80 2004/02/24 17:42:07 gbazin Exp $ * $Id: transcode.c,v 1.81 2004/03/03 11:29:26 massiot Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com> * Gildas Bazin <gbazin@netcourrier.com>
...@@ -41,6 +41,10 @@ ...@@ -41,6 +41,10 @@
# include <avcodec.h> # include <avcodec.h>
#endif #endif
#if LIBAVCODEC_BUILD < 4704
# define AV_NOPTS_VALUE 0
#endif
/***************************************************************************** /*****************************************************************************
* Exported prototypes * Exported prototypes
*****************************************************************************/ *****************************************************************************/
...@@ -1306,7 +1310,8 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, ...@@ -1306,7 +1310,8 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
b_gotpicture = 1; b_gotpicture = 1;
/* Set PTS */ /* Set PTS */
frame->pts = p_sys->i_input_pts; frame->pts = p_sys->i_input_pts ? p_sys->i_input_pts :
AV_NOPTS_VALUE;
} }
if( i_used < 0 ) if( i_used < 0 )
...@@ -1324,7 +1329,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, ...@@ -1324,7 +1329,7 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
/* Get the pts of the decoded frame if any, otherwise keep the /* Get the pts of the decoded frame if any, otherwise keep the
* interpolated one */ * interpolated one */
if( frame->pts > 0 ) if( frame->pts != AV_NOPTS_VALUE )
{ {
p_sys->i_output_pts = frame->pts; p_sys->i_output_pts = frame->pts;
} }
...@@ -1594,6 +1599,9 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream, ...@@ -1594,6 +1599,9 @@ static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
p_out->i_dts = p_block->i_dts; p_out->i_dts = p_block->i_dts;
p_out->i_pts = p_block->i_pts; p_out->i_pts = p_block->i_pts;
p_out->i_length = p_block->i_length; p_out->i_length = p_block->i_length;
p_out->i_flags =
(p_block->i_flags << SOUT_BUFFER_FLAGS_BLOCK_SHIFT)
& SOUT_BUFFER_FLAGS_BLOCK_MASK;
sout_BufferChain( out, p_out ); sout_BufferChain( out, p_out );
p_block = p_block->p_next; p_block = p_block->p_next;
...@@ -1652,6 +1660,9 @@ static int EncoderThread( sout_stream_sys_t * p_sys ) ...@@ -1652,6 +1660,9 @@ static int EncoderThread( sout_stream_sys_t * p_sys )
p_out->i_dts = p_block->i_dts; p_out->i_dts = p_block->i_dts;
p_out->i_pts = p_block->i_pts; p_out->i_pts = p_block->i_pts;
p_out->i_length = p_block->i_length; p_out->i_length = p_block->i_length;
p_out->i_flags =
(p_block->i_flags << SOUT_BUFFER_FLAGS_BLOCK_SHIFT)
& SOUT_BUFFER_FLAGS_BLOCK_MASK;
sout_BufferChain( &p_sys->p_buffers, p_out ); sout_BufferChain( &p_sys->p_buffers, p_out );
p_block = p_block->p_next; p_block = p_block->p_next;
...@@ -1701,7 +1712,7 @@ static int transcode_video_ffmpeg_getframebuf(struct AVCodecContext *p_context, ...@@ -1701,7 +1712,7 @@ static int transcode_video_ffmpeg_getframebuf(struct AVCodecContext *p_context,
sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_context->opaque; sout_stream_sys_t *p_sys = (sout_stream_sys_t *)p_context->opaque;
/* Set PTS */ /* Set PTS */
p_frame->pts = p_sys->i_input_pts; p_frame->pts = p_sys->i_input_pts ? p_sys->i_input_pts : AV_NOPTS_VALUE;
return avcodec_default_get_buffer( p_context, p_frame ); return avcodec_default_get_buffer( p_context, p_frame );
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment