1 /***************************************************************************
2 \fn ADM_x264
3 \brief Front end for x264 Mpeg4 asp encoder
4 -------------------
5
6 copyright : (C) 2002/2011 by mean/gruntster
7 email : fixounet@free.fr/gruntster@razorbyte.au
8 ***************************************************************************/
9
10 /***************************************************************************
11 * *
12 * This program is free software; you can redistribute it and/or modify *
13 * it under the terms of the GNU General Public License as published by *
14 * the Free Software Foundation; either version 2 of the License, or *
15 * (at your option) any later version. *
16 * *
17 ***************************************************************************/
18
19 #include "ADM_default.h"
20 #include "ADM_x264.h"
21 #undef ADM_MINIMAL_UI_INTERFACE // we need the full UI
22 #include "DIA_factory.h"
23 #include "DIA_coreToolkit.h"
24 #include "ADM_vidMisc.h"
25 #include "ADM_coreUtils.h"
26 #include <climits>
27
28 #if 1
29 #define aprintf(...) {}
30 #define avsnprintf(...) {}
31 #else
32 #define aprintf ADM_info
33 #define avsnprintf vsnprintf
34 #endif
35 static const char *TrueFalse[2]={"False","True"};
36 static void dumpx264Setup(x264_param_t *param);
37 extern "C"
38 {
logger(void * cooki,int i_level,const char * psz,va_list list)39 static void logger( void *cooki, int i_level, const char *psz, va_list list)
40 {
41 static char buffer[2048];
42 avsnprintf(buffer,2048,psz,list);
43 aprintf(">>%s\n",buffer);
44 }
45 }
46 #define MMSET(x) memset(&(x),0,sizeof(x))
47
48 extern x264_encoder x264Settings;
49 /**
50 \fn setup
51 */
setup(void)52 bool x264Encoder::setup(void)
53 {
54 ADM_info("=============x264, setting up==============\n");
55 MMSET(param);
56
57 x264_param_default( ¶m);
58 param.pf_log=logger;
59 firstIdr=true;
60 image=new ADMImageDefault(getWidth(),getHeight());
61
62 // -------------- preset, tune, idc ------------
63 if(!x264Settings.useAdvancedConfiguration)
64 {
65 std::string tune;
66 if(x264Settings.general.tuning != std::string("none"))
67 tune = x264Settings.general.tuning;
68 if(x264Settings.general.fast_decode)
69 {
70 tune += std::string(",");
71 tune += std::string("fastdecode");
72 }
73 if(x264Settings.general.zero_latency)
74 {
75 tune += std::string(",");
76 tune += std::string("zerolatency");
77 }
78 if(tune.empty())
79 x264_param_default_preset(¶m, x264Settings.general.preset.c_str(), NULL);
80 else
81 x264_param_default_preset(¶m, x264Settings.general.preset.c_str(), tune.c_str());
82 }else
83 {
84 param.b_bluray_compat=x264Settings.general.blueray_compatibility;
85 param.b_fake_interlaced=x264Settings.general.fake_interlaced;
86 }
87 param.i_level_idc=x264Settings.level;
88
89 // Threads..
90 switch(x264Settings.general.threads)
91 {
92 case 1: case 2: case 4: param.i_threads = x264Settings.general.threads;break;
93 case 0: case 99: break; //auto
94 default: ADM_error("UNKNOWN NB OF THREADS\n");break;
95 }
96 param.i_width = getWidth();
97 param.i_height = getHeight();
98 param.i_csp = X264_CSP_I420;
99 param.i_log_level=X264_LOG_INFO; //DEBUG; //INFO;
100
101 //Framerate
102 int n,d;
103 uint64_t f=source->getInfo()->frameIncrement;
104 usSecondsToFrac(f,&n,&d,INT_MAX);
105 param.i_fps_num = d;
106 param.i_fps_den = n;
107 n = source->getInfo()->timeBaseNum & 0x7FFFFFFF;
108 d = source->getInfo()->timeBaseDen & 0x7FFFFFFF;
109 ADM_assert(d);
110 param.i_timebase_num = n;
111 param.i_timebase_den = d;
112 #if 0
113 bool constantFps = (n * 1000 * 1000 + (d / 2))/ d >= f;
114 param.b_vfr_input = !constantFps;
115 #else
116 // We do pseudo cfr ...
117 param.b_vfr_input=0;
118 #endif
119
120 // -------------- vui------------
121 #undef MKPARAM
122 #undef MKPARAMF
123 #undef MKPARAMB
124 #define MKPARAM(x,y) {param.vui.x = x264Settings.vui.y;aprintf("[x264] vui."#x" = %d\n",param.vui.x);}
125 #define MKPARAMF(x,y) {param.vui.x = (float)x264Settings.vui.y; aprintf("[x264] vui."#x" = %.2f\n",param.vui.x);}
126 #define MKPARAMB(x,y) {param.vui.x = x264Settings.vui.y ;aprintf("[x264] vui."#x" = %s\n",TrueFalse[param.vui.x&1]);}
127 MKPARAM (i_sar_width,sar_width)
128 MKPARAM (i_sar_height,sar_height)
129
130 // -------------- rate control------------
131 switch(x264Settings.general.params.mode)
132 {
133 case COMPRESS_2PASS:
134 case COMPRESS_2PASS_BITRATE:
135 uint32_t bitrate;
136 if(passNumber!=1 && passNumber!=2)
137 {
138 ADM_error("No pass number specified! (%d)\n",(int)passNumber);
139 return false;
140 }
141 ADM_info("Starting pass :%d\n",passNumber);
142 if(x264Settings.general.params.mode==COMPRESS_2PASS)
143 {
144 uint64_t duration=source->getInfo()->totalDuration; // in us
145 ADM_info("Source duration :%s\n",ADM_us2plain(duration));
146 ADM_info("Target size :%d\n",(int)x264Settings.general.params.finalsize);
147 uint32_t avg;
148 if(false==ADM_computeAverageBitrateFromDuration(duration,
149 x264Settings.general.params.finalsize,
150 &avg))
151 {
152 ADM_error("[x264] No source duration!\n");
153 return false;
154 }
155 bitrate=(uint32_t)avg;
156 }
157 else
158 bitrate=x264Settings.general.params.avg_bitrate;
159 ADM_info("Using average bitrate of %d kb/s\n",(int)bitrate);
160 param.rc.i_rc_method = X264_RC_ABR;
161 param.rc.i_bitrate = bitrate;
162 if(passNumber==1)
163 {
164 param.rc.b_stat_write=1;
165 param.rc.b_stat_read=0;
166 param.rc.psz_stat_out=logFile;
167 //#warning FIXME
168 #if 0
169 if(x264Settings.)
170 x264_param_apply_fastfirstpass(&_param);
171 #endif
172
173 }else
174 {
175 param.rc.b_stat_write=0;
176 param.rc.b_stat_read=1;
177 param.rc.psz_stat_in=logFile;
178 if(!ADM_fileExist(logFile))
179 {
180 ADM_error("Logfile %s does not exist \n",logFile);
181 return false;
182 }
183 }
184 break;
185 case COMPRESS_AQ: param.rc.i_rc_method = X264_RC_CRF;
186 param.rc.f_rf_constant = x264Settings.general.params.qz;
187 break;
188 case COMPRESS_CQ: param.rc.i_rc_method = X264_RC_CQP;
189 param.rc.i_qp_constant = x264Settings.general.params.qz;
190 break;
191
192 case COMPRESS_CBR:
193 param.rc.i_rc_method = X264_RC_ABR;
194 param.rc.i_bitrate = x264Settings.general.params.bitrate;
195 param.rc.i_qp_constant = 0;
196 param.rc.f_rf_constant = 0;
197 break;
198 default:
199 GUI_Error_HIG(QT_TRANSLATE_NOOP("x264","Not coded"),QT_TRANSLATE_NOOP("x264","this mode has not been implemented\n"));
200 return false;
201 break;
202
203 }
204
205 if(globalHeader)
206 param.b_repeat_headers=0;
207 else
208 param.b_repeat_headers=1;
209
210 if(x264Settings.useAdvancedConfiguration)
211 {
212
213 #undef MKPARAM
214 #undef MKPARAMF
215 #undef MKPARAMB
216 #define MKPARAM(x,y) {param.x = x264Settings.y;aprintf("[x264] "#x" = %d\n",param.x);}
217 #define MKPARAMF(x,y) {param.x = (float)x264Settings.y; aprintf("[x264] "#x" = %.2f\n",param.x);}
218 #define MKPARAMB(x,y) {param.x = x264Settings.y ;aprintf("[x264] "#x" = %s\n",TrueFalse[param.x&1]);}
219 MKPARAM(i_frame_reference,MaxRefFrames);
220 MKPARAM(i_keyint_min,MinIdr);
221 MKPARAM(i_keyint_max,MaxIdr);
222 MKPARAM(i_scenecut_threshold,i_scenecut_threshold);
223 MKPARAMB(b_intra_refresh,intra_refresh);
224 MKPARAM(i_bframe,MaxBFrame);
225
226 MKPARAM(i_bframe_adaptive,i_bframe_adaptive);
227 MKPARAM(i_bframe_bias,i_bframe_bias);
228 MKPARAM(i_bframe_pyramid,i_bframe_pyramid);
229 MKPARAMB(b_deblocking_filter,b_deblocking_filter);
230 if(param.b_deblocking_filter)
231 {
232 MKPARAM(i_deblocking_filter_alphac0,i_deblocking_filter_alphac0);
233 MKPARAM(i_deblocking_filter_beta,i_deblocking_filter_beta);
234 }
235 MKPARAMB(b_cabac,cabac);
236 MKPARAMB(b_interlaced,interlaced);
237 MKPARAMB(b_constrained_intra,constrained_intra);
238 MKPARAMB(b_tff,tff);
239 MKPARAMB(b_fake_interlaced,fake_interlaced);
240
241 // -------------- analyze------------
242 #undef MKPARAM
243 #undef MKPARAMF
244 #undef MKPARAMB
245 #define MKPARAM(x,y) {param.analyse.x = x264Settings.analyze.y;aprintf("[x264] analyse."#x" = %d\n",param.analyse.x);}
246 #define MKPARAMF(x,y) {param.analyse.x = (float)x264Settings.analyze.y; aprintf("[x264] analyse."#x" = %.2f\n",param.analyse.x);}
247 #define MKPARAMB(x,y) {param.analyse.x = x264Settings.analyze.y ;aprintf("[x264] analyse."#x" = %s\n",TrueFalse[param.analyse.x&1]);}
248 #define MKFLAGS(fieldout,fieldin,mask) {if(x264Settings.analyze.fieldin) param.analyse.fieldout|=mask;}
249 MKPARAMB(b_transform_8x8,b_8x8)
250 MKPARAMB(b_weighted_bipred,weighted_bipred)
251 MKPARAM (i_weighted_pred,weighted_pred)
252 MKPARAM (i_direct_mv_pred,direct_mv_pred)
253 MKPARAM (i_chroma_qp_offset,chroma_offset)
254
255 MKPARAM (i_me_method,me_method)
256 MKPARAM (i_me_range,me_range)
257 MKPARAM (i_mv_range,mv_range)
258 MKPARAM (i_mv_range_thread,mv_range_thread)
259 MKPARAM (i_subpel_refine,subpel_refine)
260 MKPARAMB(b_chroma_me,chroma_me)
261 MKPARAMB(b_mixed_references,mixed_references)
262 MKPARAM (i_trellis,trellis)
263 MKPARAMB(b_fast_pskip,fast_pskip)
264 MKPARAMB(b_dct_decimate,dct_decimate)
265 MKPARAMB(b_psy,psy)
266 MKPARAMF(f_psy_rd,psy_rd)
267 MKPARAMF(f_psy_trellis,psy_trellis)
268 MKPARAM (i_noise_reduction,noise_reduction)
269 MKPARAM (i_luma_deadzone[0],inter_luma)
270 MKPARAM (i_luma_deadzone[1],intra_luma)
271
272 MKFLAGS(inter,b_i4x4,X264_ANALYSE_I4x4)
273 MKFLAGS(inter,b_i8x8,X264_ANALYSE_I8x8)
274 MKFLAGS(inter,b_p16x16,X264_ANALYSE_PSUB16x16)
275 MKFLAGS(inter,b_p8x8,X264_ANALYSE_PSUB8x8)
276 MKFLAGS(inter,b_b16x16,X264_ANALYSE_BSUB16x16)
277
278 //---------------- ratecontrol -------------------
279 #undef MKPARAM
280 #undef MKPARAMF
281 #undef MKPARAMB
282 #define MKPARAM(x,y) {param.rc.x = x264Settings.ratecontrol.y;aprintf("[x264] rc."#x" = %d\n",param.rc.x);}
283 #define MKPARAMF(x,y) {param.rc.x = (float)x264Settings.ratecontrol.y; aprintf("[x264] rc."#x" = %.2f\n",param.rc.x);}
284 #define MKPARAMB(x,y) {param.rc.x = x264Settings.ratecontrol.y ;aprintf("[x264] rc."#x" = %s\n",TrueFalse[param.rc.x&1]);}
285
286 MKPARAM(i_qp_min,qp_min);
287 MKPARAM(i_qp_max,qp_max);
288 MKPARAM(i_qp_step,qp_step);
289 MKPARAM(f_rate_tolerance,rate_tolerance);
290 MKPARAM(f_ip_factor,ip_factor);
291 MKPARAM(f_pb_factor,pb_factor);
292 MKPARAMB(b_mb_tree,mb_tree);
293 MKPARAM(i_lookahead,lookahead);
294 MKPARAM(i_aq_mode,aq_mode);
295 MKPARAMF(f_aq_strength,aq_strength);
296
297 MKPARAM(i_vbv_max_bitrate,vbv_max_bitrate)
298 MKPARAM(i_vbv_buffer_size,vbv_buffer_size)
299
300 param.rc.f_vbv_buffer_init=((float)x264Settings.ratecontrol.vbv_buffer_init)/100.;
301 }
302
303 if(!param.i_bframe) encoderDelay=0;
304 else
305 {
306 if(2>=param.i_frame_reference)
307 {
308 encoderDelay=f*2*2;
309 }
310 else
311 {
312 encoderDelay=2*f*(x264Settings.MaxRefFrames-1);
313 }
314 }
315
316 //
317 if(true==x264Settings.general.fast_first_pass)
318 {
319 if(passNumber==1)
320 {
321 switch(x264Settings.general.params.mode)
322 {
323 case COMPRESS_2PASS:
324 case COMPRESS_2PASS_BITRATE:
325 ADM_info("Appling fast first pass settings\n");
326 x264_param_apply_fastfirstpass(¶m);
327 break;
328 default:
329 break;
330 }
331 }
332 }
333
334 if(!x264Settings.useAdvancedConfiguration)
335 {
336 x264_param_apply_profile(¶m, x264Settings.general.profile.c_str());
337 }
338
339 setConstraintsByLevel();
340
341 dumpx264Setup(¶m);
342 ADM_info("Creating x264 encoder\n");
343 handle = x264_encoder_open (¶m);
344 if (!handle)
345 {
346 ADM_error("Cannot initialize x264\n");
347 return 0;
348 }
349
350
351 ADM_info("x264, setup ok\n");
352 if (globalHeader)
353 {
354 ADM_info("Creating global header\n");
355 return createHeader ();
356 }else
357 ADM_info("No need for global header\n");
358
359 return true;
360 }
361 /**
362 \fn setConstraintsByLevel
363 \brief Copied from Handbrake code
364 */
setConstraintsByLevel(void)365 bool x264Encoder::setConstraintsByLevel(void)
366 {
367 if(param.i_level_idc < 0)
368 return true;
369 if(param.i_width <= 0 || param.i_height <= 0)
370 {
371 ADM_warning("Invalid dimensions: %d:%d\n",param.i_width,param.i_height);
372 return false;
373 }
374 const x264_level_t *level = NULL;
375 int val = param.i_level_idc;
376 for(int i=0; x264_levels[i].level_idc; i++)
377 {
378 if(x264_levels[i].level_idc == val)
379 {
380 level = &x264_levels[i];
381 break;
382 }
383 }
384 if(!level)
385 {
386 ADM_warning("Invalid level %d\n",val);
387 return false;
388 }
389 if(level->frame_only && (param.b_interlaced || param.b_fake_interlaced))
390 {
391 ADM_warning("Interlaced flag not supported for level %d, disabling",val);
392 param.b_interlaced = param.b_fake_interlaced = 0;
393 }
394 // Calculate frame dimensions and rate (in macroblocks)
395 int mbW = (param.i_width + 15) >> 4;
396 int mbH = (param.i_height + 15) >> 4;
397 if(param.b_interlaced || param.b_fake_interlaced)
398 {
399 // interlaced: encoded height must divide cleanly by 32
400 mbH = (mbH + 1) & ~1;
401 }
402 int nbMb = mbW * mbH;
403 int mbRate;
404 if(param.i_fps_den <= 0 || param.i_fps_num <= 0)
405 mbRate = 0;
406 else
407 mbRate = (int64_t)nbMb * param.i_fps_num / param.i_fps_den;
408 // Sanitize frame_reference
409 if(param.i_keyint_max != 1)
410 {
411 int decBufSize = level->dpb / nbMb;
412 if(decBufSize < 1) decBufSize = 1;
413 if(decBufSize > 16) decBufSize = 16;
414 if(decBufSize < param.i_frame_reference)
415 {
416 ADM_warning("Number of ref frames %d too high for the IDC level, setting to %d\n",param.i_frame_reference,decBufSize);
417 param.i_frame_reference = decBufSize;
418 }
419 // Now disable B-frames and pyramid if necessary.
420 if(decBufSize < 2)
421 {
422 if(param.i_bframe)
423 {
424 ADM_warning("B-frames forbidden by the IDC level, disabling.\n");
425 param.i_bframe = 0;
426 }
427 }else if(decBufSize < 4 && param.i_bframe_pyramid != X264_B_PYRAMID_NONE)
428 {
429 ADM_warning("B-frame pyramid forbidden by the IDC level, disabling.\n");
430 param.i_bframe_pyramid = X264_B_PYRAMID_NONE;
431 }
432 }
433 // Sanitize VBV depending on profile, simple mode only
434 if(!x264Settings.useAdvancedConfiguration && x264Settings.general.profile != std::string("high444"))
435 {
436 int codedPicBufFactor = 4;
437 if(x264Settings.general.profile == std::string("high"))
438 codedPicBufFactor = 5;
439 int maxVbvBitrate = (level->bitrate * codedPicBufFactor) >> 2;
440 if(!param.rc.i_vbv_max_bitrate || param.rc.i_vbv_max_bitrate > maxVbvBitrate)
441 {
442 param.rc.i_vbv_max_bitrate = maxVbvBitrate;
443 }
444 int maxVbvBufSize = (level->cpb * codedPicBufFactor) >> 2;
445 if(!param.rc.i_vbv_buffer_size || param.rc.i_vbv_buffer_size > maxVbvBitrate)
446 {
447 param.rc.i_vbv_buffer_size = maxVbvBitrate;
448 }
449 }
450 // Log warnings about constraints violation which are impossible to correct
451 if(level->frame_size < nbMb)
452 ADM_warning("Too many macroblocks per frame for the IDC level: %d (max: %d)\n",nbMb,level->frame_size);
453 if(level->mbps < mbRate)
454 {
455 ADM_warning("Framerate %d/%d too high for IDC level (mb/s: %d, max: %d)\n",param.i_fps_num,param.i_fps_den,mbRate,level->mbps);
456 }
457 return true;
458 }
459 /**
460 \fn dumpx264Setup
461 */
dumpx264Setup(x264_param_t * param)462 static void dumpx264Setup(x264_param_t *param)
463 {
464 #define PI(x) printf(#x"\t:%d\n",(int)param->x);
465 PI(cpu);
466 PI(i_threads);
467 PI(b_sliced_threads);
468 PI(b_deterministic);
469 PI(i_sync_lookahead);
470
471 PI(i_width);
472 PI(i_height);
473 PI(i_width);
474 PI(i_level_idc);
475 PI(i_frame_total);
476
477 #define VI(x) printf(#x"\t:%d\n",(int)param->vui.x);
478
479 VI(i_sar_height);
480 VI(i_sar_width);
481 VI(i_overscan);
482 VI(i_vidformat);
483 VI(b_fullrange);
484 VI(i_colorprim);
485 VI(i_transfer);
486 VI(i_colmatrix);
487 VI(i_chroma_loc);
488
489 PI(i_fps_num);
490 PI(i_fps_den);
491
492 PI(i_timebase_num);
493 PI(i_timebase_den);
494 PI(b_vfr_input);
495
496 PI(i_frame_reference);
497 PI(i_keyint_max);
498 PI(i_keyint_min);
499 PI(i_scenecut_threshold);
500 PI(b_intra_refresh);
501
502 PI(i_bframe);
503 PI(i_bframe_adaptive);
504 PI(i_bframe_bias);
505 PI(i_bframe_pyramid);
506
507 PI(b_deblocking_filter);
508 PI(i_deblocking_filter_alphac0);
509 PI(i_deblocking_filter_beta);
510
511 PI(b_cabac);
512 PI(i_cabac_init_idc);
513
514 PI(b_interlaced);
515 PI(b_tff);
516 PI(b_fake_interlaced);
517 PI(b_bluray_compat);
518 PI(b_constrained_intra);
519
520 #define AI(x) printf(#x"\t:%d\n",(int)param->analyse.x);
521 #define AF(x) printf(#x"\t:%f\n",(float)param->analyse.x);
522 printf("*************************************\n");
523 printf("********* Analyse *********\n");
524 printf("*************************************\n");
525
526 AI(intra);
527 AI(inter);
528
529 AI(b_transform_8x8);
530 AI(i_weighted_pred);
531 AI(b_weighted_bipred);
532 AI(i_chroma_qp_offset);
533
534 AI(i_me_method);
535 AI(i_me_range);
536 AI(i_mv_range);
537 AI(i_mv_range_thread);
538 AI(i_subpel_refine);
539 AI(b_chroma_me);
540 AI(b_mixed_references);
541 AI(i_trellis);
542 AI(b_fast_pskip);
543
544 AI(b_dct_decimate);
545 AI(i_noise_reduction);
546 AF(f_psy_rd);
547 AF(f_psy_trellis);
548 AI(b_psy);
549
550 PI(b_aud);
551 PI(b_repeat_headers);
552 PI(b_annexb);
553
554 AI(i_luma_deadzone[0]);
555 AI(i_luma_deadzone[1]);
556
557 PI(i_sps_id);
558
559 PI(i_slice_max_size);
560 PI(i_slice_max_mbs);
561 PI(i_slice_count);
562
563 #define RI(x) printf(#x"\t:%d\n",(int)param->rc.x)
564 #define RF(x) printf(#x"\t:%f\n",(float)param->rc.x)
565 printf("*************************************\n");
566 printf("********* RC *********\n");
567 printf("*************************************\n");
568 RI(i_rc_method);
569 RI(i_qp_constant);
570 RF(f_rf_constant);
571 RI(i_qp_min);
572 RI(i_qp_max);
573 RI(i_qp_step);
574
575
576 RI(i_bitrate);
577 RI(i_qp_constant);
578 RF(f_rate_tolerance);
579 RI(i_vbv_max_bitrate);
580 RI(i_vbv_buffer_size);
581 RF(f_vbv_buffer_init);
582 RF(f_ip_factor);
583 RF(f_pb_factor);
584
585 RI(i_aq_mode);
586 RF(f_aq_strength);
587 RI(b_mb_tree);
588 RI(i_lookahead);
589
590 }
591 /**
592 * \fn x264LoadProfile
593 * @param profile
594 */
595 extern bool x264_encoder_jserialize(const char *file, const x264_encoder *key);
596 extern bool x264_encoder_jdeserialize(const char *file, const ADM_paramList *tmpl,x264_encoder *key);
597 extern "C"
598 {
599 extern const ADM_paramList x264_encoder_param[];
600 }
601
x264LoadProfile(const char * profile)602 bool x264LoadProfile(const char *profile)
603 {
604 x264_encoder param=x264Settings;
605 std::string rootPath;
606 ADM_pluginGetPath("x264",1,rootPath);
607 std::string fullPath=rootPath+std::string("/")+profile+std::string(".json");
608 ADM_info("Trying to load %s\n",fullPath.c_str());
609 if(false==x264_encoder_jdeserialize(fullPath.c_str(),x264_encoder_param,¶m))
610 {
611 ADM_warning("Failed\n");
612 return false;
613 }
614 ADM_info("Profile loaded ok\n");
615 x264Settings=param;
616 return true;
617 }
618
619 // EOF
620
621
622