]> git.sesse.net Git - x264/commitdiff
Add TFF/BFF detection to all demuxers
authorSteven Walters <kemuri9@gmail.com>
Wed, 7 Apr 2010 02:08:21 +0000 (22:08 -0400)
committerFiona Glaser <fiona@x264.com>
Wed, 7 Apr 2010 02:15:46 +0000 (19:15 -0700)
Fix interlaced Avisynth input, automatically weave field-based input.

input/avs.c
input/ffms.c
input/input.h
input/lavf.c
x264.c

index 9e20665bbc97b14d63697311890f251cd2264fd4..59634f4fcad7ef41a406e2ed5d2f600796f761b8 100644 (file)
@@ -117,6 +117,15 @@ static void avs_build_filter_sequence( char *filename_ext, const char *filter[AV
         filter[i++] = all_purpose[j];
 }
 
+static AVS_Value update_clip( avs_hnd_t *h, const AVS_VideoInfo **vi, AVS_Value res, AVS_Value release )
+{
+    h->func.avs_release_clip( h->clip );
+    h->clip = h->func.avs_take_clip( res, h->env );
+    h->func.avs_release_value( release );
+    *vi = h->func.avs_get_video_info( h->clip );
+    return res;
+}
+
 static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
 {
     FILE *fh = fopen( psz_filename, "r" );
@@ -213,17 +222,36 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
         fprintf( stderr, "avs [error]: `%s' has no video data\n", psz_filename );
         return -1;
     }
+    /* if the clip is made of fields instead of frames, call weave to make them frames */
+    if( avs_is_field_based( vi ) )
+    {
+        fprintf( stderr, "avs [warning]: detected fieldbased (separated) input, weaving to frames\n" );
+        AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
+        if( avs_is_error( tmp ) )
+        {
+            fprintf( stderr, "avs [error]: couldn't weave fields into frames\n" );
+            return -1;
+        }
+        res = update_clip( h, &vi, tmp, res );
+    }
     if( vi->width&1 || vi->height&1 )
     {
         fprintf( stderr, "avs [error]: input clip width or height not divisible by 2 (%dx%d)\n",
                  vi->width, vi->height );
         return -1;
     }
+    /* bff/tff flags in avisynth are not technically mutually exclusive, which can lead to both being set.
+     * avisynth's own functions enact mutual exclusion, but source filters are not guaranteed to do this. */
+    int tff = avs_is_tff( vi );
+    if( avs_is_bff( vi ) ^ tff )
+    {
+        info->interlaced = 1;
+        info->tff = !!tff;
+    }
     /* always call ConvertToYV12 to convert non YV12 planar colorspaces to YV12 when user's AVS supports them,
        as all planar colorspaces are flagged as YV12. If it is already YV12 in this case, the call does nothing */
     if( !avs_is_yv12( vi ) || avs_version >= AVS_INTERFACE_OTHER_PLANAR )
     {
-        h->func.avs_release_clip( h->clip );
         fprintf( stderr, "avs %s\n", !avs_is_yv12( vi ) ? "[warning]: converting input clip to YV12"
                : "[info]: avisynth 2.6+ detected, forcing conversion to YV12" );
         const char *arg_name[2] = { NULL, "interlaced" };
@@ -234,9 +262,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
             fprintf( stderr, "avs [error]: couldn't convert input clip to YV12\n" );
             return -1;
         }
-        h->clip = h->func.avs_take_clip( res2, h->env );
-        h->func.avs_release_value( res2 );
-        vi = h->func.avs_get_video_info( h->clip );
+        res = update_clip( h, &vi, res2, res );
     }
     h->func.avs_release_value( res );
 
index 14962c74f57f5d944bb53d5f43bd471698067fe1..01a1257815b6bb2118a8d2cd9cfcbe918cc4196e 100644 (file)
@@ -133,6 +133,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
     h->init_height = h->cur_height = info->height = frame->EncodedHeight;
     h->cur_pix_fmt = frame->EncodedPixelFormat;
     info->interlaced = frame->InterlacedFrame;
+    info->tff        = frame->TopFieldFirst;
 
     if( h->cur_pix_fmt != PIX_FMT_YUV420P )
         fprintf( stderr, "ffms [warning]: converting from %s to YV12\n",
index 7be6fcf01ff1d5d31e3bb6a722f7605b1aa83c77..b6cd218dbc9a469bdf2ad662ac745163fc425fc5 100644 (file)
@@ -44,6 +44,7 @@ typedef struct
     int interlaced;
     int sar_width;
     int sar_height;
+    int tff;
     int timebase_num;
     int timebase_den;
     int vfr;
index 6ecc6b02a0ef43e6b4601c7f06d8a8d60855306e..4b0375fae5d41be2bdaec64f4fe1dcab0e818373 100644 (file)
@@ -124,7 +124,10 @@ static int read_frame_internal( x264_picture_t *p_pic, lavf_hnd_t *h, int i_fram
     sws_scale( h->scaler, frame->data, frame->linesize, 0, c->height, p_pic->img.plane, p_pic->img.i_stride );
 
     if( info )
+    {
         info->interlaced = frame->interlaced_frame;
+        info->tff = frame->top_field_first;
+    }
 
     if( h->vfr_input )
     {
diff --git a/x264.c b/x264.c
index 08fd3133cb96df18f41bbff5da656ee7b3853312..76ff85dbbcf3b700ed9d79afad225b2bf0596d94 100644 (file)
--- a/x264.c
+++ b/x264.c
@@ -1134,6 +1134,7 @@ generic_option:
     info.interlaced = param->b_interlaced;
     info.sar_width  = param->vui.i_sar_width;
     info.sar_height = param->vui.i_sar_height;
+    info.tff        = param->b_tff;
     info.vfr        = param->b_vfr_input;
 
     if( select_input( demuxer, demuxername, input_filename, &opt->hin, &info, &input_opt ) )
@@ -1180,9 +1181,11 @@ generic_option:
     param->i_width     = info.width;
     if( !b_user_interlaced && info.interlaced )
     {
-        fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling interlaced mode.\n"
-                         "                If you want otherwise, use --no-interlaced\n" );
+        fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling %cff interlaced mode.\n"
+                         "                If you want otherwise, use --no-interlaced or --%cff\n",
+                 info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
         param->b_interlaced = 1;
+        param->b_tff = !!info.tff;
     }
     if( !b_user_fps )
     {