Advertisement
Guest User

Untitled

a guest
Jun 2nd, 2017
539
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 107.15 KB | None | 0 0
  1. From aa1a8435000228c4d9e74da0f9fd3d16e85a3e80 Mon Sep 17 00:00:00 2001
  2. From: Loren Merritt <pengvado@akuvian.org>
  3. Date: Sat, 26 Jun 2010 20:55:59 -0700
  4. Subject: [PATCH 1/6] Simplify pixel_ads
  5.  
  6. ---
  7. common/macroblock.c    |    2 +-
  8.  common/x86/pixel-a.asm |  175 +++++++++++++++++------------------------------
  9.  encoder/me.c           |    2 +-
  10.  3 files changed, 65 insertions(+), 114 deletions(-)
  11.  
  12. diff --git a/common/macroblock.c b/common/macroblock.c
  13. index 8e9b06d..4561d8a 100644
  14. --- a/common/macroblock.c
  15. +++ b/common/macroblock.c
  16. @@ -341,7 +341,7 @@ int x264_macroblock_thread_allocate( x264_t *h, int b_lookahead )
  17.          int buf_ssim = h->param.analyse.b_ssim * 8 * (h->param.i_width/4+3) * sizeof(int);
  18.          int me_range = X264_MIN(h->param.analyse.i_me_range, h->param.analyse.i_mv_range);
  19.          int buf_tesa = (h->param.analyse.i_me_method >= X264_ME_ESA) *
  20. -            ((me_range*2+18) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
  21. +            ((me_range*2+24) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
  22.          scratch_size = X264_MAX3( buf_hpel, buf_ssim, buf_tesa );
  23.      }
  24.      int buf_mbtree = h->param.rc.b_mb_tree * ((h->mb.i_mb_width+3)&~3) * sizeof(int);
  25. diff --git a/common/x86/pixel-a.asm b/common/x86/pixel-a.asm
  26. index 78ca4c7..1756f86 100644
  27. --- a/common/x86/pixel-a.asm
  28. +++ b/common/x86/pixel-a.asm
  29. @@ -2142,34 +2142,24 @@ cglobal pixel_ssim_end4_sse2, 3,3,7
  30.  ; Successive Elimination ADS
  31.  ;=============================================================================
  32.  
  33. -%macro ADS_START 1 ; unroll_size
  34. -%ifdef ARCH_X86_64
  35. -    %define t0 r6
  36. +%macro ADS_START 0
  37.  %ifdef WIN64
  38. -    mov     r4,  r4mp
  39. -    movsxd  r5,  dword r5m
  40. +    movsxd  r5,  r5d
  41.  %endif
  42. -    mov     r10, rsp
  43. -%else
  44. -    %define t0 r4
  45. -    mov     rbp, rsp
  46. -%endif
  47. -    mov     r0d, r5m
  48. -    sub     rsp, r0
  49. -    sub     rsp, %1*4-1
  50. -    and     rsp, ~15
  51. -    mov     t0,  rsp
  52. +    mov     r0d, r5d
  53. +    lea     r6,  [r4+r5+15]
  54. +    and     r6,  ~15;
  55.      shl     r2d,  1
  56.  %endmacro
  57.  
  58. -%macro ADS_END 1
  59. +%macro ADS_END 1 ; unroll_size
  60.      add     r1, 8*%1
  61.      add     r3, 8*%1
  62. -    add     t0, 4*%1
  63. +    add     r6, 4*%1
  64.      sub     r0d, 4*%1
  65.      jg .loop
  66.  %ifdef WIN64
  67. -    RESTORE_XMM r10
  68. +    RESTORE_XMM rsp
  69.  %endif
  70.      jmp ads_mvs
  71.  %endmacro
  72. @@ -2180,14 +2170,14 @@ cglobal pixel_ssim_end4_sse2, 3,3,7
  73.  ; int pixel_ads4( int enc_dc[4], uint16_t *sums, int delta,
  74.  ;                 uint16_t *cost_mvx, int16_t *mvs, int width, int thresh )
  75.  ;-----------------------------------------------------------------------------
  76. -cglobal pixel_ads4_mmxext, 4,7
  77. +cglobal pixel_ads4_mmxext, 6,7
  78.      movq    mm6, [r0]
  79.      movq    mm4, [r0+8]
  80.      pshufw  mm7, mm6, 0
  81.      pshufw  mm6, mm6, 0xAA
  82.      pshufw  mm5, mm4, 0
  83.      pshufw  mm4, mm4, 0xAA
  84. -    ADS_START 1
  85. +    ADS_START
  86.  .loop:
  87.      movq    mm0, [r1]
  88.      movq    mm1, [r1+16]
  89. @@ -2204,25 +2194,19 @@ cglobal pixel_ads4_mmxext, 4,7
  90.      ABS1    mm3, mm1
  91.      paddw   mm0, mm2
  92.      paddw   mm0, mm3
  93. -%ifdef WIN64
  94. -    pshufw  mm1, [r10+stack_offset+56], 0
  95. -%elifdef ARCH_X86_64
  96. -    pshufw  mm1, [r10+8], 0
  97. -%else
  98. -    pshufw  mm1, [ebp+stack_offset+28], 0
  99. -%endif
  100. +    pshufw  mm1, r6m, 0
  101.      paddusw mm0, [r3]
  102.      psubusw mm1, mm0
  103.      packsswb mm1, mm1
  104. -    movd    [t0], mm1
  105. +    movd    [r6], mm1
  106.      ADS_END 1
  107.  
  108. -cglobal pixel_ads2_mmxext, 4,7
  109. +cglobal pixel_ads2_mmxext, 6,7
  110.      movq    mm6, [r0]
  111.      pshufw  mm5, r6m, 0
  112.      pshufw  mm7, mm6, 0
  113.      pshufw  mm6, mm6, 0xAA
  114. -    ADS_START 1
  115. +    ADS_START
  116.  .loop:
  117.      movq    mm0, [r1]
  118.      movq    mm1, [r1+r2]
  119. @@ -2235,13 +2219,13 @@ cglobal pixel_ads2_mmxext, 4,7
  120.      movq    mm4, mm5
  121.      psubusw mm4, mm0
  122.      packsswb mm4, mm4
  123. -    movd    [t0], mm4
  124. +    movd    [r6], mm4
  125.      ADS_END 1
  126.  
  127. -cglobal pixel_ads1_mmxext, 4,7
  128. +cglobal pixel_ads1_mmxext, 6,7
  129.      pshufw  mm7, [r0], 0
  130.      pshufw  mm6, r6m, 0
  131. -    ADS_START 2
  132. +    ADS_START
  133.  .loop:
  134.      movq    mm0, [r1]
  135.      movq    mm1, [r1+8]
  136. @@ -2256,11 +2240,11 @@ cglobal pixel_ads1_mmxext, 4,7
  137.      psubusw mm4, mm0
  138.      psubusw mm5, mm1
  139.      packsswb mm4, mm5
  140. -    movq    [t0], mm4
  141. +    movq    [r6], mm4
  142.      ADS_END 2
  143.  
  144.  %macro ADS_SSE2 1
  145. -cglobal pixel_ads4_%1, 4,7,12
  146. +cglobal pixel_ads4_%1, 6,7,12
  147.      movdqa  xmm4, [r0]
  148.      pshuflw xmm7, xmm4, 0
  149.      pshuflw xmm6, xmm4, 0xAA
  150. @@ -2273,7 +2257,7 @@ cglobal pixel_ads4_%1, 4,7,12
  151.  %ifdef ARCH_X86_64
  152.      pshuflw xmm8, r6m, 0
  153.      punpcklqdq xmm8, xmm8
  154. -    ADS_START 2
  155. +    ADS_START
  156.      movdqu  xmm10, [r1]
  157.      movdqu  xmm11, [r1+r2]
  158.  .loop:
  159. @@ -2299,9 +2283,9 @@ cglobal pixel_ads4_%1, 4,7,12
  160.      movdqa  xmm1, xmm8
  161.      psubusw xmm1, xmm0
  162.      packsswb xmm1, xmm1
  163. -    movq    [t0], xmm1
  164. +    movq    [r6], xmm1
  165.  %else
  166. -    ADS_START 2
  167. +    ADS_START
  168.  .loop:
  169.      movdqu  xmm0, [r1]
  170.      movdqu  xmm1, [r1+16]
  171. @@ -2318,18 +2302,18 @@ cglobal pixel_ads4_%1, 4,7,12
  172.      ABS1    xmm3, xmm1
  173.      paddw   xmm0, xmm2
  174.      paddw   xmm0, xmm3
  175. -    movd    xmm1, [ebp+stack_offset+28]
  176. +    movd    xmm1, r6m
  177.      movdqu  xmm2, [r3]
  178.      pshuflw xmm1, xmm1, 0
  179.      punpcklqdq xmm1, xmm1
  180.      paddusw xmm0, xmm2
  181.      psubusw xmm1, xmm0
  182.      packsswb xmm1, xmm1
  183. -    movq    [t0], xmm1
  184. +    movq    [r6], xmm1
  185.  %endif ; ARCH
  186.      ADS_END 2
  187.  
  188. -cglobal pixel_ads2_%1, 4,7,8
  189. +cglobal pixel_ads2_%1, 6,7,8
  190.      movq    xmm6, [r0]
  191.      movd    xmm5, r6m
  192.      pshuflw xmm7, xmm6, 0
  193. @@ -2338,7 +2322,7 @@ cglobal pixel_ads2_%1, 4,7,8
  194.      punpcklqdq xmm7, xmm7
  195.      punpcklqdq xmm6, xmm6
  196.      punpcklqdq xmm5, xmm5
  197. -    ADS_START 2
  198. +    ADS_START
  199.  .loop:
  200.      movdqu  xmm0, [r1]
  201.      movdqu  xmm1, [r1+r2]
  202. @@ -2352,17 +2336,17 @@ cglobal pixel_ads2_%1, 4,7,8
  203.      movdqa  xmm1, xmm5
  204.      psubusw xmm1, xmm0
  205.      packsswb xmm1, xmm1
  206. -    movq    [t0], xmm1
  207. +    movq    [r6], xmm1
  208.      ADS_END 2
  209.  
  210. -cglobal pixel_ads1_%1, 4,7,8
  211. +cglobal pixel_ads1_%1, 6,7,8
  212.      movd    xmm7, [r0]
  213.      movd    xmm6, r6m
  214.      pshuflw xmm7, xmm7, 0
  215.      pshuflw xmm6, xmm6, 0
  216.      punpcklqdq xmm7, xmm7
  217.      punpcklqdq xmm6, xmm6
  218. -    ADS_START 4
  219. +    ADS_START
  220.  .loop:
  221.      movdqu  xmm0, [r1]
  222.      movdqu  xmm1, [r1+16]
  223. @@ -2379,7 +2363,7 @@ cglobal pixel_ads1_%1, 4,7,8
  224.      psubusw xmm4, xmm0
  225.      psubusw xmm5, xmm1
  226.      packsswb xmm4, xmm5
  227. -    movdqa  [t0], xmm4
  228. +    movdqa  [r6], xmm4
  229.      ADS_END 4
  230.  %endmacro
  231.  
  232. @@ -2401,90 +2385,57 @@ ADS_SSE2 ssse3
  233.  ;     }
  234.  ;     return nmv;
  235.  ; }
  236. +
  237. +%macro TEST 1
  238. +    mov     [r4+r0*2], r1w
  239. +    test    r2d, 0xff<<(%1*8)
  240. +    setne   r3b
  241. +    add     r0d, r3d
  242. +    inc     r1d
  243. +%endmacro
  244. +
  245.  cglobal pixel_ads_mvs, 0,7,0
  246.  ads_mvs:
  247. -%ifdef ARCH_X86_64
  248. +    lea     r6,  [r4+r5+15]
  249. +    and     r6,  ~15;
  250.      ; mvs = r4
  251. -    ; masks = rsp
  252. +    ; masks = r6
  253.      ; width = r5
  254.      ; clear last block in case width isn't divisible by 8. (assume divisible by 4, so clearing 4 bytes is enough.)
  255. -%ifdef WIN64
  256. -    mov     r8, r4
  257. -    mov     r9, r5
  258. -%endif
  259. -    xor     eax, eax
  260. -    xor     esi, esi
  261. -    mov     dword [rsp+r9], 0
  262. +    xor     r0d, r0d
  263. +    xor     r1d, r1d
  264. +    mov     [r6+r5], r0d
  265.      jmp .loopi
  266. +ALIGN 16
  267.  .loopi0:
  268. -    add     esi, 8
  269. -    cmp     esi, r9d
  270. +    add     r1d, 8
  271. +    cmp     r1d, r5d
  272.      jge .end
  273.  .loopi:
  274. -    mov     rdi, [rsp+rsi]
  275. -    test    rdi, rdi
  276. +    mov     r2,  [r6+r1]
  277. +%ifdef ARCH_X86_64
  278. +    test    r2,  r2
  279. +%else
  280. +    mov     r3,  r2
  281. +    or      r3d, [r6+r1+4]
  282. +%endif
  283.      jz .loopi0
  284. -    xor     ecx, ecx
  285. -%macro TEST 1
  286. -    mov     [r8+rax*2], si
  287. -    test    edi, 0xff<<(%1*8)
  288. -    setne   cl
  289. -    add     eax, ecx
  290. -    inc     esi
  291. -%endmacro
  292. +    xor     r3d, r3d
  293.      TEST 0
  294.      TEST 1
  295.      TEST 2
  296.      TEST 3
  297. -    shr     rdi, 32
  298. +%ifdef ARCH_X86_64
  299. +    shr     r2,  32
  300. +%else
  301. +    mov     r2d, [r6+r1]
  302. +%endif
  303.      TEST 0
  304.      TEST 1
  305.      TEST 2
  306.      TEST 3
  307. -    cmp     esi, r9d
  308. -    jl .loopi
  309. -.end:
  310. -    mov     rsp, r10
  311. -    RET
  312. -
  313. -%else
  314. -    xor     eax, eax
  315. -    xor     esi, esi
  316. -    mov     ebx, [ebp+stack_offset+20] ; mvs
  317. -    mov     edi, [ebp+stack_offset+24] ; width
  318. -    mov     dword [esp+edi], 0
  319. -    push    ebp
  320. -    jmp .loopi
  321. -.loopi0:
  322. -    add     esi, 8
  323. -    cmp     esi, edi
  324. -    jge .end
  325. -.loopi:
  326. -    mov     ebp, [esp+esi+4]
  327. -    mov     edx, [esp+esi+8]
  328. -    mov     ecx, ebp
  329. -    or      ecx, edx
  330. -    jz .loopi0
  331. -    xor     ecx, ecx
  332. -%macro TEST 2
  333. -    mov     [ebx+eax*2], si
  334. -    test    %2, 0xff<<(%1*8)
  335. -    setne   cl
  336. -    add     eax, ecx
  337. -    inc     esi
  338. -%endmacro
  339. -    TEST 0, ebp
  340. -    TEST 1, ebp
  341. -    TEST 2, ebp
  342. -    TEST 3, ebp
  343. -    TEST 0, edx
  344. -    TEST 1, edx
  345. -    TEST 2, edx
  346. -    TEST 3, edx
  347. -    cmp     esi, edi
  348. +    cmp     r1d, r5d
  349.      jl .loopi
  350.  .end:
  351. -    pop     esp
  352. +    movifnidn eax, r0d
  353.      RET
  354. -%endif ; ARCH
  355. -
  356. diff --git a/encoder/me.c b/encoder/me.c
  357. index 291104a..19c5b2b 100644
  358. --- a/encoder/me.c
  359. +++ b/encoder/me.c
  360. @@ -609,7 +609,7 @@ void x264_me_search_ref( x264_t *h, x264_me_t *m, int16_t (*mvc)[2], int i_mvc,
  361.              if( h->mb.i_me_method == X264_ME_TESA )
  362.              {
  363.                  // ADS threshold, then SAD threshold, then keep the best few SADs, then SATD
  364. -                mvsad_t *mvsads = (mvsad_t *)(xs + ((width+15)&~15));
  365. +                mvsad_t *mvsads = (mvsad_t *)(xs + ((width+15)&~15) + 4);
  366.                  int nmvsad = 0, limit;
  367.                  int sad_thresh = i_me_range <= 16 ? 10 : i_me_range <= 24 ? 11 : 12;
  368.                  int bsad = h->pixf.sad[i_pixel]( p_fenc, FENC_STRIDE, p_fref_w+bmy*stride+bmx, stride )
  369. --
  370. 1.7.0.4
  371.  
  372.  
  373. From 8b5d1903ccd13ed8f5141de0048601b4c020de98 Mon Sep 17 00:00:00 2001
  374. From: Jason Garrett-Glaser <darkshikari@gmail.com>
  375. Date: Mon, 28 Jun 2010 15:02:33 -0700
  376. Subject: [PATCH 2/6] Callback feature for low-latency per-slice output
  377.  Add a callback to allow the calling application to send slices immediately after being encoded.
  378.  Also add some extra information to the x264_nal_t structure to help inform such a calling application how the NAL units should be ordered.
  379.  
  380. Full documentation is in x264.h.
  381. ---
  382. common/bitstream.c |    7 ++-
  383.  common/bitstream.h |    1 -
  384.  encoder/encoder.c  |   26 ++++++++---
  385.  x264.h             |  128 +++++++++++++++++++++++++++++++++-------------------
  386.  4 files changed, 105 insertions(+), 57 deletions(-)
  387.  
  388. diff --git a/common/bitstream.c b/common/bitstream.c
  389. index 0aaac21..ad8c16e 100644
  390. --- a/common/bitstream.c
  391. +++ b/common/bitstream.c
  392. @@ -44,7 +44,7 @@ uint8_t *x264_nal_escape_sse2( uint8_t *dst, uint8_t *src, uint8_t *end );
  393.  /****************************************************************************
  394.   * x264_nal_encode:
  395.   ****************************************************************************/
  396. -int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startcode )
  397. +void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal )
  398.  {
  399.      uint8_t *src = nal->p_payload;
  400.      uint8_t *end = nal->p_payload + nal->i_payload;
  401. @@ -52,7 +52,7 @@ int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startc
  402.  
  403.      if( h->param.b_annexb )
  404.      {
  405. -        if( b_long_startcode )
  406. +        if( nal->b_long_startcode )
  407.              *dst++ = 0x00;
  408.          *dst++ = 0x00;
  409.          *dst++ = 0x00;
  410. @@ -77,7 +77,8 @@ int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startc
  411.          orig_dst[3] = size>> 0;
  412.      }
  413.  
  414. -    return size+4;
  415. +    nal->i_payload = size+4;
  416. +    nal->p_payload = orig_dst;
  417.  }
  418.  
  419.  void x264_bitstream_init( int cpu, x264_bitstream_function_t *pf )
  420. diff --git a/common/bitstream.h b/common/bitstream.h
  421. index 9ce5bd7..dd8118d 100644
  422. --- a/common/bitstream.h
  423. +++ b/common/bitstream.h
  424. @@ -68,7 +68,6 @@ typedef struct
  425.      uint8_t *(*nal_escape) ( uint8_t *dst, uint8_t *src, uint8_t *end );
  426.  } x264_bitstream_function_t;
  427.  
  428. -int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startcode );
  429.  void x264_bitstream_init( int cpu, x264_bitstream_function_t *pf );
  430.  
  431.  /* A larger level table size theoretically could help a bit at extremely
  432. diff --git a/encoder/encoder.c b/encoder/encoder.c
  433. index f54fe85..fe97aef 100644
  434. --- a/encoder/encoder.c
  435. +++ b/encoder/encoder.c
  436. @@ -427,6 +427,8 @@ static int x264_validate_parameters( x264_t *h )
  437.      else
  438.          h->param.b_sliced_threads = 0;
  439.      h->i_thread_frames = h->param.b_sliced_threads ? 1 : h->param.i_threads;
  440. +    if( h->i_thread_frames > 1 )
  441. +        h->param.nalu_process = NULL;
  442.  
  443.      if( h->param.b_interlaced )
  444.      {
  445. @@ -1253,8 +1255,9 @@ static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
  446.  {
  447.      x264_nal_t *nal = &h->out.nal[h->out.i_nal];
  448.  
  449. -    nal->i_ref_idc = i_ref_idc;
  450. -    nal->i_type    = i_type;
  451. +    nal->i_ref_idc        = i_ref_idc;
  452. +    nal->i_type           = i_type;
  453. +    nal->b_long_startcode = 1;
  454.  
  455.      nal->i_payload= 0;
  456.      nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8];
  457. @@ -1280,6 +1283,8 @@ static int x264_nal_end( x264_t *h )
  458.  {
  459.      x264_nal_t *nal = &h->out.nal[h->out.i_nal];
  460.      nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8] - nal->p_payload;
  461. +    if( h->param.nalu_process )
  462. +        h->param.nalu_process( h, nal );
  463.      h->out.i_nal++;
  464.  
  465.      return x264_nal_check_buffer( h );
  466. @@ -1289,6 +1294,13 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
  467.  {
  468.      int nal_size = 0, previous_nal_size = 0;
  469.  
  470. +    if( h->param.nalu_process )
  471. +    {
  472. +        for( int i = start; i < h->out.i_nal; i++ )
  473. +            nal_size += h->out.nal[i].i_payload;
  474. +        return nal_size;
  475. +    }
  476. +
  477.      for( int i = 0; i < start; i++ )
  478.          previous_nal_size += h->out.nal[i].i_payload;
  479.  
  480. @@ -1311,11 +1323,9 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
  481.  
  482.      for( int i = start; i < h->out.i_nal; i++ )
  483.      {
  484. -        int long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
  485. -        int size = x264_nal_encode( h, nal_buffer, &h->out.nal[i], long_startcode );
  486. -        h->out.nal[i].i_payload = size;
  487. -        h->out.nal[i].p_payload = nal_buffer;
  488. -        nal_buffer += size;
  489. +        h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
  490. +        x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
  491. +        nal_buffer += h->out.nal[i].i_payload;
  492.      }
  493.  
  494.      x264_emms();
  495. @@ -1805,6 +1815,7 @@ static int x264_slice_write( x264_t *h )
  496.  
  497.      /* Slice */
  498.      x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
  499. +    h->out.nal[h->out.i_nal].i_first_mb = h->sh.i_first_mb;
  500.  
  501.      /* Slice header */
  502.      x264_macroblock_thread_init( h );
  503. @@ -2020,6 +2031,7 @@ static int x264_slice_write( x264_t *h )
  504.              i_mb_x = 0;
  505.          }
  506.      }
  507. +    h->out.nal[h->out.i_nal].i_last_mb = h->sh.i_last_mb;
  508.  
  509.      if( h->param.b_cabac )
  510.      {
  511. diff --git a/x264.h b/x264.h
  512. index 1138a8b..6a663ed 100644
  513. --- a/x264.h
  514. +++ b/x264.h
  515. @@ -35,13 +35,61 @@
  516.  
  517.  #include <stdarg.h>
  518.  
  519. -#define X264_BUILD 100
  520. +#define X264_BUILD 101
  521.  
  522.  /* x264_t:
  523.   *      opaque handler for encoder */
  524.  typedef struct x264_t x264_t;
  525.  
  526.  /****************************************************************************
  527. + * NAL structure and functions
  528. + ****************************************************************************/
  529. +
  530. +enum nal_unit_type_e
  531. +{
  532. +    NAL_UNKNOWN     = 0,
  533. +    NAL_SLICE       = 1,
  534. +    NAL_SLICE_DPA   = 2,
  535. +    NAL_SLICE_DPB   = 3,
  536. +    NAL_SLICE_DPC   = 4,
  537. +    NAL_SLICE_IDR   = 5,    /* ref_idc != 0 */
  538. +    NAL_SEI         = 6,    /* ref_idc == 0 */
  539. +    NAL_SPS         = 7,
  540. +    NAL_PPS         = 8,
  541. +    NAL_AUD         = 9,
  542. +    NAL_FILLER      = 12,
  543. +    /* ref_idc == 0 for 6,9,10,11,12 */
  544. +};
  545. +enum nal_priority_e
  546. +{
  547. +    NAL_PRIORITY_DISPOSABLE = 0,
  548. +    NAL_PRIORITY_LOW        = 1,
  549. +    NAL_PRIORITY_HIGH       = 2,
  550. +    NAL_PRIORITY_HIGHEST    = 3,
  551. +};
  552. +
  553. +/* The data within the payload is already NAL-encapsulated; the ref_idc and type
  554. + * are merely in the struct for easy access by the calling application.
  555. + * All data returned in an x264_nal_t, including the data in p_payload, is no longer
  556. + * valid after the next call to x264_encoder_encode.  Thus it must be used or copied
  557. + * before calling x264_encoder_encode or x264_encoder_headers again. */
  558. +typedef struct
  559. +{
  560. +    int i_ref_idc;  /* nal_priority_e */
  561. +    int i_type;     /* nal_unit_type_e */
  562. +    int b_long_startcode;
  563. +    int i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */
  564. +    int i_last_mb;  /* If this NAL is a slice, the index of the last MB in the slice. */
  565. +
  566. +    /* Size of payload in bytes. */
  567. +    int     i_payload;
  568. +    /* If param->b_annexb is set, Annex-B bytestream with 4-byte startcode.
  569. +     * Otherwise, startcode is replaced with a 4-byte size.
  570. +     * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
  571. +    uint8_t *p_payload;
  572. +} x264_nal_t;
  573. +
  574. +/****************************************************************************
  575.   * Encoder parameters
  576.   ****************************************************************************/
  577.  /* CPU flags
  578. @@ -377,8 +425,41 @@ typedef struct x264_param_t
  579.       * i.e. when an x264_param_t is passed to x264_t in an x264_picture_t or in zones.
  580.       * Not used when x264_encoder_reconfig is called directly. */
  581.      void (*param_free)( void* );
  582. +
  583. +    /* Optional low-level callback for low-latency encoding.  Called for each output NAL unit
  584. +     * immediately after the NAL unit is finished encoding.  This allows the calling application
  585. +     * to begin processing video data (e.g. by sending packets over a network) before the frame
  586. +     * is done encoding.
  587. +     *
  588. +     * This callback MUST do the following in order to work correctly:
  589. +     * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 16.
  590. +     * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer.
  591. +     * After these steps, the content of nal is valid and can be used in the same way as if
  592. +     * the NAL unit were output by x264_encoder_encode.
  593. +     *
  594. +     * This does not need to be synchronous with the encoding process: the data pointed to
  595. +     * by nal (both before and after x264_nal_encode) will remain valid until the next
  596. +     * x264_encoder_encode call.
  597. +     *
  598. +     * This callback does not work with frame-based threads; threads must be disabled
  599. +     * or sliced-threads enabled.  This callback also does not work as one would expect
  600. +     * with HRD -- since the buffering period SEI cannot be calculated until the frame
  601. +     * is finished encoding, it will not be sent via this callback.
  602. +     *
  603. +     * Note also that the NALs are not necessarily returned in order when sliced threads is
  604. +     * enabled.  Accordingly, the variable i_first_mb and i_last_mb are available in
  605. +     * x264_nal_t to help the calling application reorder the slices if necessary.
  606. +     *
  607. +     * When this callback is enabled, x264_encoder_encode does not return valid NALs;
  608. +     * the calling application is expected to acquire all output NALs through the callback.
  609. +     *
  610. +     * It is generally sensible to combine this callback with a use of slice-max-mbs or
  611. +     * slice-max-size. */
  612. +    void (*nalu_process) ( x264_t *h, x264_nal_t *nal );
  613.  } x264_param_t;
  614.  
  615. +void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal );
  616. +
  617.  /****************************************************************************
  618.   * H.264 level restriction information
  619.   ****************************************************************************/
  620. @@ -586,51 +667,6 @@ int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_heigh
  621.  void x264_picture_clean( x264_picture_t *pic );
  622.  
  623.  /****************************************************************************
  624. - * NAL structure and functions
  625. - ****************************************************************************/
  626. -
  627. -enum nal_unit_type_e
  628. -{
  629. -    NAL_UNKNOWN     = 0,
  630. -    NAL_SLICE       = 1,
  631. -    NAL_SLICE_DPA   = 2,
  632. -    NAL_SLICE_DPB   = 3,
  633. -    NAL_SLICE_DPC   = 4,
  634. -    NAL_SLICE_IDR   = 5,    /* ref_idc != 0 */
  635. -    NAL_SEI         = 6,    /* ref_idc == 0 */
  636. -    NAL_SPS         = 7,
  637. -    NAL_PPS         = 8,
  638. -    NAL_AUD         = 9,
  639. -    NAL_FILLER      = 12,
  640. -    /* ref_idc == 0 for 6,9,10,11,12 */
  641. -};
  642. -enum nal_priority_e
  643. -{
  644. -    NAL_PRIORITY_DISPOSABLE = 0,
  645. -    NAL_PRIORITY_LOW        = 1,
  646. -    NAL_PRIORITY_HIGH       = 2,
  647. -    NAL_PRIORITY_HIGHEST    = 3,
  648. -};
  649. -
  650. -/* The data within the payload is already NAL-encapsulated; the ref_idc and type
  651. - * are merely in the struct for easy access by the calling application.
  652. - * All data returned in an x264_nal_t, including the data in p_payload, is no longer
  653. - * valid after the next call to x264_encoder_encode.  Thus it must be used or copied
  654. - * before calling x264_encoder_encode or x264_encoder_headers again. */
  655. -typedef struct
  656. -{
  657. -    int i_ref_idc;  /* nal_priority_e */
  658. -    int i_type;     /* nal_unit_type_e */
  659. -
  660. -    /* Size of payload in bytes. */
  661. -    int     i_payload;
  662. -    /* If param->b_annexb is set, Annex-B bytestream with 4-byte startcode.
  663. -     * Otherwise, startcode is replaced with a 4-byte size.
  664. -     * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
  665. -    uint8_t *p_payload;
  666. -} x264_nal_t;
  667. -
  668. -/****************************************************************************
  669.   * Encoder functions
  670.   ****************************************************************************/
  671.  
  672. --
  673. 1.7.0.4
  674.  
  675.  
  676. From a90edcc40772e54d3cb2c3da65ce52d45c178c29 Mon Sep 17 00:00:00 2001
  677. From: Lamont Alston <wewk584@gmail.com>
  678. Date: Tue, 29 Jun 2010 10:11:42 -0700
  679. Subject: [PATCH 3/6] Make open-GOP Blu-ray compatible
  680.  Blu-ray is even more braindamaged than we thought.
  681.  Accordingly, open-gop options are now "normal" and "bluray", as opposed to display and coded.
  682.  Normal should be used in all cases besides Blu-ray authoring.
  683.  
  684. ---
  685. encoder/encoder.c   |    2 +-
  686.  encoder/slicetype.c |   28 +++++++---------------------
  687.  x264.c              |    8 ++++----
  688.  x264.h              |    8 ++++----
  689.  4 files changed, 16 insertions(+), 30 deletions(-)
  690.  
  691. diff --git a/encoder/encoder.c b/encoder/encoder.c
  692. index fe97aef..5cd3307 100644
  693. --- a/encoder/encoder.c
  694. +++ b/encoder/encoder.c
  695. @@ -577,7 +577,7 @@ static int x264_validate_parameters( x264_t *h )
  696.          h->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
  697.      }
  698.      h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_MIN( X264_BFRAME_MAX, h->param.i_keyint_max-1 ) );
  699. -    h->param.i_open_gop = x264_clip3( h->param.i_open_gop, X264_OPEN_GOP_NONE, X264_OPEN_GOP_CODED_ORDER );
  700. +    h->param.i_open_gop = x264_clip3( h->param.i_open_gop, X264_OPEN_GOP_NONE, X264_OPEN_GOP_BLURAY );
  701.      if( h->param.i_keyint_max == 1 )
  702.          h->param.b_intra_refresh = 0;
  703.      h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 );
  704. diff --git a/encoder/slicetype.c b/encoder/slicetype.c
  705. index 2703f02..4ede8cf 100644
  706. --- a/encoder/slicetype.c
  707. +++ b/encoder/slicetype.c
  708. @@ -1233,17 +1233,11 @@ void x264_slicetype_analyse( x264_t *h, int keyframe )
  709.      if( !h->param.b_intra_refresh )
  710.          for( int i = keyint_limit+1; i <= num_frames; i += h->param.i_keyint_max )
  711.          {
  712. -            int j = i;
  713. -            if( h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
  714. -            {
  715. -                while( IS_X264_TYPE_B( frames[i]->i_type ) )
  716. -                    i++;
  717. -                while( IS_X264_TYPE_B( frames[j-1]->i_type ) )
  718. -                    j--;
  719. -            }
  720.              frames[i]->i_type = X264_TYPE_I;
  721.              reset_start = X264_MIN( reset_start, i+1 );
  722. -            i = j;
  723. +            if( h->param.i_open_gop == X264_OPEN_GOP_BLURAY )
  724. +                while( IS_X264_TYPE_B( frames[i-1]->i_type ) )
  725. +                    i--;
  726.          }
  727.  
  728.      if( vbv_lookahead )
  729. @@ -1337,16 +1331,8 @@ void x264_slicetype_decide( x264_t *h )
  730.              if( frm->i_type == X264_TYPE_AUTO || frm->i_type == X264_TYPE_I )
  731.                  frm->i_type = h->param.i_open_gop && h->lookahead->i_last_keyframe >= 0 ? X264_TYPE_I : X264_TYPE_IDR;
  732.              int warn = frm->i_type != X264_TYPE_IDR;
  733. -            if( warn && h->param.i_open_gop == X264_OPEN_GOP_DISPLAY_ORDER )
  734. -                warn &= frm->i_type != X264_TYPE_I && frm->i_type != X264_TYPE_KEYFRAME;
  735. -            if( warn && h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
  736. -            {
  737. -                /* if this minigop ends with i, it's not a violation */
  738. -                int j = bframes;
  739. -                while( IS_X264_TYPE_B( h->lookahead->next.list[j]->i_type ) )
  740. -                    j++;
  741. -                warn = h->lookahead->next.list[j]->i_type != X264_TYPE_I && h->lookahead->next.list[j]->i_type != X264_TYPE_KEYFRAME;
  742. -            }
  743. +            if( warn && h->param.i_open_gop )
  744. +                warn &= frm->i_type != X264_TYPE_I;
  745.              if( warn )
  746.                  x264_log( h, X264_LOG_WARNING, "specified frame type (%d) at %d is not compatible with keyframe interval\n", frm->i_type, frm->i_frame );
  747.          }
  748. @@ -1355,8 +1341,8 @@ void x264_slicetype_decide( x264_t *h )
  749.              if( h->param.i_open_gop )
  750.              {
  751.                  h->lookahead->i_last_keyframe = frm->i_frame; // Use display order
  752. -                if( h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
  753. -                    h->lookahead->i_last_keyframe -= bframes; // Use coded order
  754. +                if( h->param.i_open_gop == X264_OPEN_GOP_BLURAY )
  755. +                    h->lookahead->i_last_keyframe -= bframes; // Use bluray order
  756.                  frm->b_keyframe = 1;
  757.              }
  758.              else
  759. diff --git a/x264.c b/x264.c
  760. index df04385..f08ab41 100644
  761. --- a/x264.c
  762. +++ b/x264.c
  763. @@ -382,10 +382,10 @@ static void Help( x264_param_t *defaults, int longhelp )
  764.          "                                  - normal: Non-strict (not Blu-ray compatible)\n",
  765.          strtable_lookup( x264_b_pyramid_names, defaults->i_bframe_pyramid ) );
  766.      H1( "      --open-gop <string>     Use recovery points to close GOPs [none]\n"
  767. -        "                                  - none: Use standard closed GOPs\n"
  768. -        "                                  - display: Base GOP length on display order\n"
  769. -        "                                             (not Blu-ray compatible)\n"
  770. -        "                                  - coded: Base GOP length on coded order\n"
  771. +        "                                  - none: closed GOPs only\n"
  772. +        "                                  - normal: standard open GOPs\n"
  773. +        "                                            (not Blu-ray compatible)\n"
  774. +        "                                  - bluray: Blu-ray-compatible open GOPs\n"
  775.          "                              Only available with b-frames\n" );
  776.      H1( "      --no-cabac              Disable CABAC\n" );
  777.      H1( "  -r, --ref <integer>         Number of reference frames [%d]\n", defaults->i_frame_reference );
  778. diff --git a/x264.h b/x264.h
  779. index 6a663ed..604ca45 100644
  780. --- a/x264.h
  781. +++ b/x264.h
  782. @@ -153,8 +153,8 @@ typedef struct
  783.  #define X264_B_PYRAMID_NORMAL        2
  784.  #define X264_KEYINT_MIN_AUTO         0
  785.  #define X264_OPEN_GOP_NONE           0
  786. -#define X264_OPEN_GOP_DISPLAY_ORDER  1
  787. -#define X264_OPEN_GOP_CODED_ORDER    2
  788. +#define X264_OPEN_GOP_NORMAL         1
  789. +#define X264_OPEN_GOP_BLURAY         2
  790.  
  791.  static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
  792.  static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
  793. @@ -166,7 +166,7 @@ static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "
  794.  static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", 0 };
  795.  static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", 0 };
  796.  static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
  797. -static const char * const x264_open_gop_names[] = { "none", "display", "coded", 0 };
  798. +static const char * const x264_open_gop_names[] = { "none", "normal", "bluray", 0 };
  799.  
  800.  /* Colorspace type
  801.   * legacy only; nothing other than I420 is really supported. */
  802. @@ -276,7 +276,7 @@ typedef struct x264_param_t
  803.      int         i_bframe_adaptive;
  804.      int         i_bframe_bias;
  805.      int         i_bframe_pyramid;   /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
  806. -    int         i_open_gop;         /* Open gop: 1=display order, 2=coded order to determine gop size */
  807. +    int         i_open_gop;         /* Open gop: 1=display order, 2=bluray compatibility braindamage mode */
  808.  
  809.      int         b_deblocking_filter;
  810.      int         i_deblocking_filter_alphac0;    /* [-6, 6] -6 light filter, 6 strong */
  811. --
  812. 1.7.0.4
  813.  
  814.  
  815. From 495f11a3dd9c4bdd866142b351c170832f65b678 Mon Sep 17 00:00:00 2001
  816. From: Steven Walters <kemuri9@gmail.com>
  817. Date: Sat, 26 Jun 2010 16:28:49 -0400
  818. Subject: [PATCH 4/6] Centralize logging within x264cli
  819.  x264cli messages will now respect the log level they pertain to.
  820.  Slightly reduces binary size.
  821.  
  822. ---
  823. input/avs.c             |   88 +++++-------------
  824.  input/ffms.c            |   58 +++--------
  825.  input/input.h           |    2 +
  826.  input/lavf.c            |   55 +++--------
  827.  input/thread.c          |    9 +-
  828.  input/timecode.c        |  111 ++++++----------------
  829.  input/y4m.c             |   23 +----
  830.  input/yuv.c             |    8 +-
  831.  muxers.h                |   61 ------------
  832.  output/flv.c            |   10 +-
  833.  output/flv_bytestream.c |    2 +-
  834.  output/matroska.c       |    2 +-
  835.  output/matroska_ebml.c  |    2 +-
  836.  output/mp4.c            |   12 +--
  837.  output/output.h         |    2 +
  838.  output/raw.c            |    2 +-
  839.  x264.c                  |  246 +++++++++++++++++++++--------------------------
  840.  x264cli.h               |   67 +++++++++++++
  841.  18 files changed, 289 insertions(+), 471 deletions(-)
  842.  delete mode 100644 muxers.h
  843.  create mode 100644 x264cli.h
  844.  
  845. diff --git a/input/avs.c b/input/avs.c
  846. index 07add40..b83f715 100644
  847. --- a/input/avs.c
  848. +++ b/input/avs.c
  849. @@ -20,8 +20,9 @@
  850.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  851.   *****************************************************************************/
  852.  
  853. -#include "muxers.h"
  854. +#include "input.h"
  855.  #include <windows.h>
  856. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "avs", __VA_ARGS__ )
  857.  
  858.  /* the AVS interface currently uses __declspec to link function declarations to their definitions in the dll.
  859.     this has a side effect of preventing program execution if the avisynth dll is not found,
  860. @@ -131,27 +132,15 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  861.      FILE *fh = fopen( psz_filename, "r" );
  862.      if( !fh )
  863.          return -1;
  864. -    else if( !x264_is_regular_file( fh ) )
  865. -    {
  866. -        fprintf( stderr, "avs [error]: AVS input is incompatible with non-regular file `%s'\n", psz_filename );
  867. -        return -1;
  868. -    }
  869. +    FAIL_IF_ERROR( !x264_is_regular_file( fh ), "AVS input is incompatible with non-regular file `%s'\n", psz_filename );
  870.      fclose( fh );
  871.  
  872.      avs_hnd_t *h = malloc( sizeof(avs_hnd_t) );
  873.      if( !h )
  874.          return -1;
  875. -    if( avs_load_library( h ) )
  876. -    {
  877. -        fprintf( stderr, "avs [error]: failed to load avisynth\n" );
  878. -        return -1;
  879. -    }
  880. +    FAIL_IF_ERROR( avs_load_library( h ), "failed to load avisynth\n" )
  881.      h->env = h->func.avs_create_script_environment( AVS_INTERFACE_YV12 );
  882. -    if( !h->env )
  883. -    {
  884. -        fprintf( stderr, "avs [error]: failed to initiate avisynth\n" );
  885. -        return -1;
  886. -    }
  887. +    FAIL_IF_ERROR( !h->env, "failed to initiate avisynth\n" )
  888.      AVS_Value arg = avs_new_value_string( psz_filename );
  889.      AVS_Value res;
  890.      char *filename_ext = get_filename_extension( psz_filename );
  891. @@ -159,11 +148,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  892.      if( !strcasecmp( filename_ext, "avs" ) )
  893.      {
  894.          res = h->func.avs_invoke( h->env, "Import", arg, NULL );
  895. -        if( avs_is_error( res ) )
  896. -        {
  897. -            fprintf( stderr, "avs [error]: %s\n", avs_as_string( res ) );
  898. -            return -1;
  899. -        }
  900. +        FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_string( res ) )
  901.          /* check if the user is using a multi-threaded script and apply distributor if necessary.
  902.             adapted from avisynth's vfw interface */
  903.          AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
  904. @@ -184,78 +169,55 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  905.          int i;
  906.          for( i = 0; filter[i]; i++ )
  907.          {
  908. -            fprintf( stderr, "avs [info]: trying %s... ", filter[i] );
  909. +            x264_cli_log( "avs", X264_LOG_INFO, "trying %s... ", filter[i] );
  910.              if( !h->func.avs_function_exists( h->env, filter[i] ) )
  911.              {
  912. -                fprintf( stderr, "not found\n" );
  913. +                x264_cli_printf( X264_LOG_INFO, "not found\n" );
  914.                  continue;
  915.              }
  916.              if( !strncasecmp( filter[i], "FFmpegSource", 12 ) )
  917.              {
  918. -                fprintf( stderr, "indexing... " );
  919. +                x264_cli_printf( X264_LOG_INFO, "indexing... " );
  920.                  fflush( stderr );
  921.              }
  922.              res = h->func.avs_invoke( h->env, filter[i], arg, NULL );
  923.              if( !avs_is_error( res ) )
  924.              {
  925. -                fprintf( stderr, "succeeded\n" );
  926. +                x264_cli_printf( X264_LOG_INFO, "succeeded\n" );
  927.                  break;
  928.              }
  929. -            fprintf( stderr, "failed\n" );
  930. -        }
  931. -        if( !filter[i] )
  932. -        {
  933. -            fprintf( stderr, "avs [error]: unable to find source filter to open `%s'\n", psz_filename );
  934. -            return -1;
  935. +            x264_cli_printf( X264_LOG_INFO, "failed\n" );
  936.          }
  937. +        FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename )
  938.      }
  939. -    if( !avs_is_clip( res ) )
  940. -    {
  941. -        fprintf( stderr, "avs [error]: `%s' didn't return a video clip\n", psz_filename );
  942. -        return -1;
  943. -    }
  944. +    FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename )
  945.      h->clip = h->func.avs_take_clip( res, h->env );
  946.      int avs_version = h->func.avs_get_version( h->clip );
  947.      const AVS_VideoInfo *vi = h->func.avs_get_video_info( h->clip );
  948. -    if( !avs_has_video( vi ) )
  949. -    {
  950. -        fprintf( stderr, "avs [error]: `%s' has no video data\n", psz_filename );
  951. -        return -1;
  952. -    }
  953. +    FAIL_IF_ERROR( !avs_has_video( vi ), "`%s' has no video data\n", psz_filename )
  954.      /* if the clip is made of fields instead of frames, call weave to make them frames */
  955.      if( avs_is_field_based( vi ) )
  956.      {
  957. -        fprintf( stderr, "avs [warning]: detected fieldbased (separated) input, weaving to frames\n" );
  958. +        x264_cli_log( "avs", X264_LOG_WARNING, "detected fieldbased (separated) input, weaving to frames\n" );
  959.          AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
  960. -        if( avs_is_error( tmp ) )
  961. -        {
  962. -            fprintf( stderr, "avs [error]: couldn't weave fields into frames\n" );
  963. -            return -1;
  964. -        }
  965. +        FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames\n" )
  966.          res = update_clip( h, &vi, tmp, res );
  967.          info->interlaced = 1;
  968.          info->tff = avs_is_tff( vi );
  969.      }
  970. -    if( vi->width&1 || vi->height&1 )
  971. -    {
  972. -        fprintf( stderr, "avs [error]: input clip width or height not divisible by 2 (%dx%d)\n",
  973. -                 vi->width, vi->height );
  974. -        return -1;
  975. -    }
  976. +    FAIL_IF_ERROR( vi->width&1 || vi->height&1, "input clip width or height not divisible by 2 (%dx%d)\n", vi->width, vi->height )
  977.      /* always call ConvertToYV12 to convert non YV12 planar colorspaces to YV12 when user's AVS supports them,
  978.         as all planar colorspaces are flagged as YV12. If it is already YV12 in this case, the call does nothing */
  979.      if( !avs_is_yv12( vi ) || avs_version >= AVS_INTERFACE_OTHER_PLANAR )
  980.      {
  981. -        fprintf( stderr, "avs %s\n", !avs_is_yv12( vi ) ? "[warning]: converting input clip to YV12"
  982. -               : "[info]: avisynth 2.6+ detected, forcing conversion to YV12" );
  983. +        if( !avs_is_yv12( vi ) )
  984. +            x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to YV12" );
  985. +        else
  986. +            x264_cli_log( "avs", X264_LOG_INFO, "avisynth 2.6+ detected, forcing conversion to YV12" );
  987.          const char *arg_name[2] = { NULL, "interlaced" };
  988.          AVS_Value arg_arr[2] = { res, avs_new_value_bool( info->interlaced ) };
  989.          AVS_Value res2 = h->func.avs_invoke( h->env, "ConvertToYV12", avs_new_value_array( arg_arr, 2 ), arg_name );
  990. -        if( avs_is_error( res2 ) )
  991. -        {
  992. -            fprintf( stderr, "avs [error]: couldn't convert input clip to YV12\n" );
  993. -            return -1;
  994. -        }
  995. +        FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to YV12\n" )
  996.          res = update_clip( h, &vi, res2, res );
  997.      }
  998.      h->func.avs_release_value( res );
  999. @@ -294,11 +256,7 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  1000.          return -1;
  1001.      AVS_VideoFrame *frm = p_pic->opaque = h->func.avs_get_frame( h->clip, i_frame );
  1002.      const char *err = h->func.avs_clip_get_error( h->clip );
  1003. -    if( err )
  1004. -    {
  1005. -        fprintf( stderr, "avs [error]: %s occurred while reading frame %d\n", err, i_frame );
  1006. -        return -1;
  1007. -    }
  1008. +    FAIL_IF_ERROR( err, "%s occurred while reading frame %d\n", err, i_frame )
  1009.      for( int i = 0; i < 3; i++ )
  1010.      {
  1011.          /* explicitly cast away the const attribute to avoid a warning */
  1012. diff --git a/input/ffms.c b/input/ffms.c
  1013. index b2a253e..fe8bf7e 100644
  1014. --- a/input/ffms.c
  1015. +++ b/input/ffms.c
  1016. @@ -21,8 +21,10 @@
  1017.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1018.   *****************************************************************************/
  1019.  
  1020. -#include "muxers.h"
  1021. +#include "input.h"
  1022.  #include <ffms.h>
  1023. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "ffms", __VA_ARGS__ )
  1024. +
  1025.  #undef DECLARE_ALIGNED
  1026.  #include <libavcodec/avcodec.h>
  1027.  #include <libswscale/swscale.h>
  1028. @@ -86,28 +88,16 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1029.      {
  1030.          idx = FFMS_MakeIndex( psz_filename, 0, 0, NULL, NULL, 0, update_progress, NULL, &e );
  1031.          fprintf( stderr, "                                            \r" );
  1032. -        if( !idx )
  1033. -        {
  1034. -            fprintf( stderr, "ffms [error]: could not create index\n" );
  1035. -            return -1;
  1036. -        }
  1037. +        FAIL_IF_ERROR( !idx, "could not create index\n" )
  1038.          if( opt->index_file && FFMS_WriteIndex( opt->index_file, idx, &e ) )
  1039. -            fprintf( stderr, "ffms [warning]: could not write index file\n" );
  1040. +            x264_cli_log( "ffms", X264_LOG_WARNING, "could not write index file\n" );
  1041.      }
  1042.  
  1043.      int trackno = FFMS_GetFirstTrackOfType( idx, FFMS_TYPE_VIDEO, &e );
  1044. -    if( trackno < 0 )
  1045. -    {
  1046. -        fprintf( stderr, "ffms [error]: could not find video track\n" );
  1047. -        return -1;
  1048. -    }
  1049. +    FAIL_IF_ERROR( trackno < 0, "could not find video track\n" )
  1050.  
  1051.      h->video_source = FFMS_CreateVideoSource( psz_filename, trackno, idx, 1, seekmode, &e );
  1052. -    if( !h->video_source )
  1053. -    {
  1054. -        fprintf( stderr, "ffms [error]: could not create video source\n" );
  1055. -        return -1;
  1056. -    }
  1057. +    FAIL_IF_ERROR( !h->video_source, "could not create video source\n" )
  1058.  
  1059.      h->track = FFMS_GetTrackFromVideo( h->video_source );
  1060.  
  1061. @@ -121,11 +111,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1062.      h->vfr_input       = info->vfr;
  1063.  
  1064.      const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, 0, &e );
  1065. -    if( !frame )
  1066. -    {
  1067. -        fprintf( stderr, "ffms [error]: could not read frame 0\n" );
  1068. -        return -1;
  1069. -    }
  1070. +    FAIL_IF_ERROR( !frame, "could not read frame 0\n" )
  1071.  
  1072.      h->init_width  = h->cur_width  = info->width  = frame->EncodedWidth;
  1073.      h->init_height = h->cur_height = info->height = frame->EncodedHeight;
  1074. @@ -134,8 +120,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1075.      info->tff        = frame->TopFieldFirst;
  1076.  
  1077.      if( h->cur_pix_fmt != PIX_FMT_YUV420P )
  1078. -        fprintf( stderr, "ffms [warning]: converting from %s to YV12\n",
  1079. -                 avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
  1080. +        x264_cli_log( "ffms", X264_LOG_WARNING, "converting from %s to YV12\n",
  1081. +                       avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
  1082.  
  1083.      /* ffms timestamps are in milliseconds. ffms also uses int64_ts for timebase,
  1084.       * so we need to reduce large timebases to prevent overflow */
  1085. @@ -173,19 +159,15 @@ static int check_swscale( ffms_hnd_t *h, const FFMS_Frame *frame, int i_frame )
  1086.      if( h->scaler )
  1087.      {
  1088.          sws_freeContext( h->scaler );
  1089. -        fprintf( stderr, "ffms [warning]: stream properties changed to %dx%d, %s at frame %d  \n", frame->EncodedWidth,
  1090. -                 frame->EncodedHeight, avcodec_get_pix_fmt_name( frame->EncodedPixelFormat ), i_frame );
  1091. +        x264_cli_log( "ffms", X264_LOG_WARNING, "stream properties changed to %dx%d, %s at frame %d  \n", frame->EncodedWidth,
  1092. +                      frame->EncodedHeight, avcodec_get_pix_fmt_name( frame->EncodedPixelFormat ), i_frame );
  1093.          h->cur_width   = frame->EncodedWidth;
  1094.          h->cur_height  = frame->EncodedHeight;
  1095.          h->cur_pix_fmt = frame->EncodedPixelFormat;
  1096.      }
  1097.      h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
  1098.                                  PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
  1099. -    if( !h->scaler )
  1100. -    {
  1101. -        fprintf( stderr, "ffms [error]: could not open swscale context\n" );
  1102. -        return -1;
  1103. -    }
  1104. +    FAIL_IF_ERROR( !h->scaler, "could not open swscale context\n" )
  1105.      return 0;
  1106.  }
  1107.  
  1108. @@ -195,11 +177,7 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  1109.      FFMS_ErrorInfo e;
  1110.      e.BufferSize = 0;
  1111.      const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, i_frame, &e );
  1112. -    if( !frame )
  1113. -    {
  1114. -        fprintf( stderr, "ffms [error]: could not read frame %d\n", i_frame );
  1115. -        return -1;
  1116. -    }
  1117. +    FAIL_IF_ERROR( !frame, "could not read frame %d\n", i_frame )
  1118.  
  1119.      if( check_swscale( h, frame, i_frame ) )
  1120.          return -1;
  1121. @@ -214,12 +192,8 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  1122.  
  1123.      if( h->vfr_input )
  1124.      {
  1125. -        if( info->PTS == AV_NOPTS_VALUE )
  1126. -        {
  1127. -            fprintf( stderr, "ffms [error]: invalid timestamp. "
  1128. -                     "Use --force-cfr and specify a framerate with --fps\n" );
  1129. -            return -1;
  1130. -        }
  1131. +        FAIL_IF_ERROR( info->PTS == AV_NOPTS_VALUE, "invalid timestamp. "
  1132. +                       "Use --force-cfr and specify a framerate with --fps\n" )
  1133.  
  1134.          if( !h->pts_offset_flag )
  1135.          {
  1136. diff --git a/input/input.h b/input/input.h
  1137. index f89b13b..f588f3c 100644
  1138. --- a/input/input.h
  1139. +++ b/input/input.h
  1140. @@ -25,6 +25,8 @@
  1141.  #ifndef X264_INPUT_H
  1142.  #define X264_INPUT_H
  1143.  
  1144. +#include "x264cli.h"
  1145. +
  1146.  /* options that are used by only some demuxers */
  1147.  typedef struct
  1148.  {
  1149. diff --git a/input/lavf.c b/input/lavf.c
  1150. index 4b0375f..54a275f 100644
  1151. --- a/input/lavf.c
  1152. +++ b/input/lavf.c
  1153. @@ -21,7 +21,8 @@
  1154.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1155.   *****************************************************************************/
  1156.  
  1157. -#include "muxers.h"
  1158. +#include "input.h"
  1159. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "lavf", __VA_ARGS__ )
  1160.  #undef DECLARE_ALIGNED
  1161.  #include <libavformat/avformat.h>
  1162.  #include <libswscale/swscale.h>
  1163. @@ -59,19 +60,15 @@ static int check_swscale( lavf_hnd_t *h, AVCodecContext *c, int i_frame )
  1164.      if( h->scaler )
  1165.      {
  1166.          sws_freeContext( h->scaler );
  1167. -        fprintf( stderr, "lavf [warning]: stream properties changed to %dx%d, %s at frame %d  \n",
  1168. -                 c->width, c->height, avcodec_get_pix_fmt_name( c->pix_fmt ), i_frame );
  1169. +        x264_cli_log( "lavf", X264_LOG_WARNING, "stream properties changed to %dx%d, %s at frame %d  \n",
  1170. +                      c->width, c->height, avcodec_get_pix_fmt_name( c->pix_fmt ), i_frame );
  1171.          h->cur_width   = c->width;
  1172.          h->cur_height  = c->height;
  1173.          h->cur_pix_fmt = c->pix_fmt;
  1174.      }
  1175.      h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
  1176.                                  PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
  1177. -    if( !h->scaler )
  1178. -    {
  1179. -        fprintf( stderr, "lavf [error]: could not open swscale context\n" );
  1180. -        return -1;
  1181. -    }
  1182. +    FAIL_IF_ERROR( !h->scaler, "could not open swscale context\n" )
  1183.      return 0;
  1184.  }
  1185.  
  1186. @@ -106,12 +103,12 @@ static int read_frame_internal( x264_picture_t *p_pic, lavf_hnd_t *h, int i_fram
  1187.              {
  1188.                  c->reordered_opaque = pkt->pts;
  1189.                  if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
  1190. -                    fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
  1191. +                    x264_cli_log( "lavf", X264_LOG_WARNING, "video decoding failed on frame %d\n", h->next_frame );
  1192.              }
  1193.          if( !finished )
  1194.          {
  1195.              if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
  1196. -                fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
  1197. +                x264_cli_log( "lavf", X264_LOG_WARNING, "video decoding failed on frame %d\n", h->next_frame );
  1198.              if( !finished )
  1199.                  return -1;
  1200.          }
  1201. @@ -166,26 +163,13 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1202.      if( !strcmp( psz_filename, "-" ) )
  1203.          psz_filename = "pipe:";
  1204.  
  1205. -    if( av_open_input_file( &h->lavf, psz_filename, NULL, 0, NULL ) )
  1206. -    {
  1207. -        fprintf( stderr, "lavf [error]: could not open input file\n" );
  1208. -        return -1;
  1209. -    }
  1210. -
  1211. -    if( av_find_stream_info( h->lavf ) < 0 )
  1212. -    {
  1213. -        fprintf( stderr, "lavf [error]: could not find input stream info\n" );
  1214. -        return -1;
  1215. -    }
  1216. +    FAIL_IF_ERROR( av_open_input_file( &h->lavf, psz_filename, NULL, 0, NULL ), "could not open input file\n" )
  1217. +    FAIL_IF_ERROR( av_find_stream_info( h->lavf ) < 0, "could not find input stream info\n" )
  1218.  
  1219.      int i = 0;
  1220.      while( i < h->lavf->nb_streams && h->lavf->streams[i]->codec->codec_type != CODEC_TYPE_VIDEO )
  1221.          i++;
  1222. -    if( i == h->lavf->nb_streams )
  1223. -    {
  1224. -        fprintf( stderr, "lavf [error]: could not find video stream\n" );
  1225. -        return -1;
  1226. -    }
  1227. +    FAIL_IF_ERROR( i == h->lavf->nb_streams, "could not find video stream\n" )
  1228.      h->stream_id       = i;
  1229.      h->next_frame      = 0;
  1230.      h->pts_offset_flag = 0;
  1231. @@ -207,22 +191,15 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1232.          info->csp |= X264_CSP_VFLIP;
  1233.  
  1234.      if( h->cur_pix_fmt != PIX_FMT_YUV420P )
  1235. -        fprintf( stderr, "lavf [warning]: converting from %s to YV12\n",
  1236. -                 avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
  1237. -
  1238. -    if( avcodec_open( c, avcodec_find_decoder( c->codec_id ) ) )
  1239. -    {
  1240. -        fprintf( stderr, "lavf [error]: could not find decoder for video stream\n" );
  1241. -        return -1;
  1242. -    }
  1243. +        x264_cli_log( "lavf", X264_LOG_WARNING, "converting from %s to YV12\n",
  1244. +                      avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
  1245. +    FAIL_IF_ERROR( avcodec_open( c, avcodec_find_decoder( c->codec_id ) ),
  1246. +                   "could not find decoder for video stream\n" )
  1247.  
  1248.      /* prefetch the first frame and set/confirm flags */
  1249.      h->first_pic = malloc( sizeof(x264_picture_t) );
  1250. -    if( !h->first_pic || lavf_input.picture_alloc( h->first_pic, info->csp, info->width, info->height ) )
  1251. -    {
  1252. -        fprintf( stderr, "lavf [error]: malloc failed\n" );
  1253. -        return -1;
  1254. -    }
  1255. +    FAIL_IF_ERROR( !h->first_pic || lavf_input.picture_alloc( h->first_pic, info->csp, info->width, info->height ),
  1256. +                   "malloc failed\n" )
  1257.      else if( read_frame_internal( h->first_pic, h, 0, info ) )
  1258.          return -1;
  1259.  
  1260. diff --git a/input/thread.c b/input/thread.c
  1261. index c4b07fa..98af22b 100644
  1262. --- a/input/thread.c
  1263. +++ b/input/thread.c
  1264. @@ -21,7 +21,7 @@
  1265.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1266.   *****************************************************************************/
  1267.  
  1268. -#include "muxers.h"
  1269. +#include "input.h"
  1270.  
  1271.  extern cli_input_t input;
  1272.  
  1273. @@ -47,11 +47,8 @@ typedef struct thread_input_arg_t
  1274.  static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
  1275.  {
  1276.      thread_hnd_t *h = malloc( sizeof(thread_hnd_t) );
  1277. -    if( !h || input.picture_alloc( &h->pic, info->csp, info->width, info->height ) )
  1278. -    {
  1279. -        fprintf( stderr, "x264 [error]: malloc failed\n" );
  1280. -        return -1;
  1281. -    }
  1282. +    FAIL_IF_ERR( !h || input.picture_alloc( &h->pic, info->csp, info->width, info->height ),
  1283. +                 "x264", "malloc failed\n" )
  1284.      h->input = input;
  1285.      h->p_handle = *p_handle;
  1286.      h->next_frame = -1;
  1287. diff --git a/input/timecode.c b/input/timecode.c
  1288. index a307327..7821e76 100644
  1289. --- a/input/timecode.c
  1290. +++ b/input/timecode.c
  1291. @@ -20,7 +20,8 @@
  1292.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1293.   *****************************************************************************/
  1294.  
  1295. -#include "muxers.h"
  1296. +#include "input.h"
  1297. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "timecode", __VA_ARGS__ )
  1298.  #include <math.h>
  1299.  
  1300.  extern cli_input_t input;
  1301. @@ -61,12 +62,8 @@ static double correct_fps( double fps, timecode_hnd_t *h )
  1302.      {
  1303.          fps_den = i * h->timebase_num;
  1304.          fps_num = round( fps_den * fps_sig ) * exponent;
  1305. -        if( fps_num > UINT32_MAX )
  1306. -        {
  1307. -            fprintf( stderr, "timecode [error]: tcfile fps correction failed.\n"
  1308. -                             "                  Specify an appropriate timebase manually or remake tcfile.\n" );
  1309. -            return -1;
  1310. -        }
  1311. +        FAIL_IF_ERROR( fps_num > UINT32_MAX, "tcfile fps correction failed.\n"
  1312. +                       "                  Specify an appropriate timebase manually or remake tcfile.\n" )
  1313.          if( fabs( ((double)fps_num / fps_den) / exponent - fps_sig ) < DOUBLE_EPSILON )
  1314.              break;
  1315.          ++i;
  1316. @@ -91,12 +88,8 @@ static int try_mkv_timebase_den( double *fpss, timecode_hnd_t *h, int loop_num )
  1317.          double fps_sig = sigexp10( fpss[num], &exponent );
  1318.          fps_den = round( MKV_TIMEBASE_DEN / fps_sig ) / exponent;
  1319.          h->timebase_num = fps_den && h->timebase_num ? gcd( h->timebase_num, fps_den ) : fps_den;
  1320. -        if( h->timebase_num > UINT32_MAX || !h->timebase_num )
  1321. -        {
  1322. -            fprintf( stderr, "timecode [error]: automatic timebase generation failed.\n"
  1323. -                             "                  Specify timebase manually.\n" );
  1324. -            return -1;
  1325. -        }
  1326. +        FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || !h->timebase_num, "automatic timebase generation failed.\n"
  1327. +                       "                  Specify timebase manually.\n" )
  1328.      }
  1329.      return 0;
  1330.  }
  1331. @@ -110,11 +103,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1332.      double *fpss = NULL;
  1333.  
  1334.      ret = fscanf( tcfile_in, "# timecode format v%d", &tcfv );
  1335. -    if( ret != 1 || (tcfv != 1 && tcfv != 2) )
  1336. -    {
  1337. -        fprintf( stderr, "timecode [error]: unsupported timecode format\n" );
  1338. -        return -1;
  1339. -    }
  1340. +    FAIL_IF_ERROR( ret != 1 || (tcfv != 1 && tcfv != 2), "unsupported timecode format\n" )
  1341.  
  1342.      if( tcfv == 1 )
  1343.      {
  1344. @@ -128,18 +117,11 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1345.          {
  1346.              if( buff[0] == '#' || buff[0] == '\n' || buff[0] == '\r' )
  1347.                  continue;
  1348. -            if( sscanf( buff, "assume %lf", &h->assume_fps ) != 1 && sscanf( buff, "Assume %lf", &h->assume_fps ) != 1 )
  1349. -            {
  1350. -                fprintf( stderr, "timecode [error]: tcfile parsing error: assumed fps not found\n" );
  1351. -                return -1;
  1352. -            }
  1353. +            FAIL_IF_ERROR( sscanf( buff, "assume %lf", &h->assume_fps ) != 1 && sscanf( buff, "Assume %lf", &h->assume_fps ) != 1,
  1354. +                           "tcfile parsing error: assumed fps not found\n" )
  1355.              break;
  1356.          }
  1357. -        if( h->assume_fps <= 0 )
  1358. -        {
  1359. -            fprintf( stderr, "timecode [error]: invalid assumed fps %.6f\n", h->assume_fps );
  1360. -            return -1;
  1361. -        }
  1362. +        FAIL_IF_ERROR( h->assume_fps <= 0, "invalid assumed fps %.6f\n", h->assume_fps )
  1363.  
  1364.          file_pos = ftell( tcfile_in );
  1365.          h->stored_pts_num = 0;
  1366. @@ -152,16 +134,9 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1367.                  continue;
  1368.              }
  1369.              ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
  1370. -            if( ret != 3 && ret != EOF )
  1371. -            {
  1372. -                fprintf( stderr, "timecode [error]: invalid input tcfile\n" );
  1373. -                return -1;
  1374. -            }
  1375. -            if( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0 )
  1376. -            {
  1377. -                fprintf( stderr, "timecode [error]: invalid input tcfile at line %d: %s\n", num, buff );
  1378. -                return -1;
  1379. -            }
  1380. +            FAIL_IF_ERROR( ret != 3 && ret != EOF, "invalid input tcfile\n" )
  1381. +            FAIL_IF_ERROR( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0,
  1382. +                           "invalid input tcfile at line %d: %s\n", num, buff )
  1383.              prev_start = start;
  1384.              prev_end = end;
  1385.              if( h->auto_timebase_den || h->auto_timebase_num )
  1386. @@ -259,11 +234,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1387.              ++num;
  1388.          }
  1389.          timecodes_num = h->stored_pts_num + h->seek;
  1390. -        if( !timecodes_num )
  1391. -        {
  1392. -            fprintf( stderr, "timecode [error]: input tcfile doesn't have any timecodes!\n" );
  1393. -            return -1;
  1394. -        }
  1395. +        FAIL_IF_ERROR( !timecodes_num, "input tcfile doesn't have any timecodes!\n" )
  1396.          fseek( tcfile_in, file_pos, SEEK_SET );
  1397.  
  1398.          timecodes = malloc( timecodes_num * sizeof(double) );
  1399. @@ -272,11 +243,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1400.  
  1401.          fgets( buff, sizeof(buff), tcfile_in );
  1402.          ret = sscanf( buff, "%lf", &timecodes[0] );
  1403. -        if( ret != 1 )
  1404. -        {
  1405. -            fprintf( stderr, "timecode [error]: invalid input tcfile for frame 0\n" );
  1406. -            goto fail;
  1407. -        }
  1408. +        FAIL_IF_ERROR( ret != 1, "invalid input tcfile for frame 0\n" )
  1409.          for( num = 1; num < timecodes_num; )
  1410.          {
  1411.              fgets( buff, sizeof(buff), tcfile_in );
  1412. @@ -284,11 +251,8 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1413.                  continue;
  1414.              ret = sscanf( buff, "%lf", &timecodes[num] );
  1415.              timecodes[num] *= 1e-3;         /* Timecode format v2 is expressed in milliseconds. */
  1416. -            if( ret != 1 || timecodes[num] <= timecodes[num - 1] )
  1417. -            {
  1418. -                fprintf( stderr, "timecode [error]: invalid input tcfile for frame %d\n", num );
  1419. -                goto fail;
  1420. -            }
  1421. +            FAIL_IF_ERROR( ret != 1 || timecodes[num] <= timecodes[num - 1],
  1422. +                           "invalid input tcfile for frame %d\n", num )
  1423.              ++num;
  1424.          }
  1425.  
  1426. @@ -342,14 +306,10 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1427.          uint64_t i = gcd( h->timebase_num, h->timebase_den );
  1428.          h->timebase_num /= i;
  1429.          h->timebase_den /= i;
  1430. -        fprintf( stderr, "timecode [info]: automatic timebase generation %"PRIu64"/%"PRIu64"\n", h->timebase_num, h->timebase_den );
  1431. -    }
  1432. -    else if( h->timebase_den > UINT32_MAX || !h->timebase_den )
  1433. -    {
  1434. -        fprintf( stderr, "timecode [error]: automatic timebase generation failed.\n"
  1435. -                         "                  Specify an appropriate timebase manually.\n" );
  1436. -        goto fail;
  1437. +        x264_cli_log( "timecode", X264_LOG_INFO, "automatic timebase generation %"PRIu64"/%"PRIu64"\n", h->timebase_num, h->timebase_den );
  1438.      }
  1439. +    else FAIL_IF_ERROR( h->timebase_den > UINT32_MAX || !h->timebase_den, "automatic timebase generation failed.\n"
  1440. +                        "                  Specify an appropriate timebase manually.\n" )
  1441.  
  1442.      h->pts = malloc( h->stored_pts_num * sizeof(int64_t) );
  1443.      if( !h->pts )
  1444. @@ -360,11 +320,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
  1445.      {
  1446.          h->pts[num] = (int64_t)( timecodes[h->seek + num] * ((double)h->timebase_den / h->timebase_num) + 0.5 );
  1447.          h->pts[num] -= pts_seek_offset;
  1448. -        if( h->pts[num] <= h->pts[num - 1] )
  1449. -        {
  1450. -            fprintf( stderr, "timecode [error]: invalid timebase or timecode for frame %d\n", num );
  1451. -            goto fail;
  1452. -        }
  1453. +        FAIL_IF_ERROR( h->pts[num] <= h->pts[num - 1], "invalid timebase or timecode for frame %d\n", num )
  1454.      }
  1455.  
  1456.      free( timecodes );
  1457. @@ -386,11 +342,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1458.      int ret = 0;
  1459.      FILE *tcfile_in;
  1460.      timecode_hnd_t *h = malloc( sizeof(timecode_hnd_t) );
  1461. -    if( !h )
  1462. -    {
  1463. -        fprintf( stderr, "timecode [error]: malloc failed\n" );
  1464. -        return -1;
  1465. -    }
  1466. +    FAIL_IF_ERROR( !h, "malloc failed\n" )
  1467.      h->input = input;
  1468.      h->p_handle = *p_handle;
  1469.      h->frame_total = input.get_frame_total( h->p_handle );
  1470. @@ -400,11 +352,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1471.          ret = sscanf( opt->timebase, "%"SCNu64"/%"SCNu64, &h->timebase_num, &h->timebase_den );
  1472.          if( ret == 1 )
  1473.              h->timebase_num = strtoul( opt->timebase, NULL, 10 );
  1474. -        if( h->timebase_num > UINT32_MAX || h->timebase_den > UINT32_MAX )
  1475. -        {
  1476. -            fprintf( stderr, "timecode [error]: timebase you specified exceeds H.264 maximum\n" );
  1477. -            return -1;
  1478. -        }
  1479. +        FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || h->timebase_den > UINT32_MAX,
  1480. +                       "timebase you specified exceeds H.264 maximum\n" )
  1481.      }
  1482.      h->auto_timebase_num = !ret;
  1483.      h->auto_timebase_den = ret < 2;
  1484. @@ -418,14 +367,10 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1485.      *p_handle = h;
  1486.  
  1487.      tcfile_in = fopen( psz_filename, "rb" );
  1488. -    if( !tcfile_in )
  1489. -    {
  1490. -        fprintf( stderr, "timecode [error]: can't open `%s'\n", psz_filename );
  1491. -        return -1;
  1492. -    }
  1493. +    FAIL_IF_ERROR( !tcfile_in, "can't open `%s'\n", psz_filename )
  1494.      else if( !x264_is_regular_file( tcfile_in ) )
  1495.      {
  1496. -        fprintf( stderr, "timecode [error]: tcfile input incompatible with non-regular file `%s'\n", psz_filename );
  1497. +        x264_cli_log( "timecode", X264_LOG_ERROR, "tcfile input incompatible with non-regular file `%s'\n", psz_filename );
  1498.          fclose( tcfile_in );
  1499.          return -1;
  1500.      }
  1501. @@ -466,8 +411,8 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
  1502.      {
  1503.          if( h->pts )
  1504.          {
  1505. -            fprintf( stderr, "timecode [info]: input timecode file missing data for frame %d and later\n"
  1506. -                             "                 assuming constant fps %.6f\n", i_frame, h->assume_fps );
  1507. +            x264_cli_log( "timecode", X264_LOG_INFO, "input timecode file missing data for frame %d and later\n"
  1508. +                          "                 assuming constant fps %.6f\n", i_frame, h->assume_fps );
  1509.              free( h->pts );
  1510.              h->pts = NULL;
  1511.          }
  1512. diff --git a/input/y4m.c b/input/y4m.c
  1513. index fd42140..9b39d2f 100644
  1514. --- a/input/y4m.c
  1515. +++ b/input/y4m.c
  1516. @@ -21,7 +21,8 @@
  1517.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1518.   *****************************************************************************/
  1519.  
  1520. -#include "muxers.h"
  1521. +#include "input.h"
  1522. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "y4m", __VA_ARGS__ )
  1523.  
  1524.  typedef struct
  1525.  {
  1526. @@ -162,11 +163,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1527.      if( colorspace == X264_CSP_NONE )
  1528.          colorspace = X264_CSP_I420;
  1529.  
  1530. -    if( colorspace != X264_CSP_I420 )
  1531. -    {
  1532. -        fprintf( stderr, "y4m [error]: colorspace unhandled\n" );
  1533. -        return -1;
  1534. -    }
  1535. +    FAIL_IF_ERROR( colorspace != X264_CSP_I420, "colorspace unhandled\n" )
  1536.  
  1537.      *p_handle = h;
  1538.      return 0;
  1539. @@ -202,21 +199,13 @@ static int read_frame_internal( x264_picture_t *p_pic, y4m_hnd_t *h )
  1540.          return -1;
  1541.  
  1542.      header[slen] = 0;
  1543. -    if( strncmp( header, Y4M_FRAME_MAGIC, slen ) )
  1544. -    {
  1545. -        fprintf( stderr, "y4m [error]: bad header magic (%"PRIx32" <=> %s)\n",
  1546. -                 M32(header), header );
  1547. -        return -1;
  1548. -    }
  1549. +    FAIL_IF_ERROR( strncmp( header, Y4M_FRAME_MAGIC, slen ), "bad header magic (%"PRIx32" <=> %s)\n",
  1550. +                   M32(header), header )
  1551.  
  1552.      /* Skip most of it */
  1553.      while( i < MAX_FRAME_HEADER && fgetc( h->fh ) != '\n' )
  1554.          i++;
  1555. -    if( i == MAX_FRAME_HEADER )
  1556. -    {
  1557. -        fprintf( stderr, "y4m [error]: bad frame header!\n" );
  1558. -        return -1;
  1559. -    }
  1560. +    FAIL_IF_ERROR( i == MAX_FRAME_HEADER, "bad frame header!\n" )
  1561.      h->frame_header_len = i+slen+1;
  1562.  
  1563.      if( fread( p_pic->img.plane[0], h->width * h->height, 1, h->fh ) <= 0
  1564. diff --git a/input/yuv.c b/input/yuv.c
  1565. index cbed7fc..613662c 100644
  1566. --- a/input/yuv.c
  1567. +++ b/input/yuv.c
  1568. @@ -21,7 +21,7 @@
  1569.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1570.   *****************************************************************************/
  1571.  
  1572. -#include "muxers.h"
  1573. +#include "input.h"
  1574.  
  1575.  typedef struct
  1576.  {
  1577. @@ -45,11 +45,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
  1578.      }
  1579.      else
  1580.          sscanf( opt->resolution, "%ux%u", &info->width, &info->height );
  1581. -    if( !info->width || !info->height )
  1582. -    {
  1583. -        fprintf( stderr, "yuv [error]: rawyuv input requires a resolution.\n" );
  1584. -        return -1;
  1585. -    }
  1586. +    FAIL_IF_ERR( !info->width || !info->height, "yuv", "rawyuv input requires a resolution.\n" )
  1587.  
  1588.      h->next_frame = 0;
  1589.      info->vfr     = 0;
  1590. diff --git a/muxers.h b/muxers.h
  1591. deleted file mode 100644
  1592. index b309320..0000000
  1593. --- a/muxers.h
  1594. +++ /dev/null
  1595. @@ -1,61 +0,0 @@
  1596. -/*****************************************************************************
  1597. - * muxers.h: h264 file i/o modules
  1598. - *****************************************************************************
  1599. - * Copyright (C) 2003-2009 x264 project
  1600. - *
  1601. - * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  1602. - *          Loren Merritt <lorenm@u.washington.edu>
  1603. - *
  1604. - * This program is free software; you can redistribute it and/or modify
  1605. - * it under the terms of the GNU General Public License as published by
  1606. - * the Free Software Foundation; either version 2 of the License, or
  1607. - * (at your option) any later version.
  1608. - *
  1609. - * This program is distributed in the hope that it will be useful,
  1610. - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  1611. - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1612. - * GNU General Public License for more details.
  1613. - *
  1614. - * You should have received a copy of the GNU General Public License
  1615. - * along with this program; if not, write to the Free Software
  1616. - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1617. - *****************************************************************************/
  1618. -
  1619. -#ifndef X264_MUXERS_H
  1620. -#define X264_MUXERS_H
  1621. -
  1622. -#include "common/common.h"
  1623. -#include "x264.h"
  1624. -
  1625. -typedef void *hnd_t;
  1626. -
  1627. -static inline int64_t gcd( int64_t a, int64_t b )
  1628. -{
  1629. -    while( 1 )
  1630. -    {
  1631. -        int64_t c = a % b;
  1632. -        if( !c )
  1633. -            return b;
  1634. -        a = b;
  1635. -        b = c;
  1636. -    }
  1637. -}
  1638. -
  1639. -static inline int64_t lcm( int64_t a, int64_t b )
  1640. -{
  1641. -    return ( a / gcd( a, b ) ) * b;
  1642. -}
  1643. -
  1644. -static inline char *get_filename_extension( char *filename )
  1645. -{
  1646. -    char *ext = filename + strlen( filename );
  1647. -    while( *ext != '.' && ext > filename )
  1648. -        ext--;
  1649. -    ext += *ext == '.';
  1650. -    return ext;
  1651. -}
  1652. -
  1653. -#include "input/input.h"
  1654. -#include "output/output.h"
  1655. -
  1656. -#endif
  1657. diff --git a/output/flv.c b/output/flv.c
  1658. index e441b6d..9831a5b 100644
  1659. --- a/output/flv.c
  1660. +++ b/output/flv.c
  1661. @@ -18,7 +18,7 @@
  1662.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1663.   *****************************************************************************/
  1664.  
  1665. -#include "muxers.h"
  1666. +#include "output.h"
  1667.  #include "flv_bytestream.h"
  1668.  
  1669.  #define CHECK(x)\
  1670. @@ -223,14 +223,14 @@ static int write_frame( hnd_t handle, uint8_t *p_nalu, int i_size, x264_picture_
  1671.          if( prev_dts == dts )
  1672.          {
  1673.              double fps = ((double)p_flv->i_timebase_den / p_flv->i_timebase_num) / (p_picture->i_dts - p_flv->i_prev_dts);
  1674. -            fprintf( stderr, "flv [warning]: duplicate DTS %"PRId64" generated by rounding\n"
  1675. -                             "               current internal decoding framerate: %.6f fps\n", dts, fps );
  1676. +            x264_cli_log( "flv", X264_LOG_WARNING, "duplicate DTS %"PRId64" generated by rounding\n"
  1677. +                          "               current internal decoding framerate: %.6f fps\n", dts, fps );
  1678.          }
  1679.          if( prev_cts == cts )
  1680.          {
  1681.              double fps = ((double)p_flv->i_timebase_den / p_flv->i_timebase_num) / (p_picture->i_pts - p_flv->i_prev_pts);
  1682. -            fprintf( stderr, "flv [warning]: duplicate CTS %"PRId64" generated by rounding\n"
  1683. -                             "               current internal composition framerate: %.6f fps\n", cts, fps );
  1684. +            x264_cli_log( "flv", X264_LOG_WARNING, "duplicate CTS %"PRId64" generated by rounding\n"
  1685. +                          "               current internal composition framerate: %.6f fps\n", cts, fps );
  1686.          }
  1687.      }
  1688.      p_flv->i_prev_dts = p_picture->i_dts;
  1689. diff --git a/output/flv_bytestream.c b/output/flv_bytestream.c
  1690. index 316114c..e02476c 100644
  1691. --- a/output/flv_bytestream.c
  1692. +++ b/output/flv_bytestream.c
  1693. @@ -18,7 +18,7 @@
  1694.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1695.   *****************************************************************************/
  1696.  
  1697. -#include "muxers.h"
  1698. +#include "output.h"
  1699.  #include "flv_bytestream.h"
  1700.  
  1701.  uint64_t dbl2int( double value )
  1702. diff --git a/output/matroska.c b/output/matroska.c
  1703. index 0304c84..a1219d0 100644
  1704. --- a/output/matroska.c
  1705. +++ b/output/matroska.c
  1706. @@ -18,7 +18,7 @@
  1707.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1708.   *****************************************************************************/
  1709.  
  1710. -#include "muxers.h"
  1711. +#include "output.h"
  1712.  #include "matroska_ebml.h"
  1713.  
  1714.  typedef struct
  1715. diff --git a/output/matroska_ebml.c b/output/matroska_ebml.c
  1716. index 31b62f8..adfcaa8 100644
  1717. --- a/output/matroska_ebml.c
  1718. +++ b/output/matroska_ebml.c
  1719. @@ -18,7 +18,7 @@
  1720.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1721.   *****************************************************************************/
  1722.  
  1723. -#include "muxers.h"
  1724. +#include "output.h"
  1725.  #include "matroska_ebml.h"
  1726.  
  1727.  #define CLSIZE 1048576
  1728. diff --git a/output/mp4.c b/output/mp4.c
  1729. index 0e3c2fc..f2fc5f5 100644
  1730. --- a/output/mp4.c
  1731. +++ b/output/mp4.c
  1732. @@ -21,7 +21,7 @@
  1733.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1734.   *****************************************************************************/
  1735.  
  1736. -#include "muxers.h"
  1737. +#include "output.h"
  1738.  #include <gpac/isomedia.h>
  1739.  
  1740.  #if HAVE_GF_MALLOC
  1741. @@ -61,12 +61,12 @@ static void recompute_bitrate_mp4( GF_ISOFile *p_file, int i_track )
  1742.  
  1743.      timescale = gf_isom_get_media_timescale( p_file, i_track );
  1744.      count = gf_isom_get_sample_count( p_file, i_track );
  1745. -    for( int i = 0; i < count; i++ )
  1746. +    for( u32 i = 0; i < count; i++ )
  1747.      {
  1748.          GF_ISOSample *samp = gf_isom_get_sample_info( p_file, i_track, i+1, &di, &offset );
  1749.          if( !samp )
  1750.          {
  1751. -            fprintf( stderr, "mp4 [error]: failure reading back frame %u\n", i );
  1752. +            x264_cli_log( "mp4", X264_LOG_ERROR, "failure reading back frame %u\n", i );
  1753.              break;
  1754.          }
  1755.  
  1756. @@ -163,11 +163,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle )
  1757.      FILE *fh = fopen( psz_filename, "w" );
  1758.      if( !fh )
  1759.          return -1;
  1760. -    else if( !x264_is_regular_file( fh ) )
  1761. -    {
  1762. -        fprintf( stderr, "mp4 [error]: MP4 output is incompatible with non-regular file `%s'\n", psz_filename );
  1763. -        return -1;
  1764. -    }
  1765. +    FAIL_IF_ERR( !x264_is_regular_file( fh ), "MP4 output is incompatible with non-regular file `%s'\n", psz_filename )
  1766.      fclose( fh );
  1767.  
  1768.      if( !(p_mp4 = malloc( sizeof(mp4_hnd_t) )) )
  1769. diff --git a/output/output.h b/output/output.h
  1770. index c79b48e..094fefc 100644
  1771. --- a/output/output.h
  1772. +++ b/output/output.h
  1773. @@ -24,6 +24,8 @@
  1774.  #ifndef X264_OUTPUT_H
  1775.  #define X264_OUTPUT_H
  1776.  
  1777. +#include "x264cli.h"
  1778. +
  1779.  typedef struct
  1780.  {
  1781.      int (*open_file)( char *psz_filename, hnd_t *p_handle );
  1782. diff --git a/output/raw.c b/output/raw.c
  1783. index 02e4c56..fc418fb 100644
  1784. --- a/output/raw.c
  1785. +++ b/output/raw.c
  1786. @@ -21,7 +21,7 @@
  1787.   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  1788.   *****************************************************************************/
  1789.  
  1790. -#include "muxers.h"
  1791. +#include "output.h"
  1792.  
  1793.  static int open_file( char *psz_filename, hnd_t *p_handle )
  1794.  {
  1795. diff --git a/x264.c b/x264.c
  1796. index f08ab41..741570c 100644
  1797. --- a/x264.c
  1798. +++ b/x264.c
  1799. @@ -31,9 +31,11 @@
  1800.  #include <getopt.h>
  1801.  
  1802.  #include "common/common.h"
  1803. -#include "common/cpu.h"
  1804. -#include "x264.h"
  1805. -#include "muxers.h"
  1806. +#include "x264cli.h"
  1807. +#include "input/input.h"
  1808. +#include "output/output.h"
  1809. +
  1810. +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "x264", __VA_ARGS__ )
  1811.  
  1812.  #ifdef _WIN32
  1813.  #include <windows.h>
  1814. @@ -96,6 +98,7 @@ static const char * const muxer_names[] =
  1815.  };
  1816.  
  1817.  static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
  1818. +static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 };
  1819.  
  1820.  typedef struct{
  1821.      int mod;
  1822. @@ -141,6 +144,48 @@ static void Help( x264_param_t *defaults, int longhelp );
  1823.  static int  Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
  1824.  static int  Encode( x264_param_t *param, cli_opt_t *opt );
  1825.  
  1826. +/* logging and printing for within the cli system */
  1827. +static int cli_log_level;
  1828. +void x264_cli_log( const char *name, int i_level, const char *fmt, ... )
  1829. +{
  1830. +    if( i_level > cli_log_level )
  1831. +        return;
  1832. +    char *s_level;
  1833. +    switch( i_level )
  1834. +    {
  1835. +        case X264_LOG_ERROR:
  1836. +            s_level = "error";
  1837. +            break;
  1838. +        case X264_LOG_WARNING:
  1839. +            s_level = "warning";
  1840. +            break;
  1841. +        case X264_LOG_INFO:
  1842. +            s_level = "info";
  1843. +            break;
  1844. +        case X264_LOG_DEBUG:
  1845. +            s_level = "debug";
  1846. +            break;
  1847. +        default:
  1848. +            s_level = "unknown";
  1849. +            break;
  1850. +    }
  1851. +    fprintf( stderr, "%s [%s]: ", name, s_level );
  1852. +    va_list arg;
  1853. +    va_start( arg, fmt );
  1854. +    vfprintf( stderr, fmt, arg );
  1855. +    va_end( arg );
  1856. +}
  1857. +
  1858. +void x264_cli_printf( int i_level, const char *fmt, ... )
  1859. +{
  1860. +    if( i_level > cli_log_level )
  1861. +        return;
  1862. +    va_list arg;
  1863. +    va_start( arg, fmt );
  1864. +    vfprintf( stderr, fmt, arg );
  1865. +    va_end( arg );
  1866. +}
  1867. +
  1868.  /****************************************************************************
  1869.   * main:
  1870.   ****************************************************************************/
  1871. @@ -571,6 +616,9 @@ static void Help( x264_param_t *defaults, int longhelp )
  1872.      H1( "  -v, --verbose               Print stats for each frame\n" );
  1873.      H1( "      --no-progress           Don't show the progress indicator while encoding\n" );
  1874.      H0( "      --quiet                 Quiet Mode\n" );
  1875. +    H1( "      --log-level <string>    Specify the maximum level of logging [\"%s\"]\n"
  1876. +        "                                  - %s\n", strtable_lookup( log_level_names, cli_log_level - X264_LOG_NONE ),
  1877. +                                       stringify_names( buf, log_level_names ) );
  1878.      H1( "      --psnr                  Enable PSNR computation\n" );
  1879.      H1( "      --ssim                  Enable SSIM computation\n" );
  1880.      H1( "      --threads <integer>     Force a specific number of threads\n" );
  1881. @@ -616,6 +664,7 @@ enum {
  1882.      OPT_TCFILE_OUT,
  1883.      OPT_TIMEBASE,
  1884.      OPT_PULLDOWN,
  1885. +    OPT_LOG_LEVEL
  1886.  } OptionsOPT;
  1887.  
  1888.  static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
  1889. @@ -729,6 +778,7 @@ static struct option long_options[] =
  1890.      { "ssim",              no_argument, NULL, 0 },
  1891.      { "quiet",             no_argument, NULL, OPT_QUIET },
  1892.      { "verbose",           no_argument, NULL, 'v' },
  1893. +    { "log-level",   required_argument, NULL, OPT_LOG_LEVEL },
  1894.      { "no-progress",       no_argument, NULL, OPT_NOPROGRESS },
  1895.      { "visualize",         no_argument, NULL, OPT_VISUALIZE },
  1896.      { "dump-yuv",    required_argument, NULL, 0 },
  1897. @@ -780,11 +830,11 @@ static int select_output( const char *muxer, char *filename, x264_param_t *param
  1898.          param->b_repeat_headers = 0;
  1899.          if( param->i_nal_hrd == X264_NAL_HRD_CBR )
  1900.          {
  1901. -            fprintf( stderr, "x264 [warning]: cbr nal-hrd is not compatible with mp4\n" );
  1902. +            x264_cli_log( "x264", X264_LOG_WARNING, "cbr nal-hrd is not compatible with mp4\n" );
  1903.              param->i_nal_hrd = X264_NAL_HRD_VBR;
  1904.          }
  1905.  #else
  1906. -        fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
  1907. +        x264_cli_log( "x264", X264_LOG_ERROR, "not compiled with MP4 output support\n" );
  1908.          return -1;
  1909.  #endif
  1910.      }
  1911. @@ -833,7 +883,7 @@ static int select_input( const char *demuxer, char *used_demuxer, char *filename
  1912.          input = avs_input;
  1913.          module = "avs";
  1914.  #else
  1915. -        fprintf( stderr, "x264 [error]: not compiled with AVS input support\n" );
  1916. +        x264_cli_log( "x264", X264_LOG_ERROR, "not compiled with AVS input support\n" );
  1917.          return -1;
  1918.  #endif
  1919.      }
  1920. @@ -877,11 +927,7 @@ static int select_input( const char *demuxer, char *used_demuxer, char *filename
  1921.              input = yuv_input;
  1922.          }
  1923.  
  1924. -        if( !(*p_handle) )
  1925. -        {
  1926. -            fprintf( stderr, "x264 [error]: could not open input file `%s' via any method!\n", filename );
  1927. -            return -1;
  1928. -        }
  1929. +        FAIL_IF_ERROR( !(*p_handle), "could not open input file `%s' via any method!\n", filename )
  1930.      }
  1931.      strcpy( used_demuxer, module );
  1932.  
  1933. @@ -932,6 +978,7 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  1934.      char *tune = NULL;
  1935.  
  1936.      x264_param_default( &defaults );
  1937. +    cli_log_level = defaults.i_log_level;
  1938.  
  1939.      memset( opt, 0, sizeof(cli_opt_t) );
  1940.      memset( &input_opt, 0, sizeof(cli_input_opt_t) );
  1941. @@ -1004,32 +1051,20 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  1942.                  output_filename = optarg;
  1943.                  break;
  1944.              case OPT_MUXER:
  1945. -                if( parse_enum_name( optarg, muxer_names, &muxer ) < 0 )
  1946. -                {
  1947. -                    fprintf( stderr, "x264 [error]: Unknown muxer `%s'\n", optarg );
  1948. -                    return -1;
  1949. -                }
  1950. +                FAIL_IF_ERROR( parse_enum_name( optarg, muxer_names, &muxer ), "Unknown muxer `%s'\n", optarg )
  1951.                  break;
  1952.              case OPT_DEMUXER:
  1953. -                if( parse_enum_name( optarg, demuxer_names, &demuxer ) < 0 )
  1954. -                {
  1955. -                    fprintf( stderr, "x264 [error]: Unknown demuxer `%s'\n", optarg );
  1956. -                    return -1;
  1957. -                }
  1958. +                FAIL_IF_ERROR( parse_enum_name( optarg, demuxer_names, &demuxer ), "Unknown demuxer `%s'\n", optarg )
  1959.                  break;
  1960.              case OPT_INDEX:
  1961.                  input_opt.index_file = optarg;
  1962.                  break;
  1963.              case OPT_QPFILE:
  1964.                  opt->qpfile = fopen( optarg, "rb" );
  1965. -                if( !opt->qpfile )
  1966. -                {
  1967. -                    fprintf( stderr, "x264 [error]: can't open qpfile `%s'\n", optarg );
  1968. -                    return -1;
  1969. -                }
  1970. -                else if( !x264_is_regular_file( opt->qpfile ) )
  1971. +                FAIL_IF_ERROR( !opt->qpfile, "can't open qpfile `%s'\n", optarg )
  1972. +                if( !x264_is_regular_file( opt->qpfile ) )
  1973.                  {
  1974. -                    fprintf( stderr, "x264 [error]: qpfile incompatible with non-regular file `%s'\n", optarg );
  1975. +                    x264_cli_log( "x264", X264_LOG_ERROR, "qpfile incompatible with non-regular file `%s'\n", optarg );
  1976.                      fclose( opt->qpfile );
  1977.                      return -1;
  1978.                  }
  1979. @@ -1038,11 +1073,17 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  1980.                  b_thread_input = 1;
  1981.                  break;
  1982.              case OPT_QUIET:
  1983. -                param->i_log_level = X264_LOG_NONE;
  1984. +                cli_log_level = param->i_log_level = X264_LOG_NONE;
  1985.                  break;
  1986.              case 'v':
  1987. -                param->i_log_level = X264_LOG_DEBUG;
  1988. +                cli_log_level = param->i_log_level = X264_LOG_DEBUG;
  1989.                  break;
  1990. +            case OPT_LOG_LEVEL:
  1991. +                if( !parse_enum_value( optarg, log_level_names, &cli_log_level ) )
  1992. +                    cli_log_level += X264_LOG_NONE;
  1993. +                else
  1994. +                    cli_log_level = atoi( optarg );
  1995. +                param->i_log_level = cli_log_level;
  1996.              case OPT_NOPROGRESS:
  1997.                  opt->b_progress = 0;
  1998.                  break;
  1999. @@ -1051,7 +1092,7 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  2000.                  param->b_visualize = 1;
  2001.                  b_exit_on_ctrl_c = 1;
  2002.  #else
  2003. -                fprintf( stderr, "x264 [warning]: not compiled with visualization support\n" );
  2004. +                x264_cli_log( "x264", X264_LOG_WARNING, "not compiled with visualization support\n" );
  2005.  #endif
  2006.                  break;
  2007.              case OPT_TUNE:
  2008. @@ -1078,18 +1119,13 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
  2009.                  break;
  2010.              case OPT_TCFILE_OUT:
  2011.                  opt->tcfile_out = fopen( optarg, "wb" );
  2012. -                if( !opt->tcfile_out )
  2013. -                {
  2014. -                    fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
  2015. -                    return -1;
  2016. -                }
  2017. +                FAIL_IF_ERROR( !opt->tcfile_out, "can't open `%s'\n", optarg )
  2018.                  break;
  2019.              case OPT_TIMEBASE:
  2020.                  input_opt.timebase = optarg;
  2021.                  break;
  2022.              case OPT_PULLDOWN:
  2023. -                if( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ) < 0 )
  2024. -                    return -1;
  2025. +                FAIL_IF_ERROR( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ), "Unknown pulldown `%s'\n", optarg )
  2026.                  break;
  2027.              default:
  2028.  generic_option:
  2029. @@ -1116,7 +1152,7 @@ generic_option:
  2030.          if( b_error )
  2031.          {
  2032.              const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2];
  2033. -            fprintf( stderr, "x264 [error]: invalid argument: %s = %s\n", name, optarg );
  2034. +            x264_cli_log( "x264", X264_LOG_ERROR, "invalid argument: %s = %s\n", name, optarg );
  2035.              return -1;
  2036.          }
  2037.      }
  2038. @@ -1130,20 +1166,12 @@ generic_option:
  2039.          return -1;
  2040.  
  2041.      /* Get the file name */
  2042. -    if( optind > argc - 1 || !output_filename )
  2043. -    {
  2044. -        fprintf( stderr, "x264 [error]: No %s file. Run x264 --help for a list of options.\n",
  2045. -                 optind > argc - 1 ? "input" : "output" );
  2046. -        return -1;
  2047. -    }
  2048. +    FAIL_IF_ERROR( optind > argc - 1 || !output_filename, "No %s file. Run x264 --help for a list of options.\n",
  2049. +                   optind > argc - 1 ? "input" : "output" )
  2050.  
  2051.      if( select_output( muxer, output_filename, param ) )
  2052.          return -1;
  2053. -    if( output.open_file( output_filename, &opt->hout ) )
  2054. -    {
  2055. -        fprintf( stderr, "x264 [error]: could not open output file `%s'\n", output_filename );
  2056. -        return -1;
  2057. -    }
  2058. +    FAIL_IF_ERROR( output.open_file( output_filename, &opt->hout ), "could not open output file `%s'\n", output_filename )
  2059.  
  2060.      input_filename = argv[optind++];
  2061.      input_opt.resolution = optind < argc ? argv[optind++] : NULL;
  2062. @@ -1163,39 +1191,22 @@ generic_option:
  2063.      if( select_input( demuxer, demuxername, input_filename, &opt->hin, &info, &input_opt ) )
  2064.          return -1;
  2065.  
  2066. -    if( !opt->hin && input.open_file( input_filename, &opt->hin, &info, &input_opt ) )
  2067. -    {
  2068. -        fprintf( stderr, "x264 [error]: could not open input file `%s'\n", input_filename );
  2069. -        return -1;
  2070. -    }
  2071. +    FAIL_IF_ERROR( !opt->hin && input.open_file( input_filename, &opt->hin, &info, &input_opt ),
  2072. +                   "could not open input file `%s'\n", input_filename )
  2073.  
  2074.      x264_reduce_fraction( &info.sar_width, &info.sar_height );
  2075.      x264_reduce_fraction( &info.fps_num, &info.fps_den );
  2076. -    if( param->i_log_level >= X264_LOG_INFO )
  2077. -        fprintf( stderr, "%s [info]: %dx%d%c %d:%d @ %d/%d fps (%cfr)\n", demuxername, info.width,
  2078. -                 info.height, info.interlaced ? 'i' : 'p', info.sar_width, info.sar_height,
  2079. -                 info.fps_num, info.fps_den, info.vfr ? 'v' : 'c' );
  2080. +    x264_cli_log( demuxername, X264_LOG_INFO, "%dx%d%c %d:%d @ %d/%d fps (%cfr)\n", info.width,
  2081. +                  info.height, info.interlaced ? 'i' : 'p', info.sar_width, info.sar_height,
  2082. +                  info.fps_num, info.fps_den, info.vfr ? 'v' : 'c' );
  2083.  
  2084.      if( tcfile_name )
  2085.      {
  2086. -        if( b_user_fps )
  2087. -        {
  2088. -            fprintf( stderr, "x264 [error]: --fps + --tcfile-in is incompatible.\n" );
  2089. -            return -1;
  2090. -        }
  2091. -        if( timecode_input.open_file( tcfile_name, &opt->hin, &info, &input_opt ) )
  2092. -        {
  2093. -            fprintf( stderr, "x264 [error]: timecode input failed\n" );
  2094. -            return -1;
  2095. -        }
  2096. -        else
  2097. -            input = timecode_input;
  2098. -    }
  2099. -    else if( !info.vfr && input_opt.timebase )
  2100. -    {
  2101. -        fprintf( stderr, "x264 [error]: --timebase is incompatible with cfr input\n" );
  2102. -        return -1;
  2103. +        FAIL_IF_ERROR( b_user_fps, "--fps + --tcfile-in is incompatible.\n" )
  2104. +        FAIL_IF_ERROR( timecode_input.open_file( tcfile_name, &opt->hin, &info, &input_opt ), "timecode input failed\n" )
  2105. +        input = timecode_input;
  2106.      }
  2107. +    else FAIL_IF_ERROR( !info.vfr && input_opt.timebase, "--timebase is incompatible with cfr input\n" )
  2108.  
  2109.      /* set param flags from the info flags as necessary */
  2110.      param->i_csp       = info.csp;
  2111. @@ -1204,9 +1215,9 @@ generic_option:
  2112.      param->i_width     = info.width;
  2113.      if( !b_user_interlaced && info.interlaced )
  2114.      {
  2115. -        fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling %cff interlaced mode.\n"
  2116. -                         "                If you want otherwise, use --no-interlaced or --%cff\n",
  2117. -                 info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
  2118. +        x264_cli_log( "x264", X264_LOG_WARNING, "input appears to be interlaced, enabling %cff interlaced mode.\n"
  2119. +                      "                If you want otherwise, use --no-interlaced or --%cff\n",
  2120. +                      info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
  2121.          param->b_interlaced = 1;
  2122.          param->b_tff = !!info.tff;
  2123.      }
  2124. @@ -1230,21 +1241,14 @@ generic_option:
  2125.          uint64_t i_user_timebase_num;
  2126.          uint64_t i_user_timebase_den;
  2127.          int ret = sscanf( input_opt.timebase, "%"SCNu64"/%"SCNu64, &i_user_timebase_num, &i_user_timebase_den );
  2128. -        if( !ret )
  2129. -        {
  2130. -            fprintf( stderr, "x264 [error]: invalid argument: timebase = %s\n", input_opt.timebase );
  2131. -            return -1;
  2132. -        }
  2133. +        FAIL_IF_ERROR( !ret, "invalid argument: timebase = %s\n", input_opt.timebase )
  2134.          else if( ret == 1 )
  2135.          {
  2136.              i_user_timebase_num = param->i_timebase_num;
  2137.              i_user_timebase_den = strtoul( input_opt.timebase, NULL, 10 );
  2138.          }
  2139. -        if( i_user_timebase_num > UINT32_MAX || i_user_timebase_den > UINT32_MAX )
  2140. -        {
  2141. -            fprintf( stderr, "x264 [error]: timebase you specified exceeds H.264 maximum\n" );
  2142. -            return -1;
  2143. -        }
  2144. +        FAIL_IF_ERROR( i_user_timebase_num > UINT32_MAX || i_user_timebase_den > UINT32_MAX,
  2145. +                       "timebase you specified exceeds H.264 maximum\n" )
  2146.          opt->timebase_convert_multiplier = ((double)i_user_timebase_den / param->i_timebase_den)
  2147.                                           * ((double)param->i_timebase_num / i_user_timebase_num);
  2148.          param->i_timebase_num = i_user_timebase_num;
  2149. @@ -1261,13 +1265,8 @@ generic_option:
  2150.      if( b_thread_input || param->i_threads > 1
  2151.          || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1) )
  2152.      {
  2153. -        if( thread_input.open_file( NULL, &opt->hin, &info, NULL ) )
  2154. -        {
  2155. -            fprintf( stderr, "x264 [error]: threaded input failed\n" );
  2156. -            return -1;
  2157. -        }
  2158. -        else
  2159. -            input = thread_input;
  2160. +        FAIL_IF_ERROR( thread_input.open_file( NULL, &opt->hin, &info, NULL ), "threaded input failed\n" )
  2161. +        input = thread_input;
  2162.      }
  2163.  #endif
  2164.  
  2165. @@ -1321,7 +1320,7 @@ static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
  2166.          else ret = 0;
  2167.          if( ret != 3 || qp < -1 || qp > 51 )
  2168.          {
  2169. -            fprintf( stderr, "x264 [error]: can't parse qpfile for frame %d\n", i_frame );
  2170. +            x264_cli_log( "x264", X264_LOG_ERROR, "can't parse qpfile for frame %d\n", i_frame );
  2171.              fclose( opt->qpfile );
  2172.              opt->qpfile = NULL;
  2173.              pic->i_type = X264_TYPE_AUTO;
  2174. @@ -1344,11 +1343,7 @@ static int  Encode_frame( x264_t *h, hnd_t hout, x264_picture_t *pic, int64_t *l
  2175.  
  2176.      i_frame_size = x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out );
  2177.  
  2178. -    if( i_frame_size < 0 )
  2179. -    {
  2180. -        fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
  2181. -        return -1;
  2182. -    }
  2183. +    FAIL_IF_ERROR( i_frame_size < 0, "x264_encoder_encode failed\n" );
  2184.  
  2185.      if( i_frame_size )
  2186.      {
  2187. @@ -1424,17 +1419,14 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  2188.          param->b_pic_struct = 1;
  2189.          pulldown = &pulldown_values[opt->i_pulldown];
  2190.          param->i_timebase_num = param->i_fps_den;
  2191. -        if( fmod( param->i_fps_num * pulldown->fps_factor, 1 ) )
  2192. -        {
  2193. -            fprintf( stderr, "x264 [error]: unsupported framerate for chosen pulldown\n" );
  2194. -            return -1;
  2195. -        }
  2196. +        FAIL_IF_ERROR( fmod( param->i_fps_num * pulldown->fps_factor, 1 ),
  2197. +                       "unsupported framerate for chosen pulldown\n" )
  2198.          param->i_timebase_den = param->i_fps_num * pulldown->fps_factor;
  2199.      }
  2200.  
  2201.      if( ( h = x264_encoder_open( param ) ) == NULL )
  2202.      {
  2203. -        fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
  2204. +        x264_cli_log( "x264", X264_LOG_ERROR, "x264_encoder_open failed\n" );
  2205.          input.close_file( opt->hin );
  2206.          return -1;
  2207.      }
  2208. @@ -1445,27 +1437,19 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  2209.  
  2210.      if( output.set_param( opt->hout, param ) )
  2211.      {
  2212. -        fprintf( stderr, "x264 [error]: can't set outfile param\n" );
  2213. +        x264_cli_log( "x264", X264_LOG_ERROR, "can't set outfile param\n" );
  2214.          input.close_file( opt->hin );
  2215.          output.close_file( opt->hout, largest_pts, second_largest_pts );
  2216.          return -1;
  2217.      }
  2218.  
  2219.      /* Create a new pic */
  2220. -    if( input.picture_alloc( &pic, param->i_csp, param->i_width, param->i_height ) )
  2221. -    {
  2222. -        fprintf( stderr, "x264 [error]: malloc failed\n" );
  2223. -        return -1;
  2224. -    }
  2225. +    FAIL_IF_ERROR( input.picture_alloc( &pic, param->i_csp, param->i_width, param->i_height ), "malloc failed\n" )
  2226.  
  2227.      i_start = x264_mdate();
  2228.      /* ticks/frame = ticks/second / frames/second */
  2229.      ticks_per_frame = (int64_t)param->i_timebase_den * param->i_fps_den / param->i_timebase_num / param->i_fps_num;
  2230. -    if( ticks_per_frame < 1 )
  2231. -    {
  2232. -        fprintf( stderr, "x264 [error]: ticks_per_frame invalid: %"PRId64"\n", ticks_per_frame );
  2233. -        return -1;
  2234. -    }
  2235. +    FAIL_IF_ERROR( ticks_per_frame < 1, "ticks_per_frame invalid: %"PRId64"\n", ticks_per_frame )
  2236.  
  2237.      if( !param->b_repeat_headers )
  2238.      {
  2239. @@ -1473,12 +1457,7 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  2240.          x264_nal_t *headers;
  2241.          int i_nal;
  2242.  
  2243. -        if( x264_encoder_headers( h, &headers, &i_nal ) < 0 )
  2244. -        {
  2245. -            fprintf( stderr, "x264 [error]: x264_encoder_headers failed\n" );
  2246. -            return -1;
  2247. -        }
  2248. -
  2249. +        FAIL_IF_ERROR( x264_encoder_headers( h, &headers, &i_nal ) < 0, "x264_encoder_headers failed\n" )
  2250.          if( (i_file = output.write_headers( opt->hout, headers )) < 0 )
  2251.              return -1;
  2252.      }
  2253. @@ -1508,15 +1487,12 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  2254.  
  2255.          if( pic.i_pts <= largest_pts )
  2256.          {
  2257. -            if( param->i_log_level >= X264_LOG_WARNING )
  2258. -            {
  2259. -                if( param->i_log_level >= X264_LOG_DEBUG || pts_warning_cnt < MAX_PTS_WARNING )
  2260. -                    fprintf( stderr, "x264 [warning]: non-strictly-monotonic pts at frame %d (%"PRId64" <= %"PRId64")\n",
  2261. +            if( cli_log_level >= X264_LOG_DEBUG || pts_warning_cnt < MAX_PTS_WARNING )
  2262. +                x264_cli_log( "x264", X264_LOG_WARNING, "non-strictly-monotonic pts at frame %d (%"PRId64" <= %"PRId64")\n",
  2263.                               i_frame, output_pts, largest_pts * dts_compress_multiplier );
  2264. -                else if( pts_warning_cnt == MAX_PTS_WARNING )
  2265. -                    fprintf( stderr, "x264 [warning]: too many nonmonotonic pts warnings, suppressing further ones\n" );
  2266. -                pts_warning_cnt++;
  2267. -            }
  2268. +            else if( pts_warning_cnt == MAX_PTS_WARNING )
  2269. +                x264_cli_log( "x264", X264_LOG_WARNING, "too many nonmonotonic pts warnings, suppressing further ones\n" );
  2270. +            pts_warning_cnt++;
  2271.              pic.i_pts = largest_pts + ticks_per_frame;
  2272.              output_pts = pic.i_pts * dts_compress_multiplier;
  2273.          }
  2274. @@ -1573,8 +1549,8 @@ static int  Encode( x264_param_t *param, cli_opt_t *opt )
  2275.          if( opt->b_progress && i_frame_output % i_update_interval == 0 && i_frame_output )
  2276.              Print_status( i_start, i_frame_output, i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
  2277.      }
  2278. -    if( pts_warning_cnt >= MAX_PTS_WARNING && param->i_log_level < X264_LOG_DEBUG )
  2279. -        fprintf( stderr, "x264 [warning]: %d suppressed nonmonotonic pts warnings\n", pts_warning_cnt-MAX_PTS_WARNING );
  2280. +    if( pts_warning_cnt >= MAX_PTS_WARNING && cli_log_level < X264_LOG_DEBUG )
  2281. +        x264_cli_log( "x264", X264_LOG_WARNING, "%d suppressed nonmonotonic pts warnings\n", pts_warning_cnt-MAX_PTS_WARNING );
  2282.  
  2283.      /* duration algorithm fails when only 1 frame is output */
  2284.      if( i_frame_output == 1 )
  2285. diff --git a/x264cli.h b/x264cli.h
  2286. new file mode 100644
  2287. index 0000000..1acca56
  2288. --- /dev/null
  2289. +++ b/x264cli.h
  2290. @@ -0,0 +1,67 @@
  2291. +/*****************************************************************************
  2292. + * x264cli.h: x264cli common
  2293. + *****************************************************************************
  2294. + * Copyright (C) 2003-2010 x264 project
  2295. + *
  2296. + * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  2297. + *          Loren Merritt <lorenm@u.washington.edu>
  2298. + *
  2299. + * This program is free software; you can redistribute it and/or modify
  2300. + * it under the terms of the GNU General Public License as published by
  2301. + * the Free Software Foundation; either version 2 of the License, or
  2302. + * (at your option) any later version.
  2303. + *
  2304. + * This program is distributed in the hope that it will be useful,
  2305. + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  2306. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  2307. + * GNU General Public License for more details.
  2308. + *
  2309. + * You should have received a copy of the GNU General Public License
  2310. + * along with this program; if not, write to the Free Software
  2311. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
  2312. + *****************************************************************************/
  2313. +
  2314. +#ifndef X264_CLI_H
  2315. +#define X264_CLI_H
  2316. +
  2317. +#include "common/common.h"
  2318. +
  2319. +typedef void *hnd_t;
  2320. +
  2321. +static inline int64_t gcd( int64_t a, int64_t b )
  2322. +{
  2323. +    while( 1 )
  2324. +    {
  2325. +        int64_t c = a % b;
  2326. +        if( !c )
  2327. +            return b;
  2328. +        a = b;
  2329. +        b = c;
  2330. +    }
  2331. +}
  2332. +
  2333. +static inline int64_t lcm( int64_t a, int64_t b )
  2334. +{
  2335. +    return ( a / gcd( a, b ) ) * b;
  2336. +}
  2337. +
  2338. +static inline char *get_filename_extension( char *filename )
  2339. +{
  2340. +    char *ext = filename + strlen( filename );
  2341. +    while( *ext != '.' && ext > filename )
  2342. +        ext--;
  2343. +    ext += *ext == '.';
  2344. +    return ext;
  2345. +}
  2346. +
  2347. +void x264_cli_log( const char *name, int i_level, const char *fmt, ... );
  2348. +void x264_cli_printf( int i_level, const char *fmt, ... );
  2349. +
  2350. +#define FAIL_IF_ERR( cond, name, ... )\
  2351. +if( cond )\
  2352. +{\
  2353. +    x264_cli_log( name, X264_LOG_ERROR, __VA_ARGS__ );\
  2354. +    return -1;\
  2355. +}
  2356. +
  2357. +#endif
  2358. --
  2359. 1.7.0.4
  2360.  
  2361.  
  2362. From 871bc451d34daf6fb85dad3a9ababa1513ec2333 Mon Sep 17 00:00:00 2001
  2363. From: Jason Garrett-Glaser <darkshikari@gmail.com>
  2364. Date: Wed, 30 Jun 2010 13:06:22 -0700
  2365. Subject: [PATCH 5/6] Don't check i16x16 planar mode unless previous modes were useful
  2366.  Saves ~160 clocks per MB at subme=1, ~270 per MB at subme>1 (measured on Core i7).
  2367.  Negligle effect on compression.
  2368.  
  2369. ---
  2370. encoder/analyse.c |   27 ++++++++++++++++++---------
  2371.  1 files changed, 18 insertions(+), 9 deletions(-)
  2372.  
  2373. diff --git a/encoder/analyse.c b/encoder/analyse.c
  2374. index 696c78f..eea464a 100644
  2375. --- a/encoder/analyse.c
  2376. +++ b/encoder/analyse.c
  2377. @@ -646,16 +646,27 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
  2378.      /* 16x16 prediction selection */
  2379.      const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
  2380.  
  2381. +    /* Not heavily tuned */
  2382. +    const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
  2383. +    int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;
  2384. +
  2385.      if( !h->mb.b_lossless && predict_mode[3] >= 0 )
  2386.      {
  2387.          h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );
  2388. -        h->predict_16x16[I_PRED_16x16_P]( p_dst );
  2389. -        a->i_satd_i16x16_dir[I_PRED_16x16_P] =
  2390. -            h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
  2391. -        for( int i = 0; i < 4; i++ )
  2392. +        a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);
  2393. +        a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);
  2394. +        a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);
  2395. +        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );
  2396. +        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );
  2397. +        COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );
  2398. +
  2399. +        /* Plane is expensive, so don't check it unless one of the previous modes was useful. */
  2400. +        if( a->i_satd_i16x16 <= i16x16_thresh )
  2401.          {
  2402. -            int cost = a->i_satd_i16x16_dir[i] += lambda * bs_size_ue(i);
  2403. -            COPY2_IF_LT( a->i_satd_i16x16, cost, a->i_predict16x16, i );
  2404. +            h->predict_16x16[I_PRED_16x16_P]( p_dst );
  2405. +            a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
  2406. +            a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);
  2407. +            COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );
  2408.          }
  2409.      }
  2410.      else
  2411. @@ -681,9 +692,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
  2412.          /* cavlc mb type prefix */
  2413.          a->i_satd_i16x16 += lambda * i_mb_b_cost_table[I_16x16];
  2414.  
  2415. -    /* Not heavily tuned */
  2416. -    const uint8_t i16x16_thresh[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
  2417. -    if( a->b_fast_intra && a->i_satd_i16x16 > (i16x16_thresh[h->mb.i_subpel_refine]*i_satd_inter)>>1 )
  2418. +    if( a->i_satd_i16x16 > i16x16_thresh )
  2419.          return;
  2420.  
  2421.      /* 8x8 prediction selection */
  2422. --
  2423. 1.7.0.4
  2424.  
  2425.  
  2426. From 51473258b14b935b2963914c2367446aea775631 Mon Sep 17 00:00:00 2001
  2427. From: Jason Garrett-Glaser <darkshikari@gmail.com>
  2428. Date: Wed, 30 Jun 2010 13:55:46 -0700
  2429. Subject: [PATCH 6/6] Support infinite keyint (--keyint infinite).
  2430.  This just means x264 won't insert non-scenecut keyframes.
  2431.  Useful for streaming when using interactive error recovery or some other mechanism that makes keyframes unnecessary.
  2432.  
  2433. Also change POC logic to limit POC/framenum LSB size (to save bits per slice).
  2434. Also fix a bug in the CPB underflow detection code (didn't affect the bitstream, just resulted in the failure to print certain warning messages).
  2435. ---
  2436. common/common.c       |    7 ++++---
  2437.  encoder/encoder.c     |    8 ++++----
  2438.  encoder/ratecontrol.c |   10 +++++-----
  2439.  encoder/set.c         |   29 +++++++++++++++++------------
  2440.  encoder/slicetype.c   |    2 +-
  2441.  x264.c                |    2 +-
  2442.  x264.h                |    3 ++-
  2443.  7 files changed, 34 insertions(+), 27 deletions(-)
  2444.  
  2445. diff --git a/common/common.c b/common/common.c
  2446. index 8c7cf3c..14dd716 100644
  2447. --- a/common/common.c
  2448. +++ b/common/common.c
  2449. @@ -638,9 +638,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
  2450.          p->i_dpb_size = atoi(value);
  2451.      OPT("keyint")
  2452.      {
  2453. -        p->i_keyint_max = atoi(value);
  2454. -        if( p->i_keyint_min > p->i_keyint_max )
  2455. -            p->i_keyint_min = p->i_keyint_max;
  2456. +        if( strstr( value, "infinite" ) )
  2457. +            p->i_keyint_max = X264_KEYINT_MAX_INFINITE;
  2458. +        else
  2459. +            p->i_keyint_max = atoi(value);
  2460.      }
  2461.      OPT2("min-keyint", "keyint-min")
  2462.      {
  2463. diff --git a/encoder/encoder.c b/encoder/encoder.c
  2464. index 5cd3307..31cb84a 100644
  2465. --- a/encoder/encoder.c
  2466. +++ b/encoder/encoder.c
  2467. @@ -567,8 +567,7 @@ static int x264_validate_parameters( x264_t *h )
  2468.  
  2469.      h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, 16 );
  2470.      h->param.i_dpb_size = x264_clip3( h->param.i_dpb_size, 1, 16 );
  2471. -    if( h->param.i_keyint_max <= 0 )
  2472. -        h->param.i_keyint_max = 1;
  2473. +    h->param.i_keyint_max = x264_clip3( h->param.i_keyint_max, 1, X264_KEYINT_MAX_INFINITE );
  2474.      if( h->param.i_scenecut_threshold < 0 )
  2475.          h->param.i_scenecut_threshold = 0;
  2476.      if( !h->param.analyse.i_subpel_refine && h->param.analyse.i_direct_mv_pred > X264_DIRECT_PRED_SPATIAL )
  2477. @@ -627,9 +626,10 @@ static int x264_validate_parameters( x264_t *h )
  2478.      h->param.rc.f_qcompress = x264_clip3f( h->param.rc.f_qcompress, 0.0, 1.0 );
  2479.      if( h->param.i_keyint_max == 1 || h->param.rc.f_qcompress == 1 )
  2480.          h->param.rc.b_mb_tree = 0;
  2481. -    if( !h->param.rc.i_lookahead && !h->param.b_intra_refresh && h->param.rc.b_mb_tree )
  2482. +    if( (!h->param.b_intra_refresh && h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE) &&
  2483. +        !h->param.rc.i_lookahead && h->param.rc.b_mb_tree )
  2484.      {
  2485. -        x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh\n" );
  2486. +        x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh or infinite keyint\n" );
  2487.          h->param.rc.b_mb_tree = 0;
  2488.      }
  2489.      if( h->param.rc.b_stat_read )
  2490. diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
  2491. index 1030ef2..6fdaa98 100644
  2492. --- a/encoder/ratecontrol.c
  2493. +++ b/encoder/ratecontrol.c
  2494. @@ -492,13 +492,13 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
  2495.              // arbitrary
  2496.              #define MAX_DURATION 0.5
  2497.  
  2498. -            int max_cpb_output_delay = h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick;
  2499. +            int max_cpb_output_delay = X264_MIN( h->param.i_keyint_max * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick, INT_MAX );
  2500.              int max_dpb_output_delay = h->sps->vui.i_max_dec_frame_buffering * MAX_DURATION * h->sps->vui.i_time_scale / h->sps->vui.i_num_units_in_tick;
  2501.              int max_delay = (int)(90000.0 * (double)h->sps->vui.hrd.i_cpb_size_unscaled / h->sps->vui.hrd.i_bit_rate_unscaled + 0.5);
  2502.  
  2503.              h->sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22 );
  2504. -            h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 32 );
  2505. -            h->sps->vui.hrd.i_dpb_output_delay_length  = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 32 );
  2506. +            h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 31 );
  2507. +            h->sps->vui.hrd.i_dpb_output_delay_length  = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 31 );
  2508.  
  2509.              #undef MAX_DURATION
  2510.  
  2511. @@ -1781,10 +1781,10 @@ void x264_hrd_fullness( x264_t *h )
  2512.      uint64_t cpb_size = (uint64_t)h->sps->vui.hrd.i_cpb_size_unscaled * h->sps->vui.i_time_scale;
  2513.      uint64_t multiply_factor = 180000 / rct->hrd_multiply_denom;
  2514.  
  2515. -    if( cpb_state < 0 || cpb_state > cpb_size )
  2516. +    if( rct->buffer_fill_final < 0 || rct->buffer_fill_final > cpb_size )
  2517.      {
  2518.           x264_log( h, X264_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n",
  2519. -                   cpb_state < 0 ? "underflow" : "overflow", (float)cpb_state/denom, (float)cpb_size/denom );
  2520. +                   rct->buffer_fill_final < 0 ? "underflow" : "overflow", (float)rct->buffer_fill_final/denom, (float)cpb_size/denom );
  2521.      }
  2522.  
  2523.      h->initial_cpb_removal_delay = (multiply_factor * cpb_state + denom) / (2*denom);
  2524. diff --git a/encoder/set.c b/encoder/set.c
  2525. index 8d007aa..84077cb 100644
  2526. --- a/encoder/set.c
  2527. +++ b/encoder/set.c
  2528. @@ -99,6 +99,7 @@ static void x264_sei_write( bs_t *s, uint8_t *p_start )
  2529.  void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
  2530.  {
  2531.      sps->i_id = i_id;
  2532. +    int max_frame_num;
  2533.  
  2534.      sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0;
  2535.      if( sps->b_qpprime_y_zero_transform_bypass )
  2536. @@ -118,15 +119,27 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
  2537.      /* Never set constraint_set2, it is not necessary and not used in real world. */
  2538.      sps->b_constraint_set2  = 0;
  2539.  
  2540. -    sps->i_log2_max_frame_num = 4;  /* at least 4 */
  2541. -    while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max && sps->i_log2_max_frame_num < 10 )
  2542. +    sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
  2543. +    /* extra slot with pyramid so that we don't have to override the
  2544. +     * order of forgetting old pictures */
  2545. +    sps->vui.i_max_dec_frame_buffering =
  2546. +    sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
  2547. +                            param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
  2548. +    sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
  2549. +
  2550. +    /* number of refs + current frame */
  2551. +    max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1;
  2552. +    sps->i_log2_max_frame_num = 4;
  2553. +    while( (1 << sps->i_log2_max_frame_num) < max_frame_num )
  2554.          sps->i_log2_max_frame_num++;
  2555. -    sps->i_log2_max_frame_num++;
  2556.  
  2557.      sps->i_poc_type = 0;
  2558.      if( sps->i_poc_type == 0 )
  2559.      {
  2560. -        sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1;    /* max poc = 2*frame_num */
  2561. +        int max_delta_poc = (param->i_bframe + 2) * 2;
  2562. +        sps->i_log2_max_poc_lsb = 4;
  2563. +        while( (1 << sps->i_log2_max_frame_num) <= max_delta_poc * 2 )
  2564. +            sps->i_log2_max_poc_lsb++;
  2565.      }
  2566.      else if( sps->i_poc_type == 1 )
  2567.      {
  2568. @@ -219,14 +232,6 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
  2569.  
  2570.      // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
  2571.  
  2572. -    sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
  2573. -    /* extra slot with pyramid so that we don't have to override the
  2574. -     * order of forgetting old pictures */
  2575. -    sps->vui.i_max_dec_frame_buffering =
  2576. -    sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
  2577. -                            param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
  2578. -    sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
  2579. -
  2580.      sps->vui.b_bitstream_restriction = 1;
  2581.      if( sps->vui.b_bitstream_restriction )
  2582.      {
  2583. diff --git a/encoder/slicetype.c b/encoder/slicetype.c
  2584. index 4ede8cf..7d69b71 100644
  2585. --- a/encoder/slicetype.c
  2586. +++ b/encoder/slicetype.c
  2587. @@ -1009,7 +1009,7 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f
  2588.      float f_thresh_max = h->param.i_scenecut_threshold / 100.0;
  2589.      /* magic numbers pulled out of thin air */
  2590.      float f_thresh_min = f_thresh_max * h->param.i_keyint_min
  2591. -                         / ( h->param.i_keyint_max * 4 );
  2592. +                         / ( h->param.i_keyint_max * 4. );
  2593.      int res;
  2594.  
  2595.      if( h->param.i_keyint_min == h->param.i_keyint_max )
  2596. diff --git a/x264.c b/x264.c
  2597. index 741570c..0bede93 100644
  2598. --- a/x264.c
  2599. +++ b/x264.c
  2600. @@ -409,7 +409,7 @@ static void Help( x264_param_t *defaults, int longhelp )
  2601.      H0( "\n" );
  2602.      H0( "Frame-type options:\n" );
  2603.      H0( "\n" );
  2604. -    H0( "  -I, --keyint <integer>      Maximum GOP size [%d]\n", defaults->i_keyint_max );
  2605. +    H0( "  -I, --keyint <integer or \"infinite\"> Maximum GOP size [%d]\n", defaults->i_keyint_max );
  2606.      H2( "  -i, --min-keyint <integer>  Minimum GOP size [auto]\n" );
  2607.      H2( "      --no-scenecut           Disable adaptive I-frame decision\n" );
  2608.      H2( "      --scenecut <integer>    How aggressively to insert extra I-frames [%d]\n", defaults->i_scenecut_threshold );
  2609. diff --git a/x264.h b/x264.h
  2610. index 604ca45..330cf74 100644
  2611. --- a/x264.h
  2612. +++ b/x264.h
  2613. @@ -35,7 +35,7 @@
  2614.  
  2615.  #include <stdarg.h>
  2616.  
  2617. -#define X264_BUILD 101
  2618. +#define X264_BUILD 102
  2619.  
  2620.  /* x264_t:
  2621.   *      opaque handler for encoder */
  2622. @@ -152,6 +152,7 @@ typedef struct
  2623.  #define X264_B_PYRAMID_STRICT        1
  2624.  #define X264_B_PYRAMID_NORMAL        2
  2625.  #define X264_KEYINT_MIN_AUTO         0
  2626. +#define X264_KEYINT_MAX_INFINITE     (1<<30)
  2627.  #define X264_OPEN_GOP_NONE           0
  2628.  #define X264_OPEN_GOP_NORMAL         1
  2629.  #define X264_OPEN_GOP_BLURAY         2
  2630. --
  2631. 1.7.0.4
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement