Advertisement
Guest User

Untitled

a guest
Jul 21st, 2017
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 25.91 KB | None | 0 0
  1. From a5758310739240e7adba9131467781d49b188ec0 Mon Sep 17 00:00:00 2001
  2. From: George Stephanos <gaf.stephanos@gmail.com>
  3. Date: Tue, 14 Dec 2010 21:42:49 +0200
  4. Subject: [PATCH] --device option added with ~basic functionality.
  5.  
  6. ---
  7. common/common.c   |  269 +++++++++++++++++++++++++++++++++++++++++++++++++----
  8.  encoder/encoder.c |    2 +-
  9.  encoder/set.c     |   26 +++++-
  10.  encoder/set.h     |    1 +
  11.  x264.c            |   84 ++++++++--------
  12.  x264.h            |   50 ++++++++++-
  13.  6 files changed, 368 insertions(+), 64 deletions(-)
  14.  
  15. diff --git a/common/common.c b/common/common.c
  16. index 26b62a3..9653b62 100644
  17. --- a/common/common.c
  18. +++ b/common/common.c
  19. @@ -25,14 +25,18 @@
  20.   *****************************************************************************/
  21.  
  22.  #include "common.h"
  23. +#include "encoder/set.h"
  24.  
  25.  #include <stdarg.h>
  26.  #include <ctype.h>
  27. +#include <math.h>
  28.  
  29.  #if HAVE_MALLOC_H
  30.  #include <malloc.h>
  31.  #endif
  32.  
  33. +#define DELIMETERS ",./-+"
  34. +
  35.  const int x264_bit_depth = BIT_DEPTH;
  36.  
  37.  static void x264_log_default( void *, int, const char *, va_list );
  38. @@ -66,7 +70,7 @@ void x264_param_default( x264_param_t *param )
  39.      param->vui.i_chroma_loc= 0;  /* left center */
  40.      param->i_fps_num       = 25;
  41.      param->i_fps_den       = 1;
  42. -    param->i_level_idc     = -1;
  43. +    param->i_level_idc     = X264_LEVEL_IDC_AUTO;
  44.      param->i_slice_max_size = 0;
  45.      param->i_slice_max_mbs = 0;
  46.      param->i_slice_count = 0;
  47. @@ -297,8 +301,8 @@ static int x264_param_apply_tune( x264_param_t *param, const char *tune )
  48.      char *tmp = x264_malloc( strlen( tune ) + 1 );
  49.      if( !tmp )
  50.          return -1;
  51. -    tmp = strcpy( tmp, tune );
  52. -    char *s = strtok( tmp, ",./-+" );
  53. +    strcpy( tmp, tune );
  54. +    char *s = strtok( tmp, DELIMETERS );
  55.      int psy_tuning_used = 0;
  56.      while( s )
  57.      {
  58. @@ -392,7 +396,7 @@ static int x264_param_apply_tune( x264_param_t *param, const char *tune )
  59.      psy_failure:
  60.              x264_log( NULL, X264_LOG_WARNING, "only 1 psy tuning can be used: ignoring tune %s\n", s );
  61.          }
  62. -        s = strtok( NULL, ",./-+" );
  63. +        s = strtok( NULL, DELIMETERS );
  64.      }
  65.      x264_free( tmp );
  66.      return 0;
  67. @@ -424,21 +428,49 @@ void x264_param_apply_fastfirstpass( x264_param_t *param )
  68.      }
  69.  }
  70.  
  71. -int x264_param_apply_profile( x264_param_t *param, const char *profile )
  72. +static void x264_calculate_resolution( const x264_level_t *level, int width, int height, double fps,
  73. +                                       int b_interlaced, x264_param_compat_t *compat )
  74.  {
  75. -    if( !profile )
  76. -        return 0;
  77. +    if( !compat )
  78. +        return;
  79. +    int w = width, h = height;
  80. +    double max_mbs = X264_MIN( level->mbps / fps, level->frame_size );
  81. +    double frac = sqrt( (256 * max_mbs) / (w * h) );
  82. +    double step = 0.01*frac;
  83. +    int mbs_w = (w+15)/16;
  84. +    int mbs_h = (h+15)/16;
  85. +    while( mbs_w * mbs_h > max_mbs )
  86. +    {
  87. +        w = round( width*frac );
  88. +        h = round( height*frac );
  89. +        w &= ~1;
  90. +        h = h&~1&~(2*b_interlaced);
  91. +        mbs_w = (w+15)/16;
  92. +        mbs_h = (h+15)/16;
  93. +        frac -= step;
  94. +    }
  95. +    compat->i_width = w;
  96. +    compat->i_height = h;
  97. +}
  98.  
  99. -#if BIT_DEPTH > 8
  100. -    if( !strcasecmp( profile, "baseline" ) || !strcasecmp( profile, "main" ) ||
  101. -        !strcasecmp( profile, "high" ) )
  102. -    {
  103. -        x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support a bit depth of %d.\n", profile, BIT_DEPTH );
  104. -        return -1;
  105. -    }
  106. -#endif
  107. +static int x264_get_profile( const char *p_profile )
  108. +{
  109. +    if( !p_profile )
  110. +        return 0;
  111. +    else if( !strcasecmp( p_profile, "baseline" ) )
  112. +        return PROFILE_BASELINE;
  113. +    else if( !strcasecmp( p_profile, "main" ) )
  114. +        return PROFILE_MAIN;
  115. +    else if( !strcasecmp( p_profile, "high" ) )
  116. +        return PROFILE_HIGH;
  117. +    else if( !strcasecmp( p_profile, "high10" ) )
  118. +        return PROFILE_HIGH10;
  119. +    return 0;
  120. +}
  121.  
  122. -    if( !strcasecmp( profile, "baseline" ) )
  123. +static int x264_param_apply_profile_internal( x264_param_t *param, int profile )
  124. +{
  125. +    if( profile == PROFILE_BASELINE )
  126.      {
  127.          param->analyse.b_transform_8x8 = 0;
  128.          param->b_cabac = 0;
  129. @@ -456,12 +488,12 @@ int x264_param_apply_profile( x264_param_t *param, const char *profile )
  130.              return -1;
  131.          }
  132.      }
  133. -    else if( !strcasecmp( profile, "main" ) )
  134. +    else if( profile == PROFILE_MAIN )
  135.      {
  136.          param->analyse.b_transform_8x8 = 0;
  137.          param->i_cqm_preset = X264_CQM_FLAT;
  138.      }
  139. -    else if( !strcasecmp( profile, "high" ) || !strcasecmp( profile, "high10" ) )
  140. +    else if( profile >= PROFILE_HIGH )
  141.      {
  142.          /* Default */
  143.      }
  144. @@ -479,6 +511,209 @@ int x264_param_apply_profile( x264_param_t *param, const char *profile )
  145.      return 0;
  146.  }
  147.  
  148. +int x264_param_apply_profile( x264_param_t *param, const char *profile )
  149. +{
  150. +    if( !profile )
  151. +        return 0;
  152. +
  153. +#if BIT_DEPTH > 8
  154. +    if( x264_get_profile( profile ) <= PROFILE_HIGH )
  155. +    {
  156. +        x264_log( NULL, X264_LOG_ERROR, "%s profile doesn't support a bit depth of %d.\n", profile, BIT_DEPTH );
  157. +        return -1;
  158. +    }
  159. +#endif
  160. +
  161. +    return x264_param_apply_profile_internal( param, x264_get_profile( profile ) );
  162. +}
  163. +
  164. +static int x264_param_apply_level_internal( x264_param_t *param, int profile, x264_param_compat_t *compat )
  165. +{
  166. +    int level_idc = param->i_level_idc;
  167. +    if( level_idc == X264_LEVEL_IDC_AUTO )
  168. +        return 0;
  169. +
  170. +    int prof = BIT_DEPTH == 8 ? PROFILE_HIGH : PROFILE_HIGH10;
  171. +
  172. +    if( profile )
  173. +    {
  174. +#if BIT_DEPTH > 8
  175. +        if( profile < PROFILE_HIGH10 )
  176. +        {
  177. +            x264_log( NULL, X264_LOG_ERROR, "specified profile too low for high bit depth\n" );
  178. +            return -1;
  179. +        }
  180. +#endif
  181. +        prof = profile;
  182. +    }
  183. +
  184. +    const x264_level_t *l = x264_get_level( level_idc );
  185. +    if( !l )
  186. +    {
  187. +        x264_log( NULL, X264_LOG_ERROR, "invalid level_idc: %d\n", level_idc );
  188. +        return -1;
  189. +    }
  190. +    x264_calculate_resolution( l, param->i_width, param->i_height,
  191. +                               (double)param->i_fps_num / (double)param->i_fps_den,
  192. +                               param->b_interlaced || param->b_fake_interlaced, compat );
  193. +
  194. +    char level_name[5];
  195. +    snprintf( level_name, sizeof(level_name), "%d.%d", level_idc/10, level_idc%10 );
  196. +    if( level_idc == 9 )
  197. +        strcpy( level_name, "1b" );
  198. +    int cbp_factor = prof == PROFILE_HIGH10 ? 12 :
  199. +                     prof == PROFILE_HIGH ? 5 : 4;
  200. +    int mb_size = 384*BIT_DEPTH/8;
  201. +    int mbs;
  202. +    mbs = compat ? ((compat->i_width+15)/16) * ((compat->i_height+15)/16) :
  203. +                   ((param->i_width +15)/16) * ((param->i_height +15)/16);
  204. +    while( 1 )
  205. +    {
  206. +        int num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
  207. +        int max_dec_frame_buffering = X264_MIN(X264_REF_MAX, X264_MAX4(param->i_frame_reference, 1 + num_reorder_frames,
  208. +                                      param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
  209. +        int dpb = max_dec_frame_buffering * mbs * mb_size;
  210. +
  211. +        if( dpb <= l->dpb )
  212. +            break;
  213. +
  214. +        if( max_dec_frame_buffering == 4 && param->i_bframe_pyramid )
  215. +            param->i_bframe_pyramid = 0;
  216. +        else if( max_dec_frame_buffering == 2 && param->i_bframe )
  217. +            param->i_bframe = 0;
  218. +        else if( max_dec_frame_buffering == 1 )
  219. +        {
  220. +            x264_log( NULL, X264_LOG_WARNING, "Impossible DPB size %d required by level %s.  Lowest\n", l->dpb, level_name );
  221. +            x264_log( NULL, X264_LOG_WARNING, "possible is %d; try a higher level or lower resolution.\n", dpb );
  222. +            return 0;
  223. +        }
  224. +        else if( param->i_dpb_size > param->i_frame_reference )
  225. +            param->i_dpb_size--;
  226. +        else
  227. +            param->i_frame_reference--;
  228. +    }
  229. +
  230. +#define LIMIT( name, limit, val ) \
  231. +    if( (val) > (limit) || (val) <= 0 ) \
  232. +        val = limit;
  233. +
  234. +    LIMIT( "VBV bitrate", l->bitrate * cbp_factor / 4, param->rc.i_vbv_max_bitrate );
  235. +    LIMIT( "VBV buffer", l->cpb * cbp_factor / 4, param->rc.i_vbv_buffer_size );
  236. +    LIMIT( "MV range", l->mv_range, param->analyse.i_mv_range );
  237. +    return 0;
  238. +}
  239. +
  240. +int x264_param_apply_level( x264_param_t *param, const char *profile, x264_param_compat_t *compat )
  241. +{
  242. +    return x264_param_apply_level_internal( param, x264_get_profile( profile ), compat );
  243. +}
  244. +
  245. +typedef struct
  246. +{
  247. +    char    *name;
  248. +    int     i_screen_width;
  249. +    int     i_screen_height;
  250. +    int     i_level_idc;
  251. +    int     i_profile;
  252. +} x264_device_t;
  253. +
  254. +static const x264_device_t x264_devices[] =
  255. +{
  256. +    {"ipad",    1024, 768,  31, PROFILE_HIGH    },
  257. +    {"iphone",  480,  320,  30, PROFILE_BASELINE},
  258. +    {"iphone4", 960,  640,  31, PROFILE_MAIN    },
  259. +    {"ipod",    320,  240,  30, PROFILE_BASELINE},
  260. +    {"n900",    800,  480,  30, PROFILE_BASELINE},
  261. +    {"n8",      640,  360,  31, PROFILE_HIGH    },
  262. +    {"ps3",     1920, 1080, 41, PROFILE_HIGH    },
  263. +    {"psp",     480,  272,  30, PROFILE_MAIN    },
  264. +    {"xbox360", 1920, 1080, 41, PROFILE_HIGH    },
  265. +    {"wdtv",    1920, 1080, 41, PROFILE_HIGH    },
  266. +    {"test",    128,  96,   10, PROFILE_BASELINE}
  267. +};
  268. +
  269. +static const x264_device_t *x264_get_device( const char *device )
  270. +{
  271. +    for( int i = 0; i < sizeof(x264_devices) / sizeof(x264_device_t); i++ )
  272. +        if( !strcasecmp( device, x264_devices[i].name ) )
  273. +            return x264_devices+i;
  274. +    return NULL;
  275. +}
  276. +
  277. +/* Returns 0 if successful.
  278. + * Failure status non-existent as only bluray would generate conflicts. */
  279. +static int x264_param_apply_device_restrictions( x264_param_t *param, const char *device )
  280. +{
  281. +    if( !strcasecmp( device, "psp" ) )
  282. +    {
  283. +        if( param->i_frame_reference > 3 )
  284. +        {
  285. +            param->i_frame_reference = 3;
  286. +            x264_log( NULL, X264_LOG_WARNING, "Reference frames set to 3\n" );
  287. +        }
  288. +        if( param->i_bframe_pyramid > 0 )
  289. +        {
  290. +            param->i_bframe_pyramid = 0;
  291. +            x264_log( NULL, X264_LOG_WARNING, "B-Pyramid disabled\n" );
  292. +        }
  293. +    }
  294. +    else if( !strcasecmp( device, "n8" ) )
  295. +    {
  296. +        if( param->i_frame_reference > 6 )
  297. +        {
  298. +            param->i_frame_reference = 6;
  299. +            x264_log( NULL, X264_LOG_WARNING, "Reference frames set to 6\n" );
  300. +        }
  301. +    }
  302. +    return 0;
  303. +}
  304. +
  305. +int x264_param_apply_device( x264_param_t *param, const char *device, x264_param_compat_t *compat )
  306. +{
  307. +    if( !device )
  308. +        return -1;
  309. +    char *tmp = x264_malloc( strlen( device ) + 1 );
  310. +    if( !tmp )
  311. +        return -1;
  312. +    strcpy( tmp, device );
  313. +    char *s = strtok( tmp, DELIMETERS );
  314. +    int profile = INT_MAX;
  315. +    while( s )
  316. +    {
  317. +        const x264_device_t *device_t = x264_get_device( s );
  318. +        if( !device_t )
  319. +        {
  320. +            x264_log( NULL, X264_LOG_WARNING, "invalid device: %s\n", s );
  321. +            x264_free( tmp );
  322. +            return -1;
  323. +        }
  324. +#if BIT_DEPTH > 8
  325. +        if( device_t->i_profile < PROFILE_HIGH10 )
  326. +        {
  327. +            x264_log( NULL, X264_LOG_ERROR, "%s does not support high bit depth\n", s );
  328. +            x264_free( tmp );
  329. +            return -1;
  330. +        }
  331. +#endif
  332. +        if( param->i_level_idc > device_t->i_level_idc || //Won't work right if one
  333. +            param->i_level_idc == X264_LEVEL_IDC_AUTO)    //of the devices is a 1b
  334. +            param->i_level_idc = device_t->i_level_idc;
  335. +        if( profile > device_t->i_profile )
  336. +            profile = device_t->i_profile;
  337. +
  338. +        if( x264_param_apply_device_restrictions( param, device ) < 0 )
  339. +        {
  340. +            x264_log( NULL, X264_LOG_ERROR, "failed to apply extra restrictions of %s\n", s );
  341. +            x264_free( tmp );
  342. +            return -1;
  343. +        }
  344. +        s = strtok( NULL, DELIMETERS );
  345. +    }
  346. +    x264_free( tmp );
  347. +    return -( x264_param_apply_profile_internal( param, profile ) < 0 ||
  348. +        x264_param_apply_level_internal( param, profile, compat ) < 0 );
  349. +}
  350. +
  351.  static int parse_enum( const char *arg, const char * const *names, int *dst )
  352.  {
  353.      for( int i = 0; names[i]; i++ )
  354. diff --git a/encoder/encoder.c b/encoder/encoder.c
  355. index b5f1d1d..edc58aa 100644
  356. --- a/encoder/encoder.c
  357. +++ b/encoder/encoder.c
  358. @@ -744,7 +744,7 @@ static int x264_validate_parameters( x264_t *h )
  359.  
  360.      {
  361.          const x264_level_t *l = x264_levels;
  362. -        if( h->param.i_level_idc < 0 )
  363. +        if( h->param.i_level_idc == X264_LEVEL_IDC_AUTO )
  364.          {
  365.              int maxrate_bak = h->param.rc.i_vbv_max_bitrate;
  366.              if( h->param.rc.i_rc_method == X264_RC_ABR && h->param.rc.i_vbv_buffer_size <= 0 )
  367. diff --git a/encoder/set.c b/encoder/set.c
  368. index 622d16f..e9f7478 100644
  369. --- a/encoder/set.c
  370. +++ b/encoder/set.c
  371. @@ -115,6 +115,17 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
  372.      else
  373.          sps->i_profile_idc  = PROFILE_BASELINE;
  374.  
  375. +    /* Hack: if the user specifies a High-compatible VBV, but not a Main-compatible one,
  376. +     * switch to High profile.  Prevents spurious errors on the first pass. */
  377. +    const x264_level_t *l = x264_get_level( param->i_level_idc );
  378. +    if( l && sps->i_profile_idc <= PROFILE_MAIN &&
  379. +        l->bitrate * 5/4 >= param->rc.i_vbv_max_bitrate &&
  380. +        l->cpb     * 5/4 >= param->rc.i_vbv_buffer_size &&
  381. +        (l->bitrate < param->rc.i_vbv_max_bitrate || l->cpb < param->rc.i_vbv_buffer_size) )
  382. +    {
  383. +        sps->i_profile_idc  = PROFILE_HIGH;
  384. +    }
  385. +
  386.      sps->b_constraint_set0  = sps->i_profile_idc == PROFILE_BASELINE;
  387.      /* x264 doesn't support the features that are in Baseline and not in Main,
  388.       * namely arbitrary_slice_order and slice_groups. */
  389. @@ -711,6 +722,14 @@ const x264_level_t x264_levels[] =
  390.      { 0 }
  391.  };
  392.  
  393. +const x264_level_t *x264_get_level( int level_idc )
  394. +{
  395. +    const x264_level_t *l = x264_levels;
  396. +    while( l->level_idc && l->level_idc != level_idc )
  397. +        l++;
  398. +    return l->level_idc ? l : NULL;
  399. +}
  400. +
  401.  #define ERROR(...)\
  402.  {\
  403.      if( verbose )\
  404. @@ -721,8 +740,9 @@ const x264_level_t x264_levels[] =
  405.  int x264_validate_levels( x264_t *h, int verbose )
  406.  {
  407.      int ret = 0;
  408. -    int mbs = h->sps->i_mb_width * h->sps->i_mb_height;
  409. -    int dpb = mbs * 384 * h->sps->vui.i_max_dec_frame_buffering;
  410. +    float mbs = (float)h->param.i_width * (float)h->param.i_height / 256;
  411. +    int mb_size = 384*BIT_DEPTH/8;
  412. +    int dpb = mbs * mb_size * h->sps->vui.i_max_dec_frame_buffering;
  413.      int cbp_factor = h->sps->i_profile_idc==PROFILE_HIGH10 ? 12 :
  414.                       h->sps->i_profile_idc==PROFILE_HIGH ? 5 : 4;
  415.  
  416. @@ -737,7 +757,7 @@ int x264_validate_levels( x264_t *h, int verbose )
  417.                 h->sps->i_mb_width, h->sps->i_mb_height, l->frame_size );
  418.      if( dpb > l->dpb )
  419.          ERROR( "DPB size (%d frames, %d bytes) > level limit (%d frames, %d bytes)\n",
  420. -                h->sps->vui.i_max_dec_frame_buffering, dpb, (int)(l->dpb / (384*mbs)), l->dpb );
  421. +                h->sps->vui.i_max_dec_frame_buffering, dpb, (int)(l->dpb / (mb_size*mbs)), l->dpb );
  422.  
  423.  #define CHECK( name, limit, val ) \
  424.      if( (val) > (limit) ) \
  425. diff --git a/encoder/set.h b/encoder/set.h
  426. index 83c1bd9..d69b4cb 100644
  427. --- a/encoder/set.h
  428. +++ b/encoder/set.h
  429. @@ -33,6 +33,7 @@ void x264_pps_init( x264_pps_t *pps, int i_id, x264_param_t *param, x264_sps_t *
  430.  void x264_pps_write( bs_t *s, x264_pps_t *pps );
  431.  void x264_sei_recovery_point_write( x264_t *h, bs_t *s, int recovery_frame_cnt );
  432.  int  x264_sei_version_write( x264_t *h, bs_t *s );
  433. +const x264_level_t *x264_get_level( int level_idc );
  434.  int  x264_validate_levels( x264_t *h, int verbose );
  435.  void x264_sei_buffering_period_write( x264_t *h, bs_t *s );
  436.  void x264_sei_pic_timing_write( x264_t *h, bs_t *s );
  437. diff --git a/x264.c b/x264.c
  438. index 626617b..a4d1b20 100644
  439. --- a/x264.c
  440. +++ b/x264.c
  441. @@ -400,6 +400,11 @@ static void help( x264_param_t *defaults, int longhelp )
  442.      H0( "\n" );
  443.      H0( "Presets:\n" );
  444.      H0( "\n" );
  445. +    H0( "      --device                Force the limits of an H.264-capable device\n"
  446. +        "                                  Overrides all settings.\n"
  447. +        "                                  Devices currently supported:\n"
  448. +        "                                      ipad, iphone, iphone4, ipod, n8\n"
  449. +        "                                      n900, psp, ps3, xbox360, wdtv\n" );
  450.      H0( "      --profile               Force the limits of an H.264 profile\n"
  451.          "                                  Overrides all settings.\n" );
  452.      H2( "                                  - baseline:\n"
  453. @@ -787,7 +792,8 @@ enum
  454.      OPT_INPUT_RES,
  455.      OPT_INPUT_CSP,
  456.      OPT_INPUT_DEPTH,
  457. -    OPT_DTS_COMPRESSION
  458. +    OPT_DTS_COMPRESSION,
  459. +    OPT_DEVICE
  460.  } OptionsOPT;
  461.  
  462.  static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
  463. @@ -798,6 +804,7 @@ static struct option long_options[] =
  464.      { "fullhelp",          no_argument, NULL, OPT_FULLHELP },
  465.      { "version",           no_argument, NULL, 'V' },
  466.      { "profile",     required_argument, NULL, OPT_PROFILE },
  467. +    { "device",      required_argument, NULL, OPT_DEVICE },
  468.      { "preset",      required_argument, NULL, OPT_PRESET },
  469.      { "tune",        required_argument, NULL, OPT_TUNE },
  470.      { "slow-firstpass",    no_argument, NULL, OPT_SLOWFIRSTPASS },
  471. @@ -1088,29 +1095,6 @@ static int init_vid_filters( char *sequence, hnd_t *handle, video_info_t *info,
  472.          p += X264_MIN( tok_len+1, p_len );
  473.      }
  474.  
  475. -    /* force end result resolution */
  476. -    if( !param->i_width && !param->i_height )
  477. -    {
  478. -        param->i_height = info->height;
  479. -        param->i_width  = info->width;
  480. -    }
  481. -    /* if the current csp is supported by libx264, have libx264 use this csp.
  482. -     * otherwise change the csp to I420 and have libx264 use this.
  483. -     * when more colorspaces are supported, this decision will need to be updated. */
  484. -    int csp = info->csp & X264_CSP_MASK;
  485. -    if( csp > X264_CSP_NONE && csp < X264_CSP_MAX )
  486. -        param->i_csp = info->csp;
  487. -    else
  488. -        param->i_csp = X264_CSP_I420 | ( info->csp & X264_CSP_HIGH_DEPTH );
  489. -    if( x264_init_vid_filter( "resize", handle, &filter, info, param, NULL ) )
  490. -        return -1;
  491. -
  492. -    char args[20];
  493. -    sprintf( args, "bit_depth=%d", x264_bit_depth );
  494. -
  495. -    if( x264_init_vid_filter( "depth", handle, &filter, info, param, args ) )
  496. -        return -1;
  497. -
  498.      return 0;
  499.  }
  500.  
  501. @@ -1145,6 +1129,7 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  502.      char *tcfile_name = NULL;
  503.      x264_param_t defaults;
  504.      char *profile = NULL;
  505. +    char *devices = NULL;
  506.      char *vid_filters = NULL;
  507.      int b_thread_input = 0;
  508.      int b_turbo = 1;
  509. @@ -1314,6 +1299,9 @@ static int parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  510.              case OPT_DTS_COMPRESSION:
  511.                  output_opt.use_dts_compress = 1;
  512.                  break;
  513. +            case OPT_DEVICE:
  514. +                devices = optarg;
  515. +                break;
  516.              default:
  517.  generic_option:
  518.              {
  519. @@ -1348,10 +1336,6 @@ generic_option:
  520.      if( b_turbo )
  521.          x264_param_apply_fastfirstpass( param );
  522.  
  523. -    /* Apply profile restrictions. */
  524. -    if( x264_param_apply_profile( param, profile ) < 0 )
  525. -        return -1;
  526. -
  527.      /* Get the file name */
  528.      FAIL_IF_ERROR( optind > argc - 1 || !output_filename, "No %s file. Run x264 --help for a list of options.\n",
  529.                     optind > argc - 1 ? "input" : "output" )
  530. @@ -1460,6 +1444,8 @@ generic_option:
  531.      param->i_timebase_den = info.timebase_den;
  532.      param->vui.i_sar_width  = info.sar_width;
  533.      param->vui.i_sar_height = info.sar_height;
  534. +    param->i_height = info->height;
  535. +    param->i_width  = info->width;
  536.  
  537.      info.num_frames = X264_MAX( info.num_frames - opt->i_seek, 0 );
  538.      if( (!info.num_frames || param->i_frame_total < info.num_frames)
  539. @@ -1475,25 +1461,39 @@ generic_option:
  540.          param->b_interlaced = 1;
  541.          param->b_tff = !!info.tff;
  542.      }
  543. +    x264_param_compat_t compat = {0};
  544. +    if( x264_param_apply_profile( param, profile ) < 0 )
  545. +        return -1;
  546.  
  547. -    /* Automatically reduce reference frame count to match the user's target level
  548. -     * if the user didn't explicitly set a reference frame count. */
  549. -    if( !b_user_ref )
  550. +    if( devices )
  551.      {
  552. -        int mbs = (((param->i_width)+15)>>4) * (((param->i_height)+15)>>4);
  553. -        for( int i = 0; x264_levels[i].level_idc != 0; i++ )
  554. -            if( param->i_level_idc == x264_levels[i].level_idc )
  555. -            {
  556. -                while( mbs * 384 * param->i_frame_reference > x264_levels[i].dpb &&
  557. -                       param->i_frame_reference > 1 )
  558. -                {
  559. -                    param->i_frame_reference--;
  560. -                }
  561. -                break;
  562. -            }
  563. +        if( x264_param_apply_device( param, devices, &compat ) < 0 )
  564. +            return -1;
  565.      }
  566. +    else if( x264_param_apply_level( param, profile, &compat ) < 0 )
  567. +        return -1;
  568.  
  569. +    if( compat.i_width != 0 && compat.i_height != 0 )
  570. +    {
  571. +        param->i_width = compat.i_width;
  572. +        param->i_height = compat.i_height;
  573. +    }
  574. +    /* if the current csp is supported by libx264, have libx264 use this csp.
  575. +     * otherwise change the csp to I420 and have libx264 use this.
  576. +     * when more colorspaces are supported, this decision will need to be updated. */
  577. +    int csp = info.csp & X264_CSP_MASK;
  578. +    if( csp > X264_CSP_NONE && csp < X264_CSP_MAX )
  579. +        param->i_csp = info.csp;
  580. +    else
  581. +        param->i_csp = X264_CSP_I420 | ( info.csp & X264_CSP_HIGH_DEPTH );
  582. +    if( x264_init_vid_filter( "resize", &opt->hin, &filter, &info, param, NULL ) )
  583. +        return -1;
  584.  
  585. +    char args[20];
  586. +    sprintf( args, "bit_depth=%d", x264_bit_depth );
  587. +
  588. +    if( x264_init_vid_filter( "depth", &opt->hin, &filter, &info, param, args ) )
  589. +        return -1;
  590.      return 0;
  591.  }
  592.  
  593. diff --git a/x264.h b/x264.h
  594. index dbedd7e..31e593e 100644
  595. --- a/x264.h
  596. +++ b/x264.h
  597. @@ -41,7 +41,7 @@
  598.  
  599.  #include "x264_config.h"
  600.  
  601. -#define X264_BUILD 112
  602. +#define X264_BUILD 113
  603.  
  604.  /* x264_t:
  605.   *      opaque handler for encoder */
  606. @@ -163,6 +163,7 @@ typedef struct
  607.  #define X264_OPEN_GOP_NONE           0
  608.  #define X264_OPEN_GOP_NORMAL         1
  609.  #define X264_OPEN_GOP_BLURAY         2
  610. +#define X264_LEVEL_IDC_AUTO        (-1)
  611.  
  612.  static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
  613.  static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
  614. @@ -474,6 +475,14 @@ typedef struct x264_param_t
  615.  
  616.  void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal );
  617.  
  618. +/* defines the parameters that should be changed by the calling application
  619. + * instead in x264_param_apply_device */
  620. +typedef struct
  621. +{
  622. +    int i_width;
  623. +    int i_height;
  624. +} x264_param_compat_t;
  625. +
  626.  /****************************************************************************
  627.   * H.264 level restriction information
  628.   ****************************************************************************/
  629. @@ -529,6 +538,7 @@ int x264_param_parse( x264_param_t *, const char *name, const char *value );
  630.   * 2) Custom user options (via param_parse or directly assigned variables)
  631.   * 3) x264_param_apply_fastfirstpass
  632.   * 4) x264_param_apply_profile
  633. + * 5) x264_param_apply_level or x264_param_apply_device
  634.   *
  635.   * Additionally, x264CLI does not apply step 3 if the preset chosen is "placebo"
  636.   * or --slow-firstpass is set. */
  637. @@ -581,6 +591,44 @@ static const char * const x264_profile_names[] = { "baseline", "main", "high", "
  638.   *      returns 0 on success, negative on failure (e.g. invalid profile name). */
  639.  int     x264_param_apply_profile( x264_param_t *, const char *profile );
  640.  
  641. +/* x264_param_apply_level:
  642. + *      Applies the restrictions of the level set in the passed x264_param_t to
  643. + *      the passed x264_param_t, using the passed profile.
  644. + *      Uses the level_idc values from x264_levels[].
  645. + *
  646. + *      Also calculates resolution returned in a x264_param_compat_t to be adjusted
  647. + *      by the calling application.
  648. + *
  649. + *      Does nothing (but is considered success) if the level is set to
  650. + *      X264_LEVEL_IDC_AUTO (default).
  651. + *
  652. + *      x264_param_apply_level does not check or modify parameters related
  653. + *      to properties of the source video that may violate levels, e.g.
  654. + *      resolution, framerate, interlacing.  x264_param_apply_level is not
  655. + *      intended as a compatibility check; this is done inside x264 at the
  656. + *      start of encoding.
  657. + *
  658. + *      i_width and i_height must be initialized for x264_param_apply_level
  659. + *      to work properly.
  660. + *
  661. + *      returns 0 on success, negative on failure (e.g. invalid level). */
  662. +int     x264_param_apply_level( x264_param_t *, const char *profile, x264_param_compat_t *compat );
  663. +
  664. +/* x264_param_apply_devices:
  665. + *      Applies the constraints of device to the passed x264_param_t. Uses the list
  666. + *      of x264_device_t defined in common/common.c.
  667. + *      Currently available devices for x264_param_apply_device are: */
  668. +static const char * const x264_device_names[] = { "ipad", "iphone", "iphone4", "ipod", "n8", "n900", "psp", "ps3", "xbox360", "wdtv", 0 };
  669. +
  670. +/*      x264_param_apply_devices does not modify parameters supposed to be adjusted
  671. + *      by the calling application. An x264_param_compat_t is filled by the function
  672. + *      defining what unchangeable parameters need to be changed to.
  673. + *
  674. + *      i_width and i_height must be initialized for x264_param_apply_devices to
  675. + *      work properly.
  676. + *      Returns 0 if successful or -1 if the device couldnot be found. */
  677. +int    x264_param_apply_device( x264_param_t *param, const char *device, x264_param_compat_t *compat );
  678. +
  679.  /****************************************************************************
  680.   * Picture structures and functions
  681.   ****************************************************************************/
  682. --
  683. 1.7.1
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement