⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 video_output.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
            = config_ChainCreate( &psz_tmp, &p_cfg, p_vout->psz_filter_chain );        config_ChainDestroy( p_cfg );        free( psz_tmp );        /* Create a video filter2 var ... but don't inherit values */        var_Create( p_vout, "video-filter",                    VLC_VAR_STRING | VLC_VAR_ISCOMMAND );        p_vout->psz_vf2 = var_GetString( p_vout, "video-filter" );    }    var_AddCallback( p_vout, "video-filter", VideoFilter2Callback, NULL );    p_vout->p_vf2_chain = filter_chain_New( p_vout, "video filter2",        false, video_filter_buffer_allocation_init, NULL, p_vout );    /* Choose the video output module */    if( !p_vout->psz_filter_chain || !*p_vout->psz_filter_chain )    {        var_Create( p_vout, "vout", VLC_VAR_STRING | VLC_VAR_DOINHERIT );        var_Get( p_vout, "vout", &val );        psz_parser = val.psz_string;    }    else    {        psz_parser = strdup( p_vout->psz_filter_chain );        p_vout->b_title_show = false;    }    /* Create the vout thread */    char* psz_tmp = config_ChainCreate( &psz_name, &p_cfg, psz_parser );    free( psz_parser );    free( psz_tmp );    p_vout->p_cfg = p_cfg;    p_vout->p_module = module_Need( p_vout,        ( p_vout->psz_filter_chain && *p_vout->psz_filter_chain ) ?        "video filter" : "video output", psz_name, p_vout->psz_filter_chain && *p_vout->psz_filter_chain );    free( psz_name );    if( p_vout->p_module == NULL )    {        msg_Err( p_vout, "no suitable vout module" );        // FIXME it's ugly but that's exactly the function that need to be called.        EndThread( p_vout );        vlc_object_detach( p_vout );        vlc_object_release( p_vout );        return NULL;    }    /* Create a few object variables for interface interaction */    var_Create( p_vout, "deinterlace", VLC_VAR_STRING | VLC_VAR_HASCHOICE );    text.psz_string = _("Deinterlace");    var_Change( p_vout, "deinterlace", VLC_VAR_SETTEXT, &text, NULL );    val.psz_string = (char *)""; text.psz_string = _("Disable");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"discard"; text.psz_string = _("Discard");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"blend"; text.psz_string = _("Blend");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"mean"; text.psz_string = _("Mean");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"bob"; text.psz_string = _("Bob");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"linear"; text.psz_string = _("Linear");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = (char *)"x"; text.psz_string = (char *)"X";    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    if( var_Get( p_vout, "deinterlace-mode", &val ) == VLC_SUCCESS )    {        var_Set( p_vout, "deinterlace", val );        free( val.psz_string );    }    var_AddCallback( p_vout, "deinterlace", DeinterlaceCallback, NULL );    var_Create( p_vout, "vout-filter", VLC_VAR_STRING | VLC_VAR_DOINHERIT );    text.psz_string = _("Filters");    var_Change( p_vout, "vout-filter", VLC_VAR_SETTEXT, &text, NULL );    var_AddCallback( p_vout, "vout-filter", FilterCallback, NULL );    /* Calculate delay created by internal caching */    p_input_thread = (input_thread_t *)vlc_object_find( p_vout,                                           VLC_OBJECT_INPUT, FIND_ANYWHERE );    if( p_input_thread )    {        p_vout->i_pts_delay = p_input_thread->i_pts_delay;        vlc_object_release( p_input_thread );    }    else    {        p_vout->i_pts_delay = DEFAULT_PTS_DELAY;    }    if( vlc_thread_create( p_vout, "video output", RunThread,                           VLC_THREAD_PRIORITY_OUTPUT, true ) )    {        module_Unneed( p_vout, p_vout->p_module );        vlc_object_release( p_vout );        return NULL;    }    vlc_object_set_destructor( p_vout, vout_Destructor );    if( p_vout->b_error )    {        msg_Err( p_vout, "video output creation failed" );        vout_CloseAndRelease( p_vout );        return NULL;    }    return p_vout;}/***************************************************************************** * vout_Close: Close a vout created by vout_Create. ***************************************************************************** * You HAVE to call it on vout created by vout_Create before vlc_object_release. * You should NEVER call it on vout not obtained though vout_Create * (like with vout_Request or vlc_object_find.) * You can use vout_CloseAndRelease() as a convenient method. *****************************************************************************/void vout_Close( vout_thread_t *p_vout ){    assert( p_vout );    vlc_object_kill( p_vout );    vlc_thread_join( p_vout );    module_Unneed( p_vout, p_vout->p_module );    p_vout->p_module = NULL;}/* */static void vout_Destructor( vlc_object_t * p_this ){    vout_thread_t *p_vout = (vout_thread_t *)p_this;    /* Make sure the vout was stopped first */    assert( !p_vout->p_module );    /* Destroy the locks */    vlc_mutex_destroy( &p_vout->picture_lock );    vlc_mutex_destroy( &p_vout->change_lock );    vlc_mutex_destroy( &p_vout->vfilter_lock );    free( p_vout->psz_filter_chain );    config_ChainDestroy( p_vout->p_cfg );#ifndef __APPLE__    vout_thread_t *p_another_vout;    /* This is a dirty hack mostly for Linux, where there is no way to get the     * GUI back if you closed it while playing video. This is solved in     * Mac OS X, where we have this novelty called menubar, that will always     * allow you access to the applications main functionality. They should try     * that on linux sometime. */    p_another_vout = vlc_object_find( p_this->p_libvlc,                                      VLC_OBJECT_VOUT, FIND_ANYWHERE );    if( p_another_vout == NULL )        var_SetBool( p_this->p_libvlc, "intf-show", true );    else        vlc_object_release( p_another_vout );#endif}/***************************************************************************** * InitThread: initialize video output thread ***************************************************************************** * This function is called from RunThread and performs the second step of the * initialization. It returns 0 on success. Note that the thread's flag are not * modified inside this function. * XXX You have to enter it with change_lock taken. *****************************************************************************/static int ChromaCreate( vout_thread_t *p_vout );static void ChromaDestroy( vout_thread_t *p_vout );static bool ChromaIsEqual( const picture_heap_t *p_output, const picture_heap_t *p_render ){     if( !vout_ChromaCmp( p_output->i_chroma, p_render->i_chroma ) )         return false;     if( p_output->i_chroma != FOURCC_RV15 &&         p_output->i_chroma != FOURCC_RV16 &&         p_output->i_chroma != FOURCC_RV24 &&         p_output->i_chroma != FOURCC_RV32 )         return true;     return p_output->i_rmask == p_render->i_rmask &&            p_output->i_gmask == p_render->i_gmask &&            p_output->i_bmask == p_render->i_bmask;}static int InitThread( vout_thread_t *p_vout ){    int i, i_aspect_x, i_aspect_y;#ifdef STATS    p_vout->c_loops = 0;#endif    /* Initialize output method, it allocates direct buffers for us */    if( p_vout->pf_init( p_vout ) )        return VLC_EGENERIC;    if( !I_OUTPUTPICTURES )    {        msg_Err( p_vout, "plugin was unable to allocate at least "                         "one direct buffer" );        p_vout->pf_end( p_vout );        return VLC_EGENERIC;    }    if( I_OUTPUTPICTURES > VOUT_MAX_PICTURES )    {        msg_Err( p_vout, "plugin allocated too many direct buffers, "                         "our internal buffers must have overflown." );        p_vout->pf_end( p_vout );        return VLC_EGENERIC;    }    msg_Dbg( p_vout, "got %i direct buffer(s)", I_OUTPUTPICTURES );    AspectRatio( p_vout->fmt_render.i_aspect, &i_aspect_x, &i_aspect_y );    msg_Dbg( p_vout, "picture in %ix%i (%i,%i,%ix%i), "             "chroma %4.4s, ar %i:%i, sar %i:%i",             p_vout->fmt_render.i_width, p_vout->fmt_render.i_height,             p_vout->fmt_render.i_x_offset, p_vout->fmt_render.i_y_offset,             p_vout->fmt_render.i_visible_width,             p_vout->fmt_render.i_visible_height,             (char*)&p_vout->fmt_render.i_chroma,             i_aspect_x, i_aspect_y,             p_vout->fmt_render.i_sar_num, p_vout->fmt_render.i_sar_den );    AspectRatio( p_vout->fmt_in.i_aspect, &i_aspect_x, &i_aspect_y );    msg_Dbg( p_vout, "picture user %ix%i (%i,%i,%ix%i), "             "chroma %4.4s, ar %i:%i, sar %i:%i",             p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,             p_vout->fmt_in.i_x_offset, p_vout->fmt_in.i_y_offset,             p_vout->fmt_in.i_visible_width,             p_vout->fmt_in.i_visible_height,             (char*)&p_vout->fmt_in.i_chroma,             i_aspect_x, i_aspect_y,             p_vout->fmt_in.i_sar_num, p_vout->fmt_in.i_sar_den );    if( !p_vout->fmt_out.i_width || !p_vout->fmt_out.i_height )    {        p_vout->fmt_out.i_width = p_vout->fmt_out.i_visible_width =            p_vout->output.i_width;        p_vout->fmt_out.i_height = p_vout->fmt_out.i_visible_height =            p_vout->output.i_height;        p_vout->fmt_out.i_x_offset =  p_vout->fmt_out.i_y_offset = 0;        p_vout->fmt_out.i_aspect = p_vout->output.i_aspect;        p_vout->fmt_out.i_chroma = p_vout->output.i_chroma;    }    if( !p_vout->fmt_out.i_sar_num || !p_vout->fmt_out.i_sar_num )    {        p_vout->fmt_out.i_sar_num = p_vout->fmt_out.i_aspect *            p_vout->fmt_out.i_height;        p_vout->fmt_out.i_sar_den = VOUT_ASPECT_FACTOR *            p_vout->fmt_out.i_width;    }    vlc_ureduce( &p_vout->fmt_out.i_sar_num, &p_vout->fmt_out.i_sar_den,                 p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den, 0 );    AspectRatio( p_vout->fmt_out.i_aspect, &i_aspect_x, &i_aspect_y );    msg_Dbg( p_vout, "picture out %ix%i (%i,%i,%ix%i), "             "chroma %4.4s, ar %i:%i, sar %i:%i",             p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,             p_vout->fmt_out.i_x_offset, p_vout->fmt_out.i_y_offset,             p_vout->fmt_out.i_visible_width,             p_vout->fmt_out.i_visible_height,             (char*)&p_vout->fmt_out.i_chroma,             i_aspect_x, i_aspect_y,             p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den );    /* FIXME removed the need of both fmt_* and heap infos */    /* Calculate shifts from system-updated masks */    PictureHeapFixRgb( &p_vout->render );    VideoFormatImportRgb( &p_vout->fmt_render, &p_vout->render );    PictureHeapFixRgb( &p_vout->output );    VideoFormatImportRgb( &p_vout->fmt_out, &p_vout->output );    /* Check whether we managed to create direct buffers similar to     * the render buffers, ie same size and chroma */    if( ( p_vout->output.i_width == p_vout->render.i_width )     && ( p_vout->output.i_height == p_vout->render.i_height )     && ( ChromaIsEqual( &p_vout->output, &p_vout->render ) ) )    {        /* Cool ! We have direct buffers, we can ask the decoder to         * directly decode into them ! Map the first render buffers to         * the first direct buffers, but keep the first direct buffer         * for memcpy operations */        p_vout->b_direct = 1;        for( i = 1; i < VOUT_MAX_PICTURES; i++ )        {            if( p_vout->p_picture[ i ].i_type != DIRECT_PICTURE &&                I_RENDERPICTURES >= VOUT_MIN_DIRECT_PICTURES - 1 &&                p_vout->p_picture[ i - 1 ].i_type == DIRECT_PICTURE )            {                /* We have enough direct buffers so there's no need to                 * try to use system memory buffers. */                break;            }            PP_RENDERPICTURE[ I_RENDERPICTURES ] = &p_vout->p_picture[ i ];            I_RENDERPICTURES++;        }        msg_Dbg( p_vout, "direct render, mapping "                 "render pictures 0-%i to system pictures 1-%i",                 VOUT_MAX_PICTURES - 2, VOUT_MAX_PICTURES - 1 );    }    else    {        /* Rats... Something is wrong here, we could not find an output         * plugin able to directly render what we decode. See if we can         * find a chroma plugin to do the conversion */        p_vout->b_direct = 0;        if( ChromaCreate( p_vout ) )        {            p_vout->pf_end( p_vout );            return VLC_EGENERIC;        }        msg_Dbg( p_vout, "indirect render, mapping "                 "render pictures 0-%i to system pictures %i-%i",                 VOUT_MAX_PICTURES - 1, I_OUTPUTPICTURES,                 I_OUTPUTPICTURES + VOUT_MAX_PICTURES - 1 );        /* Append render buffers after the direct buffers */        for( i = I_OUTPUTPICTURES; i < 2 * VOUT_MAX_PICTURES; i++ )        {            PP_RENDERPICTURE[ I_RENDERPICTURES ] = &p_vout->p_picture[ i ];            I_RENDERPICTURES++;            /* Check if we have enough render pictures */            if( I_RENDERPICTURES == VOUT_MAX_PICTURES )                break;        }    }    /* Link pictures back to their heap */    for( i = 0 ; i < I_RENDERPICTURES ; i++ )    {        PP_RENDERPICTURE[ i ]->p_heap = &p_vout->render;    }    for( i = 0 ; i < I_OUTPUTPICTURES ; i++ )    {        PP_OUTPUTPICTURE[ i ]->p_heap = &p_vout->output;    }    return VLC_SUCCESS;}/***************************************************************************** * RunThread: video output thread ***************************************************************************** * Video output thread. This function does only returns when the thread is * terminated. It handles the pictures arriving in the video heap and the * display device events. *****************************************************************************/static void* RunThread( vlc_object_t *p_this ){    vout_thread_t *p_vout = (vout_thread_t *)p_this;    int             i_idle_loops = 0;  /* loops without displaying a picture */    picture_t *     p_last_picture = NULL;                   /* last picture */    subpicture_t *  p_subpic = NULL;                   /* subpicture pointer */    bool            b_drop_late;    int             i_displayed = 0, i_lost = 0;    /*     * Initialize thread     */    vlc_mutex_lock( &p_vout->change_lock );    p_vout->b_error = InitThread( p_vout );    b_drop_late = var_CreateGetBool( p_vout, "drop-late-frames" );    /* signal the creation of the vout */    vlc_thread_ready( p_vout );    if( p_vout->b_error )    {        EndThread( p_vout );        vlc_mutex_unlock( &p_vout->change_lock );        return NULL;    }    vlc_object_lock( p_vout );    if( p_vout->b_title_show )        DisplayTitleOnOSD( p_vout );    /*     * Main loop - it is not executed if an error occurred during     * initialization     */    while( vlc_object_alive( p_vout ) && !p_vout->b_error )    {        /* Initialize loop variables */        const mtime_t current_date = mdate();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -