· 8 years ago · Jun 03, 2017, 03:18 AM
1From aa1a8435000228c4d9e74da0f9fd3d16e85a3e80 Mon Sep 17 00:00:00 2001
2From: Loren Merritt <pengvado@akuvian.org>
3Date: Sat, 26 Jun 2010 20:55:59 -0700
4Subject: [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
12diff --git a/common/macroblock.c b/common/macroblock.c
13index 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);
25diff --git a/common/x86/pixel-a.asm b/common/x86/pixel-a.asm
26index 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-
356diff --git a/encoder/me.c b/encoder/me.c
357index 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--
3701.7.1
371
372
373From 8b5d1903ccd13ed8f5141de0048601b4c020de98 Mon Sep 17 00:00:00 2001
374From: Jason Garrett-Glaser <darkshikari@gmail.com>
375Date: Mon, 28 Jun 2010 15:02:33 -0700
376Subject: [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
380Full 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
388diff --git a/common/bitstream.c b/common/bitstream.c
389index 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 )
420diff --git a/common/bitstream.h b/common/bitstream.h
421index 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
432diff --git a/encoder/encoder.c b/encoder/encoder.c
433index 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 {
511diff --git a/x264.h b/x264.h
512index 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--
6731.7.1
674
675
676From a90edcc40772e54d3cb2c3da65ce52d45c178c29 Mon Sep 17 00:00:00 2001
677From: Lamont Alston <wewk584@gmail.com>
678Date: Tue, 29 Jun 2010 10:11:42 -0700
679Subject: [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
691diff --git a/encoder/encoder.c b/encoder/encoder.c
692index 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 );
704diff --git a/encoder/slicetype.c b/encoder/slicetype.c
705index 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
759diff --git a/x264.c b/x264.c
760index 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 );
778diff --git a/x264.h b/x264.h
779index 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--
8121.7.1
813
814
815From 495f11a3dd9c4bdd866142b351c170832f65b678 Mon Sep 17 00:00:00 2001
816From: Steven Walters <kemuri9@gmail.com>
817Date: Sat, 26 Jun 2010 16:28:49 -0400
818Subject: [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
845diff --git a/input/avs.c b/input/avs.c
846index 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 */
1012diff --git a/input/ffms.c b/input/ffms.c
1013index 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 {
1136diff --git a/input/input.h b/input/input.h
1137index 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 {
1149diff --git a/input/lavf.c b/input/lavf.c
1150index 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
1260diff --git a/input/thread.c b/input/thread.c
1261index 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;
1287diff --git a/input/timecode.c b/input/timecode.c
1288index 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 }
1512diff --git a/input/y4m.c b/input/y4m.c
1513index 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
1564diff --git a/input/yuv.c b/input/yuv.c
1565index 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;
1590diff --git a/muxers.h b/muxers.h
1591deleted file mode 100644
1592index 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
1657diff --git a/output/flv.c b/output/flv.c
1658index 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;
1689diff --git a/output/flv_bytestream.c b/output/flv_bytestream.c
1690index 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 )
1702diff --git a/output/matroska.c b/output/matroska.c
1703index 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
1715diff --git a/output/matroska_ebml.c b/output/matroska_ebml.c
1716index 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
1728diff --git a/output/mp4.c b/output/mp4.c
1729index 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) )) )
1769diff --git a/output/output.h b/output/output.h
1770index 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 );
1782diff --git a/output/raw.c b/output/raw.c
1783index 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 {
1795diff --git a/x264.c b/x264.c
1796index 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 )
2285diff --git a/x264cli.h b/x264cli.h
2286new file mode 100644
2287index 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--
23591.7.1
2360
2361
2362From 871bc451d34daf6fb85dad3a9ababa1513ec2333 Mon Sep 17 00:00:00 2001
2363From: Jason Garrett-Glaser <darkshikari@gmail.com>
2364Date: Wed, 30 Jun 2010 13:06:22 -0700
2365Subject: [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
2373diff --git a/encoder/analyse.c b/encoder/analyse.c
2374index 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--
24231.7.1
2424
2425
2426From ce182d5e29380cb15cdea68b72bc4a16c05b8cc2 Mon Sep 17 00:00:00 2001
2427From: Jason Garrett-Glaser <darkshikari@gmail.com>
2428Date: Wed, 30 Jun 2010 13:55:46 -0700
2429Subject: [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
2433Also change POC logic to limit POC/framenum LSB size (to save bits per slice).
2434Also 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
2445diff --git a/common/common.c b/common/common.c
2446index 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 {
2463diff --git a/encoder/encoder.c b/encoder/encoder.c
2464index 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 )
2490diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
2491index 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);
2524diff --git a/encoder/set.c b/encoder/set.c
2525index 8d007aa..9a3c7dc 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) * (!!param->i_bframe_pyramid + 1) * 2;
2562+ sps->i_log2_max_poc_lsb = 4;
2563+ while( (1 << sps->i_log2_max_poc_lsb) <= 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 {
2583diff --git a/encoder/slicetype.c b/encoder/slicetype.c
2584index 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 )
2596diff --git a/x264.c b/x264.c
2597index 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 );
2609diff --git a/x264.h b/x264.h
2610index 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--
26311.7.1