Advertisement
Guest User

Handbrake Colorspace conversion BT709 <-> BT601

a guest
Oct 21st, 2011
175
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.92 KB | None | 0 0
  1. Index: test/test.c
  2. ===================================================================
  3. --- test/test.c (révision 4300)
  4. +++ test/test.c (copie de travail)
  5. @@ -61,6 +61,8 @@
  6. static char * decomb_opt = 0;
  7. static int rotate = 0;
  8. static char * rotate_opt = 0;
  9. +static int colorspace = 0;
  10. +static char * colorspace_opt = 0;
  11. static int grayscale = 0;
  12. static int vcodec = HB_VCODEC_FFMPEG_MPEG4;
  13. static hb_list_t * audios = NULL;
  14. @@ -1374,7 +1376,13 @@
  15. hb_filter_denoise.settings = denoise_opt;
  16. hb_list_add( job->filters, &hb_filter_denoise );
  17. }
  18. + if( colorspace )
  19. + {
  20. + hb_filter_colorspace.settings = colorspace_opt;
  21. + hb_list_add( job->filters, &hb_filter_colorspace);
  22. + }
  23. +
  24. switch( anamorphic_mode )
  25. {
  26. case 0: // Non-anamorphic
  27. @@ -2368,6 +2376,18 @@
  28. {
  29. job->color_matrix_code = color_matrix_code;
  30. }
  31. +
  32. + if( colorspace )
  33. + {
  34. + int in, out;
  35. + if( 2 == sscanf( colorspace_opt, "%d:%d", &in, &out ) )
  36. + {
  37. + if( out == 601 )
  38. + job->color_matrix_code = 1;
  39. + else if( out == 709 )
  40. + job->color_matrix_code = 2;
  41. + }
  42. + }
  43.  
  44. if( advanced_opts != NULL && *advanced_opts != '\0' )
  45. {
  46. @@ -2899,6 +2919,8 @@
  47. " <QP:M> (default 5:2)\n"
  48. " --rotate Flips images axes\n"
  49. " <M> (default 3)\n"
  50. + " --colorspace Do an explicit colorspace conversion\n"
  51. + " <601:709 or 709:601> (default Off)\n"
  52. " -g, --grayscale Grayscale encoding\n"
  53. "\n"
  54.  
  55. @@ -3110,6 +3132,7 @@
  56. #define X264_PROFILE 283
  57. #define X264_PRESET 284
  58. #define X264_TUNE 285
  59. + #define COLORSPACE_FILTER 286
  60.  
  61. for( ;; )
  62. {
  63. @@ -3159,6 +3182,7 @@
  64. { "decomb", optional_argument, NULL, '5' },
  65. { "grayscale", no_argument, NULL, 'g' },
  66. { "rotate", optional_argument, NULL, ROTATE_FILTER },
  67. + { "colorspace", required_argument, NULL, COLORSPACE_FILTER },
  68. { "strict-anamorphic", no_argument, &anamorphic_mode, 1 },
  69. { "loose-anamorphic", no_argument, &anamorphic_mode, 2 },
  70. { "custom-anamorphic", no_argument, &anamorphic_mode, 3 },
  71. @@ -3485,6 +3509,13 @@
  72. }
  73. rotate = 1;
  74. break;
  75. + case COLORSPACE_FILTER:
  76. + if( optarg != NULL )
  77. + {
  78. + colorspace_opt = strdup( optarg );
  79. + }
  80. + colorspace = 1;
  81. + break;
  82. case DISPLAY_WIDTH:
  83. if( optarg != NULL )
  84. {
  85. Index: libhb/hb.c
  86. ===================================================================
  87. --- libhb/hb.c (révision 4300)
  88. +++ libhb/hb.c (copie de travail)
  89. @@ -1696,6 +1696,15 @@
  90. hb_filter_denoise.settings = (char*)settings;
  91. return &hb_filter_denoise;
  92. }
  93. +
  94. + if (filter_id == HB_FILTER_COLORSPACE)
  95. + {
  96. + hb_filter_colorspace.settings = (char*)settings;
  97. + return &hb_filter_colorspace;
  98. + }
  99. +
  100. return NULL;
  101. }
  102.  
  103. Index: libhb/internal.h
  104. ===================================================================
  105. --- libhb/internal.h (révision 4300)
  106. +++ libhb/internal.h (copie de travail)
  107. @@ -371,7 +371,8 @@
  108. FILTER_DENOISE,
  109. FILTER_DETELECINE,
  110. FILTER_DECOMB,
  111. - FILTER_ROTATE
  112. + FILTER_ROTATE,
  113. + FILTER_COLORSPACE
  114. };
  115.  
  116. // Picture flags used by filters
  117. Index: libhb/colorspace.c
  118. ===================================================================
  119. --- libhb/colorspace.c (révision 0)
  120. +++ libhb/colorspace.c (révision 0)
  121. @@ -0,0 +1,332 @@
  122. +/* This file is based on Tritical's Colormatrix AviSynth Filter:
  123. + <http://web.missouri.edu/~kes25c/>
  124. +
  125. + ColorMatrix v2.5 for Avisynth 2.5.x
  126. +
  127. + ColorMatrix 2.0 is based on the original ColorMatrix filter by Wilbert
  128. + Dijkhof. It adds the ability to convert between any of: Rec.709, FCC,
  129. + Rec.601, and SMPTE 240M. It also makes pre and post clipping optional,
  130. + adds range expansion/contraction, and more...
  131. +
  132. + Copyright (C) 2006-2009 Kevin Stone
  133. +
  134. + ColorMatrix 1.x is Copyright (C) Wilbert Dijkhof
  135. +
  136. + This program is free software; you can redistribute it and/or modify
  137. + it under the terms of the GNU General Public License as published by
  138. + the Free Software Foundation; either version 2 of the License, or
  139. + (at your option) any later version.
  140. +
  141. + This program is distributed in the hope that it will be useful,
  142. + but WITHOUT ANY WARRANTY; without even the implied warranty of
  143. + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  144. + GNU General Public License for more details.
  145. +
  146. + You should have received a copy of the GNU General Public License
  147. + along with this program; if not, write to the Free Software
  148. + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  149. +*/
  150. +
  151. +#include "hb.h"
  152. +#include "hbffmpeg.h"
  153. +
  154. +#define XMIN(a,b) ((a) < (b) ? (a) : (b))
  155. +#define XMAX(a,b) ((a) > (b) ? (a) : (b))
  156. +#define CLIP(x) XMAX(XMIN((x),255),0)
  157. +#define ns(n) (((n) < 0) ? ((int)((n)*65536.0-0.5+__DBL_EPSILON__)) : (int)((n)*65536.0+0.5))
  158. +
  159. +static const double yuv_coeffs_luma[2][3] =
  160. +{
  161. + // GBR order, only care about Rec.709 or Rec.601
  162. + { +0.7152, +0.0722, +0.2126, }, // Rec.709 (0)
  163. + { +0.5870, +0.1140, +0.2990, }, // Rec.601 (ITU-R BT.470-2/SMPTE 170M) (1)
  164. +};
  165. +
  166. +struct hb_filter_private_s
  167. +{
  168. + int pix_fmt;
  169. + int width;
  170. + int height;
  171. + int mode;
  172. + // color conversion coeffs
  173. + int c1, c2, c3, c4, c5, c6, c7, c8;
  174. +
  175. + AVPicture pic_in;
  176. + AVPicture pic_out;
  177. + hb_buffer_t * buf_out;
  178. +};
  179. +
  180. +hb_filter_private_t * hb_colorspace_init( int pix_fmt,
  181. + int width,
  182. + int height,
  183. + char * settings );
  184. +
  185. +int hb_colorspace_work( const hb_buffer_t * buf_in,
  186. + hb_buffer_t ** buf_out,
  187. + int pix_fmt,
  188. + int width,
  189. + int height,
  190. + hb_filter_private_t * pv );
  191. +
  192. +void hb_colorspace_close( hb_filter_private_t * pv );
  193. +
  194. +hb_filter_object_t hb_filter_colorspace =
  195. +{
  196. + FILTER_COLORSPACE,
  197. + "Colorspace",
  198. + NULL,
  199. + hb_colorspace_init,
  200. + hb_colorspace_work,
  201. + hb_colorspace_close,
  202. +};
  203. +
  204. +#define ma m[0][0]
  205. +#define mb m[0][1]
  206. +#define mc m[0][2]
  207. +#define md m[1][0]
  208. +#define me m[1][1]
  209. +#define mf m[1][2]
  210. +#define mg m[2][0]
  211. +#define mh m[2][1]
  212. +#define mi m[2][2]
  213. +
  214. +#define ima im[0][0]
  215. +#define imb im[0][1]
  216. +#define imc im[0][2]
  217. +#define imd im[1][0]
  218. +#define ime im[1][1]
  219. +#define imf im[1][2]
  220. +#define img im[2][0]
  221. +#define imh im[2][1]
  222. +#define imi im[2][2]
  223. +
  224. +static void inverse3x3( double im[3][3], double m[3][3] )
  225. +{
  226. + double det = ma*(me*mi-mf*mh)-mb*(md*mi-mf*mg)+mc*(md*mh-me*mg);
  227. + det = 1.0/det;
  228. + ima = det*(me*mi-mf*mh);
  229. + imb = det*(mc*mh-mb*mi);
  230. + imc = det*(mb*mf-mc*me);
  231. + imd = det*(mf*mg-md*mi);
  232. + ime = det*(ma*mi-mc*mg);
  233. + imf = det*(mc*md-ma*mf);
  234. + img = det*(md*mh-me*mg);
  235. + imh = det*(mb*mg-ma*mh);
  236. + imi = det*(ma*me-mb*md);
  237. +}
  238. +
  239. +static void solve_coefficients( double cm[3][3], double rgb[3][3], double yuv[3][3],
  240. + double yiscale, double uviscale, double yoscale, double uvoscale )
  241. +{
  242. + int i, j;
  243. +
  244. + for( i=0; i<3; ++i )
  245. + {
  246. + double toscale = ( i == 0 ? yoscale : uvoscale );
  247. + for( j=0; j<3; ++j )
  248. + {
  249. + double tiscale = ( j == 0 ? yiscale : uviscale );
  250. + cm[i][j] = (yuv[i][0]*rgb[0][j]+yuv[i][1]*rgb[1][j]+
  251. + yuv[i][2]*rgb[2][j])*tiscale*toscale;
  252. + }
  253. + }
  254. +}
  255. +
  256. +static void calc_coefficients( hb_filter_private_t * pv )
  257. +{
  258. + int i, j, k, v;
  259. + double yuv_coeff[2][3][3];
  260. + double rgb_coeffd[2][3][3];
  261. + int yuv_convert[4][3][3];
  262. + double yuv_convertd[4][3][3];
  263. + double yiscale, yoscale, uviscale, uvoscale;
  264. +
  265. + for( i=0; i<2; ++i )
  266. + {
  267. + double bscale, rscale;
  268. + yuv_coeff[i][0][0] = yuv_coeffs_luma[i][0];
  269. + yuv_coeff[i][0][1] = yuv_coeffs_luma[i][1];
  270. + yuv_coeff[i][0][2] = yuv_coeffs_luma[i][2];
  271. + bscale = 0.5/(1.0-yuv_coeff[i][0][1]);
  272. + rscale = 0.5/(1.0-yuv_coeff[i][0][2]);
  273. + yuv_coeff[i][1][0] = -yuv_coeff[i][0][0]*bscale;
  274. + yuv_coeff[i][1][1] = (1.0-yuv_coeff[i][0][1])*bscale;
  275. + yuv_coeff[i][1][2] = -yuv_coeff[i][0][2]*bscale;
  276. + yuv_coeff[i][2][0] = -yuv_coeff[i][0][0]*rscale;
  277. + yuv_coeff[i][2][1] = -yuv_coeff[i][0][1]*rscale;
  278. + yuv_coeff[i][2][2] = (1.0-yuv_coeff[i][0][2])*rscale;
  279. + }
  280. +
  281. + for( i=0; i<2; ++i )
  282. + inverse3x3( rgb_coeffd[i], yuv_coeff[i] );
  283. +
  284. + yiscale = 1.0/219.0;
  285. + uviscale = 1.0/224.0;
  286. + yoscale = 219.0;
  287. + uvoscale = 224.0;
  288. +
  289. + v = 0;
  290. + for ( i=0; i<2; ++i )
  291. + {
  292. + for ( j=0; j<2; ++j )
  293. + {
  294. + solve_coefficients( yuv_convertd[v], rgb_coeffd[i], yuv_coeff[j],
  295. + yiscale, uviscale, yoscale, uvoscale );
  296. + for ( k=0; k<3; ++k )
  297. + {
  298. + yuv_convert[v][k][0] = ns(yuv_convertd[v][k][0]);
  299. + yuv_convert[v][k][1] = ns(yuv_convertd[v][k][1]);
  300. + yuv_convert[v][k][2] = ns(yuv_convertd[v][k][2]);
  301. + }
  302. + if ( yuv_convert[v][0][0] != 65536 ||
  303. + yuv_convert[v][1][0] != 0 || yuv_convert[v][2][0] != 0)
  304. + hb_log( "colorspace: error calculating conversion coefficients" );
  305. + ++v;
  306. + }
  307. + }
  308. +
  309. + pv->c1 = yuv_convert[pv->mode][0][0];
  310. + pv->c2 = yuv_convert[pv->mode][0][1];
  311. + pv->c3 = yuv_convert[pv->mode][0][2];
  312. + pv->c4 = yuv_convert[pv->mode][1][1];
  313. + pv->c5 = yuv_convert[pv->mode][1][2];
  314. + pv->c6 = yuv_convert[pv->mode][2][1];
  315. + pv->c7 = yuv_convert[pv->mode][2][2];
  316. + pv->c8 = ( 67584 - yuv_convert[pv->mode][0][0] )<<4 ;
  317. +}
  318. +
  319. +static int get_filter_mode( hb_filter_private_t * pv, const char * settings )
  320. +{
  321. + int src, dst;
  322. +
  323. + if( sscanf( settings, "%d:%d", &src, &dst ) != 2 )
  324. + return -1;
  325. +
  326. + if( src == 709 && dst == 601 )
  327. + return 1;
  328. + else if( src == 601 && dst == 709 )
  329. + return 2;
  330. + else
  331. + return -1;
  332. +}
  333. +
  334. +static void colorspace_filter( hb_filter_private_t * pv,
  335. + AVPicture * dst,
  336. + AVPicture * src )
  337. +{
  338. + const int width = pv->width;
  339. + const int height = pv->height;
  340. + const int strideY = src->linesize[0];
  341. + const int strideUV = src->linesize[1];
  342. +
  343. + int x, y;
  344. + uint8_t *srcYt = src->data[0];
  345. + uint8_t *srcYb = src->data[0] + strideY;
  346. + uint8_t *srcU = src->data[1];
  347. + uint8_t *srcV = src->data[2];
  348. + uint8_t *dstYt = dst->data[0];
  349. + uint8_t *dstYb = dst->data[0] + strideY;
  350. + uint8_t *dstU = dst->data[1];
  351. + uint8_t *dstV = dst->data[2];
  352. +
  353. + for( y=0; y<height; y+=2 )
  354. + {
  355. + for( x=0; x<width; x+=2 )
  356. + {
  357. + const int u = srcU[x>>1] - 128;
  358. + const int v = srcV[x>>1] - 128;
  359. + const int uv = pv->c2*u + pv->c3*v + pv->c8;
  360. + dstYt[x] = CLIP((pv->c1*srcYt[x] + uv) >> 16);
  361. + dstYt[x+1] = CLIP((pv->c1*srcYt[x+1] + uv) >> 16);
  362. + dstYb[x] = CLIP((pv->c1*srcYb[x] + uv) >> 16);
  363. + dstYb[x+1] = CLIP((pv->c1*srcYb[x+1] + uv) >> 16);
  364. + dstU[x>>1] = CLIP((pv->c4*u + pv->c5*v + 8421376) >> 16); // 8421376 = 128.5 to 16.16 fixed
  365. + dstV[x>>1] = CLIP((pv->c6*u + pv->c7*v + 8421376) >> 16);
  366. + }
  367. + srcYt += strideY<<1;
  368. + srcYb += strideY<<1;
  369. + srcU += strideUV;
  370. + srcV += strideUV;
  371. + dstYt += strideY<<1;
  372. + dstYb += strideY<<1;
  373. + dstU += strideUV;
  374. + dstV += strideUV;
  375. + }
  376. +}
  377. +
  378. +hb_filter_private_t * hb_colorspace_init( int pix_fmt,
  379. + int width,
  380. + int height,
  381. + char * settings )
  382. +{
  383. + if( pix_fmt != PIX_FMT_YUV420P || !settings )
  384. + {
  385. + return 0;
  386. + }
  387. +
  388. + hb_filter_private_t * pv = malloc( sizeof(struct hb_filter_private_s) );
  389. +
  390. + pv->pix_fmt = pix_fmt;
  391. + pv->width = width;
  392. + pv->height = height;
  393. + pv->mode = get_filter_mode( pv, settings );
  394. +
  395. + if( pv->mode > 0 )
  396. + {
  397. + calc_coefficients( pv );
  398. + }
  399. + else
  400. + {
  401. + return 0;
  402. + }
  403. +
  404. + pv->buf_out = hb_video_buffer_init( width, height );
  405. +
  406. + return pv;
  407. +}
  408. +
  409. +void hb_colorspace_close( hb_filter_private_t * pv )
  410. +{
  411. + if( !pv )
  412. + {
  413. + return;
  414. + }
  415. +
  416. + if( pv->buf_out )
  417. + {
  418. + hb_buffer_close( &pv->buf_out );
  419. + }
  420. +
  421. + free( pv );
  422. +}
  423. +
  424. +int hb_colorspace_work( const hb_buffer_t * buf_in,
  425. + hb_buffer_t ** buf_out,
  426. + int pix_fmt,
  427. + int width,
  428. + int height,
  429. + hb_filter_private_t * pv )
  430. +{
  431. + if( !pv ||
  432. + pix_fmt != pv->pix_fmt ||
  433. + width != pv->width ||
  434. + height != pv->height )
  435. + {
  436. + return FILTER_FAILED;
  437. + }
  438. +
  439. + avpicture_fill( &pv->pic_in, buf_in->data,
  440. + pix_fmt, width, height );
  441. +
  442. + avpicture_fill( &pv->pic_out, pv->buf_out->data,
  443. + pix_fmt, width, height );
  444. +
  445. + colorspace_filter( pv, &pv->pic_out, &pv->pic_in );
  446. +
  447. + hb_buffer_copy_settings( pv->buf_out, buf_in );
  448. +
  449. + *buf_out = pv->buf_out;
  450. +
  451. + return FILTER_OK;
  452. +}
  453. +
  454. Index: libhb/common.h
  455. ===================================================================
  456. --- libhb/common.h (révision 4300)
  457. +++ libhb/common.h (copie de travail)
  458. @@ -865,6 +865,7 @@
  459. #define HB_FILTER_DENOISE 4
  460. #define HB_FILTER_DECOMB 5
  461. #define HB_FILTER_ROTATE 6
  462. +#define HB_FILTER_COLORSPACE 7
  463.  
  464. extern hb_filter_object_t hb_filter_detelecine;
  465. extern hb_filter_object_t hb_filter_deinterlace;
  466. @@ -872,6 +873,7 @@
  467. extern hb_filter_object_t hb_filter_denoise;
  468. extern hb_filter_object_t hb_filter_decomb;
  469. extern hb_filter_object_t hb_filter_rotate;
  470. +extern hb_filter_object_t hb_filter_colorspace;
  471.  
  472. typedef void hb_error_handler_t( const char *errmsg );
  473.  
  474.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement