]> git.sesse.net Git - vlc/blobdiff - modules/codec/avcodec/video.c
Avcodec: deactivate DR for Camtasia
[vlc] / modules / codec / avcodec / video.c
index 9313dcab3ee1323c5291f298e14a831ec5472e97..6c9b865134cf3257412b5ed2e5a18de5050a7cca 100644 (file)
 #if defined(HAVE_AVCODEC_VAAPI) || defined(HAVE_AVCODEC_DXVA2)
 #   define HAVE_AVCODEC_VA
 #endif
-#if defined(FF_THREAD_FRAME)
-#   define HAVE_AVCODEC_MT
-#endif
 
 /*****************************************************************************
  * decoder_sys_t : decoder descriptor
  *****************************************************************************/
 struct decoder_sys_t
 {
-    FFMPEG_COMMON_MEMBERS
+    AVCODEC_COMMON_MEMBERS
 
     /* Video decoder specific part */
     mtime_t i_pts;
@@ -210,8 +207,8 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
     if( ( p_dec->p_sys = p_sys = calloc( 1, sizeof(decoder_sys_t) ) ) == NULL )
         return VLC_ENOMEM;
 
-    p_codec->type = CODEC_TYPE_VIDEO;
-    p_context->codec_type = CODEC_TYPE_VIDEO;
+    p_codec->type = AVMEDIA_TYPE_VIDEO;
+    p_context->codec_type = AVMEDIA_TYPE_VIDEO;
     p_context->codec_id = i_codec_id;
     p_sys->p_context = p_context;
     p_sys->p_codec = p_codec;
@@ -261,7 +258,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
             p_sys->p_context->skip_frame = AVDISCARD_DEFAULT;
             break;
         case 1:
-            p_sys->p_context->skip_frame = AVDISCARD_BIDIR;
+            p_sys->p_context->skip_frame = AVDISCARD_NONREF;
             break;
         case 2:
             p_sys->p_context->skip_frame = AVDISCARD_NONKEY;
@@ -284,7 +281,7 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
             p_sys->p_context->skip_idct = AVDISCARD_DEFAULT;
             break;
         case 1:
-            p_sys->p_context->skip_idct = AVDISCARD_BIDIR;
+            p_sys->p_context->skip_idct = AVDISCARD_NONREF;
             break;
         case 2:
             p_sys->p_context->skip_idct = AVDISCARD_NONKEY;
@@ -304,8 +301,8 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
     if( var_CreateGetBool( p_dec, "ffmpeg-dr" ) &&
        (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
         /* No idea why ... but this fixes flickering on some TSCC streams */
-        p_sys->i_codec_id != CODEC_ID_TSCC &&
-#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 68, 2 )
+        p_sys->i_codec_id != CODEC_ID_TSCC && p_sys->i_codec_id != CODEC_ID_CSCD &&
+#if (LIBAVCODEC_VERSION_INT >= AV_VERSION_INT( 52, 68, 2 ) ) && (LIBAVCODEC_VERSION_INT < AV_VERSION_INT( 52, 100, 1 ) )
         /* avcodec native vp8 decode doesn't handle EMU_EDGE flag, and I
            don't have idea howto implement fallback to libvpx decoder */
         p_sys->i_codec_id != CODEC_ID_VP8 &&
@@ -346,13 +343,20 @@ int InitVideoDec( decoder_t *p_dec, AVCodecContext *p_context,
 
 #ifdef HAVE_AVCODEC_VA
     const bool b_use_hw = var_CreateGetBool( p_dec, "ffmpeg-hw" );
-    if( b_use_hw )
+    if( b_use_hw &&
+        (i_codec_id == CODEC_ID_MPEG1VIDEO || i_codec_id == CODEC_ID_MPEG2VIDEO ||
+         i_codec_id == CODEC_ID_MPEG4 ||
+         i_codec_id == CODEC_ID_H264 ||
+         i_codec_id == CODEC_ID_VC1 || i_codec_id == CODEC_ID_WMV3) )
     {
 #ifdef HAVE_AVCODEC_MT
-        msg_Err( p_dec, "ffmpeg-hw is not compatible with ffmpeg-mt" );
-#else
-        p_sys->p_context->get_format = ffmpeg_GetFormat;
+        if( p_sys->p_context->thread_type & FF_THREAD_FRAME )
+        {
+            msg_Warn( p_dec, "threaded frame decoding is not compatible with ffmpeg-hw, disabled" );
+            p_sys->p_context->thread_type &= ~FF_THREAD_FRAME;
+        }
 #endif
+        p_sys->p_context->get_format = ffmpeg_GetFormat;
     }
 #endif
 
@@ -493,8 +497,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
         if( p_sys->i_late_frames < 12 )
         {
             p_context->skip_frame =
-                    (p_sys->i_skip_frame <= AVDISCARD_BIDIR) ?
-                    AVDISCARD_BIDIR : p_sys->i_skip_frame;
+                    (p_sys->i_skip_frame <= AVDISCARD_NONREF) ?
+                    AVDISCARD_NONREF : p_sys->i_skip_frame;
         }
         else
         {
@@ -555,6 +559,7 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
     {
         int i_used, b_gotpicture;
         picture_t *p_pic;
+        AVPacket pkt;
 
         /* Set the PTS/DTS in the context reordered_opaque field */
         if( p_block->i_pts > VLC_TS_INVALID  )
@@ -571,9 +576,11 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
 
         post_mt( p_sys );
 
-        i_used = avcodec_decode_video( p_context, p_sys->p_ff_pic,
-                                       &b_gotpicture,
-                                       p_block->i_buffer <= 0 && p_sys->b_flush ? NULL : p_block->p_buffer, p_block->i_buffer );
+        av_init_packet( &pkt );
+        pkt.data = p_block->p_buffer;
+        pkt.size = p_block->i_buffer;
+        i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
+                                       &b_gotpicture, &pkt );
 
         if( b_null_size && !p_sys->b_flush &&
             p_context->width > 0 && p_context->height > 0 )
@@ -582,9 +589,8 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             b_null_size = false;
             if( p_sys->b_hurry_up )
                 p_context->skip_frame = p_sys->i_skip_frame;
-            i_used = avcodec_decode_video( p_context, p_sys->p_ff_pic,
-                                           &b_gotpicture, p_block->p_buffer,
-                                           p_block->i_buffer );
+            i_used = avcodec_decode_video2( p_context, p_sys->p_ff_pic,
+                                           &b_gotpicture, &pkt );
         }
         wait_mt( p_sys );
 
@@ -619,6 +625,12 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             continue;
         }
 
+        /* Sanity check (seems to be needed for some streams) */
+        if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
+        {
+            p_sys->b_has_b_frames = true;
+        }
+
         /* Compute the PTS */
         mtime_t i_pts = VLC_TS_INVALID;
         if( p_sys->p_ff_pic->reordered_opaque != INT64_MIN )
@@ -632,6 +644,15 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
                     !p_sys->p_ff_pic->reference ||
                     p_sys->i_pts <= VLC_TS_INVALID )
                     i_pts = i_ts;
+
+                /* Guess what ? The rules are different for Real Video :( */
+                if( (p_dec->fmt_in.i_codec == VLC_CODEC_RV30 ||
+                     p_dec->fmt_in.i_codec == VLC_CODEC_RV40) &&
+                    p_sys->b_has_b_frames )
+                {
+                    i_pts = VLC_TS_INVALID;
+                    if(p_sys->p_ff_pic->reference) i_pts = i_ts;
+                }
             }
             else
             {
@@ -707,12 +728,6 @@ picture_t *DecodeVideo( decoder_t *p_dec, block_t **pp_block )
             decoder_LinkPicture( p_dec, p_pic );
         }
 
-        /* Sanity check (seems to be needed for some streams) */
-        if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
-        {
-            p_sys->b_has_b_frames = true;
-        }
-
         if( !p_dec->fmt_in.video.i_sar_num || !p_dec->fmt_in.video.i_sar_den )
         {
             /* Fetch again the aspect ratio in case it changed */
@@ -930,10 +945,10 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
     if( p_sys->p_va )
     {
 #ifdef HAVE_AVCODEC_VA
-        /* hwaccel_context is not present in old fffmpeg version */
+        /* hwaccel_context is not present in old ffmpeg version */
         if( vlc_va_Setup( p_sys->p_va,
-                          &p_sys->p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
-                          p_sys->p_context->width, p_sys->p_context->height ) )
+                          &p_context->hwaccel_context, &p_dec->fmt_out.video.i_chroma,
+                          p_context->width, p_context->height ) )
         {
             msg_Err( p_dec, "vlc_va_Setup failed" );
             return -1;
@@ -961,13 +976,12 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
     }
 
     wait_mt( p_sys );
-
     /* Some codecs set pix_fmt only after the 1st frame has been decoded,
      * so we need to check for direct rendering again. */
 
-    int i_width = p_sys->p_context->width;
-    int i_height = p_sys->p_context->height;
-    avcodec_align_dimensions( p_sys->p_context, &i_width, &i_height );
+    int i_width = p_context->width;
+    int i_height = p_context->height;
+    avcodec_align_dimensions( p_context, &i_width, &i_height );
 
     if( GetVlcChroma( &p_dec->fmt_out.video, p_context->pix_fmt ) != VLC_SUCCESS ||
         p_context->pix_fmt == PIX_FMT_PAL8 )
@@ -976,7 +990,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
     p_dec->fmt_out.i_codec = p_dec->fmt_out.video.i_chroma;
 
     /* Get a new picture */
-    p_pic = ffmpeg_NewPictBuf( p_dec, p_sys->p_context );
+    p_pic = ffmpeg_NewPictBuf( p_dec, p_context );
     if( !p_pic )
         goto no_dr;
     bool b_compatible = true;
@@ -1022,7 +1036,7 @@ static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
         p_sys->i_direct_rendering_used = 1;
     }
 
