timecode.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*****************************************************************************
  2. * timecode.c: timecode file input
  3. *****************************************************************************
  4. * Copyright (C) 2010-2018 x264 project
  5. *
  6. * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation; either version 2 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
  21. *
  22. * This program is also available under a commercial proprietary license.
  23. * For more information, contact us at licensing@x264.com.
  24. *****************************************************************************/
  25. #include "input.h"
  26. #define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "timecode", __VA_ARGS__ )
  27. typedef struct
  28. {
  29. cli_input_t input;
  30. hnd_t p_handle;
  31. int auto_timebase_num;
  32. int auto_timebase_den;
  33. uint64_t timebase_num;
  34. uint64_t timebase_den;
  35. int stored_pts_num;
  36. int64_t *pts;
  37. double assume_fps;
  38. double last_timecode;
  39. } timecode_hnd_t;
  40. static inline double sigexp10( double value, double *exponent )
  41. {
  42. /* This function separates significand and exp10 from double floating point. */
  43. *exponent = pow( 10, floor( log10( value ) ) );
  44. return value / *exponent;
  45. }
  46. #define DOUBLE_EPSILON 5e-6
  47. #define MKV_TIMEBASE_DEN 1000000000
  48. static double correct_fps( double fps, timecode_hnd_t *h )
  49. {
  50. int i = 1;
  51. uint64_t fps_num, fps_den;
  52. double exponent;
  53. double fps_sig = sigexp10( fps, &exponent );
  54. while( 1 )
  55. {
  56. fps_den = i * h->timebase_num;
  57. fps_num = round( fps_den * fps_sig ) * exponent;
  58. FAIL_IF_ERROR( fps_num > UINT32_MAX, "tcfile fps correction failed.\n"
  59. " Specify an appropriate timebase manually or remake tcfile.\n" );
  60. if( fabs( ((double)fps_num / fps_den) / exponent - fps_sig ) < DOUBLE_EPSILON )
  61. break;
  62. ++i;
  63. }
  64. if( h->auto_timebase_den )
  65. {
  66. h->timebase_den = h->timebase_den ? lcm( h->timebase_den, fps_num ) : fps_num;
  67. if( h->timebase_den > UINT32_MAX )
  68. h->auto_timebase_den = 0;
  69. }
  70. return (double)fps_num / fps_den;
  71. }
  72. static int try_mkv_timebase_den( double *fpss, timecode_hnd_t *h, int loop_num )
  73. {
  74. h->timebase_num = 0;
  75. h->timebase_den = MKV_TIMEBASE_DEN;
  76. for( int num = 0; num < loop_num; num++ )
  77. {
  78. uint64_t fps_den;
  79. double exponent;
  80. double fps_sig = sigexp10( fpss[num], &exponent );
  81. fps_den = round( MKV_TIMEBASE_DEN / fps_sig ) / exponent;
  82. h->timebase_num = fps_den && h->timebase_num ? gcd( h->timebase_num, fps_den ) : fps_den;
  83. FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || !h->timebase_num, "automatic timebase generation failed.\n"
  84. " Specify timebase manually.\n" );
  85. }
  86. return 0;
  87. }
  88. static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info )
  89. {
  90. char buff[256];
  91. int ret, tcfv, num, seq_num, timecodes_num;
  92. double *timecodes = NULL;
  93. double *fpss = NULL;
  94. ret = fscanf( tcfile_in, "# timecode format v%d", &tcfv );
  95. FAIL_IF_ERROR( ret != 1 || (tcfv != 1 && tcfv != 2), "unsupported timecode format\n" );
  96. #define NO_TIMECODE_LINE (buff[0] == '#' || buff[0] == '\n' || buff[0] == '\r')
  97. if( tcfv == 1 )
  98. {
  99. uint64_t file_pos;
  100. double assume_fps, seq_fps;
  101. int start, end = -1;
  102. int prev_start = -1, prev_end = -1;
  103. h->assume_fps = 0;
  104. for( num = 2; fgets( buff, sizeof(buff), tcfile_in ) != NULL; num++ )
  105. {
  106. if( NO_TIMECODE_LINE )
  107. continue;
  108. FAIL_IF_ERROR( sscanf( buff, "assume %lf", &h->assume_fps ) != 1 && sscanf( buff, "Assume %lf", &h->assume_fps ) != 1,
  109. "tcfile parsing error: assumed fps not found\n" );
  110. break;
  111. }
  112. FAIL_IF_ERROR( h->assume_fps <= 0, "invalid assumed fps %.6f\n", h->assume_fps );
  113. file_pos = ftell( tcfile_in );
  114. h->stored_pts_num = 0;
  115. for( seq_num = 0; fgets( buff, sizeof(buff), tcfile_in ) != NULL; num++ )
  116. {
  117. if( NO_TIMECODE_LINE )
  118. {
  119. if( sscanf( buff, "# TDecimate Mode 3: Last Frame = %d", &end ) == 1 )
  120. h->stored_pts_num = end + 1;
  121. continue;
  122. }
  123. ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
  124. FAIL_IF_ERROR( ret != 3 && ret != EOF, "invalid input tcfile\n" );
  125. FAIL_IF_ERROR( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0,
  126. "invalid input tcfile at line %d: %s\n", num, buff );
  127. prev_start = start;
  128. prev_end = end;
  129. if( h->auto_timebase_den || h->auto_timebase_num )
  130. ++seq_num;
  131. }
  132. if( !h->stored_pts_num )
  133. h->stored_pts_num = end + 2;
  134. timecodes_num = h->stored_pts_num;
  135. fseek( tcfile_in, file_pos, SEEK_SET );
  136. timecodes = malloc( timecodes_num * sizeof(double) );
  137. if( !timecodes )
  138. return -1;
  139. if( h->auto_timebase_den || h->auto_timebase_num )
  140. {
  141. fpss = malloc( (seq_num + 1) * sizeof(double) );
  142. if( !fpss )
  143. goto fail;
  144. }
  145. assume_fps = correct_fps( h->assume_fps, h );
  146. if( assume_fps < 0 )
  147. goto fail;
  148. timecodes[0] = 0;
  149. for( num = seq_num = 0; num < timecodes_num - 1 && fgets( buff, sizeof(buff), tcfile_in ) != NULL; )
  150. {
  151. if( NO_TIMECODE_LINE )
  152. continue;
  153. ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
  154. if( ret != 3 )
  155. start = end = timecodes_num - 1;
  156. for( ; num < start && num < timecodes_num - 1; num++ )
  157. timecodes[num + 1] = timecodes[num] + 1 / assume_fps;
  158. if( num < timecodes_num - 1 )
  159. {
  160. if( h->auto_timebase_den || h->auto_timebase_num )
  161. fpss[seq_num++] = seq_fps;
  162. seq_fps = correct_fps( seq_fps, h );
  163. if( seq_fps < 0 )
  164. goto fail;
  165. for( num = start; num <= end && num < timecodes_num - 1; num++ )
  166. timecodes[num + 1] = timecodes[num] + 1 / seq_fps;
  167. }
  168. }
  169. for( ; num < timecodes_num - 1; num++ )
  170. timecodes[num + 1] = timecodes[num] + 1 / assume_fps;
  171. if( h->auto_timebase_den || h->auto_timebase_num )
  172. fpss[seq_num] = h->assume_fps;
  173. if( h->auto_timebase_num && !h->auto_timebase_den )
  174. {
  175. double exponent;
  176. double assume_fps_sig, seq_fps_sig;
  177. if( try_mkv_timebase_den( fpss, h, seq_num + 1 ) < 0 )
  178. goto fail;
  179. fseek( tcfile_in, file_pos, SEEK_SET );
  180. assume_fps_sig = sigexp10( h->assume_fps, &exponent );
  181. assume_fps = MKV_TIMEBASE_DEN / ( round( MKV_TIMEBASE_DEN / assume_fps_sig ) / exponent );
  182. for( num = 0; num < timecodes_num - 1 && fgets( buff, sizeof(buff), tcfile_in ) != NULL; )
  183. {
  184. if( NO_TIMECODE_LINE )
  185. continue;
  186. ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
  187. if( ret != 3 )
  188. start = end = timecodes_num - 1;
  189. seq_fps_sig = sigexp10( seq_fps, &exponent );
  190. seq_fps = MKV_TIMEBASE_DEN / ( round( MKV_TIMEBASE_DEN / seq_fps_sig ) / exponent );
  191. for( ; num < start && num < timecodes_num - 1; num++ )
  192. timecodes[num + 1] = timecodes[num] + 1 / assume_fps;
  193. for( num = start; num <= end && num < timecodes_num - 1; num++ )
  194. timecodes[num + 1] = timecodes[num] + 1 / seq_fps;
  195. }
  196. for( ; num < timecodes_num - 1; num++ )
  197. timecodes[num + 1] = timecodes[num] + 1 / assume_fps;
  198. }
  199. if( fpss )
  200. {
  201. free( fpss );
  202. fpss = NULL;
  203. }
  204. h->assume_fps = assume_fps;
  205. h->last_timecode = timecodes[timecodes_num - 1];
  206. }
  207. else /* tcfv == 2 */
  208. {
  209. uint64_t file_pos = ftell( tcfile_in );
  210. h->stored_pts_num = 0;
  211. while( fgets( buff, sizeof(buff), tcfile_in ) != NULL )
  212. {
  213. if( NO_TIMECODE_LINE )
  214. {
  215. if( !h->stored_pts_num )
  216. file_pos = ftell( tcfile_in );
  217. continue;
  218. }
  219. h->stored_pts_num++;
  220. }
  221. timecodes_num = h->stored_pts_num;
  222. FAIL_IF_ERROR( !timecodes_num, "input tcfile doesn't have any timecodes!\n" );
  223. fseek( tcfile_in, file_pos, SEEK_SET );
  224. timecodes = malloc( timecodes_num * sizeof(double) );
  225. if( !timecodes )
  226. return -1;
  227. num = 0;
  228. if( fgets( buff, sizeof(buff), tcfile_in ) != NULL )
  229. {
  230. ret = sscanf( buff, "%lf", &timecodes[0] );
  231. timecodes[0] *= 1e-3; /* Timecode format v2 is expressed in milliseconds. */
  232. FAIL_IF_ERROR( ret != 1, "invalid input tcfile for frame 0\n" );
  233. for( num = 1; num < timecodes_num && fgets( buff, sizeof(buff), tcfile_in ) != NULL; )
  234. {
  235. if( NO_TIMECODE_LINE )
  236. continue;
  237. ret = sscanf( buff, "%lf", &timecodes[num] );
  238. timecodes[num] *= 1e-3; /* Timecode format v2 is expressed in milliseconds. */
  239. FAIL_IF_ERROR( ret != 1 || timecodes[num] <= timecodes[num - 1],
  240. "invalid input tcfile for frame %d\n", num );
  241. ++num;
  242. }
  243. }
  244. FAIL_IF_ERROR( num < timecodes_num, "failed to read input tcfile for frame %d", num );
  245. if( timecodes_num == 1 )
  246. h->timebase_den = info->fps_num;
  247. else if( h->auto_timebase_den )
  248. {
  249. fpss = malloc( (timecodes_num - 1) * sizeof(double) );
  250. if( !fpss )
  251. goto fail;
  252. for( num = 0; num < timecodes_num - 1; num++ )
  253. {
  254. fpss[num] = 1 / (timecodes[num + 1] - timecodes[num]);
  255. if( h->auto_timebase_den )
  256. {
  257. int i = 1;
  258. uint64_t fps_num, fps_den;
  259. double exponent;
  260. double fps_sig = sigexp10( fpss[num], &exponent );
  261. while( 1 )
  262. {
  263. fps_den = i * h->timebase_num;
  264. fps_num = round( fps_den * fps_sig ) * exponent;
  265. if( fps_num > UINT32_MAX || fabs( ((double)fps_num / fps_den) / exponent - fps_sig ) < DOUBLE_EPSILON )
  266. break;
  267. ++i;
  268. }
  269. h->timebase_den = fps_num && h->timebase_den ? lcm( h->timebase_den, fps_num ) : fps_num;
  270. if( h->timebase_den > UINT32_MAX )
  271. {
  272. h->auto_timebase_den = 0;
  273. continue;
  274. }
  275. }
  276. }
  277. if( h->auto_timebase_num && !h->auto_timebase_den )
  278. if( try_mkv_timebase_den( fpss, h, timecodes_num - 1 ) < 0 )
  279. goto fail;
  280. free( fpss );
  281. fpss = NULL;
  282. }
  283. if( timecodes_num > 1 )
  284. h->assume_fps = 1 / (timecodes[timecodes_num - 1] - timecodes[timecodes_num - 2]);
  285. else
  286. h->assume_fps = (double)info->fps_num / info->fps_den;
  287. h->last_timecode = timecodes[timecodes_num - 1];
  288. }
  289. #undef NO_TIMECODE_LINE
  290. if( h->auto_timebase_den || h->auto_timebase_num )
  291. {
  292. uint64_t i = gcd( h->timebase_num, h->timebase_den );
  293. h->timebase_num /= i;
  294. h->timebase_den /= i;
  295. x264_cli_log( "timecode", X264_LOG_INFO, "automatic timebase generation %"PRIu64"/%"PRIu64"\n", h->timebase_num, h->timebase_den );
  296. }
  297. else FAIL_IF_ERROR( h->timebase_den > UINT32_MAX || !h->timebase_den, "automatic timebase generation failed.\n"
  298. " Specify an appropriate timebase manually.\n" );
  299. h->pts = malloc( h->stored_pts_num * sizeof(int64_t) );
  300. if( !h->pts )
  301. goto fail;
  302. for( num = 0; num < h->stored_pts_num; num++ )
  303. {
  304. h->pts[num] = timecodes[num] * ((double)h->timebase_den / h->timebase_num) + 0.5;
  305. FAIL_IF_ERROR( num > 0 && h->pts[num] <= h->pts[num - 1], "invalid timebase or timecode for frame %d\n", num );
  306. }
  307. free( timecodes );
  308. return 0;
  309. fail:
  310. if( timecodes )
  311. free( timecodes );
  312. if( fpss )
  313. free( fpss );
  314. return -1;
  315. }
  316. #undef DOUBLE_EPSILON
  317. #undef MKV_TIMEBASE_DEN
  318. static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
  319. {
  320. int ret = 0;
  321. FILE *tcfile_in;
  322. timecode_hnd_t *h = malloc( sizeof(timecode_hnd_t) );
  323. FAIL_IF_ERROR( !h, "malloc failed\n" );
  324. h->input = cli_input;
  325. h->p_handle = *p_handle;
  326. h->pts = NULL;
  327. if( opt->timebase )
  328. {
  329. ret = sscanf( opt->timebase, "%"SCNu64"/%"SCNu64, &h->timebase_num, &h->timebase_den );
  330. if( ret == 1 )
  331. {
  332. h->timebase_num = strtoul( opt->timebase, NULL, 10 );
  333. h->timebase_den = 0; /* set later by auto timebase generation */
  334. }
  335. FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || h->timebase_den > UINT32_MAX,
  336. "timebase you specified exceeds H.264 maximum\n" );
  337. }
  338. h->auto_timebase_num = !ret;
  339. h->auto_timebase_den = ret < 2;
  340. if( h->auto_timebase_num )
  341. h->timebase_num = info->fps_den; /* can be changed later by auto timebase generation */
  342. if( h->auto_timebase_den )
  343. h->timebase_den = 0; /* set later by auto timebase generation */
  344. tcfile_in = x264_fopen( psz_filename, "rb" );
  345. FAIL_IF_ERROR( !tcfile_in, "can't open `%s'\n", psz_filename );
  346. if( !x264_is_regular_file( tcfile_in ) )
  347. {
  348. x264_cli_log( "timecode", X264_LOG_ERROR, "tcfile input incompatible with non-regular file `%s'\n", psz_filename );
  349. fclose( tcfile_in );
  350. return -1;
  351. }
  352. if( parse_tcfile( tcfile_in, h, info ) < 0 )
  353. {
  354. if( h->pts )
  355. free( h->pts );
  356. fclose( tcfile_in );
  357. return -1;
  358. }
  359. fclose( tcfile_in );
  360. info->timebase_num = h->timebase_num;
  361. info->timebase_den = h->timebase_den;
  362. info->vfr = 1;
  363. *p_handle = h;
  364. return 0;
  365. }
  366. static int64_t get_frame_pts( timecode_hnd_t *h, int frame, int real_frame )
  367. {
  368. if( frame < h->stored_pts_num )
  369. return h->pts[frame];
  370. else
  371. {
  372. if( h->pts && real_frame )
  373. {
  374. x264_cli_log( "timecode", X264_LOG_INFO, "input timecode file missing data for frame %d and later\n"
  375. " assuming constant fps %.6f\n", frame, h->assume_fps );
  376. free( h->pts );
  377. h->pts = NULL;
  378. }
  379. double timecode = h->last_timecode + 1 / h->assume_fps;
  380. if( real_frame )
  381. h->last_timecode = timecode;
  382. return timecode * ((double)h->timebase_den / h->timebase_num) + 0.5;
  383. }
  384. }
  385. static int read_frame( cli_pic_t *pic, hnd_t handle, int frame )
  386. {
  387. timecode_hnd_t *h = handle;
  388. if( h->input.read_frame( pic, h->p_handle, frame ) )
  389. return -1;
  390. pic->pts = get_frame_pts( h, frame, 1 );
  391. pic->duration = get_frame_pts( h, frame + 1, 0 ) - pic->pts;
  392. return 0;
  393. }
  394. static int release_frame( cli_pic_t *pic, hnd_t handle )
  395. {
  396. timecode_hnd_t *h = handle;
  397. if( h->input.release_frame )
  398. return h->input.release_frame( pic, h->p_handle );
  399. return 0;
  400. }
  401. static int picture_alloc( cli_pic_t *pic, hnd_t handle, int csp, int width, int height )
  402. {
  403. timecode_hnd_t *h = handle;
  404. return h->input.picture_alloc( pic, h->p_handle, csp, width, height );
  405. }
  406. static void picture_clean( cli_pic_t *pic, hnd_t handle )
  407. {
  408. timecode_hnd_t *h = handle;
  409. h->input.picture_clean( pic, h->p_handle );
  410. }
  411. static int close_file( hnd_t handle )
  412. {
  413. timecode_hnd_t *h = handle;
  414. if( h->pts )
  415. free( h->pts );
  416. h->input.close_file( h->p_handle );
  417. free( h );
  418. return 0;
  419. }
  420. const cli_input_t timecode_input = { open_file, picture_alloc, read_frame, release_frame, picture_clean, close_file };