/*****************************************************************************
* frame.c: frame handling
*****************************************************************************
- * Copyright (C) 2003-2011 x264 project
+ * Copyright (C) 2003-2013 x264 project
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Loren Merritt <lorenm@u.washington.edu>
int i_mb_count = h->mb.i_mb_count;
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 align = 16;
+#if ARCH_X86 || ARCH_X86_64
+ if( h->param.cpu&X264_CPU_CACHELINE_64 )
+ align = 64;
+ else if( h->param.cpu&X264_CPU_CACHELINE_32 || h->param.cpu&X264_CPU_AVX2 )
+ align = 32;
+#endif
+#if ARCH_PPC
+ int disalign = 1<<9;
+#else
+ int disalign = 1<<10;
+#endif
CHECKED_MALLOCZERO( frame, sizeof(x264_frame_t) );
}
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 );
+#if HAVE_OPENCL
+ x264_opencl_frame_delete( frame );
+#endif
}
x264_free( frame );
}
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->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 );
}
#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 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) >> v_shift;
+ int height = (pad_bot ? 16*(h->mb.i_mb_height - mb_y) >> SLICE_MBAFF : 16) >> v_shift;
int padh = PADH;
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 >> (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 >> v_shift);
- plane_expand_border( pix, stride*2, width, height, padh, padv, b_start, b_end, h_shift );
- plane_expand_border( pix+stride, stride*2, width, height, padh, padv, b_start, b_end, h_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) >> v_shift;
+ height = (pad_bot ? 16*(h->mb.i_mb_height - mb_y) : 32) >> v_shift;
if( b_end && !b_start )
height += 4 >> v_shift;
- pix = frame->plane[i] + X264_MAX(0, (16*mb_y-4)*stride >> v_shift);
- plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end, h_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 >> v_shift);
- plane_expand_border( pix, stride, width, height, padh, padv, b_start, b_end, h_shift );
+ pix = frame->plane[i] + (starty*stride >> v_shift);
+ plane_expand_border( pix, stride, width, height, padh, padv, pad_top, pad_bot, h_shift );
}
}
}
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 );
+}
+
+int x264_frame_new_slice( x264_t *h, x264_frame_t *frame )
+{
+ if( h->param.i_slice_count_max )
+ {
+ int slice_count;
+ if( h->param.b_sliced_threads )
+ slice_count = x264_pthread_fetch_and_add( &frame->i_slice_count, 1, &frame->mutex );
+ else
+ slice_count = frame->i_slice_count++;
+ if( slice_count >= h->param.i_slice_count_max )
+ return -1;
+ }
+ return 0;
+}
+
/* list operators */
void x264_frame_push( x264_frame_t **list, x264_frame_t *frame )
frame->b_scenecut = 1;
frame->b_keyframe = 0;
frame->b_corrupt = 0;
+ frame->i_slice_count = h->param.b_sliced_threads ? h->param.i_threads : 1;
memset( frame->weight, 0, sizeof(frame->weight) );
memset( frame->f_weighted_cost_delta, 0, sizeof(frame->f_weighted_cost_delta) );
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. */