-    p_sys->p_context->draw_horiz_band = NULL;
+    p_context->draw_horiz_band = NULL;
 
     p_ff_pic->opaque = (void*)p_pic;
     p_ff_pic->type = FF_BUFFER_TYPE_USER;
@@ -1089,10 +1103,10 @@ static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
 }
 
 #ifdef HAVE_AVCODEC_VA
-static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
+static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_context,
                                           const enum PixelFormat *pi_fmt )
 {
-    decoder_t *p_dec = p_codec->opaque;
+    decoder_t *p_dec = p_context->opaque;
     decoder_sys_t *p_sys = p_dec->p_sys;
 
     if( p_sys->p_va )
@@ -1127,7 +1141,7 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
             }
 #ifdef HAVE_AVCODEC_VAAPI
             msg_Dbg( p_dec, "Trying VA API" );
-            p_sys->p_va = vlc_va_NewVaapi( p_sys->i_codec_id );
+            p_sys->p_va = vlc_va_NewVaapi( VLC_OBJECT(p_dec), p_sys->i_codec_id );
             if( !p_sys->p_va )
                 msg_Warn( p_dec, "Failed to open VA API" );
 #else
@@ -1145,14 +1159,14 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
 #endif
 
         if( p_sys->p_va &&
-            p_sys->p_context->width > 0 && p_sys->p_context->height > 0 )
+            p_context->width > 0 && p_context->height > 0 )
         {
             /* We try to call vlc_va_Setup when possible to detect errors when
              * possible (later is too late) */
             if( vlc_va_Setup( p_sys->p_va,
-                              &p_sys->p_context->hwaccel_context,
+                              &p_context->hwaccel_context,
                               &p_dec->fmt_out.video.i_chroma,
-                              p_sys->p_context->width, p_sys->p_context->height ) )
+                              p_context->width, p_context->height ) )
             {
                 msg_Err( p_dec, "vlc_va_Setup failed" );
                 vlc_va_Delete( p_sys->p_va );
@@ -1169,13 +1183,13 @@ static enum PixelFormat ffmpeg_GetFormat( AVCodecContext *p_codec,
              * even if a new pixel format is renegociated
              */
             p_sys->b_direct_rendering = false;
-            p_sys->p_context->draw_horiz_band = NULL;
+            p_context->draw_horiz_band = NULL;
             return pi_fmt[i];
         }
     }
 
     /* Fallback to default behaviour */
-    return avcodec_default_get_format( p_codec, pi_fmt );
+    return avcodec_default_get_format( p_context, pi_fmt );
 }
 #endif