示例#1
0
文件: ports.c 项目: Eddy805/HandBrake
/************************************************************************
 * hb_thread_init()
 ************************************************************************
 * name:     user-friendly name
 * function: the thread routine
 * arg:      argument of the routine
 * priority: HB_LOW_PRIORITY or HB_NORMAL_PRIORITY
 ***********************************************************************/
hb_thread_t * hb_thread_init( char * name, void (* function)(void *),
                              void * arg, int priority )
{
    hb_thread_t * t = calloc( sizeof( hb_thread_t ), 1 );

    t->name     = strdup( name );
    t->function = function;
    t->arg      = arg;
    t->priority = priority;

    t->lock     = hb_lock_init();

    /* Create and start the thread */
#if defined( SYS_BEOS )
    t->thread = spawn_thread( (thread_func) hb_thread_func,
                              name, priority, t );
    resume_thread( t->thread );

#elif USE_PTHREAD
    pthread_create( &t->thread, NULL,
                    (void * (*)( void * )) hb_thread_func, t );

//#elif defined( SYS_CYGWIN )
//    t->thread = CreateThread( NULL, 0,
//        (LPTHREAD_START_ROUTINE) hb_thread_func, t, 0, NULL );
//
//    /* Maybe use THREAD_PRIORITY_LOWEST instead */
//    if( priority == HB_LOW_PRIORITY )
//        SetThreadPriority( GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL );
#endif

    hb_deep_log( 2, "thread %"PRIx64" started (\"%s\")", hb_thread_to_integer( t ), t->name );
    return t;
}
示例#2
0
static int hb_qsv_filter_pre_init( hb_filter_object_t * filter,
                               hb_filter_init_t * init ){
    filter->private_data = calloc( 1, sizeof(struct hb_filter_private_s) );
    hb_filter_private_t * pv = filter->private_data;
    pv->job = init->job;

    pv->pre.frame_go             = 0;
    pv->pre.frame_completed      = hb_cond_init();
    pv->pre.frame_completed_lock = hb_lock_init();

    pv->post.frame_go            = 0;
    pv->post.frame_completed     = hb_cond_init();
    pv->post.frame_completed_lock = hb_lock_init();

    pv->pre_busy.frame_go            = 0;
    pv->pre_busy.frame_completed     = hb_cond_init();
    pv->pre_busy.frame_completed_lock = hb_lock_init();

    pv->post_busy.frame_go               = 0;
    pv->post_busy.frame_completed        = hb_cond_init();
    pv->post_busy.frame_completed_lock   = hb_lock_init();

    pv->list = hb_list_init();

    // just to remind:
    // PIX_FMT_YUV420P,   ///< planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples) , 3 planes: Y, U, V
    // PIX_FMT_NV12,      ///< planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (first byte U and the following byte V)
    pv->sws_context_from_nv12 = hb_sws_get_context(
        pv->job->title->geometry.width, pv->job->title->geometry.height,
        AV_PIX_FMT_NV12,
        pv->job->title->geometry.width, pv->job->title->geometry.height,
        AV_PIX_FMT_YUV420P,
        SWS_LANCZOS|SWS_ACCURATE_RND);
    pv->sws_context_to_nv12 = hb_sws_get_context(
        pv->job->title->geometry.width, pv->job->title->geometry.height,
        AV_PIX_FMT_YUV420P,
        pv->job->title->geometry.width, pv->job->title->geometry.height,
        AV_PIX_FMT_NV12,
        SWS_LANCZOS|SWS_ACCURATE_RND);
    return 0;
}
示例#3
0
hb_fifo_t * hb_fifo_init( int capacity, int thresh )
{
    hb_fifo_t * f;
    f             = calloc( sizeof( hb_fifo_t ), 1 );
    f->lock       = hb_lock_init();
    f->cond_full  = hb_cond_init();
    f->cond_empty = hb_cond_init();
    f->capacity   = capacity;
    f->thresh     = thresh;
    f->buffer_size = 0;
    return f;
}
示例#4
0
void hb_buffer_pool_init( void )
{
    buffers.lock = hb_lock_init();
    buffers.allocated = 0;

    /* we allocate pools for sizes 2^10 through 2^25. requests larger than
     * 2^25 will get passed through to malloc. */
    int i;
    for ( i = 10; i < 26; ++i )
    {
        buffers.pool[i] = hb_fifo_init(BUFFER_POOL_MAX_ELEMENTS, 1);
        buffers.pool[i]->buffer_size = 1 << i;
    }
    /* requests smaller than 2^10 are satisfied from the 2^10 pool. */
    for ( i = 1; i < 10; ++i )
    {
        buffers.pool[i] = buffers.pool[10];
    }
}
示例#5
0
/***********************************************************************
 * hb_work_sync_init
 ***********************************************************************
 * Initialize the work object
 **********************************************************************/
