先羅列出代碼中與多線程有關的宏定義、結構體、變量、函數等,鎖定為需要重點關注的對象,在接下來的研究中逐步深入探討這些對象的含義和作用。 [cpp] #define X264_THREAD_MAX 128 #define X264_LOOKAHEAD_THREAD_MAX 16 #define X264_LOOKAHEAD_MAX 250 // arbitrary, but low because SATD scores are 1/4 normal #define X264_LOOKAHEAD_QP (12+QP_BD_OFFSET) // number of pixels (per thread) in progress at any given time. // 16 for the macroblock in progress + 3 for deblocking + 3 for motion compensation filter + 2 for extra safety #define X264_THREAD_HEIGHT 24 [cpp] #define x264_pthread_t pthread_t #define x264_pthread_create pthread_create #define x264_pthread_join pthread_join #define x264_pthread_mutex_t pthread_mutex_t #define x264_pthread_mutex_init pthread_mutex_init #define x264_pthread_mutex_destroy pthread_mutex_destroy #define x264_pthread_mutex_lock pthread_mutex_lock #define x264_pthread_mutex_unlock pthread_mutex_unlock #define x264_pthread_cond_t pthread_cond_t #define x264_pthread_cond_init pthread_cond_init #define x264_pthread_cond_destroy pthread_cond_destroy #define x264_pthread_cond_broadcast pthread_cond_broadcast #define x264_pthread_cond_wait pthread_cond_wait #define x264_pthread_attr_t pthread_attr_t #define x264_pthread_attr_init pthread_attr_init #define x264_pthread_attr_destroy pthread_attr_destroy #define x264_pthread_num_processors_np pthread_num_processors_np #define X264_PTHREAD_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER [cpp] typedef struct x264_lookahead_t { volatile uint8_t b_exit_thread; uint8_t b_thread_active; uint8_t b_analyse_keyframe; int i_last_keyframe; int i_slicetype_length; x264_frame_t *last_nonb; x264_pthread_t thread_handle; x264_sync_frame_list_t ifbuf; x264_sync_frame_list_t next; x264_sync_frame_list_t ofbuf; } x264_lookahead_t; [cpp] /* synchronized frame list */ typedef struct { x264_frame_t **list; int i_max_size; int i_size; x264_pthread_mutex_t mutex; x264_pthread_cond_t cv_fill; /* event signaling that the list became fuller */ x264_pthread_cond_t cv_empty; /* event signaling that the list became emptier */ } x264 typedef struct x264_frame //!< 為節省篇幅,僅附上與線程有關的成員變量 { /* threading */ int i_lines_completed; /* in pixels */ int i_lines_weighted; /* FIXME: this only supports weighting of one reference frame */ int i_reference_count; /* number of threads using this frame (not necessarily the number of pointers) */ x264_pthread_mutex_t mutex; x264_pthread_cond_t cv; } x264_frame_t; [cpp] /* threading */ void x264_frame_cond_broadcast( x264_frame_t *frame, int i_lines_completed ) { x264_pthread_mutex_lock( &frame->mutex ); frame->i_lines_completed = i_lines_completed; x264_pthread_cond_broadcast( &frame->cv ); x264_pthread_mutex_unlock( &frame->mutex ); } void x264_frame_cond_wait( x264_frame_t *frame, int i_lines_completed ) { x264_pthread_mutex_lock( &frame->mutex ); while( frame->i_lines_completed < i_lines_completed ) x264_pthread_cond_wait( &frame->cv, &frame->mutex ); 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 ); } [cpp] int x264_sync_frame_list_init( x264_sync_frame_list_t *slist, int max_size ) { if( max_size < 0 ) return -1; slist->i_max_size = max_size; slist->i_size = 0; CHECKED_MALLOCZERO( slist->list, (max_size+1) * sizeof(x264_frame_t*) ); if( x264_pthread_mutex_init( &slist->mutex, NULL ) || x264_pthread_cond_init( &slist->cv_fill, NULL ) || x264_pthread_cond_init( &slist->cv_empty, NULL ) ) return -1; return 0; fail: return -1; } void x264_sync_frame_list_delete( x264_sync_frame_list_t *slist ) { x264_pthread_mutex_destroy( &slist->mutex ); x264_pthread_cond_destroy( &slist->cv_fill ); x264_pthread_cond_destroy( &slist->cv_empty ); x264_frame_delete_list( slist->list ); } void x264_sync_frame_list_push( x264_sync_frame_list_t *slist, x264_frame_t *frame ) { x264_pthread_mutex_lock( &slist->mutex ); while( slist->i_size == slist->i_max_size ) x264_pthread_cond_wait( &slist->cv_empty, &slist->mutex ); slist->list[ slist->i_size++ ] = frame; x264_pthread_mutex_unlock( &slist->mutex ); x264_pthread_cond_broadcast( &slist->cv_fill ); } x264_frame_t *x264_sync_frame_list_pop( x264_sync_frame_list_t *slist ) { x264_frame_t *frame; x264_pthread_mutex_lock( &slist->mutex ); while( !slist->i_size ) x264_pthread_cond_wait( &slist->cv_fill, &slist->mutex ); frame = slist->list[ --slist->i_size ]; slist->list[ slist->i_size ] = NULL; x264_pthread_cond_broadcast( &slist->cv_empty ); x264_pthread_mutex_unlock( &slist->mutex ); return frame; }