x264代码剖析(八):encode()函数之x264_encoder_close()函数

encode()函数是x264的主干函数。主要包含x264_encoder_open()函数、x264_encoder_headers()函数、x264_encoder_encode()函数与x264_encoder_close()函数四大部分,当中x264_encoder_encode()函数是其核心部分,详细的H.264视频编码算法均在此模块。

上三篇博文主要分析了x264_encoder_open()函数、x264_encoder_headers()函数与x264_encoder_encode()函数(兴许会继续深入)。本文主要学习x264_encoder_close()函数。

x264_encoder_close()是libx264的一个API函数。该函数用于关闭编码器,同一时候输出一些统计信息。例如以下图所看到的,调用了下面函数:

x264_lookahead_delete():释放Lookahead相关的变量。

x264_ratecontrol_summary():汇总码率控制信息。

x264_ratecontrol_delete():关闭码率控制。

相应的代码例如以下:

  1. /******************************************************************/
  2. /******************************************************************/
  3. /*
  4. ======Analysed by RuiDong Fang
  5. ======Csdn Blog:http://blog.csdn.net/frd2009041510
  6. ======Date:2016.03.10
  7. */
  8. /******************************************************************/
  9. /******************************************************************/
  10.  
  11. /************====== x264_encoder_close()函数 ======************/
  12. /*
  13. 功能:关闭编码器,同一时候输出一些统计信息。
  14. */
  15. /****************************************************************************
  16. * x264_encoder_close:
  17. ****************************************************************************/
  18. void x264_encoder_close ( x264_t *h )
  19. {
  20. int64_t i_yuv_size = FRAME_SIZE( h->param.i_width * h->param.i_height );
  21. int64_t i_mb_count_size[2][7] = {{0}};
  22. char buf[200];
  23. int b_print_pcm = h->stat.i_mb_count[SLICE_TYPE_I][I_PCM]
  24. || h->stat.i_mb_count[SLICE_TYPE_P][I_PCM]
  25. || h->stat.i_mb_count[SLICE_TYPE_B][I_PCM];
  26.  
  27. x264_lookahead_delete( h ); ////////////////////////释放lookahead相关的变量
  28.  
  29. #if HAVE_OPENCL
  30. x264_opencl_lookahead_delete( h );
  31. x264_opencl_function_t *ocl = h->opencl.ocl;
  32. #endif
  33.  
  34. if( h->param.b_sliced_threads )
  35. x264_threadpool_wait_all( h );
  36. if( h->param.i_threads > 1 )
  37. x264_threadpool_delete( h->threadpool );
  38. if( h->param.i_lookahead_threads > 1 )
  39. x264_threadpool_delete( h->lookaheadpool );
  40. if( h->i_thread_frames > 1 )
  41. {
  42. for( int i = 0; i < h->i_thread_frames; i++ )
  43. if( h->thread[i]->b_thread_active )
  44. {
  45. assert( h->thread[i]->fenc->i_reference_count == 1 );
  46. x264_frame_delete( h->thread[i]->fenc );
  47. }
  48.  
  49. x264_t *thread_prev = h->thread[h->i_thread_phase];
  50. x264_thread_sync_ratecontrol( h, thread_prev, h );
  51. x264_thread_sync_ratecontrol( thread_prev, thread_prev, h );
  52. h->i_frame = thread_prev->i_frame + 1 - h->i_thread_frames;
  53. }
  54. h->i_frame++;
  55.  
  56. /* Slices used and PSNR */
  57. /* 演示样例
  58. * x264 [info]: frame I:2 Avg QP:20.51 size: 20184 PSNR Mean Y:45.32 U:47.54 V:47.62 Avg:45.94 Global:45.52
  59. * x264 [info]: frame P:33 Avg QP:23.08 size: 3230 PSNR Mean Y:43.23 U:47.06 V:46.87 Avg:44.15 Global:44.00
  60. * x264 [info]: frame B:65 Avg QP:27.87 size: 352 PSNR Mean Y:42.76 U:47.21 V:47.05 Avg:43.79 Global:43.65
  61. */
  62. for( int i = 0; i < 3; i++ )
  63. {
  64. static const uint8_t slice_order[] = { SLICE_TYPE_I, SLICE_TYPE_P, SLICE_TYPE_B };
  65. int i_slice = slice_order[i];
  66.  
  67. if( h->stat.i_frame_count[i_slice] > 0 )
  68. {
  69. int i_count = h->stat.i_frame_count[i_slice];
  70. double dur = h->stat.f_frame_duration[i_slice];
  71. if( h->param.analyse.b_psnr )
  72. {
  73. //输出统计信息-包括PSNR
  74. //注意PSNR都是通过SSD换算过来的,换算方法就是调用x264_psnr()方法
  75. x264_log( h, X264_LOG_INFO,
  76. "frame %c:%-5d Avg QP:%5.2f size:%6.0f PSNR Mean Y:%5.2f U:%5.2f V:%5.2f Avg:%5.2f Global:%5.2f\n",
  77. slice_type_to_char[i_slice],
  78. i_count,
  79. h->stat.f_frame_qp[i_slice] / i_count,
  80. (double)h->stat.i_frame_size[i_slice] / i_count,
  81. h->stat.f_psnr_mean_y[i_slice] / dur, h->stat.f_psnr_mean_u[i_slice] / dur, h->stat.f_psnr_mean_v[i_slice] / dur,
  82. h->stat.f_psnr_average[i_slice] / dur,
  83. x264_psnr( h->stat.f_ssd_global[i_slice], dur * i_yuv_size ) );
  84. }
  85. else
  86. {
  87. //输出统计信息-不包括PSNR
  88. x264_log( h, X264_LOG_INFO,
  89. "frame %c:%-5d Avg QP:%5.2f size:%6.0f\n",
  90. slice_type_to_char[i_slice],
  91. i_count,
  92. h->stat.f_frame_qp[i_slice] / i_count,
  93. (double)h->stat.i_frame_size[i_slice] / i_count );
  94. }
  95. }
  96. }
  97.  
  98. /* 演示样例
  99. * x264 [info]: consecutive B-frames: 3.0% 10.0% 63.0% 24.0%
  100. *
  101. */
  102. if( h->param.i_bframe && h->stat.i_frame_count[SLICE_TYPE_B] )
  103. {
  104. //B帧相关信息
  105. char *p = buf;
  106. int den = 0;
  107. // weight by number of frames (including the I/P-frames) that are in a sequence of N B-frames
  108. for( int i = 0; i <= h->param.i_bframe; i++ )
  109. den += (i+1) * h->stat.i_consecutive_bframes[i];
  110. for( int i = 0; i <= h->param.i_bframe; i++ )
  111. p += sprintf( p, " %4.1f%%", 100. * (i+1) * h->stat.i_consecutive_bframes[i] / den );
  112. x264_log( h, X264_LOG_INFO, "consecutive B-frames:%s\n", buf );
  113. }
  114.  
  115. for( int i_type = 0; i_type < 2; i_type++ )
  116. for( int i = 0; i < X264_PARTTYPE_MAX; i++ )
  117. {
  118. if( i == D_DIRECT_8x8 ) continue; /* direct is counted as its own type */
  119. i_mb_count_size[i_type][x264_mb_partition_pixel_table[i]] += h->stat.i_mb_partition[i_type][i];
  120. }
  121.  
  122. /* MB types used */
  123. /* 演示样例
  124. * x264 [info]: mb I I16..4: 15.3% 37.5% 47.3%
  125. * x264 [info]: mb P I16..4: 0.6% 0.4% 0.2% P16..4: 34.6% 21.2% 12.7% 0.0% 0.0% skip:30.4%
  126. * x264 [info]: mb B I16..4: 0.0% 0.0% 0.0% B16..8: 21.2% 4.1% 0.7% direct: 0.8% skip:73.1% L0:28.7% L1:53.0% BI:18.3%
  127. */
  128. if( h->stat.i_frame_count[SLICE_TYPE_I] > 0 )
  129. {
  130. int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_I];
  131. double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_I] * h->mb.i_mb_count / 100.0;
  132.  
  133. //Intra宏块信息-存于buf
  134. //从左到右3个信息,依次为I16x16,I8x8,I4x4
  135. x264_print_intra( i_mb_count, i_count, b_print_pcm, buf );
  136. x264_log( h, X264_LOG_INFO, "mb I %s\n", buf );
  137. }
  138. if( h->stat.i_frame_count[SLICE_TYPE_P] > 0 )
  139. {
  140. int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_P];
  141. double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_P] * h->mb.i_mb_count / 100.0;
  142. int64_t *i_mb_size = i_mb_count_size[SLICE_TYPE_P];
  143.  
  144. x264_print_intra( i_mb_count, i_count, b_print_pcm, buf );//Intra宏块信息-存于buf
  145.  
  146. //Intra宏块信息-放在最前面
  147. //后面加入P宏块信息
  148. //从左到右6个信息,依次为P16x16, P16x8+P8x16, P8x8, P8x4+P4x8, P4x4, PSKIP
  149. x264_log( h, X264_LOG_INFO,
  150. "mb P %s P16..4: %4.1f%% %4.1f%% %4.1f%% %4.1f%% %4.1f%% skip:%4.1f%%\n",
  151. buf,
  152. i_mb_size[PIXEL_16x16] / (i_count*4),
  153. (i_mb_size[PIXEL_16x8] + i_mb_size[PIXEL_8x16]) / (i_count*4),
  154. i_mb_size[PIXEL_8x8] / (i_count*4),
  155. (i_mb_size[PIXEL_8x4] + i_mb_size[PIXEL_4x8]) / (i_count*4),
  156. i_mb_size[PIXEL_4x4] / (i_count*4),
  157. i_mb_count[P_SKIP] / i_count );
  158. }
  159. if( h->stat.i_frame_count[SLICE_TYPE_B] > 0 )
  160. {
  161. int64_t *i_mb_count = h->stat.i_mb_count[SLICE_TYPE_B];
  162. double i_count = (double)h->stat.i_frame_count[SLICE_TYPE_B] * h->mb.i_mb_count / 100.0;
  163. double i_mb_list_count;
  164. int64_t *i_mb_size = i_mb_count_size[SLICE_TYPE_B];
  165. int64_t list_count[3] = {0}; /* 0 == L0, 1 == L1, 2 == BI */
  166. x264_print_intra( i_mb_count, i_count, b_print_pcm, buf );//Intra宏块信息
  167. for( int i = 0; i < X264_PARTTYPE_MAX; i++ )
  168. for( int j = 0; j < 2; j++ )
  169. {
  170. int l0 = x264_mb_type_list_table[i][0][j];
  171. int l1 = x264_mb_type_list_table[i][1][j];
  172. if( l0 || l1 )
  173. list_count[l1+l0*l1] += h->stat.i_mb_count[SLICE_TYPE_B][i] * 2;
  174. }
  175. list_count[0] += h->stat.i_mb_partition[SLICE_TYPE_B][D_L0_8x8];
  176. list_count[1] += h->stat.i_mb_partition[SLICE_TYPE_B][D_L1_8x8];
  177. list_count[2] += h->stat.i_mb_partition[SLICE_TYPE_B][D_BI_8x8];
  178. i_mb_count[B_DIRECT] += (h->stat.i_mb_partition[SLICE_TYPE_B][D_DIRECT_8x8]+2)/4;
  179. i_mb_list_count = (list_count[0] + list_count[1] + list_count[2]) / 100.0;
  180.  
  181. //Intra宏块信息-放在最前面
  182. //后面加入B宏块信息
  183. //从左到右5个信息。依次为B16x16, B16x8+B8x16, B8x8, BDIRECT, BSKIP
  184. //
  185. //SKIP和DIRECT差别
  186. //P_SKIP的CBP为0,无像素残差,无运动矢量残
  187. //B_SKIP宏块的模式为B_DIRECT且CBP为0,无像素残差,无运动矢量残
  188. //B_DIRECT的CBP不为0,有像素残差,无运动矢量残
  189. sprintf( buf + strlen(buf), " B16..8: %4.1f%% %4.1f%% %4.1f%% direct:%4.1f%% skip:%4.1f%%",
  190. i_mb_size[PIXEL_16x16] / (i_count*4),
  191. (i_mb_size[PIXEL_16x8] + i_mb_size[PIXEL_8x16]) / (i_count*4),
  192. i_mb_size[PIXEL_8x8] / (i_count*4),
  193. i_mb_count[B_DIRECT] / i_count,
  194. i_mb_count[B_SKIP] / i_count );
  195. if( i_mb_list_count != 0 )
  196. sprintf( buf + strlen(buf), " L0:%4.1f%% L1:%4.1f%% BI:%4.1f%%",
  197. list_count[0] / i_mb_list_count,
  198. list_count[1] / i_mb_list_count,
  199. list_count[2] / i_mb_list_count );
  200. x264_log( h, X264_LOG_INFO, "mb B %s\n", buf );
  201. }
  202.  
  203. x264_ratecontrol_summary( h ); ////////////////////////汇总码率控制信息
  204.  
  205. if( h->stat.i_frame_count[SLICE_TYPE_I] + h->stat.i_frame_count[SLICE_TYPE_P] + h->stat.i_frame_count[SLICE_TYPE_B] > 0 )
  206. {
  207. #define SUM3(p) (p[SLICE_TYPE_I] + p[SLICE_TYPE_P] + p[SLICE_TYPE_B])
  208. #define SUM3b(p,o) (p[SLICE_TYPE_I][o] + p[SLICE_TYPE_P][o] + p[SLICE_TYPE_B][o])
  209. int64_t i_i8x8 = SUM3b( h->stat.i_mb_count, I_8x8 );
  210. int64_t i_intra = i_i8x8 + SUM3b( h->stat.i_mb_count, I_4x4 )
  211. + SUM3b( h->stat.i_mb_count, I_16x16 );
  212. int64_t i_all_intra = i_intra + SUM3b( h->stat.i_mb_count, I_PCM);
  213. int64_t i_skip = SUM3b( h->stat.i_mb_count, P_SKIP )
  214. + SUM3b( h->stat.i_mb_count, B_SKIP );
  215. const int i_count = h->stat.i_frame_count[SLICE_TYPE_I] +
  216. h->stat.i_frame_count[SLICE_TYPE_P] +
  217. h->stat.i_frame_count[SLICE_TYPE_B];
  218. int64_t i_mb_count = (int64_t)i_count * h->mb.i_mb_count;
  219. int64_t i_inter = i_mb_count - i_skip - i_intra;
  220. const double duration = h->stat.f_frame_duration[SLICE_TYPE_I] +
  221. h->stat.f_frame_duration[SLICE_TYPE_P] +
  222. h->stat.f_frame_duration[SLICE_TYPE_B];
  223. float f_bitrate = SUM3(h->stat.i_frame_size) / duration / 125;
  224.  
  225. if( PARAM_INTERLACED )//隔行
  226. {
  227. char *fieldstats = buf;
  228. fieldstats[0] = 0;
  229. if( i_inter )
  230. fieldstats += sprintf( fieldstats, " inter:%.1f%%", h->stat.i_mb_field[1] * 100.0 / i_inter );
  231. if( i_skip )
  232. fieldstats += sprintf( fieldstats, " skip:%.1f%%", h->stat.i_mb_field[2] * 100.0 / i_skip );
  233. x264_log( h, X264_LOG_INFO, "field mbs: intra: %.1f%%%s\n",
  234. h->stat.i_mb_field[0] * 100.0 / i_intra, buf );
  235. }
  236.  
  237. if( h->pps->b_transform_8x8_mode )//8x8DCT信息
  238. {
  239. buf[0] = 0;
  240. if( h->stat.i_mb_count_8x8dct[0] )
  241. sprintf( buf, " inter:%.1f%%", 100. * h->stat.i_mb_count_8x8dct[1] / h->stat.i_mb_count_8x8dct[0] );
  242. x264_log( h, X264_LOG_INFO, "8x8 transform intra:%.1f%%%s\n", 100. * i_i8x8 / i_intra, buf );
  243. }
  244.  
  245. if( (h->param.analyse.i_direct_mv_pred == X264_DIRECT_PRED_AUTO ||
  246. (h->stat.i_direct_frames[0] && h->stat.i_direct_frames[1]))
  247. && h->stat.i_frame_count[SLICE_TYPE_B] )
  248. {
  249. x264_log( h, X264_LOG_INFO, "direct mvs spatial:%.1f%% temporal:%.1f%%\n",
  250. h->stat.i_direct_frames[1] * 100. / h->stat.i_frame_count[SLICE_TYPE_B],
  251. h->stat.i_direct_frames[0] * 100. / h->stat.i_frame_count[SLICE_TYPE_B] );
  252. }
  253.  
  254. buf[0] = 0;
  255. int csize = CHROMA444 ? 4 : 1;
  256. if( i_mb_count != i_all_intra )
  257. sprintf( buf, " inter: %.1f%% %.1f%% %.1f%%",
  258. h->stat.i_mb_cbp[1] * 100.0 / ((i_mb_count - i_all_intra)*4),
  259. h->stat.i_mb_cbp[3] * 100.0 / ((i_mb_count - i_all_intra)*csize),
  260. h->stat.i_mb_cbp[5] * 100.0 / ((i_mb_count - i_all_intra)*csize) );
  261.  
  262. /*
  263. * 演示样例
  264. * x264 [info]: coded y,uvDC,uvAC intra: 74.1% 83.3% 58.9% inter: 10.4% 6.6% 0.4%
  265. */
  266. x264_log( h, X264_LOG_INFO, "coded y,%s,%s intra: %.1f%% %.1f%% %.1f%%%s\n",
  267. CHROMA444?
  268.  
  269. "u":"uvDC", CHROMA444?"v":"uvAC",
  270. h->stat.i_mb_cbp[0] * 100.0 / (i_all_intra*4),
  271. h->stat.i_mb_cbp[2] * 100.0 / (i_all_intra*csize),
  272. h->stat.i_mb_cbp[4] * 100.0 / (i_all_intra*csize), buf );
  273.  
  274. /*
  275. * 帧内预測信息
  276. * 从上到下分别为I16x16,I8x8,I4x4
  277. * 从左到右顺序为Vertical, Horizontal, DC, Plane ....
  278. *
  279. * 演示样例
  280. *
  281. * x264 [info]: i16 v,h,dc,p: 21% 25% 7% 48%
  282. * x264 [info]: i8 v,h,dc,ddl,ddr,vr,hd,vl,hu: 25% 23% 13% 6% 5% 5% 6% 8% 10%
  283. * x264 [info]: i4 v,h,dc,ddl,ddr,vr,hd,vl,hu: 22% 20% 9% 7% 7% 8% 8% 7% 12%
  284. * x264 [info]: i8c dc,h,v,p: 43% 20% 27% 10%
  285. *
  286. */
  287.  
  288. int64_t fixed_pred_modes[4][9] = {{0}};
  289. int64_t sum_pred_modes[4] = {0};
  290. for( int i = 0; i <= I_PRED_16x16_DC_128; i++ )
  291. {
  292. fixed_pred_modes[0][x264_mb_pred_mode16x16_fix[i]] += h->stat.i_mb_pred_mode[0][i];
  293. sum_pred_modes[0] += h->stat.i_mb_pred_mode[0][i];
  294. }
  295. if( sum_pred_modes[0] )
  296. x264_log( h, X264_LOG_INFO, "i16 v,h,dc,p: %2.0f%% %2.0f%% %2.0f%% %2.0f%%\n",
  297. fixed_pred_modes[0][0] * 100.0 / sum_pred_modes[0],
  298. fixed_pred_modes[0][1] * 100.0 / sum_pred_modes[0],
  299. fixed_pred_modes[0][2] * 100.0 / sum_pred_modes[0],
  300. fixed_pred_modes[0][3] * 100.0 / sum_pred_modes[0] );
  301. for( int i = 1; i <= 2; i++ )
  302. {
  303. for( int j = 0; j <= I_PRED_8x8_DC_128; j++ )
  304. {
  305. fixed_pred_modes[i][x264_mb_pred_mode4x4_fix(j)] += h->stat.i_mb_pred_mode[i][j];
  306. sum_pred_modes[i] += h->stat.i_mb_pred_mode[i][j];
  307. }
  308. if( sum_pred_modes[i] )
  309. x264_log( h, X264_LOG_INFO, "i%d v,h,dc,ddl,ddr,vr,hd,vl,hu: %2.0f%% %2.0f%% %2.0f%% %2.0f%% %2.0f%% %2.0f%% %2.0f%% %2.0f%% %2.0f%%\n", (3-i)*4,
  310. fixed_pred_modes[i][0] * 100.0 / sum_pred_modes[i],
  311. fixed_pred_modes[i][1] * 100.0 / sum_pred_modes[i],
  312. fixed_pred_modes[i][2] * 100.0 / sum_pred_modes[i],
  313. fixed_pred_modes[i][3] * 100.0 / sum_pred_modes[i],
  314. fixed_pred_modes[i][4] * 100.0 / sum_pred_modes[i],
  315. fixed_pred_modes[i][5] * 100.0 / sum_pred_modes[i],
  316. fixed_pred_modes[i][6] * 100.0 / sum_pred_modes[i],
  317. fixed_pred_modes[i][7] * 100.0 / sum_pred_modes[i],
  318. fixed_pred_modes[i][8] * 100.0 / sum_pred_modes[i] );
  319. }
  320. for( int i = 0; i <= I_PRED_CHROMA_DC_128; i++ )
  321. {
  322. fixed_pred_modes[3][x264_mb_chroma_pred_mode_fix[i]] += h->stat.i_mb_pred_mode[3][i];
  323. sum_pred_modes[3] += h->stat.i_mb_pred_mode[3][i];
  324. }
  325. if( sum_pred_modes[3] && !CHROMA444 )
  326. x264_log( h, X264_LOG_INFO, "i8c dc,h,v,p: %2.0f%% %2.0f%% %2.0f%% %2.0f%%\n",
  327. fixed_pred_modes[3][0] * 100.0 / sum_pred_modes[3],
  328. fixed_pred_modes[3][1] * 100.0 / sum_pred_modes[3],
  329. fixed_pred_modes[3][2] * 100.0 / sum_pred_modes[3],
  330. fixed_pred_modes[3][3] * 100.0 / sum_pred_modes[3] );
  331.  
  332. if( h->param.analyse.i_weighted_pred >= X264_WEIGHTP_SIMPLE && h->stat.i_frame_count[SLICE_TYPE_P] > 0 )
  333. x264_log( h, X264_LOG_INFO, "Weighted P-Frames: Y:%.1f%% UV:%.1f%%\n",
  334. h->stat.i_wpred[0] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P],
  335. h->stat.i_wpred[1] * 100.0 / h->stat.i_frame_count[SLICE_TYPE_P] );
  336.  
  337. /*
  338. * 參考帧信息
  339. * 从左到右依次为不同序号的參考帧
  340. *
  341. * 演示样例
  342. *
  343. * x264 [info]: ref P L0: 62.5% 19.7% 13.8% 4.0%
  344. * x264 [info]: ref B L0: 88.8% 9.4% 1.9%
  345. * x264 [info]: ref B L1: 92.6% 7.4%
  346. *
  347. */
  348. for( int i_list = 0; i_list < 2; i_list++ )
  349. for( int i_slice = 0; i_slice < 2; i_slice++ )
  350. {
  351. char *p = buf;
  352. int64_t i_den = 0;
  353. int i_max = 0;
  354. for( int i = 0; i < X264_REF_MAX*2; i++ )
  355. if( h->stat.i_mb_count_ref[i_slice][i_list][i] )
  356. {
  357. i_den += h->stat.i_mb_count_ref[i_slice][i_list][i];
  358. i_max = i;
  359. }
  360. if( i_max == 0 )
  361. continue;
  362. for( int i = 0; i <= i_max; i++ )
  363. p += sprintf( p, " %4.1f%%", 100. * h->stat.i_mb_count_ref[i_slice][i_list][i] / i_den );
  364. x264_log( h, X264_LOG_INFO, "ref %c L%d:%s\n", "PB"[i_slice], i_list, buf );
  365. }
  366.  
  367. if( h->param.analyse.b_ssim )
  368. {
  369. float ssim = SUM3( h->stat.f_ssim_mean_y ) / duration;
  370. x264_log( h, X264_LOG_INFO, "SSIM Mean Y:%.7f (%6.3fdb)\n", ssim, x264_ssim( ssim ) );
  371. }
  372.  
  373. /*
  374. * 演示样例
  375. *
  376. * x264 [info]: PSNR Mean Y:42.967 U:47.163 V:47.000 Avg:43.950 Global:43.796 kb/s:339.67
  377. *
  378. */
  379. if( h->param.analyse.b_psnr )
  380. {
  381. x264_log( h, X264_LOG_INFO,
  382. "PSNR Mean Y:%6.3f U:%6.3f V:%6.3f Avg:%6.3f Global:%6.3f kb/s:%.2f\n",
  383. SUM3( h->stat.f_psnr_mean_y ) / duration,
  384. SUM3( h->stat.f_psnr_mean_u ) / duration,
  385. SUM3( h->stat.f_psnr_mean_v ) / duration,
  386. SUM3( h->stat.f_psnr_average ) / duration,
  387. x264_psnr( SUM3( h->stat.f_ssd_global ), duration * i_yuv_size ),
  388. f_bitrate );
  389. }
  390. else
  391. x264_log( h, X264_LOG_INFO, "kb/s:%.2f\n", f_bitrate );
  392. }
  393.  
  394. /* rc */
  395. x264_ratecontrol_delete( h ); ////////////////////////关闭码率控制
  396.  
  397. /* param */
  398. if( h->param.rc.psz_stat_out )
  399. free( h->param.rc.psz_stat_out );
  400. if( h->param.rc.psz_stat_in )
  401. free( h->param.rc.psz_stat_in );
  402.  
  403. //free......
  404. x264_cqm_delete( h );
  405. x264_free( h->nal_buffer );
  406. x264_free( h->reconfig_h );
  407. x264_analyse_free_costs( h );
  408.  
  409. if( h->i_thread_frames > 1 )
  410. h = h->thread[h->i_thread_phase];
  411.  
  412. /* frames */
  413. x264_frame_delete_list( h->frames.unused[0] );
  414. x264_frame_delete_list( h->frames.unused[1] );
  415. x264_frame_delete_list( h->frames.current );
  416. x264_frame_delete_list( h->frames.blank_unused );
  417.  
  418. h = h->thread[0];
  419.  
  420. for( int i = 0; i < h->i_thread_frames; i++ )
  421. if( h->thread[i]->b_thread_active )
  422. for( int j = 0; j < h->thread[i]->i_ref[0]; j++ )
  423. if( h->thread[i]->fref[0][j] && h->thread[i]->fref[0][j]->b_duplicate )
  424. x264_frame_delete( h->thread[i]->fref[0][j] );
  425.  
  426. if( h->param.i_lookahead_threads > 1 )
  427. for( int i = 0; i < h->param.i_lookahead_threads; i++ )
  428. x264_free( h->lookahead_thread[i] );
  429.  
  430. for( int i = h->param.i_threads - 1; i >= 0; i-- )
  431. {
  432. x264_frame_t **frame;
  433.  
  434. if( !h->param.b_sliced_threads || i == 0 )
  435. {
  436. for( frame = h->thread[i]->frames.reference; *frame; frame++ )
  437. {
  438. assert( (*frame)->i_reference_count > 0 );
  439. (*frame)->i_reference_count--;
  440. if( (*frame)->i_reference_count == 0 )
  441. x264_frame_delete( *frame );
  442. }
  443. frame = &h->thread[i]->fdec;
  444. if( *frame )
  445. {
  446. assert( (*frame)->i_reference_count > 0 );
  447. (*frame)->i_reference_count--;
  448. if( (*frame)->i_reference_count == 0 )
  449. x264_frame_delete( *frame );
  450. }
  451. x264_macroblock_cache_free( h->thread[i] );
  452. }
  453. x264_macroblock_thread_free( h->thread[i], 0 );
  454. x264_free( h->thread[i]->out.p_bitstream );
  455. x264_free( h->thread[i]->out.nal );
  456. x264_pthread_mutex_destroy( &h->thread[i]->mutex );
  457. x264_pthread_cond_destroy( &h->thread[i]->cv );
  458. x264_free( h->thread[i] );
  459. }
  460. #if HAVE_OPENCL
  461. x264_opencl_close_library( ocl );
  462. #endif
  463. }

最后给出结果示意图,例如以下图:

至此。x264的主干函数(x264_encoder_open()函数、x264_encoder_headers()函数、x264_encoder_encode()函数与x264_encoder_close()函数)就简单粗暴地呈现出来了。接下来将深入H.264算法继续进行分析。

x264代码剖析(八):encode()函数之x264_encoder_close()函数的更多相关文章

  1. x264代码剖析(三):主函数main()、解析函数parse()与编码函数encode()

    x264代码剖析(三):主函数main().解析函数parse()与编码函数encode() x264的入口函数为main().main()函数首先调用parse()解析输入的參数,然后调用encod ...

  2. x264代码剖析(十三):核心算法之帧间预測函数x264_mb_analyse_inter_*()

    x264代码剖析(十三):核心算法之帧间预測函数x264_mb_analyse_inter_*() 帧间预測是指利用视频时间域相关性,使用临近已编码图像像素预測当前图像的像素,以达到有效去除视频时域冗 ...

  3. x264代码剖析(十五):核心算法之宏块编码中的变换编码

    x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率.须要对图像进行压缩,通常採用变换编码及量化来消除图像中的相关性以降低图像编码的动态范围.本文主要介绍变换编码的相 ...

  4. (转)x264代码详细阅读之x264.c,common.c,encoder.c

    转自:http://alphamailpost.blog.163.com/blog/static/201118081201281103931932/ x264代码详细阅读第一之x264.chttp:/ ...

  5. libevent源码深度剖析八

    libevent源码深度剖析八 ——集成信号处理 张亮 现在我们已经了解了libevent的基本框架:事件管理框架和事件主循环.上节提到了libevent中I/O事件和Signal以及Timer事件的 ...

  6. 手机自动化测试:Appium源码分析之跟踪代码分析八

    手机自动化测试:Appium源码分析之跟踪代码分析八   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家 ...

  7. HDFS集中式的缓存管理原理与代码剖析--转载

    原文地址:http://yanbohappy.sinaapp.com/?p=468 Hadoop 2.3.0已经发布了,其中最大的亮点就是集中式的缓存管理(HDFS centralized cache ...

  8. HDFS集中式的缓存管理原理与代码剖析

    转载自:http://www.infoq.com/cn/articles/hdfs-centralized-cache/ HDFS集中式的缓存管理原理与代码剖析 Hadoop 2.3.0已经发布了,其 ...

  9. 《VR入门系列教程》之22---GearVR SDK代码剖析

    GearVR SDK代码剖析     接下来我们来了解一下GearVR开发包的底层代码,它底层的代码和之前在第三章中讲的桌面SDK代码非常类似,当然,也有许多不同的地方.     首先,我们看看如何构 ...

