Share Pastebin
Guest
Public paste!

Untitled

By: a guest | Feb 9th, 2010 | Syntax: None | Size: 18.06 KB | Hits: 25 | Expires: Never
Copy text to clipboard
  1. diff --git a/common/common.h b/common/common.h
  2. index 950f48f..984008a 100644
  3. --- a/common/common.h
  4. +++ b/common/common.h
  5.  -431,7 +431,7 @@ struct x264_t
  6.          int     i_bframe_delay;
  7.          int64_t i_bframe_delay_time;
  8.          int64_t i_init_delta;
  9. -        int64_t i_prev_dts[2];
  10. +        int64_t i_prev_reordered_pts[2];
  11.          int b_have_lowres;  /* Whether 1/2 resolution luma planes are being used */
  12.          int b_have_sub8x8_esa;
  13.      } frames;
  14. diff --git a/encoder/encoder.c b/encoder/encoder.c
  15. index d873cd0..3b14e51 100644
  16. --- a/encoder/encoder.c
  17. +++ b/encoder/encoder.c
  18.  -868,10 +868,12 @@ x264_t *x264_encoder_open( x264_param_t *param )
  19.          /* h->i_dts_compress_multiplier == h->frames.i_bframe_delay + 1 */
  20.          h->i_dts_compress_multiplier = h->param.i_bframe ? (h->param.i_bframe_pyramid ? 3 : 2) : 1;
  21.          if( h->i_dts_compress_multiplier != 1 )
  22. +        {
  23.              x264_log( h, X264_LOG_DEBUG, "DTS compresion changed timebase: %d/%d -> %d/%d\n",
  24.                        h->param.i_timebase_num, h->param.i_timebase_den,
  25.                        h->param.i_timebase_num, h->param.i_timebase_den * h->i_dts_compress_multiplier );
  26. -        h->param.i_timebase_den *= h->i_dts_compress_multiplier;
  27. +            h->param.i_timebase_den *= h->i_dts_compress_multiplier;
  28. +        }
  29.      }
  30.      else
  31.          h->i_dts_compress_multiplier = 1;
  32.  -2404,7 +2406,7 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
  33.      pic_out->i_pts = h->fenc->i_pts *= h->i_dts_compress_multiplier;
  34.      if( h->frames.i_bframe_delay )
  35.      {
  36. -        int64_t *i_prev_dts = thread_current->frames.i_prev_dts;
  37. +        int64_t *prev_reordered_pts = thread_current->frames.i_prev_reordered_pts;
  38.          if( h->i_frame <= h->frames.i_bframe_delay )
  39.          {
  40.              if( h->i_dts_compress_multiplier == 1 )
  41.  -2418,8 +2420,8 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
  42.              }
  43.          }
  44.          else
  45. -            pic_out->i_dts = i_prev_dts[ (h->i_frame - h->frames.i_bframe_delay) % h->frames.i_bframe_delay ];
  46. -        i_prev_dts[ h->i_frame % h->frames.i_bframe_delay ] = h->fenc->i_reordered_pts * h->i_dts_compress_multiplier;
  47. +            pic_out->i_dts = prev_reordered_pts[ (h->i_frame - h->frames.i_bframe_delay) % h->frames.i_bframe_delay ];
  48. +        prev_reordered_pts[ h->i_frame % h->frames.i_bframe_delay ] = h->fenc->i_reordered_pts * h->i_dts_compress_multiplier;
  49.      }
  50.      else
  51.          pic_out->i_dts = h->fenc->i_reordered_pts;
  52. diff --git a/x264.c b/x264.c
  53. index 58bc1f4..0aab46c 100644
  54. --- a/x264.c
  55. +++ b/x264.c
  56.  -57,6 +57,8 @@ typedef struct {
  57.      hnd_t hin;
  58.      hnd_t hout;
  59.      FILE *qpfile;
  60. +    FILE *in_tcfile;
  61. +    FILE *out_tcfile;
  62.  } cli_opt_t;
  63.  
  64.  /* i/o file operation function pointer structs */
  65.  -513,6 +515,9 @@ static void Help( x264_param_t *defaults, int longhelp )
  66.      H2( "      --sps-id <integer>      Set SPS and PPS id numbers [%d]\n", defaults->i_sps_id );
  67.      H2( "      --aud                   Use access unit delimiters\n" );
  68.      H2( "      --force-cfr             Force constant framerate timestamp generation\n" );
  69. +    H2( "      --in-tcfile <string>    Force timestamp generation with timecode format file\n" );
  70. +    H2( "      --out-tcfile <string>   Output timecode format v2 file from input source\n" );
  71. +    H2( "      --timebase <den|num/den> Specify timebase for precise timestamp generation\n" );
  72.      H0( "\n" );
  73.  }
  74.  
  75.  -534,6 +539,9 @@ static void Help( x264_param_t *defaults, int longhelp )
  76.  #define OPT_DEMUXER 271
  77.  #define OPT_INDEX 272
  78.  #define OPT_INTERLACED 273
  79. +#define OPT_IN_TCFILE 274
  80. +#define OPT_OUT_TCFILE 275
  81. +#define OPT_TIMEBASE 276
  82.  
  83.  static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
  84.  static struct option long_options[] =
  85.  -668,6 +676,9 @@ static struct option long_options[] =
  86.      { "colormatrix", required_argument, NULL, 0 },
  87.      { "chromaloc",   required_argument, NULL, 0 },
  88.      { "force-cfr",         no_argument, NULL, 0 },
  89. +    { "in-tcfile",   required_argument, NULL, OPT_IN_TCFILE },
  90. +    { "out-tcfile",  required_argument, NULL, OPT_OUT_TCFILE },
  91. +    { "timebase",    required_argument, NULL, OPT_TIMEBASE },
  92.      {0, 0, 0, 0}
  93.  };
  94.  
  95.  -808,6 +819,7 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  96.      int b_user_ref = 0;
  97.      int b_user_fps = 0;
  98.      int b_user_interlaced = 0;
  99. +    int b_user_timebase = 0;
  100.      int i;
  101.      cli_input_opt_t input_opt;
  102.  
  103.  -1117,6 +1129,34 @@ psy_failure:
  104.                      return -1;
  105.                  }
  106.                  break;
  107. +            case OPT_IN_TCFILE:
  108. +                opt->in_tcfile = fopen( optarg, "rb" );
  109. +                if( !opt->in_tcfile )
  110. +                {
  111. +                    fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
  112. +                    return -1;
  113. +                }
  114. +                else if( !x264_is_regular_file( opt->in_tcfile ) )
  115. +                {
  116. +                    fprintf( stderr, "x264 [error]: input tcfile incompatible with non-regular file `%s'\n", optarg );
  117. +                    fclose( opt->in_tcfile );
  118. +                    return -1;
  119. +                }
  120. +                break;
  121. +            case OPT_OUT_TCFILE:
  122. +                opt->out_tcfile = fopen( optarg, "wb" );
  123. +                if( !opt->out_tcfile )
  124. +                {
  125. +                    fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
  126. +                    return -1;
  127. +                }
  128. +                else if( !x264_is_regular_file( opt->out_tcfile ) )
  129. +                {
  130. +                    fprintf( stderr, "x264 [error]: output tcfile incompatible with non-regular file `%s'\n", optarg );
  131. +                    fclose( opt->out_tcfile );
  132. +                    return -1;
  133. +                }
  134. +                break;
  135.              case OPT_THREAD_INPUT:
  136.                  b_thread_input = 1;
  137.                  break;
  138.  -1159,6 +1199,16 @@ psy_failure:
  139.              case OPT_INTERLACED:
  140.                  b_user_interlaced = 1;
  141.                  goto generic_option;
  142. +            case OPT_TIMEBASE:
  143. +                b_user_timebase = 1;
  144. +                if( sscanf( optarg, "%d/%d", &param->i_timebase_num, &param->i_timebase_den ) == 2 )
  145. +                    ;
  146. +                else
  147. +                {
  148. +                    param->i_timebase_num = 0;
  149. +                    param->i_timebase_den = atoi( optarg );
  150. +                }
  151. +                break;
  152.              default:
  153.  generic_option:
  154.              {
  155.  -1290,6 +1340,20 @@ generic_option:
  156.      param->i_height    = info.height;
  157.      param->b_vfr_input = info.vfr;
  158.      param->i_width     = info.width;
  159. +
  160. +    /* Input of timecode file is always as VFR input. */
  161. +    if( opt->in_tcfile )
  162. +    {
  163. +        if( info.interlaced )
  164. +        {
  165. +            fprintf( stderr, "x264 [warning]: input appears to be interlaced, closing input timecode format file.\n" );
  166. +            fclose( opt->in_tcfile );
  167. +            opt->in_tcfile = NULL;
  168. +        }
  169. +        else
  170. +            param->b_vfr_input = 1;
  171. +    }
  172. +
  173.      if( !b_user_interlaced && info.interlaced )
  174.      {
  175.          fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling interlaced mode.\n"
  176.  -1301,15 +1365,44 @@ generic_option:
  177.          param->i_fps_num = info.fps_num;
  178.          param->i_fps_den = info.fps_den;
  179.      }
  180. -    if( param->b_vfr_input )
  181. +    if( !b_user_timebase )
  182.      {
  183. -        param->i_timebase_num = info.timebase_num;
  184. -        param->i_timebase_den = info.timebase_den;
  185. +        if( opt->in_tcfile )
  186. +        {
  187. +            param->i_timebase_num = param->i_fps_den;
  188. +            param->i_timebase_den = 0;
  189. +        }
  190. +        else if( param->b_vfr_input )
  191. +        {
  192. +            param->i_timebase_num = info.timebase_num;
  193. +            param->i_timebase_den = info.timebase_den;
  194. +        }
  195. +        else
  196. +        {
  197. +            param->i_timebase_num = param->i_fps_den;
  198. +            param->i_timebase_den = param->i_fps_num;
  199. +        }
  200.      }
  201.      else
  202.      {
  203. -        param->i_timebase_den = param->i_fps_num;
  204. -        param->i_timebase_num = param->i_fps_den;
  205. +        if( !opt->in_tcfile )
  206. +        {
  207. +            fprintf( stderr, "x264 [warning]: specifying timebase is ignored in the VFR input without timecode format file" );
  208. +            param->i_timebase_num = info.timebase_num;
  209. +            param->i_timebase_den = info.timebase_den;
  210. +        }
  211. +        else
  212. +        {
  213. +            if( !param->i_timebase_num )
  214. +                param->i_timebase_num = param->i_fps_den;
  215. +            int old_timebase_num = param->i_timebase_num;
  216. +            int old_timebase_den = param->i_timebase_den;
  217. +            x264_reduce_fraction( &param->i_timebase_num, &param->i_timebase_den );
  218. +            if( old_timebase_num != param->i_timebase_num )
  219. +                fprintf( stderr, "x264 [info]: reduce timebase you specified %d/%d -> %d/%d\n",
  220. +                        old_timebase_num, old_timebase_den,
  221. +                        param->i_timebase_num, param->i_timebase_den );
  222. +        }
  223.      }
  224.      if( !param->vui.i_sar_width || !param->vui.i_sar_height )
  225.      {
  226.  -1391,6 +1484,166 @@ static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
  227.      }
  228.  }
  229.  
  230. +static inline int lcm( int a, int b )
  231. +{
  232. +    return ( a / gcd( a, b ) ) * b;
  233. +}
  234. +
  235. +static int parse_tcfile( x264_param_t *param, cli_opt_t *opt, int64_t *pts )
  236. +{
  237. +    int ret, tcfv, num;
  238. +    int i_frame_total = param->i_frame_total;
  239. +    double *fps;
  240. +    double *timecode;
  241. +
  242. +    if( i_frame_total < 2 )
  243. +    {
  244. +        fprintf( stderr, "x264 [error]: input tcfile requires 2 frames at least\n" );
  245. +        return -1;
  246. +    }
  247. +
  248. +    ret = fscanf( opt->in_tcfile, "# timecode format v%d\n", &tcfv );
  249. +    if( ret != 1 || (tcfv != 1 && tcfv != 2) )
  250. +    {
  251. +        fprintf( stderr, "x264 [error]: not supported timecode format\n" );
  252. +        return -1;
  253. +    }
  254. +
  255. +    CHECKED_MALLOC( timecode, sizeof(double) * i_frame_total );
  256. +    if( !param->i_timebase_den )
  257. +        CHECKED_MALLOC( fps, sizeof(double) * i_frame_total );
  258. +
  259. +    if( tcfv == 1 )
  260. +    {
  261. +        char info[128];
  262. +        double assume_fps, seq_fps;
  263. +        int start, end;
  264. +        int prev_start = -1, prev_end = -1;
  265. +
  266. +        fgets( info, sizeof(info), opt->in_tcfile );
  267. +        if( sscanf( info, "assume %lf", &assume_fps ) != 1 && sscanf( info, "Assume %lf", &assume_fps ) != 1 )
  268. +        {
  269. +            fprintf( stderr, "x264 [error]: not found assumed fps\n" );
  270. +            goto fail;
  271. +        }
  272. +        if( assume_fps <= 0 )
  273. +        {
  274. +            fprintf( stderr, "x264 [error]: invalid assumed fps %.6f\n", assume_fps );
  275. +            goto fail;
  276. +        }
  277. +
  278. +        timecode[0] = 0;
  279. +        for( num = 0; num < i_frame_total - 1; )
  280. +        {
  281. +            ret = fscanf( opt->in_tcfile, "%d,%d,%lf\n", &start, &end, &seq_fps );
  282. +            if( ret != 3 )
  283. +            {
  284. +                if( ret != EOF )
  285. +                {
  286. +                    fprintf( stderr, "x264 [error]: invalid input tcfile\n" );
  287. +                    goto fail;
  288. +                }
  289. +                start = end = i_frame_total - 1;
  290. +            }
  291. +            else
  292. +            {
  293. +                if( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0 )
  294. +                {
  295. +                    fprintf( stderr, "x264 [error]: invalid input tcfile for frame %d\n", num );
  296. +                    goto fail;
  297. +                }
  298. +                prev_start = start;
  299. +                prev_end = end;
  300. +            }
  301. +
  302. +            for( ; num < start && num < i_frame_total - 1; num++ )
  303. +            {
  304. +                timecode[num + 1] = timecode[num] + 1 / assume_fps;
  305. +                if( !param->i_timebase_den )
  306. +                    fps[num] = assume_fps;
  307. +            }
  308. +            for( num = start; num <= end && num < i_frame_total - 1; num++ )
  309. +            {
  310. +                timecode[num + 1] = timecode[num] + 1 / seq_fps;
  311. +                if( !param->i_timebase_den )
  312. +                    fps[num] = seq_fps;
  313. +            }
  314. +        }
  315. +    }
  316. +    else    /* tcfv == 2 */
  317. +    {
  318. +        ret = fscanf( opt->in_tcfile, "%lf\n", &timecode[0] );
  319. +        if( ret != 1 || timecode[0] != 0 )
  320. +        {
  321. +            fprintf( stderr, "x264 [error]: invalid input tcfile for frame 0\n" );
  322. +            goto fail;
  323. +        }
  324. +        for( num = 1; num < i_frame_total; num++ )
  325. +        {
  326. +            ret = fscanf( opt->in_tcfile, "%lf\n", &timecode[num] );
  327. +            if( ret != 1 || timecode[num] <= timecode[num - 1] )
  328. +            {
  329. +                fprintf( stderr, "x264 [error]: invalid input tcfile for frame %d\n", num );
  330. +                goto fail;
  331. +            }
  332. +            timecode[num] /= 1000;
  333. +            if( !param->i_timebase_den )
  334. +                fps[num - 1] = 1 / (timecode[num] - timecode[num - 1]);
  335. +        }
  336. +    }
  337. +
  338. +    if( param->i_timebase_den )
  339. +    {
  340. +        pts[0] = 0;
  341. +        for( num = 1; num < i_frame_total; num++ )
  342. +        {
  343. +            pts[num] = (int64_t)( timecode[num] * ((double)param->i_timebase_den / param->i_timebase_num) + 0.5 );
  344. +            if( pts[num] <= pts[num - 1] )
  345. +            {
  346. +                fprintf( stderr, "x264 [error]: invalid timebase or timecode for frame %d\n", num );
  347. +                goto fail;
  348. +            }
  349. +        }
  350. +
  351. +        x264_free( timecode );
  352. +        return 0;
  353. +    }
  354. +
  355. +    /* Generate timebase denomitor if param->timebase_den is equal to 0. */
  356. +    for( num = 0; num < i_frame_total - 1; num++ )
  357. +    {
  358. +        int timebase_den;
  359. +        int i = 1;
  360. +        while( 1 )
  361. +        {
  362. +            timebase_den = (int)( fps[num] * i * param->i_timebase_num + 0.5 );
  363. +            if( timebase_den <= 0 )
  364. +            {
  365. +                fprintf( stderr, "x264 [error]: auto timebase generation is failed.\n"
  366. +                                 "              Please specify timebase manually.\n" );
  367. +                goto fail;
  368. +            }
  369. +            if( fabs( fps[num] * i * param->i_timebase_num - (double)timebase_den ) < 0.05 )
  370. +                break;
  371. +            i++;
  372. +        }
  373. +        param->i_timebase_den = ( param->i_timebase_den ) ? lcm( param->i_timebase_den, timebase_den ) : timebase_den;
  374. +    }
  375. +    fprintf( stderr, "x264 [info]: auto timebase generation %d/%d\n", param->i_timebase_num, param->i_timebase_den );
  376. +
  377. +    for( num = 0; num < i_frame_total; num++ )
  378. +        pts[num] = (int64_t)( timecode[num] * ((double)param->i_timebase_den / param->i_timebase_num) + 0.5 );
  379. +
  380. +    x264_free( timecode );
  381. +    x264_free( fps );
  382. +    return 0;
  383. +
  384. +fail:
  385. +    x264_free( timecode );
  386. +    x264_free( fps );
  387. +    return -1;
  388. +}
  389. +
  390.  /*****************************************************************************
  391.   * Encode:
  392.   *****************************************************************************/
  393.  -1451,6 +1704,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  394.      int64_t i_file = 0;
  395.      int     i_frame_size;
  396.      int     i_update_interval;
  397. +    int64_t *pts = NULL;
  398.      int64_t last_pts = 0;
  399.  #   define  MAX_PTS_WARNING 3 /* arbitrary */
  400.      int     pts_warning_cnt = 0;
  401.  -1458,7 +1712,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  402.      int64_t second_largest_pts = -1;
  403.      int64_t ticks_per_frame;
  404.      double  duration;
  405. -    int     prev_timebase_den = param->i_timebase_den / gcd( param->i_timebase_num, param->i_timebase_den );
  406. +    int     prev_timebase_den;
  407.      int     dts_compress_multiplier;
  408.  
  409.      opt->b_progress &= param->i_log_level < X264_LOG_DEBUG;
  410.  -1470,6 +1724,20 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  411.      param->i_frame_total = i_frame_total;
  412.      i_update_interval = i_frame_total ? x264_clip3( i_frame_total / 1000, 1, 10 ) : 10;
  413.  
  414. +    if( opt->in_tcfile )
  415. +    {
  416. +        pts = x264_malloc( sizeof(int64_t) * i_frame_total );
  417. +        if( !pts || parse_tcfile( param, opt, pts ) < 0 )
  418. +        {
  419. +            x264_free( pts );
  420. +            fclose( opt->in_tcfile );
  421. +            opt->in_tcfile = NULL;
  422. +            return -1;
  423. +        }
  424. +    }
  425. +
  426. +    prev_timebase_den = param->i_timebase_den / gcd( param->i_timebase_num, param->i_timebase_den );
  427. +
  428.      if( ( h = x264_encoder_open( param ) ) == NULL )
  429.      {
  430.          fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
  431.  -1521,13 +1789,18 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  432.              return -1;
  433.      }
  434.  
  435. +    if( opt->out_tcfile )
  436. +        fprintf( opt->out_tcfile, "# timecode format v2\n" );
  437. +
  438.      /* Encode frames */
  439.      for( i_frame = 0, i_frame_output = 0; b_ctrl_c == 0 && (i_frame < i_frame_total || i_frame_total == 0); )
  440.      {
  441.          if( input.read_frame( &pic, opt->hin, i_frame + opt->i_seek ) )
  442.              break;
  443.  
  444. -        if( !param->b_vfr_input )
  445. +        if( opt->in_tcfile )
  446. +            pic.i_pts = pts[i_frame];
  447. +        else if( !param->b_vfr_input )
  448.              pic.i_pts = i_frame;
  449.          if( pic.i_pts <= largest_pts )
  450.          {
  451.  -1544,6 +1817,9 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  452.          }
  453.          second_largest_pts = largest_pts;
  454.          largest_pts = pic.i_pts;
  455. +        if( opt->out_tcfile )
  456. +            fprintf( opt->out_tcfile, "%.6f\n",
  457. +                     pic.i_pts * dts_compress_multiplier * ((double)param->i_timebase_num / param->i_timebase_den) * 1000 );
  458.  
  459.          if( opt->qpfile )
  460.              parse_qpfile( opt, &pic, i_frame + opt->i_seek );
  461.  -1603,6 +1879,18 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  462.      if( b_ctrl_c )
  463.          fprintf( stderr, "aborted at input frame %d, output frame %d\n", opt->i_seek + i_frame, i_frame_output );
  464.  
  465. +    if( opt->in_tcfile )
  466. +    {
  467. +        x264_free( pts );
  468. +        fclose( opt->in_tcfile );
  469. +        opt->in_tcfile = NULL;
  470. +    }
  471. +    if( opt->out_tcfile )
  472. +    {
  473. +        fclose( opt->out_tcfile );
  474. +        opt->out_tcfile = NULL;
  475. +    }
  476. +
  477.      input.close_file( opt->hin );
  478.      output.close_file( opt->hout, largest_pts, second_largest_pts );