Guest User

Zm_Gorynych

a guest
Mar 3rd, 2010
521
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.92 KB | None | 0 0
  1. From f62bdd3d81720509257cda864595ec83ac4f0774 Mon Sep 17 00:00:00 2001
  2. From: agiladi <agiladi@localhost.(none)>
  3. Date: Thu, 3 Sep 2009 11:22:14 -0500
  4. Subject: [PATCH] Avail speedcontrol patch update ro r1247
  5. Committer: [email protected]
  6.  
  7. ---
  8. Makefile | 1 +
  9. common/common.c | 15 +++
  10. common/common.h | 2 +
  11. encoder/encoder.c | 12 +++
  12. encoder/ratecontrol.h | 6 +
  13. encoder/speed.c | 257 +++++++++++++++++++++++++++++++++++++++++++++++++
  14. x264.c | 8 ++
  15. x264.h | 14 +++
  16. 8 files changed, 315 insertions(+), 0 deletions(-)
  17. create mode 100755 encoder/speed.c
  18.  
  19. diff --git a/Makefile b/Makefile
  20. index 04d639e..df01486 100644
  21. --- a/Makefile
  22. +++ b/Makefile
  23. -10,6 +10,7 @@ SRCS = common/mc.c common/predict.c common/pixel.c common/macroblock.c \
  24. common/quant.c common/vlc.c \
  25. encoder/analyse.c encoder/me.c encoder/ratecontrol.c \
  26. encoder/set.c encoder/macroblock.c encoder/cabac.c \
  27. + encoder/speed.c \
  28. encoder/cavlc.c encoder/encoder.c encoder/lookahead.c
  29.  
  30. SRCCLI = x264.c matroska.c muxers.c
  31. diff --git a/common/common.c b/common/common.c
  32. index 4617387..1321076 100644
  33. --- a/common/common.c
  34. +++ b/common/common.c
  35. -111,6 +111,11 @@ void x264_param_default( x264_param_t *param )
  36. param->rc.i_zones = 0;
  37. param->rc.b_mb_tree = 1;
  38.  
  39. + // speedcontrol
  40. + param->sc.f_speed = 0;
  41. + param->sc.i_buffer_size = 30;
  42. + param->sc.f_buffer_init = 0.75;
  43. +
  44. /* Log */
  45. param->pf_log = x264_log_default;
  46. param->p_log_private = NULL;
  47. -591,6 +596,14 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
  48. p->rc.f_complexity_blur = atof(value);
  49. OPT("zones")
  50. p->rc.psz_zones = strdup(value);
  51. + OPT("speed")
  52. + p->sc.f_speed = atof(value);
  53. + OPT("speed-bufsize")
  54. + p->sc.i_buffer_size = atoi(value);
  55. + OPT("speed-init")
  56. + p->sc.f_buffer_init = atof(value);
  57. + OPT("speed-alt-timer")
  58. + p->sc.b_alt_timer = atobool(value);
  59. OPT("psnr")
  60. p->analyse.b_psnr = atobool(value);
  61. OPT("ssim")
  62. -849,6 +862,8 @@ char *x264_param2string( x264_param_t *p, int b_res )
  63. s += sprintf( s, "fps=%d/%d ", p->i_fps_num, p->i_fps_den );
  64. }
  65.  
  66. + // FIXME speedcontrol stuff
  67. +
  68. s += sprintf( s, "cabac=%d", p->b_cabac );
  69. s += sprintf( s, " ref=%d", p->i_frame_reference );
  70. s += sprintf( s, " deblock=%d:%d:%d", p->b_deblocking_filter,
  71. diff --git a/common/common.h b/common/common.h
  72. index 81c7b00..8ae07c3 100644
  73. --- a/common/common.h
  74. +++ b/common/common.h
  75. -290,6 +290,7 @@ static const int x264_scan8[16+2*4+3] =
  76. */
  77.  
  78. typedef struct x264_ratecontrol_t x264_ratecontrol_t;
  79. +typedef struct x264_speedcontrol_t x264_speedcontrol_t;
  80.  
  81. struct x264_t
  82. {
  83. -602,6 +603,7 @@ struct x264_t
  84.  
  85. /* rate control encoding only */
  86. x264_ratecontrol_t *rc;
  87. + x264_speedcontrol_t *sc;
  88.  
  89. /* stats */
  90. struct
  91. diff --git a/encoder/encoder.c b/encoder/encoder.c
  92. index 56e5d5b..26ab733 100644
  93. --- a/encoder/encoder.c
  94. +++ b/encoder/encoder.c
  95. -668,6 +668,8 @@ static int x264_validate_parameters( x264_t *h )
  96. h->param.rc.f_qblur = 0;
  97. if( h->param.rc.f_complexity_blur < 0 )
  98. h->param.rc.f_complexity_blur = 0;
  99. + if( h->param.sc.i_buffer_size < 0 || h->param.sc.f_speed <= 0 )
  100. + h->param.sc.i_buffer_size = 0;
  101.  
  102. h->param.i_sps_id &= 31;
  103.  
  104. -849,6 +851,10 @@ x264_t *x264_encoder_open( x264_param_t *param )
  105.  
  106. mbcmp_init( h );
  107.  
  108. + if( h->param.sc.i_buffer_size )
  109. + x264_speedcontrol_new( h );
  110. +
  111. +
  112. p = buf + sprintf( buf, "using cpu capabilities:" );
  113. for( i=0; x264_cpu_names[i].flags; i++ )
  114. {
  115. -1740,6 +1746,8 @@ int x264_encoder_encode( x264_t *h,
  116. x264_reference_build_list( h, h->fdec->i_poc );
  117.  
  118. /* Init the rate control */
  119. + if( h->param.sc.i_buffer_size )
  120. + x264_speedcontrol_frame( h );
  121. x264_ratecontrol_start( h, h->fenc->i_qpplus1 );
  122. i_global_qp = x264_ratecontrol_qp( h );
  123.  
  124. -1877,6 +1885,9 @@ static int x264_encoder_frame_end( x264_t *h, x264_t *thread_current,
  125. x264_emms();
  126.  
  127. x264_noise_reduction_update( thread_current );
  128. +
  129. + if( h->param.sc.i_buffer_size )
  130. + x264_speedcontrol_frame_end( h );
  131.  
  132. /* ---------------------- Compute/Print statistics --------------------- */
  133. x264_thread_sync_stat( h, h->thread[0] );
  134. -2221,6 +2232,7 @@ void x264_encoder_close ( x264_t *h )
  135.  
  136. /* rc */
  137. x264_ratecontrol_delete( h );
  138. + x264_speedcontrol_delete( h );
  139.  
  140. /* param */
  141. if( h->param.rc.psz_stat_out )
  142. diff --git a/encoder/ratecontrol.h b/encoder/ratecontrol.h
  143. index ed8abab..a4cc388 100644
  144. --- a/encoder/ratecontrol.h
  145. +++ b/encoder/ratecontrol.h
  146. -41,5 +41,11 @@ void x264_ratecontrol_set_estimated_size( x264_t *, int bits );
  147. int x264_ratecontrol_get_estimated_size( x264_t const *);
  148. int x264_rc_analyse_slice( x264_t *h );
  149.  
  150. +// speedcontrol
  151. +void x264_speedcontrol_new( x264_t *h );
  152. +void x264_speedcontrol_delete( x264_t *h );
  153. +void x264_speedcontrol_frame( x264_t *h );
  154. +void x264_speedcontrol_frame_end( x264_t *h );
  155. +
  156. #endif
  157.  
  158. diff --git a/encoder/speed.c b/encoder/speed.c
  159. new file mode 100755
  160. index 0000000..7b5c400
  161. --- /dev/null
  162. +++ b/encoder/speed.c
  163. -0,0 +1,257 @@
  164. +#include <stdio.h>
  165. +#include <string.h>
  166. +#include <math.h>
  167. +#include "common/common.h"
  168. +#include "common/cpu.h"
  169. +
  170. +struct x264_speedcontrol_t
  171. +{
  172. + // all times are in usec
  173. + int64_t timestamp; // when was speedcontrol last invoked
  174. + int64_t cpu_time; // time spent encoding the previous frame
  175. + int64_t buffer_size; // assumed application-side buffer of frames to be streamed,
  176. + int64_t buffer_fill; // where full = we don't have to hurry
  177. + int64_t compensation_period; // how quickly we try to return to the target buffer fullness
  178. + float fps, spf;
  179. + int preset; // which setting was used in the previous frame
  180. + int prev_frame;
  181. + float cplx_num; // rolling average of estimated spf for preset #0
  182. + float cplx_den;
  183. + float cplx_decay;
  184. + float dither;
  185. + x264_param_t user_param;
  186. +
  187. + struct {
  188. + int64_t min_buffer, max_buffer;
  189. + double avg_preset;
  190. + int den;
  191. + } stat;
  192. +};
  193. +
  194. +void x264_speedcontrol_new( x264_t *h )
  195. +{
  196. + x264_speedcontrol_t *sc = h->sc = x264_malloc( sizeof(x264_speedcontrol_t) );
  197. + x264_emms();
  198. + memset( sc, 0, sizeof(x264_speedcontrol_t) );
  199. +
  200. + if( h->param.sc.f_speed <= 0 )
  201. + h->param.sc.f_speed = 1;
  202. + sc->fps = h->param.i_fps_num / h->param.i_fps_den;
  203. + sc->spf = 1e6 / sc->fps;
  204. + h->param.sc.i_buffer_size = X264_MAX( 3, h->param.sc.i_buffer_size );
  205. + sc->buffer_size = h->param.sc.i_buffer_size * 1e6 / sc->fps;
  206. + sc->buffer_fill = sc->buffer_size * h->param.sc.f_buffer_init;
  207. + sc->buffer_fill = x264_clip3( sc->buffer_fill, sc->spf, sc->buffer_size );
  208. + sc->compensation_period = sc->buffer_size/4;
  209. + sc->timestamp = x264_mdate();
  210. + sc->preset = -1;
  211. + sc->prev_frame = 0;
  212. + sc->cplx_num = 3e3; //FIXME estimate initial complexity
  213. + sc->cplx_den = .1;
  214. + sc->cplx_decay = 1 - 1./h->param.sc.i_buffer_size;
  215. + sc->stat.min_buffer = sc->buffer_size;
  216. + sc->stat.max_buffer = 0;
  217. + sc->user_param = h->param;
  218. +}
  219. +
  220. +void x264_speedcontrol_delete( x264_t *h )
  221. +{
  222. + x264_speedcontrol_t *sc = h->sc;
  223. + if( !sc )
  224. + return;
  225. + x264_log( h, X264_LOG_INFO, "speedcontrol: avg preset=%.3f buffer min=%.3f max=%.3f\n",
  226. + sc->stat.avg_preset / sc->stat.den,
  227. + (float)sc->stat.min_buffer / sc->buffer_size,
  228. + (float)sc->stat.max_buffer / sc->buffer_size );
  229. +// x264_log( h, X264_LOG_INFO, "speedcontrol: avg cplx=%.5f\n", sc->cplx_num / sc->cplx_den );
  230. + x264_free( sc );
  231. +}
  232. +
  233. +static int dither( x264_speedcontrol_t *sc, float f )
  234. +{
  235. + int i = f;
  236. + if( f < 0 )
  237. + i--;
  238. + sc->dither += f - i;
  239. + if( sc->dither >= 1. )
  240. + {
  241. + sc->dither--;
  242. + i++;
  243. + }
  244. + return i;
  245. +}
  246. +
  247. +typedef struct
  248. +{
  249. + float time; // relative encoding time, compared to the other presets
  250. + int subme;
  251. + int me;
  252. + int refs;
  253. + int mix;
  254. + int trellis;
  255. + int partitions;
  256. + int chromame;
  257. + float psy_rd;
  258. + float psy_trellis;
  259. +} sc_preset_t;
  260. +
  261. +#define PRESETS 13
  262. +static const sc_preset_t presets[PRESETS] =
  263. +{
  264. +#define I4 X264_ANALYSE_I4x4
  265. +#define I8 X264_ANALYSE_I8x8
  266. +#define P8 X264_ANALYSE_PSUB16x16
  267. +#define B8 X264_ANALYSE_BSUB16x16
  268. +/*0*/ { .time=1.060, .subme=1, .me=X264_ME_DIA, .refs=1, .mix=0, .chromame=0, .trellis=0, .partitions=0, .psy_rd=0 },
  269. +/*1*/ { .time=1.120, .subme=1, .me=X264_ME_DIA, .refs=1, .mix=0, .chromame=0, .trellis=0, .partitions=I8|I4, .psy_rd=0 },
  270. +/*2*/ { .time=1.440, .subme=3, .me=X264_ME_HEX, .refs=1, .mix=0, .chromame=0, .trellis=0, .partitions=I8|I4, .psy_rd=0 },
  271. +/*3*/ { .time=1.620, .subme=5, .me=X264_ME_HEX, .refs=1, .mix=0, .chromame=0, .trellis=0, .partitions=I8|I4, .psy_rd=1.0 },
  272. +/*4*/ { .time=2.660, .subme=6, .me=X264_ME_HEX, .refs=1, .mix=0, .chromame=0, .trellis=0, .partitions=I8|I4, .psy_rd=1.0 },
  273. +/*5*/ { .time=3.560, .subme=6, .me=X264_ME_HEX, .refs=1, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4, .psy_rd=1.0 },
  274. +/*6*/ { .time=4.640, .subme=6, .me=X264_ME_HEX, .refs=2, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4, .psy_rd=1.0 },
  275. +/*7*/ { .time=5.190, .subme=7, .me=X264_ME_HEX, .refs=2, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4, .psy_rd=1.0 },
  276. +/*8*/ { .time=6.190, .subme=7, .me=X264_ME_HEX, .refs=2, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4|P8|B8, .psy_rd=1.0 },
  277. +/*9*/ { .time=6.920, .subme=7, .me=X264_ME_HEX, .refs=3, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4|P8|B8, .psy_rd=1.0 },
  278. +/*10*/ { .time=7.070, .subme=8, .me=X264_ME_HEX, .refs=3, .mix=0, .chromame=0, .trellis=1, .partitions=I8|I4|P8|B8, .psy_rd=1.0 },
  279. +/*11*/ { .time=12.800, .subme=9, .me=X264_ME_HEX, .refs=3, .mix=1, .chromame=1, .trellis=1, .partitions=I8|I4|P8|B8, .psy_rd=1.0 },
  280. +/*12*/ { .time=18.570, .subme=10, .me=X264_ME_HEX, .refs=3, .mix=1, .chromame=1, .trellis=1, .partitions=I8|I4|P8|B8, .psy_rd=1.0 }
  281. +};
  282. +
  283. +static void apply_preset( x264_t *h, int preset )
  284. +{
  285. + x264_speedcontrol_t *sc = h->sc;
  286. + preset = x264_clip3( preset, 0, PRESETS-1 );
  287. + //if( preset != sc->preset )
  288. + {
  289. + const sc_preset_t *s = &presets[preset];
  290. + x264_param_t p = sc->user_param;
  291. +
  292. + p.i_frame_reference = s->refs;
  293. + p.analyse.inter = s->partitions;
  294. + p.analyse.i_subpel_refine = s->subme;
  295. + p.analyse.i_me_method = s->me;
  296. + p.analyse.i_trellis = s->trellis;
  297. + p.analyse.b_mixed_references = s->mix;
  298. + p.analyse.b_chroma_me = s->chromame;
  299. + p.analyse.f_psy_rd = s->psy_rd;
  300. + p.analyse.f_psy_trellis = s->psy_trellis;
  301. + x264_encoder_reconfig( h, &p );
  302. + sc->preset = preset;
  303. + x264_log( h, X264_LOG_DEBUG, "Applying speedcontrol preset %d.\n", preset );
  304. + }
  305. +}
  306. +
  307. +void x264_speedcontrol_frame_end( x264_t *h )
  308. +{
  309. + x264_speedcontrol_t *sc = h->sc;
  310. + if( h->param.sc.b_alt_timer )
  311. + sc->cpu_time = x264_mdate() - sc->timestamp;
  312. +}
  313. +
  314. +void x264_speedcontrol_frame( x264_t *h )
  315. +{
  316. + x264_speedcontrol_t *sc = h->sc;
  317. + int64_t t, delta_t, delta_buffer;
  318. + int delta_f;
  319. +
  320. + x264_emms();
  321. +
  322. + // update buffer state after encoding and outputting the previous frame(s)
  323. + t = x264_mdate();
  324. + delta_f = h->i_frame - sc->prev_frame;
  325. + delta_t = t - sc->timestamp;
  326. + delta_buffer = delta_f * sc->spf / h->param.sc.f_speed - delta_t;
  327. + sc->buffer_fill += delta_buffer;
  328. + sc->prev_frame = h->i_frame;
  329. + sc->timestamp = t;
  330. +
  331. + // update the time predictor
  332. + if( delta_f )
  333. + {
  334. + int cpu_time = h->param.sc.b_alt_timer ? sc->cpu_time : delta_t;
  335. + float decay = powf( sc->cplx_decay, delta_f );
  336. + sc->cplx_num *= decay;
  337. + sc->cplx_den *= decay;
  338. + sc->cplx_num += cpu_time / presets[sc->preset].time;
  339. + sc->cplx_den += delta_f;
  340. +
  341. + sc->stat.avg_preset += sc->preset * delta_f;
  342. + sc->stat.den += delta_f;
  343. + }
  344. + sc->stat.min_buffer = X264_MIN( sc->buffer_fill, sc->stat.min_buffer );
  345. + sc->stat.max_buffer = X264_MAX( sc->buffer_fill, sc->stat.max_buffer );
  346. +
  347. + if( sc->buffer_fill > sc->buffer_size ) // oops, cpu was idle
  348. + {
  349. + // not really an error, but we'll warn for debugging purposes
  350. + static int64_t idle_t = 0, print_interval = 0;
  351. + idle_t += sc->buffer_fill - sc->buffer_size;
  352. + if( t - print_interval > 1e6 )
  353. + {
  354. + x264_log( h, X264_LOG_WARNING, "speedcontrol idle (%.6f sec)\n", idle_t/1e6 );
  355. + print_interval = t;
  356. + idle_t = 0;
  357. + }
  358. + sc->buffer_fill = sc->buffer_size;
  359. + }
  360. + else if( sc->buffer_fill < 0 && delta_buffer < 0 ) // oops, we're late
  361. + {
  362. + // don't clip fullness to 0; we'll hope the real buffer was bigger than
  363. + // specified, and maybe we can catch up. if the application had to drop
  364. + // frames, then it should override the buffer fullness (FIXME implement this).
  365. + x264_log( h, X264_LOG_WARNING, "speedcontrol underflow (%.6f sec)\n", sc->buffer_fill/1e6 );
  366. + }
  367. +
  368. + {
  369. + // pick the preset that should return the buffer to 3/4-full within a time
  370. + // specified by compensation_period
  371. + float target = sc->spf / h->param.sc.f_speed
  372. + * (sc->buffer_fill + sc->compensation_period)
  373. + / (sc->buffer_size*3/4 + sc->compensation_period);
  374. + float cplx = sc->cplx_num / sc->cplx_den;
  375. + float set, t0, t1;
  376. + float filled = (float) sc->buffer_fill / sc->buffer_size;
  377. + int i;
  378. + t0 = presets[0].time * cplx;
  379. + for( i=1;; i++ )
  380. + {
  381. + t1 = presets[i].time * cplx;
  382. + if( t1 >= target || i == PRESETS-1 )
  383. + break;
  384. + t0 = t1;
  385. + }
  386. + // linear interpolation between states
  387. + set = i-1 + (target - t0) / (t1 - t0);
  388. + // Even if our time estimations in the PRESETS array are off
  389. + // this will push us towards our target fullness
  390. + set += (20 * (filled-0.75));
  391. + set = x264_clip3f(set,0,PRESETS-1);
  392. + apply_preset( h, dither( sc, set ) );
  393. +
  394. + // FIXME
  395. + if (h->param.i_log_level >= X264_LOG_DEBUG)
  396. + {
  397. + static float cpu, wall, tgt, den;
  398. + float decay = 1-1/100.;
  399. + cpu = cpu*decay + sc->cpu_time;
  400. + wall = wall*decay + delta_t;
  401. + tgt = tgt*decay + target;
  402. + den = den*decay + 1;
  403. + fprintf( stderr, "speed: %.2f %d[%.5f] (t/c/w: %6.0f/%6.0f/%6.0f = %.4f) fps=%.2f\r",
  404. + set, sc->preset, (float)sc->buffer_fill / sc->buffer_size,
  405. + tgt/den, cpu/den, wall/den, cpu/wall, 1e6*den/wall );
  406. + }
  407. + }
  408. +
  409. +}
  410. +
  411. +void x264_speedcontrol_sync( x264_t *h, float f_buffer_fill, int i_buffer_size )
  412. +{
  413. + x264_speedcontrol_t *sc = h->sc;
  414. + if( !h->param.sc.i_buffer_size )
  415. + return;
  416. + if( i_buffer_size )
  417. + h->param.sc.i_buffer_size = X264_MAX( 3, h->param.sc.i_buffer_size );
  418. + sc->buffer_size = h->param.sc.i_buffer_size * 1e6 / sc->fps;
  419. + sc->buffer_fill = sc->buffer_size * f_buffer_fill;
  420. +}
  421. diff --git a/x264.c b/x264.c
  422. index 0ed538a..b308a71 100644
  423. --- a/x264.c
  424. +++ b/x264.c
  425. -245,6 +245,12 @@ static void Help( x264_param_t *defaults, int b_longhelp )
  426. H1( " --qpfile <string> Force frametypes and QPs for some or all frames\n"
  427. " Format of each line: framenumber frametype QP\n"
  428. " QP of -1 lets x264 choose. Frametypes: I,i,P,B,b.\n" );
  429. + H1( "\n" );
  430. + H1( "Speedcontrol:\n" );
  431. + H1( "\n" );
  432. + H1( " --speed <float> Automatically adjust other options to achieve this\n" );
  433. + H1( " fraction of realtime.\n" );
  434. + H1( " --speed-bufsize <int> Averaging period for speed. (in frames) [%d]\n", defaults->sc.i_buffer_size );
  435. H0( "\n" );
  436. H0( "Analysis:\n" );
  437. H0( "\n" );
  438. -464,6 +470,8 @@ static struct option long_options[] =
  439. { "zones", required_argument, NULL, 0 },
  440. { "qpfile", required_argument, NULL, OPT_QPFILE },
  441. { "threads", required_argument, NULL, 0 },
  442. + { "speed", required_argument, NULL, 0 },
  443. + { "speed-bufsize", required_argument, NULL, 0 },
  444. { "slice-max-size", required_argument, NULL, 0 },
  445. { "slice-max-mbs", required_argument, NULL, 0 },
  446. { "slices", required_argument, NULL, 0 },
  447. diff --git a/x264.h b/x264.h
  448. index 66f4f28..25853a3 100644
  449. --- a/x264.h
  450. +++ b/x264.h
  451. -295,6 +295,15 @@ typedef struct x264_param_t
  452. char *psz_zones; /* alternate method of specifying zones */
  453. } rc;
  454.  
  455. + /* Speed control parameters */
  456. + struct
  457. + {
  458. + float f_speed; /* ratio from realtime */
  459. + int i_buffer_size; /* number of frames */
  460. + float f_buffer_init; /* fraction of size */
  461. + int b_alt_timer; /* use a different method of measuring encode time FIXME */
  462. + } sc;
  463. +
  464. /* Muxing parameters */
  465. int b_aud; /* generate access unit delimiters */
  466. int b_repeat_headers; /* put SPS/PPS before each keyframe */
  467. -469,4 +478,9 @@ void x264_encoder_close ( x264_t * );
  468. * this should be used at the end of the stream, to know when you have all the encoded frames. */
  469. int x264_encoder_delayed_frames( x264_t * );
  470.  
  471. +/* x264_speedcontrol_sync:
  472. + * override speedcontrol's internal clock */
  473. +void x264_speedcontrol_sync( x264_t *, float f_buffer_fill, int i_buffer_size );
  474. +
  475. +
  476. #endif
  477. --
  478. 1.6.4
Advertisement
Add Comment
Please, Sign In to add comment