/*****************************************************************************
* frame.c: frame handling
*****************************************************************************
- * Copyright (C) 2003-2011 x264 project
+ * Copyright (C) 2003-2012 x264 project
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Loren Merritt <lorenm@u.washington.edu>
case X264_CSP_I420:
case X264_CSP_YV12:
return X264_CSP_NV12;
+ case X264_CSP_NV16:
+ case X264_CSP_I422:
+ case X264_CSP_YV16:
+ return X264_CSP_NV16;
case X264_CSP_I444:
case X264_CSP_YV24:
case X264_CSP_BGR:
x264_frame_t *frame;
int i_csp = x264_frame_internal_csp( h->param.i_csp );
int i_mb_count = h->mb.i_mb_count;
- int i_stride, i_width, i_lines;
+ int i_stride, i_width, i_lines, luma_plane_count;
int i_padv = PADV << PARAM_INTERLACED;
int align = h->param.cpu&X264_CPU_CACHELINE_64 ? 64 : h->param.cpu&X264_CPU_CACHELINE_32 ? 32 : 16;
int disalign = h->param.cpu&X264_CPU_ALTIVEC ? 1<<9 : 1<<10;
- int luma_plane_count = i_csp == X264_CSP_NV12 ? 1 : 3;
CHECKED_MALLOCZERO( frame, sizeof(x264_frame_t) );
i_lines = h->mb.i_mb_height*16;
i_stride = align_stride( i_width + 2*PADH, align, disalign );
- if( i_csp == X264_CSP_NV12 )
+ if( i_csp == X264_CSP_NV12 || i_csp == X264_CSP_NV16 )
{
+ luma_plane_count = 1;
frame->i_plane = 2;
for( int i = 0; i < 2; i++ )
{
frame->i_width[i] = i_width >> i;
- frame->i_lines[i] = i_lines >> i;
+ frame->i_lines[i] = i_lines >> (i && i_csp == X264_CSP_NV12);
frame->i_stride[i] = i_stride;
}
}
else if( i_csp == X264_CSP_I444 )
{
+ luma_plane_count = 3;
frame->i_plane = 3;
for( int i = 0; i < 3; i++ )
{
frame->orig = frame;
- if( i_csp == X264_CSP_NV12 )
+ if( i_csp == X264_CSP_NV12 || i_csp == X264_CSP_NV16 )
{
- int chroma_plane_size = (frame->i_stride[1] * (frame->i_lines[1] + i_padv));
+ int chroma_padv = i_padv >> (i_csp == X264_CSP_NV12);
+ int chroma_plane_size = (frame->i_stride[1] * (frame->i_lines[1] + 2*chroma_padv));
CHECKED_MALLOC( frame->buffer[1], chroma_plane_size * sizeof(pixel) );
- frame->plane[1] = frame->buffer[1] + frame->i_stride[1] * i_padv/2 + PADH;
+ frame->plane[1] = frame->buffer[1] + frame->i_stride[1] * chroma_padv + PADH;
if( PARAM_INTERLACED )
{
CHECKED_MALLOC( frame->buffer_fld[1], chroma_plane_size * sizeof(pixel) );
- frame->plane_fld[1] = frame->buffer_fld[1] + frame->i_stride[1] * i_padv/2 + PADH;
+ frame->plane_fld[1] = frame->buffer_fld[1] + frame->i_stride[1] * chroma_padv + PADH;
}
}
}
if( PARAM_INTERLACED )
CHECKED_MALLOC( frame->field, i_mb_count * sizeof(uint8_t) );
+ if( h->param.analyse.b_mb_info )
+ CHECKED_MALLOC( frame->effective_qp, i_mb_count * sizeof(uint8_t) );
}
else /* fenc frame */
{
x264_free( frame->f_row_qp );
x264_free( frame->f_row_qscale );
x264_free( frame->field );
+ x264_free( frame->effective_qp );
x264_free( frame->mb_type );
x264_free( frame->mb_partition );
x264_free( frame->mv[0] );
x264_free( frame->mv16x16-1 );
x264_free( frame->ref[0] );
x264_free( frame->ref[1] );
+ if( frame->param && frame->param->param_free )
+ frame->param->param_free( frame->param );
+ if( frame->mb_info_free )
+ frame->mb_info_free( frame->mb_info );
+ if( frame->extra_sei.sei_free )
+ {
+ for( int i = 0; i < frame->extra_sei.num_payloads; i++ )
+ frame->extra_sei.sei_free( frame->extra_sei.payloads[i].payload );
+ frame->extra_sei.sei_free( frame->extra_sei.payloads );
+ }
x264_pthread_mutex_destroy( &frame->mutex );
x264_pthread_cond_destroy( &frame->cv );
}
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;
- if( i_csp <= X264_CSP_NONE || i_csp >= X264_CSP_MAX )
+ if( dst->i_csp != x264_frame_internal_csp( i_csp ) )
{
x264_log( h, X264_LOG_ERROR, "Invalid input colorspace\n" );
return -1;
dst->param = src->param;
dst->i_pic_struct = src->i_pic_struct;
dst->extra_sei = src->extra_sei;
+ dst->opaque = src->opaque;
+ dst->mb_info = h->param.analyse.b_mb_info ? src->prop.mb_info : NULL;
+ dst->mb_info_free = h->param.analyse.b_mb_info ? src->prop.mb_info_free : NULL;
uint8_t *pix[3];
int stride[3];
pix[0] += (h->param.i_height-1) * stride[0];
stride[0] = -stride[0];
}
- int b = i_csp==X264_CSP_RGB ? 2 : 0;
- h->mc.plane_copy_deinterleave_rgb( dst->plane[1], dst->i_stride[1],
- dst->plane[b], dst->i_stride[b],
+ int b = i_csp==X264_CSP_RGB;
+ h->mc.plane_copy_deinterleave_rgb( dst->plane[1+b], dst->i_stride[1+b],
+ dst->plane[0], dst->i_stride[0],
dst->plane[2-b], dst->i_stride[2-b],
(pixel*)pix[0], stride[0]/sizeof(pixel), i_csp==X264_CSP_BGRA ? 4 : 3, h->param.i_width, h->param.i_height );
}
else
{
+ int v_shift = CHROMA_V_SHIFT;
get_plane_ptr( h, src, &pix[0], &stride[0], 0, 0, 0 );
h->mc.plane_copy( dst->plane[0], dst->i_stride[0], (pixel*)pix[0],
stride[0]/sizeof(pixel), h->param.i_width, h->param.i_height );
- if( i_csp == X264_CSP_NV12 )
+ if( i_csp == X264_CSP_NV12 || i_csp == X264_CSP_NV16 )
{
- get_plane_ptr( h, src, &pix[1], &stride[1], 1, 0, 1 );
+ get_plane_ptr( h, src, &pix[1], &stride[1], 1, 0, v_shift );
h->mc.plane_copy( dst->plane[1], dst->i_stride[1], (pixel*)pix[1],
- stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height>>1 );
+ stride[1]/sizeof(pixel), h->param.i_width, h->param.i_height>>v_shift );
}
- else if( i_csp == X264_CSP_I420 || i_csp == X264_CSP_YV12 )
+ else if( i_csp == X264_CSP_I420 || i_csp == X264_CSP_I422 || i_csp == X264_CSP_YV12 || i_csp == X264_CSP_YV16 )
{
- get_plane_ptr( h, src, &pix[1], &stride[1], i_csp==X264_CSP_I420 ? 1 : 2, 1, 1 );
- get_plane_ptr( h, src, &pix[2], &stride[2], i_csp==X264_CSP_I420 ? 2 : 1, 1, 1 );
+ int uv_swap = i_csp == X264_CSP_YV12 || i_csp == X264_CSP_YV16;
+ get_plane_ptr( h, src, &pix[1], &stride[1], uv_swap ? 2 : 1, 1, v_shift );
+ get_plane_ptr( h, src, &pix[2], &stride[2], uv_swap ? 1 : 2, 1, v_shift );
h->mc.plane_copy_interleave( dst->plane[1], dst->i_stride[1],
(pixel*)pix[1], stride[1]/sizeof(pixel),
(pixel*)pix[2], stride[2]/sizeof(pixel),
- h->param.i_width>>1, h->param.i_height>>1 );
+ h->param.i_width>>1, h->param.i_height>>v_shift );
}
else //if( i_csp == X264_CSP_I444 || i_csp == X264_CSP_YV24 )
{
static void ALWAYS_INLINE pixel_memset( pixel *dst, pixel *src, int len, int size )
{
uint8_t *dstp = (uint8_t*)dst;
- uint8_t v1 = *src;
- uint16_t v2 = size == 1 ? v1 + (v1 << 8) : M16( src );
+ uint32_t v1 = *src;
+ uint32_t v2 = size == 1 ? v1 + (v1 << 8) : M16( src );
uint32_t v4 = size <= 2 ? v2 + (v2 << 16) : M32( src );
int i = 0;
len *= size;
#undef PPIXEL
}
-void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y, int b_end )
+void x264_frame_expand_border( x264_t *h, x264_frame_t *frame, int mb_y )
{
- int b_start = !mb_y;
+ int pad_top = mb_y == 0;
+ int pad_bot = mb_y == h->mb.i_mb_height - (1 << SLICE_MBAFF);
+ int b_start = mb_y == h->i_threadslice_start;
+ int b_end = mb_y == h->i_threadslice_end - (1 << SLICE_MBAFF);
if( mb_y & SLICE_MBAFF )
return;
for( int i = 0; i < frame->i_plane; i++ )
{
- int shift = i && !CHROMA444;
+ int h_shift = i && CHROMA_H_SHIFT;
+ int v_shift = i && CHROMA_V_SHIFT;
int stride = frame->i_stride[i];
int width = 16*h->mb.i_mb_width;
- int height = (b_end ? 16*(h->mb.i_mb_height - mb_y) >> SLICE_MBAFF : 16) >> shift;
+ int height = (pad_bot ? 16*(h->mb.i_mb_height - mb_y) >> SLICE_MBAFF : 16) >> v_shift;
int padh = PADH;
- int padv = PADV >> shift;
+ int padv = PADV >> v_shift;
// buffer: 2 chroma, 3 luma (rounded to 4) because deblocking goes beyond the top of the mb
if( b_end && !b_start )
- height += 4 >> (shift + SLICE_MBAFF);
+ height += 4 >> (v_shift + SLICE_MBAFF);
pixel *pix;
+ int starty = 16*mb_y - 4*!b_start;
if( SLICE_MBAFF )
{
// border samples for each field are extended separately
- pix = frame->plane_fld[i] + X264_MAX(0, (16*mb_y-4)*stride >> shift);
- plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end, shift );
- plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end, shift );
+ pix = frame->plane_fld[i] + (starty*stride >> v_shift);
+ plane_expand_border( pix, stride*2, width, height, padh, padv, pad_top, pad_bot, h_shift );
+ plane_expand_border( pix+stride, stride*2, width, height, padh, padv, pad_top, pad_bot, h_shift );
- height = (b_end ? 16*(h->mb.i_mb_height - mb_y) : 32) >> shift;
+ height = (pad_bot ? 16*(h->mb.i_mb_height - mb_y) : 32) >> v_shift;
if( b_end && !b_start )
- height += 4 >> shift;
- pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> shift);
- plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end, shift );
+ height += 4 >> v_shift;
+ pix = frame->plane[i] + (starty*stride >> v_shift);
+ plane_expand_border( pix, stride, width, height, padh, padv, pad_top, pad_bot, h_shift );
}
else
{
- pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> shift);
- plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end, shift );
+ pix = frame->plane[i] + (starty*stride >> v_shift);
+ plane_expand_border( pix, stride, width, height, padh, padv, pad_top, pad_bot, h_shift );
}
}
}
void x264_frame_expand_border_chroma( x264_t *h, x264_frame_t *frame, int plane )
{
- int shift = !CHROMA444;
- plane_expand_border( frame->plane[plane], frame->i_stride[plane], 16*h->mb.i_mb_width, 16*h->mb.i_mb_height>>shift,
- PADH, PADV>>shift, 1, 1, shift );
+ int v_shift = CHROMA_V_SHIFT;
+ plane_expand_border( frame->plane[plane], frame->i_stride[plane], 16*h->mb.i_mb_width, 16*h->mb.i_mb_height>>v_shift,
+ PADH, PADV>>v_shift, 1, 1, CHROMA_H_SHIFT );
}
void x264_frame_expand_border_mod16( x264_t *h, x264_frame_t *frame )
for( int i = 0; i < frame->i_plane; i++ )
{
int i_width = h->param.i_width;
- int shift = i && !CHROMA444;
- int i_height = h->param.i_height >> shift;
+ int h_shift = i && CHROMA_H_SHIFT;
+ int v_shift = i && CHROMA_V_SHIFT;
+ int i_height = h->param.i_height >> v_shift;
int i_padx = (h->mb.i_mb_width * 16 - h->param.i_width);
- int i_pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> shift;
+ int i_pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift;
if( i_padx )
{
for( int y = 0; y < i_height; y++ )
pixel_memset( &frame->plane[i][y*frame->i_stride[i] + i_width],
- &frame->plane[i][y*frame->i_stride[i] + i_width - 1-shift],
- i_padx>>shift, sizeof(pixel)<<shift );
+ &frame->plane[i][y*frame->i_stride[i] + i_width - 1-h_shift],
+ i_padx>>h_shift, sizeof(pixel)<<h_shift );
}
if( i_pady )
{
{
for( int i = 0; i < h->fenc->i_plane; i++ )
{
- int shift = i && !CHROMA444;
+ int v_shift = i && CHROMA_V_SHIFT;
int stride = h->fenc->i_stride[i];
- int height = h->param.i_height >> shift;
- int pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> shift;
+ int height = h->param.i_height >> v_shift;
+ int pady = (h->mb.i_mb_height * 16 - h->param.i_height) >> v_shift;
pixel *fenc = h->fenc->plane[i] + 16*mb_x;
for( int y = height; y < height + pady; y++ )
memcpy( fenc + y*stride, fenc + (height-1)*stride, 16*sizeof(pixel) );
x264_pthread_mutex_unlock( &frame->mutex );
}
+void x264_threadslice_cond_broadcast( x264_t *h, int pass )
+{
+ x264_pthread_mutex_lock( &h->mutex );
+ h->i_threadslice_pass = pass;
+ if( pass > 0 )
+ x264_pthread_cond_broadcast( &h->cv );
+ x264_pthread_mutex_unlock( &h->mutex );
+}
+
+void x264_threadslice_cond_wait( x264_t *h, int pass )
+{
+ x264_pthread_mutex_lock( &h->mutex );
+ while( h->i_threadslice_pass < pass )
+ x264_pthread_cond_wait( &h->cv, &h->mutex );
+ x264_pthread_mutex_unlock( &h->mutex );
+}
+
/* list operators */
void x264_frame_push( x264_frame_t **list, x264_frame_t *frame )
return frame;
}
-void x264_weight_scale_plane( x264_t *h, pixel *dst, int i_dst_stride, pixel *src, int i_src_stride,
- int i_width, int i_height, x264_weight_t *w )
+void x264_weight_scale_plane( x264_t *h, pixel *dst, intptr_t i_dst_stride, pixel *src, intptr_t i_src_stride,
+ int i_width, int i_height, x264_weight_t *w )
{
/* Weight horizontal strips of height 16. This was found to be the optimal height
* in terms of the cache loads. */