Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From aa1a8435000228c4d9e74da0f9fd3d16e85a3e80 Mon Sep 17 00:00:00 2001
- From: Loren Merritt <pengvado@akuvian.org>
- Date: Sat, 26 Jun 2010 20:55:59 -0700
- Subject: [PATCH 1/6] Simplify pixel_ads
- ---
- common/macroblock.c | 2 +-
- common/x86/pixel-a.asm | 175 +++++++++++++++++------------------------------
- encoder/me.c | 2 +-
- 3 files changed, 65 insertions(+), 114 deletions(-)
- diff --git a/common/macroblock.c b/common/macroblock.c
- index 8e9b06d..4561d8a 100644
- --- a/common/macroblock.c
- +++ b/common/macroblock.c
- @@ -341,7 +341,7 @@ int x264_macroblock_thread_allocate( x264_t *h, int b_lookahead )
- int buf_ssim = h->param.analyse.b_ssim * 8 * (h->param.i_width/4+3) * sizeof(int);
- int me_range = X264_MIN(h->param.analyse.i_me_range, h->param.analyse.i_mv_range);
- int buf_tesa = (h->param.analyse.i_me_method >= X264_ME_ESA) *
- - ((me_range*2+18) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
- + ((me_range*2+24) * sizeof(int16_t) + (me_range+4) * (me_range+1) * 4 * sizeof(mvsad_t));
- scratch_size = X264_MAX3( buf_hpel, buf_ssim, buf_tesa );
- }
- int buf_mbtree = h->param.rc.b_mb_tree * ((h->mb.i_mb_width+3)&~3) * sizeof(int);
- diff --git a/common/x86/pixel-a.asm b/common/x86/pixel-a.asm
- index 78ca4c7..1756f86 100644
- --- a/common/x86/pixel-a.asm
- +++ b/common/x86/pixel-a.asm
- @@ -2142,34 +2142,24 @@ cglobal pixel_ssim_end4_sse2, 3,3,7
- ; Successive Elimination ADS
- ;=============================================================================
- -%macro ADS_START 1 ; unroll_size
- -%ifdef ARCH_X86_64
- - %define t0 r6
- +%macro ADS_START 0
- %ifdef WIN64
- - mov r4, r4mp
- - movsxd r5, dword r5m
- + movsxd r5, r5d
- %endif
- - mov r10, rsp
- -%else
- - %define t0 r4
- - mov rbp, rsp
- -%endif
- - mov r0d, r5m
- - sub rsp, r0
- - sub rsp, %1*4-1
- - and rsp, ~15
- - mov t0, rsp
- + mov r0d, r5d
- + lea r6, [r4+r5+15]
- + and r6, ~15;
- shl r2d, 1
- %endmacro
- -%macro ADS_END 1
- +%macro ADS_END 1 ; unroll_size
- add r1, 8*%1
- add r3, 8*%1
- - add t0, 4*%1
- + add r6, 4*%1
- sub r0d, 4*%1
- jg .loop
- %ifdef WIN64
- - RESTORE_XMM r10
- + RESTORE_XMM rsp
- %endif
- jmp ads_mvs
- %endmacro
- @@ -2180,14 +2170,14 @@ cglobal pixel_ssim_end4_sse2, 3,3,7
- ; int pixel_ads4( int enc_dc[4], uint16_t *sums, int delta,
- ; uint16_t *cost_mvx, int16_t *mvs, int width, int thresh )
- ;-----------------------------------------------------------------------------
- -cglobal pixel_ads4_mmxext, 4,7
- +cglobal pixel_ads4_mmxext, 6,7
- movq mm6, [r0]
- movq mm4, [r0+8]
- pshufw mm7, mm6, 0
- pshufw mm6, mm6, 0xAA
- pshufw mm5, mm4, 0
- pshufw mm4, mm4, 0xAA
- - ADS_START 1
- + ADS_START
- .loop:
- movq mm0, [r1]
- movq mm1, [r1+16]
- @@ -2204,25 +2194,19 @@ cglobal pixel_ads4_mmxext, 4,7
- ABS1 mm3, mm1
- paddw mm0, mm2
- paddw mm0, mm3
- -%ifdef WIN64
- - pshufw mm1, [r10+stack_offset+56], 0
- -%elifdef ARCH_X86_64
- - pshufw mm1, [r10+8], 0
- -%else
- - pshufw mm1, [ebp+stack_offset+28], 0
- -%endif
- + pshufw mm1, r6m, 0
- paddusw mm0, [r3]
- psubusw mm1, mm0
- packsswb mm1, mm1
- - movd [t0], mm1
- + movd [r6], mm1
- ADS_END 1
- -cglobal pixel_ads2_mmxext, 4,7
- +cglobal pixel_ads2_mmxext, 6,7
- movq mm6, [r0]
- pshufw mm5, r6m, 0
- pshufw mm7, mm6, 0
- pshufw mm6, mm6, 0xAA
- - ADS_START 1
- + ADS_START
- .loop:
- movq mm0, [r1]
- movq mm1, [r1+r2]
- @@ -2235,13 +2219,13 @@ cglobal pixel_ads2_mmxext, 4,7
- movq mm4, mm5
- psubusw mm4, mm0
- packsswb mm4, mm4
- - movd [t0], mm4
- + movd [r6], mm4
- ADS_END 1
- -cglobal pixel_ads1_mmxext, 4,7
- +cglobal pixel_ads1_mmxext, 6,7
- pshufw mm7, [r0], 0
- pshufw mm6, r6m, 0
- - ADS_START 2
- + ADS_START
- .loop:
- movq mm0, [r1]
- movq mm1, [r1+8]
- @@ -2256,11 +2240,11 @@ cglobal pixel_ads1_mmxext, 4,7
- psubusw mm4, mm0
- psubusw mm5, mm1
- packsswb mm4, mm5
- - movq [t0], mm4
- + movq [r6], mm4
- ADS_END 2
- %macro ADS_SSE2 1
- -cglobal pixel_ads4_%1, 4,7,12
- +cglobal pixel_ads4_%1, 6,7,12
- movdqa xmm4, [r0]
- pshuflw xmm7, xmm4, 0
- pshuflw xmm6, xmm4, 0xAA
- @@ -2273,7 +2257,7 @@ cglobal pixel_ads4_%1, 4,7,12
- %ifdef ARCH_X86_64
- pshuflw xmm8, r6m, 0
- punpcklqdq xmm8, xmm8
- - ADS_START 2
- + ADS_START
- movdqu xmm10, [r1]
- movdqu xmm11, [r1+r2]
- .loop:
- @@ -2299,9 +2283,9 @@ cglobal pixel_ads4_%1, 4,7,12
- movdqa xmm1, xmm8
- psubusw xmm1, xmm0
- packsswb xmm1, xmm1
- - movq [t0], xmm1
- + movq [r6], xmm1
- %else
- - ADS_START 2
- + ADS_START
- .loop:
- movdqu xmm0, [r1]
- movdqu xmm1, [r1+16]
- @@ -2318,18 +2302,18 @@ cglobal pixel_ads4_%1, 4,7,12
- ABS1 xmm3, xmm1
- paddw xmm0, xmm2
- paddw xmm0, xmm3
- - movd xmm1, [ebp+stack_offset+28]
- + movd xmm1, r6m
- movdqu xmm2, [r3]
- pshuflw xmm1, xmm1, 0
- punpcklqdq xmm1, xmm1
- paddusw xmm0, xmm2
- psubusw xmm1, xmm0
- packsswb xmm1, xmm1
- - movq [t0], xmm1
- + movq [r6], xmm1
- %endif ; ARCH
- ADS_END 2
- -cglobal pixel_ads2_%1, 4,7,8
- +cglobal pixel_ads2_%1, 6,7,8
- movq xmm6, [r0]
- movd xmm5, r6m
- pshuflw xmm7, xmm6, 0
- @@ -2338,7 +2322,7 @@ cglobal pixel_ads2_%1, 4,7,8
- punpcklqdq xmm7, xmm7
- punpcklqdq xmm6, xmm6
- punpcklqdq xmm5, xmm5
- - ADS_START 2
- + ADS_START
- .loop:
- movdqu xmm0, [r1]
- movdqu xmm1, [r1+r2]
- @@ -2352,17 +2336,17 @@ cglobal pixel_ads2_%1, 4,7,8
- movdqa xmm1, xmm5
- psubusw xmm1, xmm0
- packsswb xmm1, xmm1
- - movq [t0], xmm1
- + movq [r6], xmm1
- ADS_END 2
- -cglobal pixel_ads1_%1, 4,7,8
- +cglobal pixel_ads1_%1, 6,7,8
- movd xmm7, [r0]
- movd xmm6, r6m
- pshuflw xmm7, xmm7, 0
- pshuflw xmm6, xmm6, 0
- punpcklqdq xmm7, xmm7
- punpcklqdq xmm6, xmm6
- - ADS_START 4
- + ADS_START
- .loop:
- movdqu xmm0, [r1]
- movdqu xmm1, [r1+16]
- @@ -2379,7 +2363,7 @@ cglobal pixel_ads1_%1, 4,7,8
- psubusw xmm4, xmm0
- psubusw xmm5, xmm1
- packsswb xmm4, xmm5
- - movdqa [t0], xmm4
- + movdqa [r6], xmm4
- ADS_END 4
- %endmacro
- @@ -2401,90 +2385,57 @@ ADS_SSE2 ssse3
- ; }
- ; return nmv;
- ; }
- +
- +%macro TEST 1
- + mov [r4+r0*2], r1w
- + test r2d, 0xff<<(%1*8)
- + setne r3b
- + add r0d, r3d
- + inc r1d
- +%endmacro
- +
- cglobal pixel_ads_mvs, 0,7,0
- ads_mvs:
- -%ifdef ARCH_X86_64
- + lea r6, [r4+r5+15]
- + and r6, ~15;
- ; mvs = r4
- - ; masks = rsp
- + ; masks = r6
- ; width = r5
- ; clear last block in case width isn't divisible by 8. (assume divisible by 4, so clearing 4 bytes is enough.)
- -%ifdef WIN64
- - mov r8, r4
- - mov r9, r5
- -%endif
- - xor eax, eax
- - xor esi, esi
- - mov dword [rsp+r9], 0
- + xor r0d, r0d
- + xor r1d, r1d
- + mov [r6+r5], r0d
- jmp .loopi
- +ALIGN 16
- .loopi0:
- - add esi, 8
- - cmp esi, r9d
- + add r1d, 8
- + cmp r1d, r5d
- jge .end
- .loopi:
- - mov rdi, [rsp+rsi]
- - test rdi, rdi
- + mov r2, [r6+r1]
- +%ifdef ARCH_X86_64
- + test r2, r2
- +%else
- + mov r3, r2
- + or r3d, [r6+r1+4]
- +%endif
- jz .loopi0
- - xor ecx, ecx
- -%macro TEST 1
- - mov [r8+rax*2], si
- - test edi, 0xff<<(%1*8)
- - setne cl
- - add eax, ecx
- - inc esi
- -%endmacro
- + xor r3d, r3d
- TEST 0
- TEST 1
- TEST 2
- TEST 3
- - shr rdi, 32
- +%ifdef ARCH_X86_64
- + shr r2, 32
- +%else
- + mov r2d, [r6+r1]
- +%endif
- TEST 0
- TEST 1
- TEST 2
- TEST 3
- - cmp esi, r9d
- - jl .loopi
- -.end:
- - mov rsp, r10
- - RET
- -
- -%else
- - xor eax, eax
- - xor esi, esi
- - mov ebx, [ebp+stack_offset+20] ; mvs
- - mov edi, [ebp+stack_offset+24] ; width
- - mov dword [esp+edi], 0
- - push ebp
- - jmp .loopi
- -.loopi0:
- - add esi, 8
- - cmp esi, edi
- - jge .end
- -.loopi:
- - mov ebp, [esp+esi+4]
- - mov edx, [esp+esi+8]
- - mov ecx, ebp
- - or ecx, edx
- - jz .loopi0
- - xor ecx, ecx
- -%macro TEST 2
- - mov [ebx+eax*2], si
- - test %2, 0xff<<(%1*8)
- - setne cl
- - add eax, ecx
- - inc esi
- -%endmacro
- - TEST 0, ebp
- - TEST 1, ebp
- - TEST 2, ebp
- - TEST 3, ebp
- - TEST 0, edx
- - TEST 1, edx
- - TEST 2, edx
- - TEST 3, edx
- - cmp esi, edi
- + cmp r1d, r5d
- jl .loopi
- .end:
- - pop esp
- + movifnidn eax, r0d
- RET
- -%endif ; ARCH
- -
- diff --git a/encoder/me.c b/encoder/me.c
- index 291104a..19c5b2b 100644
- --- a/encoder/me.c
- +++ b/encoder/me.c
- @@ -609,7 +609,7 @@ void x264_me_search_ref( x264_t *h, x264_me_t *m, int16_t (*mvc)[2], int i_mvc,
- if( h->mb.i_me_method == X264_ME_TESA )
- {
- // ADS threshold, then SAD threshold, then keep the best few SADs, then SATD
- - mvsad_t *mvsads = (mvsad_t *)(xs + ((width+15)&~15));
- + mvsad_t *mvsads = (mvsad_t *)(xs + ((width+15)&~15) + 4);
- int nmvsad = 0, limit;
- int sad_thresh = i_me_range <= 16 ? 10 : i_me_range <= 24 ? 11 : 12;
- int bsad = h->pixf.sad[i_pixel]( p_fenc, FENC_STRIDE, p_fref_w+bmy*stride+bmx, stride )
- --
- 1.7.0.4
- From 8b5d1903ccd13ed8f5141de0048601b4c020de98 Mon Sep 17 00:00:00 2001
- From: Jason Garrett-Glaser <darkshikari@gmail.com>
- Date: Mon, 28 Jun 2010 15:02:33 -0700
- Subject: [PATCH 2/6] Callback feature for low-latency per-slice output
- Add a callback to allow the calling application to send slices immediately after being encoded.
- 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.
- Full documentation is in x264.h.
- ---
- common/bitstream.c | 7 ++-
- common/bitstream.h | 1 -
- encoder/encoder.c | 26 ++++++++---
- x264.h | 128 +++++++++++++++++++++++++++++++++-------------------
- 4 files changed, 105 insertions(+), 57 deletions(-)
- diff --git a/common/bitstream.c b/common/bitstream.c
- index 0aaac21..ad8c16e 100644
- --- a/common/bitstream.c
- +++ b/common/bitstream.c
- @@ -44,7 +44,7 @@ uint8_t *x264_nal_escape_sse2( uint8_t *dst, uint8_t *src, uint8_t *end );
- /****************************************************************************
- * x264_nal_encode:
- ****************************************************************************/
- -int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startcode )
- +void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal )
- {
- uint8_t *src = nal->p_payload;
- uint8_t *end = nal->p_payload + nal->i_payload;
- @@ -52,7 +52,7 @@ int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startc
- if( h->param.b_annexb )
- {
- - if( b_long_startcode )
- + if( nal->b_long_startcode )
- *dst++ = 0x00;
- *dst++ = 0x00;
- *dst++ = 0x00;
- @@ -77,7 +77,8 @@ int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startc
- orig_dst[3] = size>> 0;
- }
- - return size+4;
- + nal->i_payload = size+4;
- + nal->p_payload = orig_dst;
- }
- void x264_bitstream_init( int cpu, x264_bitstream_function_t *pf )
- diff --git a/common/bitstream.h b/common/bitstream.h
- index 9ce5bd7..dd8118d 100644
- --- a/common/bitstream.h
- +++ b/common/bitstream.h
- @@ -68,7 +68,6 @@ typedef struct
- uint8_t *(*nal_escape) ( uint8_t *dst, uint8_t *src, uint8_t *end );
- } x264_bitstream_function_t;
- -int x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal, int b_long_startcode );
- void x264_bitstream_init( int cpu, x264_bitstream_function_t *pf );
- /* A larger level table size theoretically could help a bit at extremely
- diff --git a/encoder/encoder.c b/encoder/encoder.c
- index f54fe85..fe97aef 100644
- --- a/encoder/encoder.c
- +++ b/encoder/encoder.c
- @@ -427,6 +427,8 @@ static int x264_validate_parameters( x264_t *h )
- else
- h->param.b_sliced_threads = 0;
- h->i_thread_frames = h->param.b_sliced_threads ? 1 : h->param.i_threads;
- + if( h->i_thread_frames > 1 )
- + h->param.nalu_process = NULL;
- if( h->param.b_interlaced )
- {
- @@ -1253,8 +1255,9 @@ static void x264_nal_start( x264_t *h, int i_type, int i_ref_idc )
- {
- x264_nal_t *nal = &h->out.nal[h->out.i_nal];
- - nal->i_ref_idc = i_ref_idc;
- - nal->i_type = i_type;
- + nal->i_ref_idc = i_ref_idc;
- + nal->i_type = i_type;
- + nal->b_long_startcode = 1;
- nal->i_payload= 0;
- nal->p_payload= &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8];
- @@ -1280,6 +1283,8 @@ static int x264_nal_end( x264_t *h )
- {
- x264_nal_t *nal = &h->out.nal[h->out.i_nal];
- nal->i_payload = &h->out.p_bitstream[bs_pos( &h->out.bs ) / 8] - nal->p_payload;
- + if( h->param.nalu_process )
- + h->param.nalu_process( h, nal );
- h->out.i_nal++;
- return x264_nal_check_buffer( h );
- @@ -1289,6 +1294,13 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
- {
- int nal_size = 0, previous_nal_size = 0;
- + if( h->param.nalu_process )
- + {
- + for( int i = start; i < h->out.i_nal; i++ )
- + nal_size += h->out.nal[i].i_payload;
- + return nal_size;
- + }
- +
- for( int i = 0; i < start; i++ )
- previous_nal_size += h->out.nal[i].i_payload;
- @@ -1311,11 +1323,9 @@ static int x264_encoder_encapsulate_nals( x264_t *h, int start )
- for( int i = start; i < h->out.i_nal; i++ )
- {
- - int long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
- - int size = x264_nal_encode( h, nal_buffer, &h->out.nal[i], long_startcode );
- - h->out.nal[i].i_payload = size;
- - h->out.nal[i].p_payload = nal_buffer;
- - nal_buffer += size;
- + h->out.nal[i].b_long_startcode = !i || h->out.nal[i].i_type == NAL_SPS || h->out.nal[i].i_type == NAL_PPS;
- + x264_nal_encode( h, nal_buffer, &h->out.nal[i] );
- + nal_buffer += h->out.nal[i].i_payload;
- }
- x264_emms();
- @@ -1805,6 +1815,7 @@ static int x264_slice_write( x264_t *h )
- /* Slice */
- x264_nal_start( h, h->i_nal_type, h->i_nal_ref_idc );
- + h->out.nal[h->out.i_nal].i_first_mb = h->sh.i_first_mb;
- /* Slice header */
- x264_macroblock_thread_init( h );
- @@ -2020,6 +2031,7 @@ static int x264_slice_write( x264_t *h )
- i_mb_x = 0;
- }
- }
- + h->out.nal[h->out.i_nal].i_last_mb = h->sh.i_last_mb;
- if( h->param.b_cabac )
- {
- diff --git a/x264.h b/x264.h
- index 1138a8b..6a663ed 100644
- --- a/x264.h
- +++ b/x264.h
- @@ -35,13 +35,61 @@
- #include <stdarg.h>
- -#define X264_BUILD 100
- +#define X264_BUILD 101
- /* x264_t:
- * opaque handler for encoder */
- typedef struct x264_t x264_t;
- /****************************************************************************
- + * NAL structure and functions
- + ****************************************************************************/
- +
- +enum nal_unit_type_e
- +{
- + NAL_UNKNOWN = 0,
- + NAL_SLICE = 1,
- + NAL_SLICE_DPA = 2,
- + NAL_SLICE_DPB = 3,
- + NAL_SLICE_DPC = 4,
- + NAL_SLICE_IDR = 5, /* ref_idc != 0 */
- + NAL_SEI = 6, /* ref_idc == 0 */
- + NAL_SPS = 7,
- + NAL_PPS = 8,
- + NAL_AUD = 9,
- + NAL_FILLER = 12,
- + /* ref_idc == 0 for 6,9,10,11,12 */
- +};
- +enum nal_priority_e
- +{
- + NAL_PRIORITY_DISPOSABLE = 0,
- + NAL_PRIORITY_LOW = 1,
- + NAL_PRIORITY_HIGH = 2,
- + NAL_PRIORITY_HIGHEST = 3,
- +};
- +
- +/* The data within the payload is already NAL-encapsulated; the ref_idc and type
- + * are merely in the struct for easy access by the calling application.
- + * All data returned in an x264_nal_t, including the data in p_payload, is no longer
- + * valid after the next call to x264_encoder_encode. Thus it must be used or copied
- + * before calling x264_encoder_encode or x264_encoder_headers again. */
- +typedef struct
- +{
- + int i_ref_idc; /* nal_priority_e */
- + int i_type; /* nal_unit_type_e */
- + int b_long_startcode;
- + int i_first_mb; /* If this NAL is a slice, the index of the first MB in the slice. */
- + int i_last_mb; /* If this NAL is a slice, the index of the last MB in the slice. */
- +
- + /* Size of payload in bytes. */
- + int i_payload;
- + /* If param->b_annexb is set, Annex-B bytestream with 4-byte startcode.
- + * Otherwise, startcode is replaced with a 4-byte size.
- + * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
- + uint8_t *p_payload;
- +} x264_nal_t;
- +
- +/****************************************************************************
- * Encoder parameters
- ****************************************************************************/
- /* CPU flags
- @@ -377,8 +425,41 @@ typedef struct x264_param_t
- * i.e. when an x264_param_t is passed to x264_t in an x264_picture_t or in zones.
- * Not used when x264_encoder_reconfig is called directly. */
- void (*param_free)( void* );
- +
- + /* Optional low-level callback for low-latency encoding. Called for each output NAL unit
- + * immediately after the NAL unit is finished encoding. This allows the calling application
- + * to begin processing video data (e.g. by sending packets over a network) before the frame
- + * is done encoding.
- + *
- + * This callback MUST do the following in order to work correctly:
- + * 1) Have available an output buffer of at least size nal->i_payload*3/2 + 5 + 16.
- + * 2) Call x264_nal_encode( h, dst, nal ), where dst is the output buffer.
- + * After these steps, the content of nal is valid and can be used in the same way as if
- + * the NAL unit were output by x264_encoder_encode.
- + *
- + * This does not need to be synchronous with the encoding process: the data pointed to
- + * by nal (both before and after x264_nal_encode) will remain valid until the next
- + * x264_encoder_encode call.
- + *
- + * This callback does not work with frame-based threads; threads must be disabled
- + * or sliced-threads enabled. This callback also does not work as one would expect
- + * with HRD -- since the buffering period SEI cannot be calculated until the frame
- + * is finished encoding, it will not be sent via this callback.
- + *
- + * Note also that the NALs are not necessarily returned in order when sliced threads is
- + * enabled. Accordingly, the variable i_first_mb and i_last_mb are available in
- + * x264_nal_t to help the calling application reorder the slices if necessary.
- + *
- + * When this callback is enabled, x264_encoder_encode does not return valid NALs;
- + * the calling application is expected to acquire all output NALs through the callback.
- + *
- + * It is generally sensible to combine this callback with a use of slice-max-mbs or
- + * slice-max-size. */
- + void (*nalu_process) ( x264_t *h, x264_nal_t *nal );
- } x264_param_t;
- +void x264_nal_encode( x264_t *h, uint8_t *dst, x264_nal_t *nal );
- +
- /****************************************************************************
- * H.264 level restriction information
- ****************************************************************************/
- @@ -586,51 +667,6 @@ int x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_heigh
- void x264_picture_clean( x264_picture_t *pic );
- /****************************************************************************
- - * NAL structure and functions
- - ****************************************************************************/
- -
- -enum nal_unit_type_e
- -{
- - NAL_UNKNOWN = 0,
- - NAL_SLICE = 1,
- - NAL_SLICE_DPA = 2,
- - NAL_SLICE_DPB = 3,
- - NAL_SLICE_DPC = 4,
- - NAL_SLICE_IDR = 5, /* ref_idc != 0 */
- - NAL_SEI = 6, /* ref_idc == 0 */
- - NAL_SPS = 7,
- - NAL_PPS = 8,
- - NAL_AUD = 9,
- - NAL_FILLER = 12,
- - /* ref_idc == 0 for 6,9,10,11,12 */
- -};
- -enum nal_priority_e
- -{
- - NAL_PRIORITY_DISPOSABLE = 0,
- - NAL_PRIORITY_LOW = 1,
- - NAL_PRIORITY_HIGH = 2,
- - NAL_PRIORITY_HIGHEST = 3,
- -};
- -
- -/* The data within the payload is already NAL-encapsulated; the ref_idc and type
- - * are merely in the struct for easy access by the calling application.
- - * All data returned in an x264_nal_t, including the data in p_payload, is no longer
- - * valid after the next call to x264_encoder_encode. Thus it must be used or copied
- - * before calling x264_encoder_encode or x264_encoder_headers again. */
- -typedef struct
- -{
- - int i_ref_idc; /* nal_priority_e */
- - int i_type; /* nal_unit_type_e */
- -
- - /* Size of payload in bytes. */
- - int i_payload;
- - /* If param->b_annexb is set, Annex-B bytestream with 4-byte startcode.
- - * Otherwise, startcode is replaced with a 4-byte size.
- - * This size is the size used in mp4/similar muxing; it is equal to i_payload-4 */
- - uint8_t *p_payload;
- -} x264_nal_t;
- -
- -/****************************************************************************
- * Encoder functions
- ****************************************************************************/
- --
- 1.7.0.4
- From a90edcc40772e54d3cb2c3da65ce52d45c178c29 Mon Sep 17 00:00:00 2001
- From: Lamont Alston <wewk584@gmail.com>
- Date: Tue, 29 Jun 2010 10:11:42 -0700
- Subject: [PATCH 3/6] Make open-GOP Blu-ray compatible
- Blu-ray is even more braindamaged than we thought.
- Accordingly, open-gop options are now "normal" and "bluray", as opposed to display and coded.
- Normal should be used in all cases besides Blu-ray authoring.
- ---
- encoder/encoder.c | 2 +-
- encoder/slicetype.c | 28 +++++++---------------------
- x264.c | 8 ++++----
- x264.h | 8 ++++----
- 4 files changed, 16 insertions(+), 30 deletions(-)
- diff --git a/encoder/encoder.c b/encoder/encoder.c
- index fe97aef..5cd3307 100644
- --- a/encoder/encoder.c
- +++ b/encoder/encoder.c
- @@ -577,7 +577,7 @@ static int x264_validate_parameters( x264_t *h )
- h->param.analyse.i_direct_mv_pred = X264_DIRECT_PRED_SPATIAL;
- }
- h->param.i_bframe = x264_clip3( h->param.i_bframe, 0, X264_MIN( X264_BFRAME_MAX, h->param.i_keyint_max-1 ) );
- - h->param.i_open_gop = x264_clip3( h->param.i_open_gop, X264_OPEN_GOP_NONE, X264_OPEN_GOP_CODED_ORDER );
- + h->param.i_open_gop = x264_clip3( h->param.i_open_gop, X264_OPEN_GOP_NONE, X264_OPEN_GOP_BLURAY );
- if( h->param.i_keyint_max == 1 )
- h->param.b_intra_refresh = 0;
- h->param.i_bframe_bias = x264_clip3( h->param.i_bframe_bias, -90, 100 );
- diff --git a/encoder/slicetype.c b/encoder/slicetype.c
- index 2703f02..4ede8cf 100644
- --- a/encoder/slicetype.c
- +++ b/encoder/slicetype.c
- @@ -1233,17 +1233,11 @@ void x264_slicetype_analyse( x264_t *h, int keyframe )
- if( !h->param.b_intra_refresh )
- for( int i = keyint_limit+1; i <= num_frames; i += h->param.i_keyint_max )
- {
- - int j = i;
- - if( h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
- - {
- - while( IS_X264_TYPE_B( frames[i]->i_type ) )
- - i++;
- - while( IS_X264_TYPE_B( frames[j-1]->i_type ) )
- - j--;
- - }
- frames[i]->i_type = X264_TYPE_I;
- reset_start = X264_MIN( reset_start, i+1 );
- - i = j;
- + if( h->param.i_open_gop == X264_OPEN_GOP_BLURAY )
- + while( IS_X264_TYPE_B( frames[i-1]->i_type ) )
- + i--;
- }
- if( vbv_lookahead )
- @@ -1337,16 +1331,8 @@ void x264_slicetype_decide( x264_t *h )
- if( frm->i_type == X264_TYPE_AUTO || frm->i_type == X264_TYPE_I )
- frm->i_type = h->param.i_open_gop && h->lookahead->i_last_keyframe >= 0 ? X264_TYPE_I : X264_TYPE_IDR;
- int warn = frm->i_type != X264_TYPE_IDR;
- - if( warn && h->param.i_open_gop == X264_OPEN_GOP_DISPLAY_ORDER )
- - warn &= frm->i_type != X264_TYPE_I && frm->i_type != X264_TYPE_KEYFRAME;
- - if( warn && h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
- - {
- - /* if this minigop ends with i, it's not a violation */
- - int j = bframes;
- - while( IS_X264_TYPE_B( h->lookahead->next.list[j]->i_type ) )
- - j++;
- - warn = h->lookahead->next.list[j]->i_type != X264_TYPE_I && h->lookahead->next.list[j]->i_type != X264_TYPE_KEYFRAME;
- - }
- + if( warn && h->param.i_open_gop )
- + warn &= frm->i_type != X264_TYPE_I;
- if( warn )
- 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 );
- }
- @@ -1355,8 +1341,8 @@ void x264_slicetype_decide( x264_t *h )
- if( h->param.i_open_gop )
- {
- h->lookahead->i_last_keyframe = frm->i_frame; // Use display order
- - if( h->param.i_open_gop == X264_OPEN_GOP_CODED_ORDER )
- - h->lookahead->i_last_keyframe -= bframes; // Use coded order
- + if( h->param.i_open_gop == X264_OPEN_GOP_BLURAY )
- + h->lookahead->i_last_keyframe -= bframes; // Use bluray order
- frm->b_keyframe = 1;
- }
- else
- diff --git a/x264.c b/x264.c
- index df04385..f08ab41 100644
- --- a/x264.c
- +++ b/x264.c
- @@ -382,10 +382,10 @@ static void Help( x264_param_t *defaults, int longhelp )
- " - normal: Non-strict (not Blu-ray compatible)\n",
- strtable_lookup( x264_b_pyramid_names, defaults->i_bframe_pyramid ) );
- H1( " --open-gop <string> Use recovery points to close GOPs [none]\n"
- - " - none: Use standard closed GOPs\n"
- - " - display: Base GOP length on display order\n"
- - " (not Blu-ray compatible)\n"
- - " - coded: Base GOP length on coded order\n"
- + " - none: closed GOPs only\n"
- + " - normal: standard open GOPs\n"
- + " (not Blu-ray compatible)\n"
- + " - bluray: Blu-ray-compatible open GOPs\n"
- " Only available with b-frames\n" );
- H1( " --no-cabac Disable CABAC\n" );
- H1( " -r, --ref <integer> Number of reference frames [%d]\n", defaults->i_frame_reference );
- diff --git a/x264.h b/x264.h
- index 6a663ed..604ca45 100644
- --- a/x264.h
- +++ b/x264.h
- @@ -153,8 +153,8 @@ typedef struct
- #define X264_B_PYRAMID_NORMAL 2
- #define X264_KEYINT_MIN_AUTO 0
- #define X264_OPEN_GOP_NONE 0
- -#define X264_OPEN_GOP_DISPLAY_ORDER 1
- -#define X264_OPEN_GOP_CODED_ORDER 2
- +#define X264_OPEN_GOP_NORMAL 1
- +#define X264_OPEN_GOP_BLURAY 2
- static const char * const x264_direct_pred_names[] = { "none", "spatial", "temporal", "auto", 0 };
- static const char * const x264_motion_est_names[] = { "dia", "hex", "umh", "esa", "tesa", 0 };
- @@ -166,7 +166,7 @@ static const char * const x264_colorprim_names[] = { "", "bt709", "undef", "", "
- static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "bt470m", "bt470bg", "smpte170m", "smpte240m", "linear", "log100", "log316", 0 };
- static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", 0 };
- static const char * const x264_nal_hrd_names[] = { "none", "vbr", "cbr", 0 };
- -static const char * const x264_open_gop_names[] = { "none", "display", "coded", 0 };
- +static const char * const x264_open_gop_names[] = { "none", "normal", "bluray", 0 };
- /* Colorspace type
- * legacy only; nothing other than I420 is really supported. */
- @@ -276,7 +276,7 @@ typedef struct x264_param_t
- int i_bframe_adaptive;
- int i_bframe_bias;
- int i_bframe_pyramid; /* Keep some B-frames as references: 0=off, 1=strict hierarchical, 2=normal */
- - int i_open_gop; /* Open gop: 1=display order, 2=coded order to determine gop size */
- + int i_open_gop; /* Open gop: 1=display order, 2=bluray compatibility braindamage mode */
- int b_deblocking_filter;
- int i_deblocking_filter_alphac0; /* [-6, 6] -6 light filter, 6 strong */
- --
- 1.7.0.4
- From 495f11a3dd9c4bdd866142b351c170832f65b678 Mon Sep 17 00:00:00 2001
- From: Steven Walters <kemuri9@gmail.com>
- Date: Sat, 26 Jun 2010 16:28:49 -0400
- Subject: [PATCH 4/6] Centralize logging within x264cli
- x264cli messages will now respect the log level they pertain to.
- Slightly reduces binary size.
- ---
- input/avs.c | 88 +++++-------------
- input/ffms.c | 58 +++--------
- input/input.h | 2 +
- input/lavf.c | 55 +++--------
- input/thread.c | 9 +-
- input/timecode.c | 111 ++++++----------------
- input/y4m.c | 23 +----
- input/yuv.c | 8 +-
- muxers.h | 61 ------------
- output/flv.c | 10 +-
- output/flv_bytestream.c | 2 +-
- output/matroska.c | 2 +-
- output/matroska_ebml.c | 2 +-
- output/mp4.c | 12 +--
- output/output.h | 2 +
- output/raw.c | 2 +-
- x264.c | 246 +++++++++++++++++++++--------------------------
- x264cli.h | 67 +++++++++++++
- 18 files changed, 289 insertions(+), 471 deletions(-)
- delete mode 100644 muxers.h
- create mode 100644 x264cli.h
- diff --git a/input/avs.c b/input/avs.c
- index 07add40..b83f715 100644
- --- a/input/avs.c
- +++ b/input/avs.c
- @@ -20,8 +20,9 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- #include <windows.h>
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "avs", __VA_ARGS__ )
- /* the AVS interface currently uses __declspec to link function declarations to their definitions in the dll.
- this has a side effect of preventing program execution if the avisynth dll is not found,
- @@ -131,27 +132,15 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- FILE *fh = fopen( psz_filename, "r" );
- if( !fh )
- return -1;
- - else if( !x264_is_regular_file( fh ) )
- - {
- - fprintf( stderr, "avs [error]: AVS input is incompatible with non-regular file `%s'\n", psz_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !x264_is_regular_file( fh ), "AVS input is incompatible with non-regular file `%s'\n", psz_filename );
- fclose( fh );
- avs_hnd_t *h = malloc( sizeof(avs_hnd_t) );
- if( !h )
- return -1;
- - if( avs_load_library( h ) )
- - {
- - fprintf( stderr, "avs [error]: failed to load avisynth\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( avs_load_library( h ), "failed to load avisynth\n" )
- h->env = h->func.avs_create_script_environment( AVS_INTERFACE_YV12 );
- - if( !h->env )
- - {
- - fprintf( stderr, "avs [error]: failed to initiate avisynth\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h->env, "failed to initiate avisynth\n" )
- AVS_Value arg = avs_new_value_string( psz_filename );
- AVS_Value res;
- char *filename_ext = get_filename_extension( psz_filename );
- @@ -159,11 +148,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- if( !strcasecmp( filename_ext, "avs" ) )
- {
- res = h->func.avs_invoke( h->env, "Import", arg, NULL );
- - if( avs_is_error( res ) )
- - {
- - fprintf( stderr, "avs [error]: %s\n", avs_as_string( res ) );
- - return -1;
- - }
- + FAIL_IF_ERROR( avs_is_error( res ), "%s\n", avs_as_string( res ) )
- /* check if the user is using a multi-threaded script and apply distributor if necessary.
- adapted from avisynth's vfw interface */
- AVS_Value mt_test = h->func.avs_invoke( h->env, "GetMTMode", avs_new_value_bool( 0 ), NULL );
- @@ -184,78 +169,55 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- int i;
- for( i = 0; filter[i]; i++ )
- {
- - fprintf( stderr, "avs [info]: trying %s... ", filter[i] );
- + x264_cli_log( "avs", X264_LOG_INFO, "trying %s... ", filter[i] );
- if( !h->func.avs_function_exists( h->env, filter[i] ) )
- {
- - fprintf( stderr, "not found\n" );
- + x264_cli_printf( X264_LOG_INFO, "not found\n" );
- continue;
- }
- if( !strncasecmp( filter[i], "FFmpegSource", 12 ) )
- {
- - fprintf( stderr, "indexing... " );
- + x264_cli_printf( X264_LOG_INFO, "indexing... " );
- fflush( stderr );
- }
- res = h->func.avs_invoke( h->env, filter[i], arg, NULL );
- if( !avs_is_error( res ) )
- {
- - fprintf( stderr, "succeeded\n" );
- + x264_cli_printf( X264_LOG_INFO, "succeeded\n" );
- break;
- }
- - fprintf( stderr, "failed\n" );
- - }
- - if( !filter[i] )
- - {
- - fprintf( stderr, "avs [error]: unable to find source filter to open `%s'\n", psz_filename );
- - return -1;
- + x264_cli_printf( X264_LOG_INFO, "failed\n" );
- }
- + FAIL_IF_ERROR( !filter[i], "unable to find source filter to open `%s'\n", psz_filename )
- }
- - if( !avs_is_clip( res ) )
- - {
- - fprintf( stderr, "avs [error]: `%s' didn't return a video clip\n", psz_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !avs_is_clip( res ), "`%s' didn't return a video clip\n", psz_filename )
- h->clip = h->func.avs_take_clip( res, h->env );
- int avs_version = h->func.avs_get_version( h->clip );
- const AVS_VideoInfo *vi = h->func.avs_get_video_info( h->clip );
- - if( !avs_has_video( vi ) )
- - {
- - fprintf( stderr, "avs [error]: `%s' has no video data\n", psz_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !avs_has_video( vi ), "`%s' has no video data\n", psz_filename )
- /* if the clip is made of fields instead of frames, call weave to make them frames */
- if( avs_is_field_based( vi ) )
- {
- - fprintf( stderr, "avs [warning]: detected fieldbased (separated) input, weaving to frames\n" );
- + x264_cli_log( "avs", X264_LOG_WARNING, "detected fieldbased (separated) input, weaving to frames\n" );
- AVS_Value tmp = h->func.avs_invoke( h->env, "Weave", res, NULL );
- - if( avs_is_error( tmp ) )
- - {
- - fprintf( stderr, "avs [error]: couldn't weave fields into frames\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( avs_is_error( tmp ), "couldn't weave fields into frames\n" )
- res = update_clip( h, &vi, tmp, res );
- info->interlaced = 1;
- info->tff = avs_is_tff( vi );
- }
- - if( vi->width&1 || vi->height&1 )
- - {
- - fprintf( stderr, "avs [error]: input clip width or height not divisible by 2 (%dx%d)\n",
- - vi->width, vi->height );
- - return -1;
- - }
- + 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 )
- /* always call ConvertToYV12 to convert non YV12 planar colorspaces to YV12 when user's AVS supports them,
- as all planar colorspaces are flagged as YV12. If it is already YV12 in this case, the call does nothing */
- if( !avs_is_yv12( vi ) || avs_version >= AVS_INTERFACE_OTHER_PLANAR )
- {
- - fprintf( stderr, "avs %s\n", !avs_is_yv12( vi ) ? "[warning]: converting input clip to YV12"
- - : "[info]: avisynth 2.6+ detected, forcing conversion to YV12" );
- + if( !avs_is_yv12( vi ) )
- + x264_cli_log( "avs", X264_LOG_WARNING, "converting input clip to YV12" );
- + else
- + x264_cli_log( "avs", X264_LOG_INFO, "avisynth 2.6+ detected, forcing conversion to YV12" );
- const char *arg_name[2] = { NULL, "interlaced" };
- AVS_Value arg_arr[2] = { res, avs_new_value_bool( info->interlaced ) };
- AVS_Value res2 = h->func.avs_invoke( h->env, "ConvertToYV12", avs_new_value_array( arg_arr, 2 ), arg_name );
- - if( avs_is_error( res2 ) )
- - {
- - fprintf( stderr, "avs [error]: couldn't convert input clip to YV12\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( avs_is_error( res2 ), "couldn't convert input clip to YV12\n" )
- res = update_clip( h, &vi, res2, res );
- }
- h->func.avs_release_value( res );
- @@ -294,11 +256,7 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- return -1;
- AVS_VideoFrame *frm = p_pic->opaque = h->func.avs_get_frame( h->clip, i_frame );
- const char *err = h->func.avs_clip_get_error( h->clip );
- - if( err )
- - {
- - fprintf( stderr, "avs [error]: %s occurred while reading frame %d\n", err, i_frame );
- - return -1;
- - }
- + FAIL_IF_ERROR( err, "%s occurred while reading frame %d\n", err, i_frame )
- for( int i = 0; i < 3; i++ )
- {
- /* explicitly cast away the const attribute to avoid a warning */
- diff --git a/input/ffms.c b/input/ffms.c
- index b2a253e..fe8bf7e 100644
- --- a/input/ffms.c
- +++ b/input/ffms.c
- @@ -21,8 +21,10 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- #include <ffms.h>
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "ffms", __VA_ARGS__ )
- +
- #undef DECLARE_ALIGNED
- #include <libavcodec/avcodec.h>
- #include <libswscale/swscale.h>
- @@ -86,28 +88,16 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- {
- idx = FFMS_MakeIndex( psz_filename, 0, 0, NULL, NULL, 0, update_progress, NULL, &e );
- fprintf( stderr, " \r" );
- - if( !idx )
- - {
- - fprintf( stderr, "ffms [error]: could not create index\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !idx, "could not create index\n" )
- if( opt->index_file && FFMS_WriteIndex( opt->index_file, idx, &e ) )
- - fprintf( stderr, "ffms [warning]: could not write index file\n" );
- + x264_cli_log( "ffms", X264_LOG_WARNING, "could not write index file\n" );
- }
- int trackno = FFMS_GetFirstTrackOfType( idx, FFMS_TYPE_VIDEO, &e );
- - if( trackno < 0 )
- - {
- - fprintf( stderr, "ffms [error]: could not find video track\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( trackno < 0, "could not find video track\n" )
- h->video_source = FFMS_CreateVideoSource( psz_filename, trackno, idx, 1, seekmode, &e );
- - if( !h->video_source )
- - {
- - fprintf( stderr, "ffms [error]: could not create video source\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h->video_source, "could not create video source\n" )
- h->track = FFMS_GetTrackFromVideo( h->video_source );
- @@ -121,11 +111,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- h->vfr_input = info->vfr;
- const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, 0, &e );
- - if( !frame )
- - {
- - fprintf( stderr, "ffms [error]: could not read frame 0\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !frame, "could not read frame 0\n" )
- h->init_width = h->cur_width = info->width = frame->EncodedWidth;
- h->init_height = h->cur_height = info->height = frame->EncodedHeight;
- @@ -134,8 +120,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- info->tff = frame->TopFieldFirst;
- if( h->cur_pix_fmt != PIX_FMT_YUV420P )
- - fprintf( stderr, "ffms [warning]: converting from %s to YV12\n",
- - avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- + x264_cli_log( "ffms", X264_LOG_WARNING, "converting from %s to YV12\n",
- + avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- /* ffms timestamps are in milliseconds. ffms also uses int64_ts for timebase,
- * so we need to reduce large timebases to prevent overflow */
- @@ -173,19 +159,15 @@ static int check_swscale( ffms_hnd_t *h, const FFMS_Frame *frame, int i_frame )
- if( h->scaler )
- {
- sws_freeContext( h->scaler );
- - fprintf( stderr, "ffms [warning]: stream properties changed to %dx%d, %s at frame %d \n", frame->EncodedWidth,
- - frame->EncodedHeight, avcodec_get_pix_fmt_name( frame->EncodedPixelFormat ), i_frame );
- + x264_cli_log( "ffms", X264_LOG_WARNING, "stream properties changed to %dx%d, %s at frame %d \n", frame->EncodedWidth,
- + frame->EncodedHeight, avcodec_get_pix_fmt_name( frame->EncodedPixelFormat ), i_frame );
- h->cur_width = frame->EncodedWidth;
- h->cur_height = frame->EncodedHeight;
- h->cur_pix_fmt = frame->EncodedPixelFormat;
- }
- h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
- PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
- - if( !h->scaler )
- - {
- - fprintf( stderr, "ffms [error]: could not open swscale context\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h->scaler, "could not open swscale context\n" )
- return 0;
- }
- @@ -195,11 +177,7 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- FFMS_ErrorInfo e;
- e.BufferSize = 0;
- const FFMS_Frame *frame = FFMS_GetFrame( h->video_source, i_frame, &e );
- - if( !frame )
- - {
- - fprintf( stderr, "ffms [error]: could not read frame %d\n", i_frame );
- - return -1;
- - }
- + FAIL_IF_ERROR( !frame, "could not read frame %d\n", i_frame )
- if( check_swscale( h, frame, i_frame ) )
- return -1;
- @@ -214,12 +192,8 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- if( h->vfr_input )
- {
- - if( info->PTS == AV_NOPTS_VALUE )
- - {
- - fprintf( stderr, "ffms [error]: invalid timestamp. "
- - "Use --force-cfr and specify a framerate with --fps\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( info->PTS == AV_NOPTS_VALUE, "invalid timestamp. "
- + "Use --force-cfr and specify a framerate with --fps\n" )
- if( !h->pts_offset_flag )
- {
- diff --git a/input/input.h b/input/input.h
- index f89b13b..f588f3c 100644
- --- a/input/input.h
- +++ b/input/input.h
- @@ -25,6 +25,8 @@
- #ifndef X264_INPUT_H
- #define X264_INPUT_H
- +#include "x264cli.h"
- +
- /* options that are used by only some demuxers */
- typedef struct
- {
- diff --git a/input/lavf.c b/input/lavf.c
- index 4b0375f..54a275f 100644
- --- a/input/lavf.c
- +++ b/input/lavf.c
- @@ -21,7 +21,8 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "lavf", __VA_ARGS__ )
- #undef DECLARE_ALIGNED
- #include <libavformat/avformat.h>
- #include <libswscale/swscale.h>
- @@ -59,19 +60,15 @@ static int check_swscale( lavf_hnd_t *h, AVCodecContext *c, int i_frame )
- if( h->scaler )
- {
- sws_freeContext( h->scaler );
- - fprintf( stderr, "lavf [warning]: stream properties changed to %dx%d, %s at frame %d \n",
- - c->width, c->height, avcodec_get_pix_fmt_name( c->pix_fmt ), i_frame );
- + x264_cli_log( "lavf", X264_LOG_WARNING, "stream properties changed to %dx%d, %s at frame %d \n",
- + c->width, c->height, avcodec_get_pix_fmt_name( c->pix_fmt ), i_frame );
- h->cur_width = c->width;
- h->cur_height = c->height;
- h->cur_pix_fmt = c->pix_fmt;
- }
- h->scaler = sws_getContext( h->cur_width, h->cur_height, h->cur_pix_fmt, h->init_width, h->init_height,
- PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL );
- - if( !h->scaler )
- - {
- - fprintf( stderr, "lavf [error]: could not open swscale context\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h->scaler, "could not open swscale context\n" )
- return 0;
- }
- @@ -106,12 +103,12 @@ static int read_frame_internal( x264_picture_t *p_pic, lavf_hnd_t *h, int i_fram
- {
- c->reordered_opaque = pkt->pts;
- if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
- - fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
- + x264_cli_log( "lavf", X264_LOG_WARNING, "video decoding failed on frame %d\n", h->next_frame );
- }
- if( !finished )
- {
- if( avcodec_decode_video2( c, frame, &finished, pkt ) < 0 )
- - fprintf( stderr, "lavf [warning]: video decoding failed on frame %d\n", h->next_frame );
- + x264_cli_log( "lavf", X264_LOG_WARNING, "video decoding failed on frame %d\n", h->next_frame );
- if( !finished )
- return -1;
- }
- @@ -166,26 +163,13 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- if( !strcmp( psz_filename, "-" ) )
- psz_filename = "pipe:";
- - if( av_open_input_file( &h->lavf, psz_filename, NULL, 0, NULL ) )
- - {
- - fprintf( stderr, "lavf [error]: could not open input file\n" );
- - return -1;
- - }
- -
- - if( av_find_stream_info( h->lavf ) < 0 )
- - {
- - fprintf( stderr, "lavf [error]: could not find input stream info\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( av_open_input_file( &h->lavf, psz_filename, NULL, 0, NULL ), "could not open input file\n" )
- + FAIL_IF_ERROR( av_find_stream_info( h->lavf ) < 0, "could not find input stream info\n" )
- int i = 0;
- while( i < h->lavf->nb_streams && h->lavf->streams[i]->codec->codec_type != CODEC_TYPE_VIDEO )
- i++;
- - if( i == h->lavf->nb_streams )
- - {
- - fprintf( stderr, "lavf [error]: could not find video stream\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( i == h->lavf->nb_streams, "could not find video stream\n" )
- h->stream_id = i;
- h->next_frame = 0;
- h->pts_offset_flag = 0;
- @@ -207,22 +191,15 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- info->csp |= X264_CSP_VFLIP;
- if( h->cur_pix_fmt != PIX_FMT_YUV420P )
- - fprintf( stderr, "lavf [warning]: converting from %s to YV12\n",
- - avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- -
- - if( avcodec_open( c, avcodec_find_decoder( c->codec_id ) ) )
- - {
- - fprintf( stderr, "lavf [error]: could not find decoder for video stream\n" );
- - return -1;
- - }
- + x264_cli_log( "lavf", X264_LOG_WARNING, "converting from %s to YV12\n",
- + avcodec_get_pix_fmt_name( h->cur_pix_fmt ) );
- + FAIL_IF_ERROR( avcodec_open( c, avcodec_find_decoder( c->codec_id ) ),
- + "could not find decoder for video stream\n" )
- /* prefetch the first frame and set/confirm flags */
- h->first_pic = malloc( sizeof(x264_picture_t) );
- - if( !h->first_pic || lavf_input.picture_alloc( h->first_pic, info->csp, info->width, info->height ) )
- - {
- - fprintf( stderr, "lavf [error]: malloc failed\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h->first_pic || lavf_input.picture_alloc( h->first_pic, info->csp, info->width, info->height ),
- + "malloc failed\n" )
- else if( read_frame_internal( h->first_pic, h, 0, info ) )
- return -1;
- diff --git a/input/thread.c b/input/thread.c
- index c4b07fa..98af22b 100644
- --- a/input/thread.c
- +++ b/input/thread.c
- @@ -21,7 +21,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- extern cli_input_t input;
- @@ -47,11 +47,8 @@ typedef struct thread_input_arg_t
- static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, cli_input_opt_t *opt )
- {
- thread_hnd_t *h = malloc( sizeof(thread_hnd_t) );
- - if( !h || input.picture_alloc( &h->pic, info->csp, info->width, info->height ) )
- - {
- - fprintf( stderr, "x264 [error]: malloc failed\n" );
- - return -1;
- - }
- + FAIL_IF_ERR( !h || input.picture_alloc( &h->pic, info->csp, info->width, info->height ),
- + "x264", "malloc failed\n" )
- h->input = input;
- h->p_handle = *p_handle;
- h->next_frame = -1;
- diff --git a/input/timecode.c b/input/timecode.c
- index a307327..7821e76 100644
- --- a/input/timecode.c
- +++ b/input/timecode.c
- @@ -20,7 +20,8 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "timecode", __VA_ARGS__ )
- #include <math.h>
- extern cli_input_t input;
- @@ -61,12 +62,8 @@ static double correct_fps( double fps, timecode_hnd_t *h )
- {
- fps_den = i * h->timebase_num;
- fps_num = round( fps_den * fps_sig ) * exponent;
- - if( fps_num > UINT32_MAX )
- - {
- - fprintf( stderr, "timecode [error]: tcfile fps correction failed.\n"
- - " Specify an appropriate timebase manually or remake tcfile.\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( fps_num > UINT32_MAX, "tcfile fps correction failed.\n"
- + " Specify an appropriate timebase manually or remake tcfile.\n" )
- if( fabs( ((double)fps_num / fps_den) / exponent - fps_sig ) < DOUBLE_EPSILON )
- break;
- ++i;
- @@ -91,12 +88,8 @@ static int try_mkv_timebase_den( double *fpss, timecode_hnd_t *h, int loop_num )
- double fps_sig = sigexp10( fpss[num], &exponent );
- fps_den = round( MKV_TIMEBASE_DEN / fps_sig ) / exponent;
- h->timebase_num = fps_den && h->timebase_num ? gcd( h->timebase_num, fps_den ) : fps_den;
- - if( h->timebase_num > UINT32_MAX || !h->timebase_num )
- - {
- - fprintf( stderr, "timecode [error]: automatic timebase generation failed.\n"
- - " Specify timebase manually.\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || !h->timebase_num, "automatic timebase generation failed.\n"
- + " Specify timebase manually.\n" )
- }
- return 0;
- }
- @@ -110,11 +103,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- double *fpss = NULL;
- ret = fscanf( tcfile_in, "# timecode format v%d", &tcfv );
- - if( ret != 1 || (tcfv != 1 && tcfv != 2) )
- - {
- - fprintf( stderr, "timecode [error]: unsupported timecode format\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( ret != 1 || (tcfv != 1 && tcfv != 2), "unsupported timecode format\n" )
- if( tcfv == 1 )
- {
- @@ -128,18 +117,11 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- {
- if( buff[0] == '#' || buff[0] == '\n' || buff[0] == '\r' )
- continue;
- - if( sscanf( buff, "assume %lf", &h->assume_fps ) != 1 && sscanf( buff, "Assume %lf", &h->assume_fps ) != 1 )
- - {
- - fprintf( stderr, "timecode [error]: tcfile parsing error: assumed fps not found\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( sscanf( buff, "assume %lf", &h->assume_fps ) != 1 && sscanf( buff, "Assume %lf", &h->assume_fps ) != 1,
- + "tcfile parsing error: assumed fps not found\n" )
- break;
- }
- - if( h->assume_fps <= 0 )
- - {
- - fprintf( stderr, "timecode [error]: invalid assumed fps %.6f\n", h->assume_fps );
- - return -1;
- - }
- + FAIL_IF_ERROR( h->assume_fps <= 0, "invalid assumed fps %.6f\n", h->assume_fps )
- file_pos = ftell( tcfile_in );
- h->stored_pts_num = 0;
- @@ -152,16 +134,9 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- continue;
- }
- ret = sscanf( buff, "%d,%d,%lf", &start, &end, &seq_fps );
- - if( ret != 3 && ret != EOF )
- - {
- - fprintf( stderr, "timecode [error]: invalid input tcfile\n" );
- - return -1;
- - }
- - if( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0 )
- - {
- - fprintf( stderr, "timecode [error]: invalid input tcfile at line %d: %s\n", num, buff );
- - return -1;
- - }
- + FAIL_IF_ERROR( ret != 3 && ret != EOF, "invalid input tcfile\n" )
- + FAIL_IF_ERROR( start > end || start <= prev_start || end <= prev_end || seq_fps <= 0,
- + "invalid input tcfile at line %d: %s\n", num, buff )
- prev_start = start;
- prev_end = end;
- if( h->auto_timebase_den || h->auto_timebase_num )
- @@ -259,11 +234,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- ++num;
- }
- timecodes_num = h->stored_pts_num + h->seek;
- - if( !timecodes_num )
- - {
- - fprintf( stderr, "timecode [error]: input tcfile doesn't have any timecodes!\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !timecodes_num, "input tcfile doesn't have any timecodes!\n" )
- fseek( tcfile_in, file_pos, SEEK_SET );
- timecodes = malloc( timecodes_num * sizeof(double) );
- @@ -272,11 +243,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- fgets( buff, sizeof(buff), tcfile_in );
- ret = sscanf( buff, "%lf", &timecodes[0] );
- - if( ret != 1 )
- - {
- - fprintf( stderr, "timecode [error]: invalid input tcfile for frame 0\n" );
- - goto fail;
- - }
- + FAIL_IF_ERROR( ret != 1, "invalid input tcfile for frame 0\n" )
- for( num = 1; num < timecodes_num; )
- {
- fgets( buff, sizeof(buff), tcfile_in );
- @@ -284,11 +251,8 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- continue;
- ret = sscanf( buff, "%lf", &timecodes[num] );
- timecodes[num] *= 1e-3; /* Timecode format v2 is expressed in milliseconds. */
- - if( ret != 1 || timecodes[num] <= timecodes[num - 1] )
- - {
- - fprintf( stderr, "timecode [error]: invalid input tcfile for frame %d\n", num );
- - goto fail;
- - }
- + FAIL_IF_ERROR( ret != 1 || timecodes[num] <= timecodes[num - 1],
- + "invalid input tcfile for frame %d\n", num )
- ++num;
- }
- @@ -342,14 +306,10 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- uint64_t i = gcd( h->timebase_num, h->timebase_den );
- h->timebase_num /= i;
- h->timebase_den /= i;
- - fprintf( stderr, "timecode [info]: automatic timebase generation %"PRIu64"/%"PRIu64"\n", h->timebase_num, h->timebase_den );
- - }
- - else if( h->timebase_den > UINT32_MAX || !h->timebase_den )
- - {
- - fprintf( stderr, "timecode [error]: automatic timebase generation failed.\n"
- - " Specify an appropriate timebase manually.\n" );
- - goto fail;
- + x264_cli_log( "timecode", X264_LOG_INFO, "automatic timebase generation %"PRIu64"/%"PRIu64"\n", h->timebase_num, h->timebase_den );
- }
- + else FAIL_IF_ERROR( h->timebase_den > UINT32_MAX || !h->timebase_den, "automatic timebase generation failed.\n"
- + " Specify an appropriate timebase manually.\n" )
- h->pts = malloc( h->stored_pts_num * sizeof(int64_t) );
- if( !h->pts )
- @@ -360,11 +320,7 @@ static int parse_tcfile( FILE *tcfile_in, timecode_hnd_t *h, video_info_t *info
- {
- h->pts[num] = (int64_t)( timecodes[h->seek + num] * ((double)h->timebase_den / h->timebase_num) + 0.5 );
- h->pts[num] -= pts_seek_offset;
- - if( h->pts[num] <= h->pts[num - 1] )
- - {
- - fprintf( stderr, "timecode [error]: invalid timebase or timecode for frame %d\n", num );
- - goto fail;
- - }
- + FAIL_IF_ERROR( h->pts[num] <= h->pts[num - 1], "invalid timebase or timecode for frame %d\n", num )
- }
- free( timecodes );
- @@ -386,11 +342,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- int ret = 0;
- FILE *tcfile_in;
- timecode_hnd_t *h = malloc( sizeof(timecode_hnd_t) );
- - if( !h )
- - {
- - fprintf( stderr, "timecode [error]: malloc failed\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( !h, "malloc failed\n" )
- h->input = input;
- h->p_handle = *p_handle;
- h->frame_total = input.get_frame_total( h->p_handle );
- @@ -400,11 +352,8 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- ret = sscanf( opt->timebase, "%"SCNu64"/%"SCNu64, &h->timebase_num, &h->timebase_den );
- if( ret == 1 )
- h->timebase_num = strtoul( opt->timebase, NULL, 10 );
- - if( h->timebase_num > UINT32_MAX || h->timebase_den > UINT32_MAX )
- - {
- - fprintf( stderr, "timecode [error]: timebase you specified exceeds H.264 maximum\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( h->timebase_num > UINT32_MAX || h->timebase_den > UINT32_MAX,
- + "timebase you specified exceeds H.264 maximum\n" )
- }
- h->auto_timebase_num = !ret;
- h->auto_timebase_den = ret < 2;
- @@ -418,14 +367,10 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- *p_handle = h;
- tcfile_in = fopen( psz_filename, "rb" );
- - if( !tcfile_in )
- - {
- - fprintf( stderr, "timecode [error]: can't open `%s'\n", psz_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !tcfile_in, "can't open `%s'\n", psz_filename )
- else if( !x264_is_regular_file( tcfile_in ) )
- {
- - fprintf( stderr, "timecode [error]: tcfile input incompatible with non-regular file `%s'\n", psz_filename );
- + x264_cli_log( "timecode", X264_LOG_ERROR, "tcfile input incompatible with non-regular file `%s'\n", psz_filename );
- fclose( tcfile_in );
- return -1;
- }
- @@ -466,8 +411,8 @@ static int read_frame( x264_picture_t *p_pic, hnd_t handle, int i_frame )
- {
- if( h->pts )
- {
- - fprintf( stderr, "timecode [info]: input timecode file missing data for frame %d and later\n"
- - " assuming constant fps %.6f\n", i_frame, h->assume_fps );
- + x264_cli_log( "timecode", X264_LOG_INFO, "input timecode file missing data for frame %d and later\n"
- + " assuming constant fps %.6f\n", i_frame, h->assume_fps );
- free( h->pts );
- h->pts = NULL;
- }
- diff --git a/input/y4m.c b/input/y4m.c
- index fd42140..9b39d2f 100644
- --- a/input/y4m.c
- +++ b/input/y4m.c
- @@ -21,7 +21,8 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "y4m", __VA_ARGS__ )
- typedef struct
- {
- @@ -162,11 +163,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- if( colorspace == X264_CSP_NONE )
- colorspace = X264_CSP_I420;
- - if( colorspace != X264_CSP_I420 )
- - {
- - fprintf( stderr, "y4m [error]: colorspace unhandled\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( colorspace != X264_CSP_I420, "colorspace unhandled\n" )
- *p_handle = h;
- return 0;
- @@ -202,21 +199,13 @@ static int read_frame_internal( x264_picture_t *p_pic, y4m_hnd_t *h )
- return -1;
- header[slen] = 0;
- - if( strncmp( header, Y4M_FRAME_MAGIC, slen ) )
- - {
- - fprintf( stderr, "y4m [error]: bad header magic (%"PRIx32" <=> %s)\n",
- - M32(header), header );
- - return -1;
- - }
- + FAIL_IF_ERROR( strncmp( header, Y4M_FRAME_MAGIC, slen ), "bad header magic (%"PRIx32" <=> %s)\n",
- + M32(header), header )
- /* Skip most of it */
- while( i < MAX_FRAME_HEADER && fgetc( h->fh ) != '\n' )
- i++;
- - if( i == MAX_FRAME_HEADER )
- - {
- - fprintf( stderr, "y4m [error]: bad frame header!\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( i == MAX_FRAME_HEADER, "bad frame header!\n" )
- h->frame_header_len = i+slen+1;
- if( fread( p_pic->img.plane[0], h->width * h->height, 1, h->fh ) <= 0
- diff --git a/input/yuv.c b/input/yuv.c
- index cbed7fc..613662c 100644
- --- a/input/yuv.c
- +++ b/input/yuv.c
- @@ -21,7 +21,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "input.h"
- typedef struct
- {
- @@ -45,11 +45,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle, video_info_t *info, c
- }
- else
- sscanf( opt->resolution, "%ux%u", &info->width, &info->height );
- - if( !info->width || !info->height )
- - {
- - fprintf( stderr, "yuv [error]: rawyuv input requires a resolution.\n" );
- - return -1;
- - }
- + FAIL_IF_ERR( !info->width || !info->height, "yuv", "rawyuv input requires a resolution.\n" )
- h->next_frame = 0;
- info->vfr = 0;
- diff --git a/muxers.h b/muxers.h
- deleted file mode 100644
- index b309320..0000000
- --- a/muxers.h
- +++ /dev/null
- @@ -1,61 +0,0 @@
- -/*****************************************************************************
- - * muxers.h: h264 file i/o modules
- - *****************************************************************************
- - * Copyright (C) 2003-2009 x264 project
- - *
- - * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- - * Loren Merritt <lorenm@u.washington.edu>
- - *
- - * This program is free software; you can redistribute it and/or modify
- - * it under the terms of the GNU General Public License as published by
- - * the Free Software Foundation; either version 2 of the License, or
- - * (at your option) any later version.
- - *
- - * This program is distributed in the hope that it will be useful,
- - * but WITHOUT ANY WARRANTY; without even the implied warranty of
- - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- - * GNU General Public License for more details.
- - *
- - * You should have received a copy of the GNU General Public License
- - * along with this program; if not, write to the Free Software
- - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- - *****************************************************************************/
- -
- -#ifndef X264_MUXERS_H
- -#define X264_MUXERS_H
- -
- -#include "common/common.h"
- -#include "x264.h"
- -
- -typedef void *hnd_t;
- -
- -static inline int64_t gcd( int64_t a, int64_t b )
- -{
- - while( 1 )
- - {
- - int64_t c = a % b;
- - if( !c )
- - return b;
- - a = b;
- - b = c;
- - }
- -}
- -
- -static inline int64_t lcm( int64_t a, int64_t b )
- -{
- - return ( a / gcd( a, b ) ) * b;
- -}
- -
- -static inline char *get_filename_extension( char *filename )
- -{
- - char *ext = filename + strlen( filename );
- - while( *ext != '.' && ext > filename )
- - ext--;
- - ext += *ext == '.';
- - return ext;
- -}
- -
- -#include "input/input.h"
- -#include "output/output.h"
- -
- -#endif
- diff --git a/output/flv.c b/output/flv.c
- index e441b6d..9831a5b 100644
- --- a/output/flv.c
- +++ b/output/flv.c
- @@ -18,7 +18,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- #include "flv_bytestream.h"
- #define CHECK(x)\
- @@ -223,14 +223,14 @@ static int write_frame( hnd_t handle, uint8_t *p_nalu, int i_size, x264_picture_
- if( prev_dts == dts )
- {
- double fps = ((double)p_flv->i_timebase_den / p_flv->i_timebase_num) / (p_picture->i_dts - p_flv->i_prev_dts);
- - fprintf( stderr, "flv [warning]: duplicate DTS %"PRId64" generated by rounding\n"
- - " current internal decoding framerate: %.6f fps\n", dts, fps );
- + x264_cli_log( "flv", X264_LOG_WARNING, "duplicate DTS %"PRId64" generated by rounding\n"
- + " current internal decoding framerate: %.6f fps\n", dts, fps );
- }
- if( prev_cts == cts )
- {
- double fps = ((double)p_flv->i_timebase_den / p_flv->i_timebase_num) / (p_picture->i_pts - p_flv->i_prev_pts);
- - fprintf( stderr, "flv [warning]: duplicate CTS %"PRId64" generated by rounding\n"
- - " current internal composition framerate: %.6f fps\n", cts, fps );
- + x264_cli_log( "flv", X264_LOG_WARNING, "duplicate CTS %"PRId64" generated by rounding\n"
- + " current internal composition framerate: %.6f fps\n", cts, fps );
- }
- }
- p_flv->i_prev_dts = p_picture->i_dts;
- diff --git a/output/flv_bytestream.c b/output/flv_bytestream.c
- index 316114c..e02476c 100644
- --- a/output/flv_bytestream.c
- +++ b/output/flv_bytestream.c
- @@ -18,7 +18,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- #include "flv_bytestream.h"
- uint64_t dbl2int( double value )
- diff --git a/output/matroska.c b/output/matroska.c
- index 0304c84..a1219d0 100644
- --- a/output/matroska.c
- +++ b/output/matroska.c
- @@ -18,7 +18,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- #include "matroska_ebml.h"
- typedef struct
- diff --git a/output/matroska_ebml.c b/output/matroska_ebml.c
- index 31b62f8..adfcaa8 100644
- --- a/output/matroska_ebml.c
- +++ b/output/matroska_ebml.c
- @@ -18,7 +18,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- #include "matroska_ebml.h"
- #define CLSIZE 1048576
- diff --git a/output/mp4.c b/output/mp4.c
- index 0e3c2fc..f2fc5f5 100644
- --- a/output/mp4.c
- +++ b/output/mp4.c
- @@ -21,7 +21,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- #include <gpac/isomedia.h>
- #if HAVE_GF_MALLOC
- @@ -61,12 +61,12 @@ static void recompute_bitrate_mp4( GF_ISOFile *p_file, int i_track )
- timescale = gf_isom_get_media_timescale( p_file, i_track );
- count = gf_isom_get_sample_count( p_file, i_track );
- - for( int i = 0; i < count; i++ )
- + for( u32 i = 0; i < count; i++ )
- {
- GF_ISOSample *samp = gf_isom_get_sample_info( p_file, i_track, i+1, &di, &offset );
- if( !samp )
- {
- - fprintf( stderr, "mp4 [error]: failure reading back frame %u\n", i );
- + x264_cli_log( "mp4", X264_LOG_ERROR, "failure reading back frame %u\n", i );
- break;
- }
- @@ -163,11 +163,7 @@ static int open_file( char *psz_filename, hnd_t *p_handle )
- FILE *fh = fopen( psz_filename, "w" );
- if( !fh )
- return -1;
- - else if( !x264_is_regular_file( fh ) )
- - {
- - fprintf( stderr, "mp4 [error]: MP4 output is incompatible with non-regular file `%s'\n", psz_filename );
- - return -1;
- - }
- + FAIL_IF_ERR( !x264_is_regular_file( fh ), "MP4 output is incompatible with non-regular file `%s'\n", psz_filename )
- fclose( fh );
- if( !(p_mp4 = malloc( sizeof(mp4_hnd_t) )) )
- diff --git a/output/output.h b/output/output.h
- index c79b48e..094fefc 100644
- --- a/output/output.h
- +++ b/output/output.h
- @@ -24,6 +24,8 @@
- #ifndef X264_OUTPUT_H
- #define X264_OUTPUT_H
- +#include "x264cli.h"
- +
- typedef struct
- {
- int (*open_file)( char *psz_filename, hnd_t *p_handle );
- diff --git a/output/raw.c b/output/raw.c
- index 02e4c56..fc418fb 100644
- --- a/output/raw.c
- +++ b/output/raw.c
- @@ -21,7 +21,7 @@
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- *****************************************************************************/
- -#include "muxers.h"
- +#include "output.h"
- static int open_file( char *psz_filename, hnd_t *p_handle )
- {
- diff --git a/x264.c b/x264.c
- index f08ab41..741570c 100644
- --- a/x264.c
- +++ b/x264.c
- @@ -31,9 +31,11 @@
- #include <getopt.h>
- #include "common/common.h"
- -#include "common/cpu.h"
- -#include "x264.h"
- -#include "muxers.h"
- +#include "x264cli.h"
- +#include "input/input.h"
- +#include "output/output.h"
- +
- +#define FAIL_IF_ERROR( cond, ... ) FAIL_IF_ERR( cond, "x264", __VA_ARGS__ )
- #ifdef _WIN32
- #include <windows.h>
- @@ -96,6 +98,7 @@ static const char * const muxer_names[] =
- };
- static const char * const pulldown_names[] = { "none", "22", "32", "64", "double", "triple", "euro", 0 };
- +static const char * const log_level_names[] = { "none", "error", "warning", "info", "debug", 0 };
- typedef struct{
- int mod;
- @@ -141,6 +144,48 @@ static void Help( x264_param_t *defaults, int longhelp );
- static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt );
- static int Encode( x264_param_t *param, cli_opt_t *opt );
- +/* logging and printing for within the cli system */
- +static int cli_log_level;
- +void x264_cli_log( const char *name, int i_level, const char *fmt, ... )
- +{
- + if( i_level > cli_log_level )
- + return;
- + char *s_level;
- + switch( i_level )
- + {
- + case X264_LOG_ERROR:
- + s_level = "error";
- + break;
- + case X264_LOG_WARNING:
- + s_level = "warning";
- + break;
- + case X264_LOG_INFO:
- + s_level = "info";
- + break;
- + case X264_LOG_DEBUG:
- + s_level = "debug";
- + break;
- + default:
- + s_level = "unknown";
- + break;
- + }
- + fprintf( stderr, "%s [%s]: ", name, s_level );
- + va_list arg;
- + va_start( arg, fmt );
- + vfprintf( stderr, fmt, arg );
- + va_end( arg );
- +}
- +
- +void x264_cli_printf( int i_level, const char *fmt, ... )
- +{
- + if( i_level > cli_log_level )
- + return;
- + va_list arg;
- + va_start( arg, fmt );
- + vfprintf( stderr, fmt, arg );
- + va_end( arg );
- +}
- +
- /****************************************************************************
- * main:
- ****************************************************************************/
- @@ -571,6 +616,9 @@ static void Help( x264_param_t *defaults, int longhelp )
- H1( " -v, --verbose Print stats for each frame\n" );
- H1( " --no-progress Don't show the progress indicator while encoding\n" );
- H0( " --quiet Quiet Mode\n" );
- + H1( " --log-level <string> Specify the maximum level of logging [\"%s\"]\n"
- + " - %s\n", strtable_lookup( log_level_names, cli_log_level - X264_LOG_NONE ),
- + stringify_names( buf, log_level_names ) );
- H1( " --psnr Enable PSNR computation\n" );
- H1( " --ssim Enable SSIM computation\n" );
- H1( " --threads <integer> Force a specific number of threads\n" );
- @@ -616,6 +664,7 @@ enum {
- OPT_TCFILE_OUT,
- OPT_TIMEBASE,
- OPT_PULLDOWN,
- + OPT_LOG_LEVEL
- } OptionsOPT;
- static char short_options[] = "8A:B:b:f:hI:i:m:o:p:q:r:t:Vvw";
- @@ -729,6 +778,7 @@ static struct option long_options[] =
- { "ssim", no_argument, NULL, 0 },
- { "quiet", no_argument, NULL, OPT_QUIET },
- { "verbose", no_argument, NULL, 'v' },
- + { "log-level", required_argument, NULL, OPT_LOG_LEVEL },
- { "no-progress", no_argument, NULL, OPT_NOPROGRESS },
- { "visualize", no_argument, NULL, OPT_VISUALIZE },
- { "dump-yuv", required_argument, NULL, 0 },
- @@ -780,11 +830,11 @@ static int select_output( const char *muxer, char *filename, x264_param_t *param
- param->b_repeat_headers = 0;
- if( param->i_nal_hrd == X264_NAL_HRD_CBR )
- {
- - fprintf( stderr, "x264 [warning]: cbr nal-hrd is not compatible with mp4\n" );
- + x264_cli_log( "x264", X264_LOG_WARNING, "cbr nal-hrd is not compatible with mp4\n" );
- param->i_nal_hrd = X264_NAL_HRD_VBR;
- }
- #else
- - fprintf( stderr, "x264 [error]: not compiled with MP4 output support\n" );
- + x264_cli_log( "x264", X264_LOG_ERROR, "not compiled with MP4 output support\n" );
- return -1;
- #endif
- }
- @@ -833,7 +883,7 @@ static int select_input( const char *demuxer, char *used_demuxer, char *filename
- input = avs_input;
- module = "avs";
- #else
- - fprintf( stderr, "x264 [error]: not compiled with AVS input support\n" );
- + x264_cli_log( "x264", X264_LOG_ERROR, "not compiled with AVS input support\n" );
- return -1;
- #endif
- }
- @@ -877,11 +927,7 @@ static int select_input( const char *demuxer, char *used_demuxer, char *filename
- input = yuv_input;
- }
- - if( !(*p_handle) )
- - {
- - fprintf( stderr, "x264 [error]: could not open input file `%s' via any method!\n", filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !(*p_handle), "could not open input file `%s' via any method!\n", filename )
- }
- strcpy( used_demuxer, module );
- @@ -932,6 +978,7 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
- char *tune = NULL;
- x264_param_default( &defaults );
- + cli_log_level = defaults.i_log_level;
- memset( opt, 0, sizeof(cli_opt_t) );
- memset( &input_opt, 0, sizeof(cli_input_opt_t) );
- @@ -1004,32 +1051,20 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
- output_filename = optarg;
- break;
- case OPT_MUXER:
- - if( parse_enum_name( optarg, muxer_names, &muxer ) < 0 )
- - {
- - fprintf( stderr, "x264 [error]: Unknown muxer `%s'\n", optarg );
- - return -1;
- - }
- + FAIL_IF_ERROR( parse_enum_name( optarg, muxer_names, &muxer ), "Unknown muxer `%s'\n", optarg )
- break;
- case OPT_DEMUXER:
- - if( parse_enum_name( optarg, demuxer_names, &demuxer ) < 0 )
- - {
- - fprintf( stderr, "x264 [error]: Unknown demuxer `%s'\n", optarg );
- - return -1;
- - }
- + FAIL_IF_ERROR( parse_enum_name( optarg, demuxer_names, &demuxer ), "Unknown demuxer `%s'\n", optarg )
- break;
- case OPT_INDEX:
- input_opt.index_file = optarg;
- break;
- case OPT_QPFILE:
- opt->qpfile = fopen( optarg, "rb" );
- - if( !opt->qpfile )
- - {
- - fprintf( stderr, "x264 [error]: can't open qpfile `%s'\n", optarg );
- - return -1;
- - }
- - else if( !x264_is_regular_file( opt->qpfile ) )
- + FAIL_IF_ERROR( !opt->qpfile, "can't open qpfile `%s'\n", optarg )
- + if( !x264_is_regular_file( opt->qpfile ) )
- {
- - fprintf( stderr, "x264 [error]: qpfile incompatible with non-regular file `%s'\n", optarg );
- + x264_cli_log( "x264", X264_LOG_ERROR, "qpfile incompatible with non-regular file `%s'\n", optarg );
- fclose( opt->qpfile );
- return -1;
- }
- @@ -1038,11 +1073,17 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
- b_thread_input = 1;
- break;
- case OPT_QUIET:
- - param->i_log_level = X264_LOG_NONE;
- + cli_log_level = param->i_log_level = X264_LOG_NONE;
- break;
- case 'v':
- - param->i_log_level = X264_LOG_DEBUG;
- + cli_log_level = param->i_log_level = X264_LOG_DEBUG;
- break;
- + case OPT_LOG_LEVEL:
- + if( !parse_enum_value( optarg, log_level_names, &cli_log_level ) )
- + cli_log_level += X264_LOG_NONE;
- + else
- + cli_log_level = atoi( optarg );
- + param->i_log_level = cli_log_level;
- case OPT_NOPROGRESS:
- opt->b_progress = 0;
- break;
- @@ -1051,7 +1092,7 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
- param->b_visualize = 1;
- b_exit_on_ctrl_c = 1;
- #else
- - fprintf( stderr, "x264 [warning]: not compiled with visualization support\n" );
- + x264_cli_log( "x264", X264_LOG_WARNING, "not compiled with visualization support\n" );
- #endif
- break;
- case OPT_TUNE:
- @@ -1078,18 +1119,13 @@ static int Parse( int argc, char **argv, x264_param_t *param, cli_opt_t *opt )
- break;
- case OPT_TCFILE_OUT:
- opt->tcfile_out = fopen( optarg, "wb" );
- - if( !opt->tcfile_out )
- - {
- - fprintf( stderr, "x264 [error]: can't open `%s'\n", optarg );
- - return -1;
- - }
- + FAIL_IF_ERROR( !opt->tcfile_out, "can't open `%s'\n", optarg )
- break;
- case OPT_TIMEBASE:
- input_opt.timebase = optarg;
- break;
- case OPT_PULLDOWN:
- - if( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ) < 0 )
- - return -1;
- + FAIL_IF_ERROR( parse_enum_value( optarg, pulldown_names, &opt->i_pulldown ), "Unknown pulldown `%s'\n", optarg )
- break;
- default:
- generic_option:
- @@ -1116,7 +1152,7 @@ generic_option:
- if( b_error )
- {
- const char *name = long_options_index > 0 ? long_options[long_options_index].name : argv[optind-2];
- - fprintf( stderr, "x264 [error]: invalid argument: %s = %s\n", name, optarg );
- + x264_cli_log( "x264", X264_LOG_ERROR, "invalid argument: %s = %s\n", name, optarg );
- return -1;
- }
- }
- @@ -1130,20 +1166,12 @@ generic_option:
- return -1;
- /* Get the file name */
- - if( optind > argc - 1 || !output_filename )
- - {
- - fprintf( stderr, "x264 [error]: No %s file. Run x264 --help for a list of options.\n",
- - optind > argc - 1 ? "input" : "output" );
- - return -1;
- - }
- + FAIL_IF_ERROR( optind > argc - 1 || !output_filename, "No %s file. Run x264 --help for a list of options.\n",
- + optind > argc - 1 ? "input" : "output" )
- if( select_output( muxer, output_filename, param ) )
- return -1;
- - if( output.open_file( output_filename, &opt->hout ) )
- - {
- - fprintf( stderr, "x264 [error]: could not open output file `%s'\n", output_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( output.open_file( output_filename, &opt->hout ), "could not open output file `%s'\n", output_filename )
- input_filename = argv[optind++];
- input_opt.resolution = optind < argc ? argv[optind++] : NULL;
- @@ -1163,39 +1191,22 @@ generic_option:
- if( select_input( demuxer, demuxername, input_filename, &opt->hin, &info, &input_opt ) )
- return -1;
- - if( !opt->hin && input.open_file( input_filename, &opt->hin, &info, &input_opt ) )
- - {
- - fprintf( stderr, "x264 [error]: could not open input file `%s'\n", input_filename );
- - return -1;
- - }
- + FAIL_IF_ERROR( !opt->hin && input.open_file( input_filename, &opt->hin, &info, &input_opt ),
- + "could not open input file `%s'\n", input_filename )
- x264_reduce_fraction( &info.sar_width, &info.sar_height );
- x264_reduce_fraction( &info.fps_num, &info.fps_den );
- - if( param->i_log_level >= X264_LOG_INFO )
- - fprintf( stderr, "%s [info]: %dx%d%c %d:%d @ %d/%d fps (%cfr)\n", demuxername, info.width,
- - info.height, info.interlaced ? 'i' : 'p', info.sar_width, info.sar_height,
- - info.fps_num, info.fps_den, info.vfr ? 'v' : 'c' );
- + x264_cli_log( demuxername, X264_LOG_INFO, "%dx%d%c %d:%d @ %d/%d fps (%cfr)\n", info.width,
- + info.height, info.interlaced ? 'i' : 'p', info.sar_width, info.sar_height,
- + info.fps_num, info.fps_den, info.vfr ? 'v' : 'c' );
- if( tcfile_name )
- {
- - if( b_user_fps )
- - {
- - fprintf( stderr, "x264 [error]: --fps + --tcfile-in is incompatible.\n" );
- - return -1;
- - }
- - if( timecode_input.open_file( tcfile_name, &opt->hin, &info, &input_opt ) )
- - {
- - fprintf( stderr, "x264 [error]: timecode input failed\n" );
- - return -1;
- - }
- - else
- - input = timecode_input;
- - }
- - else if( !info.vfr && input_opt.timebase )
- - {
- - fprintf( stderr, "x264 [error]: --timebase is incompatible with cfr input\n" );
- - return -1;
- + FAIL_IF_ERROR( b_user_fps, "--fps + --tcfile-in is incompatible.\n" )
- + FAIL_IF_ERROR( timecode_input.open_file( tcfile_name, &opt->hin, &info, &input_opt ), "timecode input failed\n" )
- + input = timecode_input;
- }
- + else FAIL_IF_ERROR( !info.vfr && input_opt.timebase, "--timebase is incompatible with cfr input\n" )
- /* set param flags from the info flags as necessary */
- param->i_csp = info.csp;
- @@ -1204,9 +1215,9 @@ generic_option:
- param->i_width = info.width;
- if( !b_user_interlaced && info.interlaced )
- {
- - fprintf( stderr, "x264 [warning]: input appears to be interlaced, enabling %cff interlaced mode.\n"
- - " If you want otherwise, use --no-interlaced or --%cff\n",
- - info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
- + x264_cli_log( "x264", X264_LOG_WARNING, "input appears to be interlaced, enabling %cff interlaced mode.\n"
- + " If you want otherwise, use --no-interlaced or --%cff\n",
- + info.tff ? 't' : 'b', info.tff ? 'b' : 't' );
- param->b_interlaced = 1;
- param->b_tff = !!info.tff;
- }
- @@ -1230,21 +1241,14 @@ generic_option:
- uint64_t i_user_timebase_num;
- uint64_t i_user_timebase_den;
- int ret = sscanf( input_opt.timebase, "%"SCNu64"/%"SCNu64, &i_user_timebase_num, &i_user_timebase_den );
- - if( !ret )
- - {
- - fprintf( stderr, "x264 [error]: invalid argument: timebase = %s\n", input_opt.timebase );
- - return -1;
- - }
- + FAIL_IF_ERROR( !ret, "invalid argument: timebase = %s\n", input_opt.timebase )
- else if( ret == 1 )
- {
- i_user_timebase_num = param->i_timebase_num;
- i_user_timebase_den = strtoul( input_opt.timebase, NULL, 10 );
- }
- - if( i_user_timebase_num > UINT32_MAX || i_user_timebase_den > UINT32_MAX )
- - {
- - fprintf( stderr, "x264 [error]: timebase you specified exceeds H.264 maximum\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( i_user_timebase_num > UINT32_MAX || i_user_timebase_den > UINT32_MAX,
- + "timebase you specified exceeds H.264 maximum\n" )
- opt->timebase_convert_multiplier = ((double)i_user_timebase_den / param->i_timebase_den)
- * ((double)param->i_timebase_num / i_user_timebase_num);
- param->i_timebase_num = i_user_timebase_num;
- @@ -1261,13 +1265,8 @@ generic_option:
- if( b_thread_input || param->i_threads > 1
- || (param->i_threads == X264_THREADS_AUTO && x264_cpu_num_processors() > 1) )
- {
- - if( thread_input.open_file( NULL, &opt->hin, &info, NULL ) )
- - {
- - fprintf( stderr, "x264 [error]: threaded input failed\n" );
- - return -1;
- - }
- - else
- - input = thread_input;
- + FAIL_IF_ERROR( thread_input.open_file( NULL, &opt->hin, &info, NULL ), "threaded input failed\n" )
- + input = thread_input;
- }
- #endif
- @@ -1321,7 +1320,7 @@ static void parse_qpfile( cli_opt_t *opt, x264_picture_t *pic, int i_frame )
- else ret = 0;
- if( ret != 3 || qp < -1 || qp > 51 )
- {
- - fprintf( stderr, "x264 [error]: can't parse qpfile for frame %d\n", i_frame );
- + x264_cli_log( "x264", X264_LOG_ERROR, "can't parse qpfile for frame %d\n", i_frame );
- fclose( opt->qpfile );
- opt->qpfile = NULL;
- pic->i_type = X264_TYPE_AUTO;
- @@ -1344,11 +1343,7 @@ static int Encode_frame( x264_t *h, hnd_t hout, x264_picture_t *pic, int64_t *l
- i_frame_size = x264_encoder_encode( h, &nal, &i_nal, pic, &pic_out );
- - if( i_frame_size < 0 )
- - {
- - fprintf( stderr, "x264 [error]: x264_encoder_encode failed\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( i_frame_size < 0, "x264_encoder_encode failed\n" );
- if( i_frame_size )
- {
- @@ -1424,17 +1419,14 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- param->b_pic_struct = 1;
- pulldown = &pulldown_values[opt->i_pulldown];
- param->i_timebase_num = param->i_fps_den;
- - if( fmod( param->i_fps_num * pulldown->fps_factor, 1 ) )
- - {
- - fprintf( stderr, "x264 [error]: unsupported framerate for chosen pulldown\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( fmod( param->i_fps_num * pulldown->fps_factor, 1 ),
- + "unsupported framerate for chosen pulldown\n" )
- param->i_timebase_den = param->i_fps_num * pulldown->fps_factor;
- }
- if( ( h = x264_encoder_open( param ) ) == NULL )
- {
- - fprintf( stderr, "x264 [error]: x264_encoder_open failed\n" );
- + x264_cli_log( "x264", X264_LOG_ERROR, "x264_encoder_open failed\n" );
- input.close_file( opt->hin );
- return -1;
- }
- @@ -1445,27 +1437,19 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- if( output.set_param( opt->hout, param ) )
- {
- - fprintf( stderr, "x264 [error]: can't set outfile param\n" );
- + x264_cli_log( "x264", X264_LOG_ERROR, "can't set outfile param\n" );
- input.close_file( opt->hin );
- output.close_file( opt->hout, largest_pts, second_largest_pts );
- return -1;
- }
- /* Create a new pic */
- - if( input.picture_alloc( &pic, param->i_csp, param->i_width, param->i_height ) )
- - {
- - fprintf( stderr, "x264 [error]: malloc failed\n" );
- - return -1;
- - }
- + FAIL_IF_ERROR( input.picture_alloc( &pic, param->i_csp, param->i_width, param->i_height ), "malloc failed\n" )
- i_start = x264_mdate();
- /* ticks/frame = ticks/second / frames/second */
- ticks_per_frame = (int64_t)param->i_timebase_den * param->i_fps_den / param->i_timebase_num / param->i_fps_num;
- - if( ticks_per_frame < 1 )
- - {
- - fprintf( stderr, "x264 [error]: ticks_per_frame invalid: %"PRId64"\n", ticks_per_frame );
- - return -1;
- - }
- + FAIL_IF_ERROR( ticks_per_frame < 1, "ticks_per_frame invalid: %"PRId64"\n", ticks_per_frame )
- if( !param->b_repeat_headers )
- {
- @@ -1473,12 +1457,7 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- x264_nal_t *headers;
- int i_nal;
- - if( x264_encoder_headers( h, &headers, &i_nal ) < 0 )
- - {
- - fprintf( stderr, "x264 [error]: x264_encoder_headers failed\n" );
- - return -1;
- - }
- -
- + FAIL_IF_ERROR( x264_encoder_headers( h, &headers, &i_nal ) < 0, "x264_encoder_headers failed\n" )
- if( (i_file = output.write_headers( opt->hout, headers )) < 0 )
- return -1;
- }
- @@ -1508,15 +1487,12 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- if( pic.i_pts <= largest_pts )
- {
- - if( param->i_log_level >= X264_LOG_WARNING )
- - {
- - if( param->i_log_level >= X264_LOG_DEBUG || pts_warning_cnt < MAX_PTS_WARNING )
- - fprintf( stderr, "x264 [warning]: non-strictly-monotonic pts at frame %d (%"PRId64" <= %"PRId64")\n",
- + if( cli_log_level >= X264_LOG_DEBUG || pts_warning_cnt < MAX_PTS_WARNING )
- + x264_cli_log( "x264", X264_LOG_WARNING, "non-strictly-monotonic pts at frame %d (%"PRId64" <= %"PRId64")\n",
- i_frame, output_pts, largest_pts * dts_compress_multiplier );
- - else if( pts_warning_cnt == MAX_PTS_WARNING )
- - fprintf( stderr, "x264 [warning]: too many nonmonotonic pts warnings, suppressing further ones\n" );
- - pts_warning_cnt++;
- - }
- + else if( pts_warning_cnt == MAX_PTS_WARNING )
- + x264_cli_log( "x264", X264_LOG_WARNING, "too many nonmonotonic pts warnings, suppressing further ones\n" );
- + pts_warning_cnt++;
- pic.i_pts = largest_pts + ticks_per_frame;
- output_pts = pic.i_pts * dts_compress_multiplier;
- }
- @@ -1573,8 +1549,8 @@ static int Encode( x264_param_t *param, cli_opt_t *opt )
- if( opt->b_progress && i_frame_output % i_update_interval == 0 && i_frame_output )
- Print_status( i_start, i_frame_output, i_frame_total, i_file, param, 2 * last_dts - prev_dts - first_dts );
- }
- - if( pts_warning_cnt >= MAX_PTS_WARNING && param->i_log_level < X264_LOG_DEBUG )
- - fprintf( stderr, "x264 [warning]: %d suppressed nonmonotonic pts warnings\n", pts_warning_cnt-MAX_PTS_WARNING );
- + if( pts_warning_cnt >= MAX_PTS_WARNING && cli_log_level < X264_LOG_DEBUG )
- + x264_cli_log( "x264", X264_LOG_WARNING, "%d suppressed nonmonotonic pts warnings\n", pts_warning_cnt-MAX_PTS_WARNING );
- /* duration algorithm fails when only 1 frame is output */
- if( i_frame_output == 1 )
- diff --git a/x264cli.h b/x264cli.h
- new file mode 100644
- index 0000000..1acca56
- --- /dev/null
- +++ b/x264cli.h
- @@ -0,0 +1,67 @@
- +/*****************************************************************************
- + * x264cli.h: x264cli common
- + *****************************************************************************
- + * Copyright (C) 2003-2010 x264 project
- + *
- + * Authors: Laurent Aimar <fenrir@via.ecp.fr>
- + * Loren Merritt <lorenm@u.washington.edu>
- + *
- + * This program is free software; you can redistribute it and/or modify
- + * it under the terms of the GNU General Public License as published by
- + * the Free Software Foundation; either version 2 of the License, or
- + * (at your option) any later version.
- + *
- + * This program is distributed in the hope that it will be useful,
- + * but WITHOUT ANY WARRANTY; without even the implied warranty of
- + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- + * GNU General Public License for more details.
- + *
- + * You should have received a copy of the GNU General Public License
- + * along with this program; if not, write to the Free Software
- + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111, USA.
- + *****************************************************************************/
- +
- +#ifndef X264_CLI_H
- +#define X264_CLI_H
- +
- +#include "common/common.h"
- +
- +typedef void *hnd_t;
- +
- +static inline int64_t gcd( int64_t a, int64_t b )
- +{
- + while( 1 )
- + {
- + int64_t c = a % b;
- + if( !c )
- + return b;
- + a = b;
- + b = c;
- + }
- +}
- +
- +static inline int64_t lcm( int64_t a, int64_t b )
- +{
- + return ( a / gcd( a, b ) ) * b;
- +}
- +
- +static inline char *get_filename_extension( char *filename )
- +{
- + char *ext = filename + strlen( filename );
- + while( *ext != '.' && ext > filename )
- + ext--;
- + ext += *ext == '.';
- + return ext;
- +}
- +
- +void x264_cli_log( const char *name, int i_level, const char *fmt, ... );
- +void x264_cli_printf( int i_level, const char *fmt, ... );
- +
- +#define FAIL_IF_ERR( cond, name, ... )\
- +if( cond )\
- +{\
- + x264_cli_log( name, X264_LOG_ERROR, __VA_ARGS__ );\
- + return -1;\
- +}
- +
- +#endif
- --
- 1.7.0.4
- From 871bc451d34daf6fb85dad3a9ababa1513ec2333 Mon Sep 17 00:00:00 2001
- From: Jason Garrett-Glaser <darkshikari@gmail.com>
- Date: Wed, 30 Jun 2010 13:06:22 -0700
- Subject: [PATCH 5/6] Don't check i16x16 planar mode unless previous modes were useful
- Saves ~160 clocks per MB at subme=1, ~270 per MB at subme>1 (measured on Core i7).
- Negligle effect on compression.
- ---
- encoder/analyse.c | 27 ++++++++++++++++++---------
- 1 files changed, 18 insertions(+), 9 deletions(-)
- diff --git a/encoder/analyse.c b/encoder/analyse.c
- index 696c78f..eea464a 100644
- --- a/encoder/analyse.c
- +++ b/encoder/analyse.c
- @@ -646,16 +646,27 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
- /* 16x16 prediction selection */
- const int8_t *predict_mode = predict_16x16_mode_available( h->mb.i_neighbour_intra );
- + /* Not heavily tuned */
- + const uint8_t i16x16_thresh_lut[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
- + int i16x16_thresh = a->b_fast_intra ? (i16x16_thresh_lut[h->mb.i_subpel_refine]*i_satd_inter)>>1 : COST_MAX;
- +
- if( !h->mb.b_lossless && predict_mode[3] >= 0 )
- {
- h->pixf.intra_mbcmp_x3_16x16( p_src, p_dst, a->i_satd_i16x16_dir );
- - h->predict_16x16[I_PRED_16x16_P]( p_dst );
- - a->i_satd_i16x16_dir[I_PRED_16x16_P] =
- - h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
- - for( int i = 0; i < 4; i++ )
- + a->i_satd_i16x16_dir[0] += lambda * bs_size_ue(0);
- + a->i_satd_i16x16_dir[1] += lambda * bs_size_ue(1);
- + a->i_satd_i16x16_dir[2] += lambda * bs_size_ue(2);
- + COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[0], a->i_predict16x16, 0 );
- + COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[1], a->i_predict16x16, 1 );
- + COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[2], a->i_predict16x16, 2 );
- +
- + /* Plane is expensive, so don't check it unless one of the previous modes was useful. */
- + if( a->i_satd_i16x16 <= i16x16_thresh )
- {
- - int cost = a->i_satd_i16x16_dir[i] += lambda * bs_size_ue(i);
- - COPY2_IF_LT( a->i_satd_i16x16, cost, a->i_predict16x16, i );
- + h->predict_16x16[I_PRED_16x16_P]( p_dst );
- + a->i_satd_i16x16_dir[I_PRED_16x16_P] = h->pixf.mbcmp[PIXEL_16x16]( p_dst, FDEC_STRIDE, p_src, FENC_STRIDE );
- + a->i_satd_i16x16_dir[I_PRED_16x16_P] += lambda * bs_size_ue(3);
- + COPY2_IF_LT( a->i_satd_i16x16, a->i_satd_i16x16_dir[I_PRED_16x16_P], a->i_predict16x16, 3 );
- }
- }
- else
- @@ -681,9 +692,7 @@ static void x264_mb_analyse_intra( x264_t *h, x264_mb_analysis_t *a, int i_satd_
- /* cavlc mb type prefix */
- a->i_satd_i16x16 += lambda * i_mb_b_cost_table[I_16x16];
- - /* Not heavily tuned */
- - const uint8_t i16x16_thresh[11] = { 2, 2, 2, 3, 3, 4, 4, 4, 4, 4, 4 };
- - if( a->b_fast_intra && a->i_satd_i16x16 > (i16x16_thresh[h->mb.i_subpel_refine]*i_satd_inter)>>1 )
- + if( a->i_satd_i16x16 > i16x16_thresh )
- return;
- /* 8x8 prediction selection */
- --
- 1.7.0.4
- From 51473258b14b935b2963914c2367446aea775631 Mon Sep 17 00:00:00 2001
- From: Jason Garrett-Glaser <darkshikari@gmail.com>
- Date: Wed, 30 Jun 2010 13:55:46 -0700
- Subject: [PATCH 6/6] Support infinite keyint (--keyint infinite).
- This just means x264 won't insert non-scenecut keyframes.
- Useful for streaming when using interactive error recovery or some other mechanism that makes keyframes unnecessary.
- Also change POC logic to limit POC/framenum LSB size (to save bits per slice).
- Also fix a bug in the CPB underflow detection code (didn't affect the bitstream, just resulted in the failure to print certain warning messages).
- ---
- common/common.c | 7 ++++---
- encoder/encoder.c | 8 ++++----
- encoder/ratecontrol.c | 10 +++++-----
- encoder/set.c | 29 +++++++++++++++++------------
- encoder/slicetype.c | 2 +-
- x264.c | 2 +-
- x264.h | 3 ++-
- 7 files changed, 34 insertions(+), 27 deletions(-)
- diff --git a/common/common.c b/common/common.c
- index 8c7cf3c..14dd716 100644
- --- a/common/common.c
- +++ b/common/common.c
- @@ -638,9 +638,10 @@ int x264_param_parse( x264_param_t *p, const char *name, const char *value )
- p->i_dpb_size = atoi(value);
- OPT("keyint")
- {
- - p->i_keyint_max = atoi(value);
- - if( p->i_keyint_min > p->i_keyint_max )
- - p->i_keyint_min = p->i_keyint_max;
- + if( strstr( value, "infinite" ) )
- + p->i_keyint_max = X264_KEYINT_MAX_INFINITE;
- + else
- + p->i_keyint_max = atoi(value);
- }
- OPT2("min-keyint", "keyint-min")
- {
- diff --git a/encoder/encoder.c b/encoder/encoder.c
- index 5cd3307..31cb84a 100644
- --- a/encoder/encoder.c
- +++ b/encoder/encoder.c
- @@ -567,8 +567,7 @@ static int x264_validate_parameters( x264_t *h )
- h->param.i_frame_reference = x264_clip3( h->param.i_frame_reference, 1, 16 );
- h->param.i_dpb_size = x264_clip3( h->param.i_dpb_size, 1, 16 );
- - if( h->param.i_keyint_max <= 0 )
- - h->param.i_keyint_max = 1;
- + h->param.i_keyint_max = x264_clip3( h->param.i_keyint_max, 1, X264_KEYINT_MAX_INFINITE );
- if( h->param.i_scenecut_threshold < 0 )
- h->param.i_scenecut_threshold = 0;
- if( !h->param.analyse.i_subpel_refine && h->param.analyse.i_direct_mv_pred > X264_DIRECT_PRED_SPATIAL )
- @@ -627,9 +626,10 @@ static int x264_validate_parameters( x264_t *h )
- h->param.rc.f_qcompress = x264_clip3f( h->param.rc.f_qcompress, 0.0, 1.0 );
- if( h->param.i_keyint_max == 1 || h->param.rc.f_qcompress == 1 )
- h->param.rc.b_mb_tree = 0;
- - if( !h->param.rc.i_lookahead && !h->param.b_intra_refresh && h->param.rc.b_mb_tree )
- + if( (!h->param.b_intra_refresh && h->param.i_keyint_max != X264_KEYINT_MAX_INFINITE) &&
- + !h->param.rc.i_lookahead && h->param.rc.b_mb_tree )
- {
- - x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh\n" );
- + x264_log( h, X264_LOG_WARNING, "lookaheadless mb-tree requires intra refresh or infinite keyint\n" );
- h->param.rc.b_mb_tree = 0;
- }
- if( h->param.rc.b_stat_read )
- diff --git a/encoder/ratecontrol.c b/encoder/ratecontrol.c
- index 1030ef2..6fdaa98 100644
- --- a/encoder/ratecontrol.c
- +++ b/encoder/ratecontrol.c
- @@ -492,13 +492,13 @@ void x264_ratecontrol_init_reconfigurable( x264_t *h, int b_init )
- // arbitrary
- #define MAX_DURATION 0.5
- - 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;
- + 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 );
- 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;
- 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);
- h->sps->vui.hrd.i_initial_cpb_removal_delay_length = 2 + x264_clip3( 32 - x264_clz( max_delay ), 4, 22 );
- - h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 32 );
- - h->sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 32 );
- + h->sps->vui.hrd.i_cpb_removal_delay_length = x264_clip3( 32 - x264_clz( max_cpb_output_delay ), 4, 31 );
- + h->sps->vui.hrd.i_dpb_output_delay_length = x264_clip3( 32 - x264_clz( max_dpb_output_delay ), 4, 31 );
- #undef MAX_DURATION
- @@ -1781,10 +1781,10 @@ void x264_hrd_fullness( x264_t *h )
- uint64_t cpb_size = (uint64_t)h->sps->vui.hrd.i_cpb_size_unscaled * h->sps->vui.i_time_scale;
- uint64_t multiply_factor = 180000 / rct->hrd_multiply_denom;
- - if( cpb_state < 0 || cpb_state > cpb_size )
- + if( rct->buffer_fill_final < 0 || rct->buffer_fill_final > cpb_size )
- {
- x264_log( h, X264_LOG_WARNING, "CPB %s: %.0lf bits in a %.0lf-bit buffer\n",
- - cpb_state < 0 ? "underflow" : "overflow", (float)cpb_state/denom, (float)cpb_size/denom );
- + rct->buffer_fill_final < 0 ? "underflow" : "overflow", (float)rct->buffer_fill_final/denom, (float)cpb_size/denom );
- }
- h->initial_cpb_removal_delay = (multiply_factor * cpb_state + denom) / (2*denom);
- diff --git a/encoder/set.c b/encoder/set.c
- index 8d007aa..84077cb 100644
- --- a/encoder/set.c
- +++ b/encoder/set.c
- @@ -99,6 +99,7 @@ static void x264_sei_write( bs_t *s, uint8_t *p_start )
- void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- {
- sps->i_id = i_id;
- + int max_frame_num;
- sps->b_qpprime_y_zero_transform_bypass = param->rc.i_rc_method == X264_RC_CQP && param->rc.i_qp_constant == 0;
- if( sps->b_qpprime_y_zero_transform_bypass )
- @@ -118,15 +119,27 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- /* Never set constraint_set2, it is not necessary and not used in real world. */
- sps->b_constraint_set2 = 0;
- - sps->i_log2_max_frame_num = 4; /* at least 4 */
- - while( (1 << sps->i_log2_max_frame_num) <= param->i_keyint_max && sps->i_log2_max_frame_num < 10 )
- + sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
- + /* extra slot with pyramid so that we don't have to override the
- + * order of forgetting old pictures */
- + sps->vui.i_max_dec_frame_buffering =
- + sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
- + param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
- + sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
- +
- + /* number of refs + current frame */
- + max_frame_num = sps->vui.i_max_dec_frame_buffering * (!!param->i_bframe_pyramid+1) + 1;
- + sps->i_log2_max_frame_num = 4;
- + while( (1 << sps->i_log2_max_frame_num) < max_frame_num )
- sps->i_log2_max_frame_num++;
- - sps->i_log2_max_frame_num++;
- sps->i_poc_type = 0;
- if( sps->i_poc_type == 0 )
- {
- - sps->i_log2_max_poc_lsb = sps->i_log2_max_frame_num + 1; /* max poc = 2*frame_num */
- + int max_delta_poc = (param->i_bframe + 2) * 2;
- + sps->i_log2_max_poc_lsb = 4;
- + while( (1 << sps->i_log2_max_frame_num) <= max_delta_poc * 2 )
- + sps->i_log2_max_poc_lsb++;
- }
- else if( sps->i_poc_type == 1 )
- {
- @@ -219,14 +232,6 @@ void x264_sps_init( x264_sps_t *sps, int i_id, x264_param_t *param )
- // NOTE: HRD related parts of the SPS are initialised in x264_ratecontrol_init_reconfigurable
- - sps->vui.i_num_reorder_frames = param->i_bframe_pyramid ? 2 : param->i_bframe ? 1 : 0;
- - /* extra slot with pyramid so that we don't have to override the
- - * order of forgetting old pictures */
- - sps->vui.i_max_dec_frame_buffering =
- - sps->i_num_ref_frames = X264_MIN(16, X264_MAX4(param->i_frame_reference, 1 + sps->vui.i_num_reorder_frames,
- - param->i_bframe_pyramid ? 4 : 1, param->i_dpb_size));
- - sps->i_num_ref_frames -= param->i_bframe_pyramid == X264_B_PYRAMID_STRICT;
- -
- sps->vui.b_bitstream_restriction = 1;
- if( sps->vui.b_bitstream_restriction )
- {
- diff --git a/encoder/slicetype.c b/encoder/slicetype.c
- index 4ede8cf..7d69b71 100644
- --- a/encoder/slicetype.c
- +++ b/encoder/slicetype.c
- @@ -1009,7 +1009,7 @@ static int scenecut_internal( x264_t *h, x264_mb_analysis_t *a, x264_frame_t **f
- float f_thresh_max = h->param.i_scenecut_threshold / 100.0;
- /* magic numbers pulled out of thin air */
- float f_thresh_min = f_thresh_max * h->param.i_keyint_min
- - / ( h->param.i_keyint_max * 4 );
- + / ( h->param.i_keyint_max * 4. );
- int res;
- if( h->param.i_keyint_min == h->param.i_keyint_max )
- diff --git a/x264.c b/x264.c
- index 741570c..0bede93 100644
- --- a/x264.c
- +++ b/x264.c
- @@ -409,7 +409,7 @@ static void Help( x264_param_t *defaults, int longhelp )
- H0( "\n" );
- H0( "Frame-type options:\n" );
- H0( "\n" );
- - H0( " -I, --keyint <integer> Maximum GOP size [%d]\n", defaults->i_keyint_max );
- + H0( " -I, --keyint <integer or \"infinite\"> Maximum GOP size [%d]\n", defaults->i_keyint_max );
- H2( " -i, --min-keyint <integer> Minimum GOP size [auto]\n" );
- H2( " --no-scenecut Disable adaptive I-frame decision\n" );
- H2( " --scenecut <integer> How aggressively to insert extra I-frames [%d]\n", defaults->i_scenecut_threshold );
- diff --git a/x264.h b/x264.h
- index 604ca45..330cf74 100644
- --- a/x264.h
- +++ b/x264.h
- @@ -35,7 +35,7 @@
- #include <stdarg.h>
- -#define X264_BUILD 101
- +#define X264_BUILD 102
- /* x264_t:
- * opaque handler for encoder */
- @@ -152,6 +152,7 @@ typedef struct
- #define X264_B_PYRAMID_STRICT 1
- #define X264_B_PYRAMID_NORMAL 2
- #define X264_KEYINT_MIN_AUTO 0
- +#define X264_KEYINT_MAX_INFINITE (1<<30)
- #define X264_OPEN_GOP_NONE 0
- #define X264_OPEN_GOP_NORMAL 1
- #define X264_OPEN_GOP_BLURAY 2
- --
- 1.7.0.4
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement