]> git.sesse.net Git - vlc/blobdiff - modules/codec/ffmpeg/video.c
Let's try this again. Detect older and new versions of ffmpeg and allow for their...
[vlc] / modules / codec / ffmpeg / video.c
index cd1296622a2abe17440a01ad809c5828193584c3..9ae5fa4452acba9cb36bae9eb19390bbd1b1cfef 100644 (file)
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
 #include <vlc/vlc.h>
 #include <vlc_codec.h>
 #include <vlc_vout.h>
 #include <vlc_input.h>                  /* hmmm, just for INPUT_RATE_DEFAULT */
 
 /* ffmpeg header */
-#ifdef HAVE_FFMPEG_AVCODEC_H
+#ifdef HAVE_LIBAVCODEC_AVCODEC_H
+#   include <libavcodec/avcodec.h>
+#elif defined(HAVE_FFMPEG_AVCODEC_H)
 #   include <ffmpeg/avcodec.h>
 #else
 #   include <avcodec.h>
@@ -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,