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

📄 video_output.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 4 页
字号:
    }    else    {        /* continue the parent's filter chain */        char *psz_end;        psz_end = strchr( ((vout_thread_t *)p_parent)->psz_filter_chain, ':' );        if( !psz_end ) psz_end = strchr(                        ((vout_thread_t *)p_parent)->psz_filter_chain, ',' );        if( psz_end && *(psz_end+1) )            p_vout->psz_filter_chain = strdup( psz_end+1 );        else p_vout->psz_filter_chain = NULL;    }    /* 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_plugin = val.psz_string;    }    else    {        /* the filter chain is a string list of filters separated by double         * colons */        char *psz_end;        psz_end = strchr( p_vout->psz_filter_chain, ':' );        if( !psz_end ) psz_end = strchr( p_vout->psz_filter_chain, ',' );        if( psz_end )            psz_plugin = strndup( p_vout->psz_filter_chain,                                  psz_end - p_vout->psz_filter_chain );        else psz_plugin = strdup( p_vout->psz_filter_chain );    }    /* Initialize the dimensions of the video window */    InitWindowSize( p_vout, &p_vout->i_window_width,                    &p_vout->i_window_height );    /* Create the vout thread */    p_vout->p_module = module_Need( p_vout,        ( p_vout->psz_filter_chain && *p_vout->psz_filter_chain ) ?        "video filter" : "video output", psz_plugin, 0 );    if( psz_plugin ) free( psz_plugin );    if( p_vout->p_module == NULL )    {        msg_Err( p_vout, "no suitable vout module" );        vlc_object_detach( p_vout );        vlc_object_destroy( 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 = ""; text.psz_string = _("Disable");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = "discard"; text.psz_string = _("Discard");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = "blend"; text.psz_string = _("Blend");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = "mean"; text.psz_string = _("Mean");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = "bob"; text.psz_string = _("Bob");    var_Change( p_vout, "deinterlace", VLC_VAR_ADDCHOICE, &val, &text );    val.psz_string = "linear"; text.psz_string = _("Linear");    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 );        if( val.psz_string ) 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, VLC_TRUE ) )    {        msg_Err( p_vout, "out of memory" );        module_Unneed( p_vout, p_vout->p_module );        vlc_object_detach( p_vout );        vlc_object_destroy( p_vout );        return NULL;    }    if( p_vout->b_error )    {        msg_Err( p_vout, "video output creation failed" );        /* Make sure the thread is destroyed */        p_vout->b_die = VLC_TRUE;        vlc_thread_join( p_vout );        vlc_object_detach( p_vout );        vlc_object_destroy( p_vout );        return NULL;    }    return p_vout;}/***************************************************************************** * vout_Destroy: destroys a previously created video output ***************************************************************************** * Destroy a terminated thread. * The function will request a destruction of the specified thread. If pi_error * is NULL, it will return once the thread is destroyed. Else, it will be * update using one of the THREAD_* constants. *****************************************************************************/void vout_Destroy( vout_thread_t *p_vout ){    vlc_object_t *p_playlist;    /* Request thread destruction */    p_vout->b_die = VLC_TRUE;    vlc_thread_join( p_vout );    var_Destroy( p_vout, "intf-change" );    p_playlist = vlc_object_find( p_vout, VLC_OBJECT_PLAYLIST,                                  FIND_ANYWHERE );    if( p_vout->psz_filter_chain ) free( p_vout->psz_filter_chain );    /* Free structure */    vlc_object_destroy( p_vout );    /* If it was the last vout, tell the interface to show up */    if( p_playlist != NULL )    {        vout_thread_t *p_another_vout = vlc_object_find( p_playlist,                                            VLC_OBJECT_VOUT, FIND_ANYWHERE );        if( p_another_vout == NULL )        {            vlc_value_t val;            val.b_bool = VLC_TRUE;            var_Set( p_playlist, "intf-show", val );        }        else        {            vlc_object_release( p_another_vout );        }        vlc_object_release( p_playlist );    }}/***************************************************************************** * 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. *****************************************************************************/static int InitThread( vout_thread_t *p_vout ){    int i, i_aspect_x, i_aspect_y;    vlc_mutex_lock( &p_vout->change_lock );#ifdef STATS    p_vout->c_loops = 0;#endif    /* Initialize output method, it allocates direct buffers for us */    if( p_vout->pf_init( p_vout ) )    {        vlc_mutex_unlock( &p_vout->change_lock );        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 );        vlc_mutex_unlock( &p_vout->change_lock );        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 );        vlc_mutex_unlock( &p_vout->change_lock );        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_reduce( &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, chroma %4.4s, ar %i:%i, sar %i:%i",             p_vout->output.i_width, p_vout->output.i_height,             (char*)&p_vout->output.i_chroma,             i_aspect_x, i_aspect_y,             p_vout->fmt_out.i_sar_num, p_vout->fmt_out.i_sar_den );    /* Calculate shifts from system-updated masks */    MaskToShift( &p_vout->output.i_lrshift, &p_vout->output.i_rrshift,                 p_vout->output.i_rmask );    MaskToShift( &p_vout->output.i_lgshift, &p_vout->output.i_rgshift,                 p_vout->output.i_gmask );    MaskToShift( &p_vout->output.i_lbshift, &p_vout->output.i_rbshift,                 p_vout->output.i_bmask );    /* 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 )     && ( vout_ChromaCmp( p_vout->output.i_chroma, p_vout->render.i_chroma ) ) )    {        /* 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;        /* Choose the best module */        p_vout->chroma.p_module = module_Need( p_vout, "chroma", NULL, 0 );        if( p_vout->chroma.p_module == NULL )        {            msg_Err( p_vout, "no chroma module for %4.4s to %4.4s",                     (char*)&p_vout->render.i_chroma,                     (char*)&p_vout->output.i_chroma );            p_vout->pf_end( p_vout );            vlc_mutex_unlock( &p_vout->change_lock );            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;    }/* XXX XXX mark thread ready */    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( vout_thread_t *p_vout){    int             i_index;                                /* index in heap */    int             i_idle_loops = 0;  /* loops without displaying a picture */    mtime_t         current_date;                            /* current date */    mtime_t         display_date;                            /* display date */

⌨️ 快捷键说明

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