X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcodec%2Fffmpeg%2Fvideo.c;h=88eb6bae71255f689dd1750069f9f5f71638531c;hb=8ede3d79d009e21d5ef49797c28bc0428b6373ce;hp=d52ca0dcba4af931162abc4b393ceb6c030e21f6;hpb=dd5f0b9f0c35ec204432e1fe650053355f511e02;p=vlc diff --git a/modules/codec/ffmpeg/video.c b/modules/codec/ffmpeg/video.c index d52ca0dcba..88eb6bae71 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; @@ -117,20 +124,38 @@ static uint32_t ffmpeg_PixFmtToChroma( int i_ff_chroma ) case PIX_FMT_YUV422: return VLC_FOURCC('Y','U','Y','2'); +#if defined(WORDS_BIGENDIAN) + case PIX_FMT_BGR8: + return VLC_FOURCC('R','G','B','8'); + case PIX_FMT_BGR555: + return VLC_FOURCC('R','V','1','5'); + case PIX_FMT_BGR565: + return VLC_FOURCC('R','V','1','6'); + case PIX_FMT_BGR24: + return VLC_FOURCC('R','V','2','4'); +#else +#if defined(PIX_FMT_RGB8) + case PIX_FMT_RGB8: + return VLC_FOURCC('R','G','B','8'); +#endif case PIX_FMT_RGB555: return VLC_FOURCC('R','V','1','5'); case PIX_FMT_RGB565: return VLC_FOURCC('R','V','1','6'); case PIX_FMT_RGB24: return VLC_FOURCC('R','V','2','4'); +#endif 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'); case PIX_FMT_YUV410P: case PIX_FMT_YUV411P: - case PIX_FMT_BGR24: default: return 0; } @@ -196,7 +221,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,12 +239,8 @@ 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_mutex_t *lock = var_GetGlobalMutex( "avcodec" ); vlc_value_t val; - if( lock == NULL ) - return VLC_EGENERIC; - /* 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 ) @@ -227,6 +248,7 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, msg_Err( p_dec, "out of memory" ); 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 +293,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,7 +402,13 @@ int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context, p_sys->p_context->palctrl = &palette_control; /* ***** Open the codec ***** */ - vlc_mutex_lock( lock ); + 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( lock ); @@ -385,8 +463,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 +486,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 +510,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 +568,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 +599,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 +821,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++ ) @@ -771,14 +852,25 @@ static void ffmpeg_CopyPicture( decoder_t *p_dec, { case PIX_FMT_YUV410P: case PIX_FMT_YUV411P: + case PIX_FMT_RGB32: + case PIX_FMT_RGB24: +#if defined(PIX_FMT_RGB8) + case PIX_FMT_RGB8: +#endif +#if defined(PIX_FMT_BRG32) + case PIX_FMT_BGR32: +#endif case PIX_FMT_BGR24: +#if defined(PIX_FMT_BGR8) + case PIX_FMT_BGR8: +#endif case PIX_FMT_PAL8: for( i = 0; i < p_pic->i_planes; i++ ) { 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,