随机推荐

  1. [Spark源代码剖析] DAGScheduler提交stage

    转载请标明出处:http://blog.csdn.net/bigbigdata/article/details/47310657 DAGScheduler通过调用submitStage来提交stage ...

  2. &lt;Machine Learning in Action &gt;之二 朴素贝叶斯 C#实现文章分类

    def trainNB0(trainMatrix,trainCategory): numTrainDocs = len(trainMatrix) numWords = len(trainMatrix[ ...

  3. Android 4.3 系统裁剪——删除不使用的app及添加自己app

    删除不使用的apk 系统自带的app位置是在/android4.3/packages/apps 以下是一些APP作用分析: | |– BasicSmsReceiver | |– Bluetooth ( ...

  4. iOS开发系列之四 - UITextView 使用方法小结

    // 初始化输入框并设置位置和大小 UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 1 ...

  5. Delegates, Events, and Anonymous Methods 委托、事件与匿名方法

    http://www.cnblogs.com/r01cn/archive/2012/11/30/2795977.html

  6. jQuery插件开发初探

    最简单的插件 $.fn.changeStyle = function (colorStr) { $(this).css('color',colorStr); } 应用如下: <!DOCTYPE ...

  7. CentOS下安装C/C++开发工具包的最佳方式

    如果你使用的是 Fedora, Red Hat, CentOS, 或者 Scientific Linux 系统,使用下面的命令安装GNU的C/C++开发包和编译器. # yum groupinstal ...

  8. hbase启动报错:Java HotSpot(TM) 64-Bit Server VM warning: ignoring option PermSize=128m; support was removed in 8.0

    输入HBASE_MASTER_OPTS只是为了快速寻找这个选项而已,如果你手工找也可以 刚才那个命令回车后直接跳到这 前面加#就好了 修改后保存.重新启动hbase就好了. 注意:各个节点都要修改哦. ...

  9. NARF(Normal Aligned Radial Feature)关键点

    NARF(Normal Aligned Radial Feature)关键点是为了从深度图像中识别物体而提出的,对NARF关键点的提取过程有以下要求: a) 提取的过程考虑边缘以及物体表面变化信息在内 ...

  10. K-序列(埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛)

    题目描述 给一个数组 a,长度为 n,若某个子序列中的和为 K 的倍数,那么这个序列被称为“K 序列”.现在要你 对数组 a 求出最长的子序列的长度,满足这个序列是 K 序列.  输入描述: 第一行为 ...