diff --git a/Makefile b/Makefile index 63338e8..daf26d6 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ include config.mak SRCS = common/mc.c common/predict.c common/pixel.c common/macroblock.c \ common/frame.c common/dct.c common/cpu.c common/cabac.c \ - common/common.c common/mdate.c common/csp.c common/set.c \ + common/common.c common/mdate.c common/set.c \ common/quant.c \ encoder/analyse.c encoder/me.c encoder/ratecontrol.c \ encoder/set.c encoder/macroblock.c encoder/cabac.c \ diff --git a/common/common.c b/common/common.c index f699d12..44d9113 100644 --- a/common/common.c +++ b/common/common.c @@ -589,63 +589,13 @@ void x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_heig pic->i_type = X264_TYPE_AUTO; pic->i_qpplus1 = 0; pic->img.i_csp = i_csp; - switch( i_csp & X264_CSP_MASK ) - { - case X264_CSP_I420: - case X264_CSP_YV12: - pic->img.i_plane = 3; - pic->img.plane[0] = x264_malloc( 3 * i_width * i_height / 2 ); - pic->img.plane[1] = pic->img.plane[0] + i_width * i_height; - pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 4; - pic->img.i_stride[0] = i_width; - pic->img.i_stride[1] = i_width / 2; - pic->img.i_stride[2] = i_width / 2; - break; - - case X264_CSP_I422: - pic->img.i_plane = 3; - pic->img.plane[0] = x264_malloc( 2 * i_width * i_height ); - pic->img.plane[1] = pic->img.plane[0] + i_width * i_height; - pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 2; - pic->img.i_stride[0] = i_width; - pic->img.i_stride[1] = i_width / 2; - pic->img.i_stride[2] = i_width / 2; - break; - - case X264_CSP_I444: - pic->img.i_plane = 3; - pic->img.plane[0] = x264_malloc( 3 * i_width * i_height ); - pic->img.plane[1] = pic->img.plane[0] + i_width * i_height; - pic->img.plane[2] = pic->img.plane[1] + i_width * i_height; - pic->img.i_stride[0] = i_width; - pic->img.i_stride[1] = i_width; - pic->img.i_stride[2] = i_width; - break; - - case X264_CSP_YUYV: - pic->img.i_plane = 1; - pic->img.plane[0] = x264_malloc( 2 * i_width * i_height ); - pic->img.i_stride[0] = 2 * i_width; - break; - - case X264_CSP_RGB: - case X264_CSP_BGR: - pic->img.i_plane = 1; - pic->img.plane[0] = x264_malloc( 3 * i_width * i_height ); - pic->img.i_stride[0] = 3 * i_width; - break; - - case X264_CSP_BGRA: - pic->img.i_plane = 1; - pic->img.plane[0] = x264_malloc( 4 * i_width * i_height ); - pic->img.i_stride[0] = 4 * i_width; - break; - - default: - fprintf( stderr, "invalid CSP\n" ); - pic->img.i_plane = 0; - break; - } + pic->img.i_plane = 3; + pic->img.plane[0] = x264_malloc( 3 * i_width * i_height / 2 ); + pic->img.plane[1] = pic->img.plane[0] + i_width * i_height; + pic->img.plane[2] = pic->img.plane[1] + i_width * i_height / 4; + pic->img.i_stride[0] = i_width; + pic->img.i_stride[1] = i_width / 2; + pic->img.i_stride[2] = i_width / 2; } /**************************************************************************** diff --git a/common/common.h b/common/common.h index 8860651..11cdbc2 100644 --- a/common/common.h +++ b/common/common.h @@ -76,7 +76,6 @@ #include "frame.h" #include "dct.h" #include "cabac.h" -#include "csp.h" #include "quant.h" /**************************************************************************** @@ -559,7 +558,6 @@ struct x264_t x264_mc_functions_t mc; x264_dct_function_t dctf; x264_zigzag_function_t zigzagf; - x264_csp_function_t csp; x264_quant_function_t quantf; x264_deblock_function_t loopf; diff --git a/common/csp.c b/common/csp.c deleted file mode 100644 index 6813291..0000000 --- a/common/csp.c +++ /dev/null @@ -1,371 +0,0 @@ -/***************************************************************************** - * csp.c: h264 encoder library - ***************************************************************************** - * Copyright (C) 2004 Laurent Aimar - * $Id: csp.c,v 1.1 2004/06/03 19:27:06 fenrir Exp $ - * - * Authors: Laurent Aimar - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - -#include "common.h" - -static inline void plane_copy_vflip( x264_mc_functions_t *mc, - uint8_t *dst, int i_dst, - uint8_t *src, int i_src, int w, int h) -{ - mc->plane_copy( dst, i_dst, src + (h -1)*i_src, -i_src, w, h ); -} - -static inline void plane_subsamplev2( uint8_t *dst, int i_dst, - uint8_t *src, int i_src, int w, int h) -{ - for( ; h > 0; h-- ) - { - uint8_t *d = dst; - uint8_t *s = src; - int i; - for( i = 0; i < w; i++ ) - { - *d++ = ( s[0] + s[i_src] + 1 ) >> 1; - s++; - } - dst += i_dst; - src += 2 * i_src; - } -} - -static inline void plane_subsamplev2_vlip( uint8_t *dst, int i_dst, - uint8_t *src, int i_src, int w, int h) -{ - plane_subsamplev2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h ); -} - -static inline void plane_subsamplehv2( uint8_t *dst, int i_dst, - uint8_t *src, int i_src, int w, int h) -{ - for( ; h > 0; h-- ) - { - uint8_t *d = dst; - uint8_t *s = src; - int i; - for( i = 0; i < w; i++ ) - { - *d++ = ( s[0] + s[1] + s[i_src] + s[i_src+1] + 1 ) >> 2; - s += 2; - } - dst += i_dst; - src += 2 * i_src; - } -} - -static inline void plane_subsamplehv2_vlip( uint8_t *dst, int i_dst, - uint8_t *src, int i_src, int w, int h) -{ - plane_subsamplehv2( dst, i_dst, src + (2*h-1)*i_src, -i_src, w, h ); -} - -static void i420_to_i420( x264_mc_functions_t *mc, - x264_frame_t *frm, x264_image_t *img, - int i_width, int i_height ) -{ - if( img->i_csp & X264_CSP_VFLIP ) - { - plane_copy_vflip( mc, frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - plane_copy_vflip( mc, frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_copy_vflip( mc, frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } - else - { - mc->plane_copy( frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - mc->plane_copy( frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - mc->plane_copy( frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } -} - -static void yv12_to_i420( x264_mc_functions_t *mc, - x264_frame_t *frm, x264_image_t *img, - int i_width, int i_height ) -{ - if( img->i_csp & X264_CSP_VFLIP ) - { - plane_copy_vflip( mc, frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - plane_copy_vflip( mc, frm->plane[2], frm->i_stride[2], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_copy_vflip( mc, frm->plane[1], frm->i_stride[1], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } - else - { - mc->plane_copy( frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - mc->plane_copy( frm->plane[2], frm->i_stride[2], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - mc->plane_copy( frm->plane[1], frm->i_stride[1], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } -} - -static void i422_to_i420( x264_mc_functions_t *mc, - x264_frame_t *frm, x264_image_t *img, - int i_width, int i_height ) -{ - if( img->i_csp & X264_CSP_VFLIP ) - { - plane_copy_vflip( mc, frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - - plane_subsamplev2_vlip( frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_subsamplev2_vlip( frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } - else - { - mc->plane_copy( frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - - plane_subsamplev2( frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_subsamplev2( frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } -} - -static void i444_to_i420( x264_mc_functions_t *mc, - x264_frame_t *frm, x264_image_t *img, - int i_width, int i_height ) -{ - if( img->i_csp & X264_CSP_VFLIP ) - { - plane_copy_vflip( mc, frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - - plane_subsamplehv2_vlip( frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_subsamplehv2_vlip( frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } - else - { - mc->plane_copy( frm->plane[0], frm->i_stride[0], - img->plane[0], img->i_stride[0], - i_width, i_height ); - - plane_subsamplehv2( frm->plane[1], frm->i_stride[1], - img->plane[1], img->i_stride[1], - i_width / 2, i_height / 2 ); - plane_subsamplehv2( frm->plane[2], frm->i_stride[2], - img->plane[2], img->i_stride[2], - i_width / 2, i_height / 2 ); - } -} -static void yuyv_to_i420( x264_mc_functions_t *mc, - x264_frame_t *frm, x264_image_t *img, - int i_width, int i_height ) -{ - uint8_t *src = img->plane[0]; - int i_src= img->i_stride[0]; - - uint8_t *y = frm->plane[0]; - uint8_t *u = frm->plane[1]; - uint8_t *v = frm->plane[2]; - - if( img->i_csp & X264_CSP_VFLIP ) - { - src += ( i_height - 1 ) * i_src; - i_src = -i_src; - } - - for( ; i_height > 0; i_height -= 2 ) - { - uint8_t *ss = src; - uint8_t *yy = y; - uint8_t *uu = u; - uint8_t *vv = v; - int w; - - for( w = i_width; w > 0; w -= 2 ) - { - *yy++ = ss[0]; - *yy++ = ss[2]; - - *uu++ = ( ss[1] + ss[1+i_src] + 1 ) >> 1; - *vv++ = ( ss[3] + ss[3+i_src] + 1 ) >> 1; - - ss += 4; - } - src += i_src; - y += frm->i_stride[0]; - u += frm->i_stride[1]; - v += frm->i_stride[2]; - - ss = src; - yy = y; - for( w = i_width; w > 0; w -= 2 ) - { - *yy++ = ss[0]; - *yy++ = ss[2]; - ss += 4; - } - src += i_src; - y += frm->i_stride[0]; - } -} - -/* Same value than in XviD */ -#define BITS 8 -#define FIX(f) ((int)((f) * (1 << BITS) + 0.5)) - -#define Y_R FIX(0.257) -#define Y_G FIX(0.504) -#define Y_B FIX(0.098) -#define Y_ADD 16 - -#define U_R FIX(0.148) -#define U_G FIX(0.291) -#define U_B FIX(0.439) -#define U_ADD 128 - -#define V_R FIX(0.439) -#define V_G FIX(0.368) -#define V_B FIX(0.071) -#define V_ADD 128 -#define RGB_TO_I420( name, POS_R, POS_G, POS_B, S_RGB ) \ -static void name( x264_mc_functions_t *mc, \ - x264_frame_t *frm, x264_image_t *img, \ - int i_width, int i_height ) \ -{ \ - uint8_t *src = img->plane[0]; \ - int i_src= img->i_stride[0]; \ - int i_y = frm->i_stride[0]; \ - uint8_t *y = frm->plane[0]; \ - uint8_t *u = frm->plane[1]; \ - uint8_t *v = frm->plane[2]; \ - \ - if( img->i_csp & X264_CSP_VFLIP ) \ - { \ - src += ( i_height - 1 ) * i_src; \ - i_src = -i_src; \ - } \ - \ - for( ; i_height > 0; i_height -= 2 ) \ - { \ - uint8_t *ss = src; \ - uint8_t *yy = y; \ - uint8_t *uu = u; \ - uint8_t *vv = v; \ - int w; \ - \ - for( w = i_width; w > 0; w -= 2 ) \ - { \ - int cr = 0,cg = 0,cb = 0; \ - int r, g, b; \ - \ - /* Luma */ \ - cr = r = ss[POS_R]; \ - cg = g = ss[POS_G]; \ - cb = b = ss[POS_B]; \ - \ - yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \ - \ - cr+= r = ss[POS_R+i_src]; \ - cg+= g = ss[POS_G+i_src]; \ - cb+= b = ss[POS_B+i_src]; \ - yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \ - yy++; \ - ss += S_RGB; \ - \ - cr+= r = ss[POS_R]; \ - cg+= g = ss[POS_G]; \ - cb+= b = ss[POS_B]; \ - \ - yy[0] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \ - \ - cr+= r = ss[POS_R+i_src]; \ - cg+= g = ss[POS_G+i_src]; \ - cb+= b = ss[POS_B+i_src]; \ - yy[i_y] = Y_ADD + ((Y_R * r + Y_G * g + Y_B * b) >> BITS); \ - yy++; \ - ss += S_RGB; \ - \ - /* Chroma */ \ - *uu++ = (uint8_t)(U_ADD + ((-U_R * cr - U_G * cg + U_B * cb) >> (BITS+2)) ); \ - *vv++ = (uint8_t)(V_ADD + (( V_R * cr - V_G * cg - V_B * cb) >> (BITS+2)) ); \ - } \ - \ - src += 2*i_src; \ - y += 2*frm->i_stride[0]; \ - u += frm->i_stride[1]; \ - v += frm->i_stride[2]; \ - } \ -} - -RGB_TO_I420( rgb_to_i420, 0, 1, 2, 3 ); -RGB_TO_I420( bgr_to_i420, 2, 1, 0, 3 ); -RGB_TO_I420( bgra_to_i420, 2, 1, 0, 4 ); - -void x264_csp_init( int cpu, int i_csp, x264_csp_function_t *pf ) -{ - switch( i_csp ) - { - case X264_CSP_I420: - pf->convert[X264_CSP_I420] = i420_to_i420; - pf->convert[X264_CSP_I422] = i422_to_i420; - pf->convert[X264_CSP_I444] = i444_to_i420; - pf->convert[X264_CSP_YV12] = yv12_to_i420; - pf->convert[X264_CSP_YUYV] = yuyv_to_i420; - pf->convert[X264_CSP_RGB ] = rgb_to_i420; - pf->convert[X264_CSP_BGR ] = bgr_to_i420; - pf->convert[X264_CSP_BGRA] = bgra_to_i420; - break; - - default: - /* For now, can't happen */ - fprintf( stderr, "arg in x264_csp_init\n" ); - exit( -1 ); - break; - } -} - diff --git a/common/csp.h b/common/csp.h deleted file mode 100644 index 5092afa..0000000 --- a/common/csp.h +++ /dev/null @@ -1,38 +0,0 @@ -/***************************************************************************** - * csp.h: h264 encoder library - ***************************************************************************** - * Copyright (C) 2004 Laurent Aimar - * $Id: csp.h,v 1.1 2004/06/03 19:27:06 fenrir Exp $ - * - * Authors: Laurent Aimar - * - * 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., 59 Temple Place - Suite 330, Boston, MA 02111, USA. - *****************************************************************************/ - -#ifndef _CSP_H -#define _CSP_H 1 - -typedef void (*x264_csp_t) ( x264_mc_functions_t *, x264_frame_t *, x264_image_t *, - int i_width, int i_height ); - -typedef struct -{ - x264_csp_t convert[X264_CSP_MAX]; -} x264_csp_function_t; - -void x264_csp_init( int cpu, int i_csp, x264_csp_function_t *pf ); - -#endif - diff --git a/common/frame.c b/common/frame.c index ce8af34..b5eec92 100644 --- a/common/frame.c +++ b/common/frame.c @@ -52,23 +52,13 @@ x264_frame_t *x264_frame_new( x264_t *h ) frame->i_plane = 3; for( i = 0; i < 3; i++ ) { - int i_divh = 1; - int i_divw = 1; - if( i > 0 ) - { - if( h->param.i_csp == X264_CSP_I420 ) - i_divh = i_divw = 2; - else if( h->param.i_csp == X264_CSP_I422 ) - i_divw = 2; - } - frame->i_stride[i] = i_stride / i_divw; - frame->i_width[i] = i_width / i_divw; - frame->i_lines[i] = i_lines / i_divh; + frame->i_stride[i] = i_stride >> !!i; + frame->i_width[i] = i_width >> !!i; + frame->i_lines[i] = i_lines >> !!i; CHECKED_MALLOC( frame->buffer[i], - frame->i_stride[i] * ( frame->i_lines[i] + 2*i_padv / i_divh ) ); - + frame->i_stride[i] * (i_lines + 2*i_padv) >> !!i ); frame->plane[i] = ((uint8_t*)frame->buffer[i]) + - frame->i_stride[i] * i_padv / i_divh + PADH / i_divw; + ((frame->i_stride[i] * i_padv + PADH) >> !!i); } frame->filtered[0] = frame->plane[0]; @@ -161,17 +151,35 @@ void x264_frame_delete( x264_frame_t *frame ) x264_free( frame ); } -void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ) +int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ) { int i_csp = src->img.i_csp & X264_CSP_MASK; + int i; + if( i_csp != X264_CSP_I420 && i_csp != X264_CSP_YV12 ) + { + x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" ); + return -1; + } + dst->i_type = src->i_type; dst->i_qpplus1 = src->i_qpplus1; dst->i_pts = src->i_pts; - if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX ) - x264_log( h, X264_LOG_ERROR, "Arg invalid CSP\n" ); - else - h->csp.convert[i_csp]( &h->mc, dst, &src->img, h->param.i_width, h->param.i_height ); + for( i=0; i<3; i++ ) + { + int s = (i_csp == X264_CSP_YV12 && i) ? i^3 : i; + uint8_t *plane = src->img.plane[s]; + int stride = src->img.i_stride[s]; + int width = h->param.i_width >> !!i; + int height = h->param.i_height >> !!i; + if( src->img.i_csp & X264_CSP_VFLIP ) + { + plane += (height-1)*stride; + stride = -stride; + } + h->mc.plane_copy( dst->plane[i], dst->i_stride[i], plane, stride, width, height ); + } + return 0; } diff --git a/common/frame.h b/common/frame.h index 0e698fd..e7693af 100644 --- a/common/frame.h +++ b/common/frame.h @@ -102,7 +102,7 @@ typedef struct x264_frame_t *x264_frame_new( x264_t *h ); void x264_frame_delete( x264_frame_t *frame ); -void x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ); +int x264_frame_copy_picture( x264_t *h, x264_frame_t *dst, x264_picture_t *src ); void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_end ); void x264_frame_expand_border_filtered( x264_t *h, x264_frame_t *frame, int mb_y, int b_end ); diff --git a/encoder/encoder.c b/encoder/encoder.c index b7baf93..5ab0ad8 100644 --- a/encoder/encoder.c +++ b/encoder/encoder.c @@ -671,7 +671,6 @@ x264_t *x264_encoder_open ( x264_param_t *param ) x264_dct_init( h->param.cpu, &h->dctf ); x264_zigzag_init( h->param.cpu, &h->zigzagf, h->param.b_interlaced ); x264_mc_init( h->param.cpu, &h->mc ); - x264_csp_init( h->param.cpu, h->param.i_csp, &h->csp ); x264_quant_init( h, h->param.cpu, &h->quantf ); x264_deblock_init( h->param.cpu, &h->loopf ); x264_dct_init_weights(); @@ -1290,7 +1289,8 @@ int x264_encoder_encode( x264_t *h, /* 1: Copy the picture to a frame and move it to a buffer */ x264_frame_t *fenc = x264_frame_pop_unused( h ); - x264_frame_copy_picture( h, fenc, pic_in ); + if( x264_frame_copy_picture( h, fenc, pic_in ) < 0 ) + return -1; if( h->param.i_width != 16 * h->sps->i_mb_width || h->param.i_height != 16 * h->sps->i_mb_height ) diff --git a/x264.h b/x264.h index f4fd1d1..70c9eaf 100644 --- a/x264.h +++ b/x264.h @@ -35,7 +35,7 @@ #include -#define X264_BUILD 57 +#define X264_BUILD 58 /* x264_t: * opaque handler for encoder */ @@ -93,6 +93,7 @@ static const char * const x264_transfer_names[] = { "", "bt709", "undef", "", "b static const char * const x264_colmatrix_names[] = { "GBR", "bt709", "undef", "", "fcc", "bt470bg", "smpte170m", "smpte240m", "YCgCo", 0 }; /* Colorspace type + * legacy only; nothing other than I420 is really supported. */ #define X264_CSP_MASK 0x00ff /* */ #define X264_CSP_NONE 0x0000 /* Invalid mode */