hb_work_object_t * hb_sync_init( hb_job_t * job )
{
    hb_title_t        * title = job->title;
    hb_chapter_t      * chapter;
    int                 i;
    uint64_t            duration;
    hb_work_private_t * pv;
    hb_sync_video_t   * sync;
    hb_work_object_t  * w;
    hb_work_object_t  * ret = NULL;

    pv = calloc( 1, sizeof( hb_work_private_t ) );
    sync = &pv->type.video;
    pv->common = calloc( 1, sizeof( hb_sync_common_t ) );
    pv->common->ref++;
    pv->common->mutex = hb_lock_init();
    pv->common->audio_pts_thresh = -1;
    pv->common->next_frame = hb_cond_init();
    pv->common->pts_count = 1;
    if ( job->frame_to_start || job->pts_to_start )
    {
        pv->common->start_found = 0;
    }
    else
    {
        pv->common->start_found = 1;
    }

    ret = w = hb_get_work( WORK_SYNC_VIDEO );
    w->private_data = pv;
    w->fifo_in = job->fifo_raw;

    // When doing subtitle indepth scan, the pipeline ends at sync
    if ( !job->indepth_scan )
        w->fifo_out = job->fifo_sync;
    else
        w->fifo_out = NULL;

    pv->job            = job;
    pv->common->pts_offset   = INT64_MIN;
    sync->first_frame = 1;

    if( job->pass == 2 )
    {
        /* We already have an accurate frame count from pass 1 */
        hb_interjob_t * interjob = hb_interjob_get( job->h );
        sync->count_frames_max = interjob->frame_count;
    }
    else
    {
        /* Calculate how many video frames we are expecting */
        if ( job->pts_to_stop )
        {
            duration = job->pts_to_stop + 90000;
        }
        else if( job->frame_to_stop )
        {
            /* Set the duration to a rough estimate */
            duration = ( job->frame_to_stop / ( title->rate / title->rate_base ) ) * 90000;
        }
        else
        {
            duration = 0;
            for( i = job->chapter_start; i <= job->chapter_end; i++ )
            {
                chapter   = hb_list_item( job->list_chapter, i - 1 );
                duration += chapter->duration;
            }
        }
        sync->count_frames_max = duration * title->rate / title->rate_base / 90000;
    }

    hb_log( "sync: expecting %d video frames", sync->count_frames_max );

    /* Initialize libsamplerate for every audio track we have */
    if ( ! job->indepth_scan )
    {
        for( i = 0; i < hb_list_count( job->list_audio ); i++ )
        {
            InitAudio( job, pv->common, i );
        }
    }
    pv->common->first_pts = malloc( sizeof(int64_t) * pv->common->pts_count );
    for ( i = 0; i < pv->common->pts_count; i++ )
        pv->common->first_pts[i] = INT64_MAX;

    return ret;
}
示例#6
0
hb_work_object_t * hb_muxer_init( hb_job_t * job )
{
    hb_title_t  * title = job->title;
    int           i;
    hb_mux_t    * mux = calloc( sizeof( hb_mux_t ), 1 );
    hb_work_object_t  * w;
    hb_work_object_t  * muxer;

    mux->mutex = hb_lock_init();

    // set up to interleave track data in blocks of 1 video frame time.
    // (the best case for buffering and playout latency). The container-
    // specific muxers can reblock this into bigger chunks if necessary.
    mux->interleave = 90000. * (double)job->vrate_base / (double)job->vrate;
    mux->pts = mux->interleave;

    /* Get a real muxer */
    if( job->pass == 0 || job->pass == 2)
    {
        switch( job->mux )
        {
        case HB_MUX_MP4:
            mux->m = hb_mux_mp4_init( job );
            break;
        case HB_MUX_MKV:
            mux->m = hb_mux_mkv_init( job );
            break;
        default:
            hb_error( "No muxer selected, exiting" );
            *job->die = 1;
            return NULL;
        }
        /* Create file, write headers */
        if( mux->m )
        {
            mux->m->init( mux->m );
        }
    }

    /* Initialize the work objects that will receive fifo data */

    muxer = hb_get_work( WORK_MUX );
    muxer->private_data = calloc( sizeof( hb_work_private_t ), 1 );
    muxer->private_data->job = job;
    muxer->private_data->mux = mux;
    mux->ref++;
    muxer->private_data->track = mux->ntracks;
    muxer->fifo_in = job->fifo_mpeg4;
    add_mux_track( mux, job->mux_data, 1 );
    muxer->done = &muxer->private_data->mux->done;

    for( i = 0; i < hb_list_count( title->list_audio ); i++ )
    {
        hb_audio_t  *audio = hb_list_item( title->list_audio, i );

        w = hb_get_work( WORK_MUX );
        w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
        w->private_data->job = job;
        w->private_data->mux = mux;
        mux->ref++;
        w->private_data->track = mux->ntracks;
        w->fifo_in = audio->priv.fifo_out;
        add_mux_track( mux, audio->priv.mux_data, 1 );
        w->done = &job->done;
        hb_list_add( job->list_work, w );
        w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
    }

    for( i = 0; i < hb_list_count( title->list_subtitle ); i++ )
    {
        hb_subtitle_t  *subtitle = hb_list_item( title->list_subtitle, i );

        if (subtitle->config.dest != PASSTHRUSUB)
            continue;

        w = hb_get_work( WORK_MUX );
        w->private_data = calloc( sizeof( hb_work_private_t ), 1 );
        w->private_data->job = job;
        w->private_data->mux = mux;
        mux->ref++;
        w->private_data->track = mux->ntracks;
        w->fifo_in = subtitle->fifo_out;
        add_mux_track( mux, subtitle->mux_data, 0 );
        w->done = &job->done;
        hb_list_add( job->list_work, w );
        w->thread = hb_thread_init( w->name, mux_loop, w, HB_NORMAL_PRIORITY );
    }
    return muxer;
}
示例#7
0
int
taskset_init( taskset_t *ts, int thread_count, size_t arg_size )
{
    int init_step;

    init_step = 0;
    memset( ts, 0, sizeof( *ts ) );
    ts->thread_count = thread_count;
    ts->arg_size = arg_size;
    ts->bitmap_elements = ( ts->thread_count + 31 ) / 32;
    ts->task_threads = malloc( sizeof( hb_thread_t* ) * ts->thread_count );
    if( ts->task_threads == NULL )
        goto fail;
    init_step++;

    if( arg_size != 0 )
    {
        ts->task_threads_args = malloc( arg_size * ts->thread_count );
        if( ts->task_threads == NULL )
            goto fail;
    }
    init_step++;

    ts->task_begin_bitmap = malloc( sizeof( uint32_t  ) * ts->bitmap_elements );
    if( ts->task_begin_bitmap == NULL )
        goto fail;
    init_step++;

    ts->task_complete_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
    if( ts->task_complete_bitmap == NULL )
        goto fail;
    init_step++;

    ts->task_stop_bitmap = malloc( sizeof( uint32_t ) * ts->bitmap_elements );
    if( ts->task_stop_bitmap == NULL )
        goto fail;
    init_step++;

    ts->task_cond_lock = hb_lock_init();
    if( ts->task_cond_lock == NULL)
        goto fail;
    init_step++;

    ts->task_begin = hb_cond_init();
    if( ts->task_begin == NULL)
        goto fail;
    init_step++;

    ts->task_complete = hb_cond_init();
    if( ts->task_complete == NULL)
        goto fail;
    init_step++;

    /*
     * Initialize all arg data to 0.
     */
    memset(ts->task_threads_args, 0, ts->arg_size * ts->thread_count );

    /*
     * Inialize bitmaps to all bits set.  This means that any unused bits
     * in the bitmap are already in the "condition satisfied" state allowing
     * us to test the bitmap 32bits at a time without having to mask off
     * the end.
     */
    memset(ts->task_begin_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
    memset(ts->task_complete_bitmap, 0xFF, sizeof( uint32_t ) * ts->bitmap_elements );
    memset(ts->task_stop_bitmap, 0, sizeof( uint32_t ) * ts->bitmap_elements );
    
    /*
     * Important to start off with the threads locked waiting
     * on input, no work completed, and not asked to stop.
     */
    bit_nclear( ts->task_begin_bitmap, 0, ts->thread_count - 1 );
    bit_nclear( ts->task_complete_bitmap, 0, ts->thread_count - 1 );
    bit_nclear( ts->task_stop_bitmap, 0, ts->thread_count - 1 );
    return (1);

fail:
    switch (init_step)
    {
        default:
            hb_cond_close( &ts->task_complete );
            /* FALL THROUGH */
        case 7:
            hb_cond_close( &ts->task_begin );
            /* FALL THROUGH */
        case 6:
            hb_lock_close( &ts->task_cond_lock );
            /* FALL THROUGH */
        case 5:
            free( ts->task_stop_bitmap );
            /* FALL THROUGH */
        case 4:
            free( ts->task_complete_bitmap );
            /* FALL THROUGH */
        case 3:
            free( ts->task_begin_bitmap );
            /* FALL THROUGH */
        case 2:
            if( ts->task_threads_args == NULL )
                free( ts->task_threads_args );
            /* FALL THROUGH */
        case 1:
            free( ts->task_threads );
            /* FALL THROUGH */
        case 0:
            break;
    }
    return (0);
}
示例#8
0
hb_filter_private_t * hb_rotate_init( int pix_fmt,
                                           int width,
                                           int height,
                                           char * settings )
{
    if( pix_fmt != PIX_FMT_YUV420P )
    {
        return 0;
    }

    hb_filter_private_t * pv = calloc( 1, sizeof(struct hb_filter_private_s) );

    pv->pix_fmt = pix_fmt;

    pv->width[0]  = width;
    pv->height[0] = height;
    pv->width[1]  = pv->width[2]  = width >> 1;
    pv->height[1] = pv->height[2] = height >> 1;

    pv->buf_out = hb_video_buffer_init( width, height );
    pv->buf_settings = hb_buffer_init( 0 );

    pv->mode     = MODE_DEFAULT;

    pv->ref_stride[0] = pv->width[0];
    pv->ref_stride[1] = pv->width[1];
    pv->ref_stride[2] = pv->width[2];
    
    if( settings )
    {
        sscanf( settings, "%d",
                &pv->mode );
    }

    pv->cpu_count = hb_get_cpu_count();


    /*
     * Create threads and locks.
     */
    pv->rotate_threads = malloc( sizeof( hb_thread_t* ) * pv->cpu_count );
    pv->rotate_begin_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
    pv->rotate_complete_lock = malloc( sizeof( hb_lock_t * ) * pv->cpu_count );
    pv->rotate_arguments = malloc( sizeof( rotate_arguments_t ) * pv->cpu_count );

    int i;
    for( i = 0; i < pv->cpu_count; i++ )
    {
        rotate_thread_arg_t *thread_args;
    
        thread_args = malloc( sizeof( rotate_thread_arg_t ) );
    
        if( thread_args ) {
            thread_args->pv = pv;
            thread_args->segment = i;
    
            pv->rotate_begin_lock[i] = hb_lock_init();
            pv->rotate_complete_lock[i] = hb_lock_init();
    
            /*
             * Important to start off with the threads locked waiting
             * on input.
             */
            hb_lock( pv->rotate_begin_lock[i] );
    
            pv->rotate_arguments[i].stop = 0;
            pv->rotate_arguments[i].dst = NULL;
            
            pv->rotate_threads[i] = hb_thread_init( "rotate_filter_segment",
                                                   rotate_filter_thread,
                                                   thread_args,
                                                   HB_NORMAL_PRIORITY );
        } else {
            hb_error( "rotate could not create threads" );
        }
    }

    return pv;
}