X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fffmpeg%2Fvideo.c;h=9ae5fa4452acba9cb36bae9eb19390bbd1b1cfef;hb=791b8caafd1957bfb1ac4a6defb188bb499adf54;hp=cd1296622a2abe17440a01ad809c5828193584c3;hpb=7326416c40e37b43e62cb8993878c36002b58878;p=vlc diff --git a/modules/codec/ffmpeg/video.c b/modules/codec/ffmpeg/video.c index cd1296622a..9ae5fa4452 100644 --- a/modules/codec/ffmpeg/video.c +++ b/modules/codec/ffmpeg/video.c @@ -25,13 +25,19 @@ /***************************************************************************** * Preamble *****************************************************************************/ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include #include #include #include /* hmmm, just for INPUT_RATE_DEFAULT */ /* ffmpeg header */ -#ifdef HAVE_FFMPEG_AVCODEC_H +#ifdef HAVE_LIBAVCODEC_AVCODEC_H +# include +#elif defined(HAVE_FFMPEG_AVCODEC_H) # include #else # include @@ -56,7 +62,8 @@ struct decoder_sys_t /* for frame skipping algo */ int b_hurry_up; - int i_frame_skip; + enum AVDiscard i_skip_frame; + enum AVDiscard i_skip_idct; /* how many decoded frames are late */ int i_late_frames; @@ -125,6 +132,10 @@ static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma ) return VLC_FOURCC('R','V','2','4'); case PIX_FMT_RGBA32: return VLC_FOURCC('R','V','3','2'); +#ifdef PIX_FMT_RGBA + case PIX_FMT_RGBA: + return VLC_FOURCC('R','G','B','A'); +#endif case PIX_FMT_GRAY8: return VLC_FOURCC('G','R','E','Y'); @@ -196,7 +207,7 @@ static inline picture_t *ffmpeg_NewPictBuf( decoder_t *p_dec, if( p_sys->p_pp && p_sys->b_pp && !p_sys->b_pp_init ) { - E_(InitPostproc)( p_dec, p_sys->p_pp, p_context->width, + E_(InitPostproc)( p_sys->p_pp, p_context->width, p_context->height, p_context->pix_fmt ); p_sys->b_pp_init = VLC_TRUE; } @@ -214,19 +225,16 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, AVCodec *p_codec, int i_codec_id, const char *psz_namecodec ) { decoder_sys_t *p_sys; - vlc_value_t lockval; vlc_value_t val; - var_Create( p_dec->p_libvlc_global, "avcodec", VLC_VAR_MUTEX ); - var_Get( p_dec->p_libvlc_global, "avcodec", &lockval ); - /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) { msg_Err( p_dec, "out of memory" ); - return VLC_EGENERIC; + return VLC_ENOMEM; } + memset( p_sys, 0, sizeof(decoder_sys_t) ); p_dec->p_sys->p_context = p_context; p_dec->p_sys->p_codec = p_codec; @@ -271,6 +279,56 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, var_Get( p_dec, "ffmpeg-hurry-up", &val ); p_sys->b_hurry_up = val.b_bool; + var_Create( p_dec, "ffmpeg-skip-frame", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Get( p_dec, "ffmpeg-skip-frame", &val ); + switch( val.i_int ) + { + case -1: + p_sys->p_context->skip_frame = AVDISCARD_NONE; + break; + case 0: + p_sys->p_context->skip_frame = AVDISCARD_DEFAULT; + break; + case 1: + p_sys->p_context->skip_frame = AVDISCARD_BIDIR; + 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; + } + p_sys->i_skip_frame = p_sys->p_context->skip_frame; + + var_Create( p_dec, "ffmpeg-skip-idct", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); + var_Get( p_dec, "ffmpeg-skip-idct", &val ); + switch( val.i_int ) + { + case -1: + p_sys->p_context->skip_idct = AVDISCARD_NONE; + break; + case 0: + p_sys->p_context->skip_idct = AVDISCARD_DEFAULT; + break; + case 1: + p_sys->p_context->skip_idct = AVDISCARD_BIDIR; + 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; + } + p_sys->i_skip_idct = p_sys->p_context->skip_idct; + /* ***** ffmpeg direct rendering ***** */ p_sys->b_direct_rendering = 0; var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT ); @@ -330,15 +388,21 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_context->palctrl = &palette_control; /* ***** Open the codec ***** */ - vlc_mutex_lock( lockval.p_address ); + vlc_mutex_t *lock = var_AcquireMutex( "avcodec" ); + if( lock == NULL ) + { + free( p_sys ); + return VLC_ENOMEM; + } + if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 ) { - vlc_mutex_unlock( lockval.p_address ); + vlc_mutex_unlock( lock ); msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec ); free( p_sys ); return VLC_EGENERIC; } - vlc_mutex_unlock( lockval.p_address ); + vlc_mutex_unlock( lock ); msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec ); @@ -385,8 +449,8 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) p_sys->i_late_frames = 0; } - if( !p_dec->b_pace_control && p_sys->i_late_frames > 0 && - mdate() - p_sys->i_late_frames_start > I64C(5000000) ) + if( !p_dec->b_pace_control && (p_sys->i_late_frames > 0) && + (mdate() - p_sys->i_late_frames_start > I64C(5000000)) ) { if( p_sys->i_pts ) { @@ -408,21 +472,22 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) p_block->i_pts = p_block->i_dts = 0; } - /* TODO implement it in a better way */ /* A good idea could be to decode all I pictures and see for the other */ if( !p_dec->b_pace_control && - p_sys->b_hurry_up && p_sys->i_late_frames > 4 ) + p_sys->b_hurry_up && + (p_sys->i_late_frames > 4) ) { b_drawpicture = 0; if( p_sys->i_late_frames < 8 ) { - p_sys->p_context->hurry_up = 2; + p_sys->p_context->skip_frame = + (p_sys->i_skip_frame <= AVDISCARD_BIDIR) ? + AVDISCARD_BIDIR : p_sys->i_skip_frame; } 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 ); p_sys->i_buffer = 0; @@ -431,17 +496,18 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) } else { - p_sys->p_context->hurry_up = 0; + if( p_sys->b_hurry_up ) + p_sys->p_context->skip_frame = p_sys->i_skip_frame; if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) b_drawpicture = 1; else b_drawpicture = 0; } - if( p_sys->p_context->width <= 0 || p_sys->p_context->height <= 0 ) { - p_sys->p_context->hurry_up = 5; + if( p_sys->b_hurry_up ) + p_sys->p_context->skip_frame = p_sys->i_skip_frame; b_null_size = VLC_TRUE; } @@ -488,7 +554,8 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) { /* Reparse it to not drop the I frame */ b_null_size = VLC_FALSE; - p_sys->p_context->hurry_up = 0; + if( p_sys->b_hurry_up ) + p_sys->p_context->skip_frame = p_sys->i_skip_frame; i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic, &b_gotpicture, (uint8_t*)p_sys->p_buffer, p_sys->i_buffer ); @@ -518,7 +585,7 @@ picture_t *E_(DecodeVideo)( decoder_t *p_dec, block_t **pp_block ) } /* Update frame late count (except when doing preroll) */ - if( p_sys->i_pts && p_sys->i_pts <= mdate() && + if( p_sys->i_pts && decoder_GetDisplayDate(p_dec, p_sys->i_pts) <= mdate() && !(p_block->i_flags & BLOCK_FLAG_PREROLL) ) { p_sys->i_late_frames++; @@ -740,7 +807,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec, int i_src_stride, i_dst_stride; if( p_sys->p_pp && p_sys->b_pp ) - E_(PostprocPict)( p_dec, p_sys->p_pp, p_pic, p_ff_pic ); + E_(PostprocPict)( p_sys->p_pp, p_pic, p_ff_pic ); else { for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) @@ -778,7 +845,7 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec, dest_pic.data[i] = p_pic->p[i].p_pixels; dest_pic.linesize[i] = p_pic->p[i].i_pitch; } -#if !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE) +#if !defined(HAVE_LIBSWSCALE_SWSCALE_H) && !defined(HAVE_FFMPEG_SWSCALE_H) && !defined(HAVE_LIBSWSCALE_TREE) img_convert( &dest_pic, PIX_FMT_YUV420P, (AVPicture *)p_ff_pic, p_sys->p_context->pix_fmt,