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

📄 video_output.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 4 页
字号:
    picture_t *     p_picture;                            /* picture pointer */    picture_t *     p_last_picture = NULL;                   /* last picture */    picture_t *     p_directbuffer;              /* direct buffer to display */    subpicture_t *  p_subpic;                          /* subpicture pointer */    /*     * Initialize thread     */    p_vout->b_error = InitThread( p_vout );    /* signal the creation of the vout */    vlc_thread_ready( p_vout );    if( p_vout->b_error )    {        /* Destroy thread structures allocated by Create and InitThread */        DestroyThread( p_vout );        return;    }    /*     * Main loop - it is not executed if an error occurred during     * initialization     */    while( (!p_vout->b_die) && (!p_vout->b_error) )    {        /* Initialize loop variables */        p_picture = NULL;        display_date = 0;        current_date = mdate();#if 0        p_vout->c_loops++;        if( !(p_vout->c_loops % VOUT_STATS_NB_LOOPS) )        {            msg_Dbg( p_vout, "picture heap: %d/%d",                     I_RENDERPICTURES, p_vout->i_heap_size );        }#endif        /*         * Find the picture to display (the one with the earliest date).         * This operation does not need lock, since only READY_PICTUREs         * are handled. */        for( i_index = 0; i_index < I_RENDERPICTURES; i_index++ )        {            if( (PP_RENDERPICTURE[i_index]->i_status == READY_PICTURE)                && ( (p_picture == NULL) ||                     (PP_RENDERPICTURE[i_index]->date < display_date) ) )            {                p_picture = PP_RENDERPICTURE[i_index];                display_date = p_picture->date;            }        }        if( p_picture )        {            /* If we met the last picture, parse again to see whether there is             * a more appropriate one. */            if( p_picture == p_last_picture )            {                for( i_index = 0; i_index < I_RENDERPICTURES; i_index++ )                {                    if( (PP_RENDERPICTURE[i_index]->i_status == READY_PICTURE)                        && (PP_RENDERPICTURE[i_index] != p_last_picture)                        && ((p_picture == p_last_picture) ||                            (PP_RENDERPICTURE[i_index]->date < display_date)) )                    {                        p_picture = PP_RENDERPICTURE[i_index];                        display_date = p_picture->date;                    }                }            }            /* If we found better than the last picture, destroy it */            if( p_last_picture && p_picture != p_last_picture )            {                vlc_mutex_lock( &p_vout->picture_lock );                if( p_last_picture->i_refcount )                {                    p_last_picture->i_status = DISPLAYED_PICTURE;                }                else                {                    p_last_picture->i_status = DESTROYED_PICTURE;                    p_vout->i_heap_size--;                }                vlc_mutex_unlock( &p_vout->picture_lock );                p_last_picture = NULL;            }            /* Compute FPS rate */            p_vout->p_fps_sample[ p_vout->c_fps_samples++ % VOUT_FPS_SAMPLES ]                = display_date;            if( !p_picture->b_force &&                p_picture != p_last_picture &&                display_date < current_date + p_vout->render_time )            {                /* Picture is late: it will be destroyed and the thread                 * will directly choose the next picture */                vlc_mutex_lock( &p_vout->picture_lock );                if( p_picture->i_refcount )                {                    /* Pretend we displayed the picture, but don't destroy                     * it since the decoder might still need it. */                    p_picture->i_status = DISPLAYED_PICTURE;                }                else                {                    /* Destroy the picture without displaying it */                    p_picture->i_status = DESTROYED_PICTURE;                    p_vout->i_heap_size--;                }                msg_Warn( p_vout, "late picture skipped ("I64Fd")",                                  current_date - display_date );                vlc_mutex_unlock( &p_vout->picture_lock );                continue;            }            if( display_date >                current_date + p_vout->i_pts_delay + VOUT_BOGUS_DELAY )            {                /* Picture is waaay too early: it will be destroyed */                vlc_mutex_lock( &p_vout->picture_lock );                if( p_picture->i_refcount )                {                    /* Pretend we displayed the picture, but don't destroy                     * it since the decoder might still need it. */                    p_picture->i_status = DISPLAYED_PICTURE;                }                else                {                    /* Destroy the picture without displaying it */                    p_picture->i_status = DESTROYED_PICTURE;                    p_vout->i_heap_size--;                }                msg_Warn( p_vout, "vout warning: early picture skipped "                          "("I64Fd")", display_date - current_date                          - p_vout->i_pts_delay );                vlc_mutex_unlock( &p_vout->picture_lock );                continue;            }            if( display_date > current_date + VOUT_DISPLAY_DELAY )            {                /* A picture is ready to be rendered, but its rendering date                 * is far from the current one so the thread will perform an                 * empty loop as if no picture were found. The picture state                 * is unchanged */                p_picture    = NULL;                display_date = 0;            }            else if( p_picture == p_last_picture )            {                /* We are asked to repeat the previous picture, but we first                 * wait for a couple of idle loops */                if( i_idle_loops < 4 )                {                    p_picture    = NULL;                    display_date = 0;                }                else                {                    /* We set the display date to something high, otherwise                     * we'll have lots of problems with late pictures */                    display_date = current_date + p_vout->render_time;                }            }        }        if( p_picture == NULL )        {            i_idle_loops++;        }        if( p_picture && p_vout->b_snapshot )        {            p_vout->b_snapshot = VLC_FALSE;            vout_Snapshot( p_vout, p_picture );        }        /*         * Check for subpictures to display         */        p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date );        /*         * Perform rendering         */        p_directbuffer = vout_RenderPicture( p_vout, p_picture, p_subpic );        /*         * Call the plugin-specific rendering method if there is one         */        if( p_picture != NULL && p_directbuffer != NULL && p_vout->pf_render )        {            /* Render the direct buffer returned by vout_RenderPicture */            p_vout->pf_render( p_vout, p_directbuffer );        }        /*         * Sleep, wake up         */        if( display_date != 0 && p_directbuffer != NULL )        {            mtime_t current_render_time = mdate() - current_date;            /* if render time is very large we don't include it in the mean */            if( current_render_time < p_vout->render_time +                VOUT_DISPLAY_DELAY )            {                /* Store render time using a sliding mean weighting to                 * current value in a 3 to 1 ratio*/                p_vout->render_time *= 3;                p_vout->render_time += current_render_time;                p_vout->render_time >>= 2;            }        }        /* Give back change lock */        vlc_mutex_unlock( &p_vout->change_lock );        /* Sleep a while or until a given date */        if( display_date != 0 )        {            /* If there are filters in the chain, better give them the picture             * in advance */            if( !p_vout->psz_filter_chain || !*p_vout->psz_filter_chain )            {                mwait( display_date - VOUT_MWAIT_TOLERANCE );            }        }        else        {            msleep( VOUT_IDLE_SLEEP );        }        /* On awakening, take back lock and send immediately picture         * to display. */        vlc_mutex_lock( &p_vout->change_lock );        /*         * Display the previously rendered picture         */        if( p_picture != NULL && p_directbuffer != NULL )        {            /* Display the direct buffer returned by vout_RenderPicture */            if( p_vout->pf_display )            {                p_vout->pf_display( p_vout, p_directbuffer );            }            /* Tell the vout this was the last picture and that it does not             * need to be forced anymore. */            p_last_picture = p_picture;            p_last_picture->b_force = 0;        }        if( p_picture != NULL )        {            /* Reinitialize idle loop count */            i_idle_loops = 0;        }        /*         * Check events and manage thread         */        if( p_vout->pf_manage && p_vout->pf_manage( p_vout ) )        {            /* A fatal error occurred, and the thread must terminate             * immediately, without displaying anything - setting b_error to 1             * causes the immediate end of the main while() loop. */            p_vout->b_error = 1;        }        if( p_vout->i_changes & VOUT_SIZE_CHANGE )        {            /* this must only happen when the vout plugin is incapable of             * rescaling the picture itself. In this case we need to destroy             * the current picture buffers and recreate new ones with the right             * dimensions */            int i;            p_vout->i_changes &= ~VOUT_SIZE_CHANGE;            p_vout->pf_end( p_vout );            for( i = 0; i < I_OUTPUTPICTURES; i++ )                 p_vout->p_picture[ i ].i_status = FREE_PICTURE;            I_OUTPUTPICTURES = 0;            if( p_vout->pf_init( p_vout ) )            {                msg_Err( p_vout, "cannot resize display" );                /* FIXME: pf_end will be called again in EndThread() */                p_vout->b_error = 1;            }            /* Need to reinitialise the chroma plugin */            if( p_vout->chroma.p_module )            {                if( p_vout->chroma.p_module->pf_deactivate )                    p_vout->chroma.p_module->pf_deactivate( VLC_OBJECT(p_vout) );                p_vout->chroma.p_module->pf_activate( VLC_OBJECT(p_vout) );            }        }        if( p_vout->i_changes & VOUT_PICTURE_BUFFERS_CHANGE )        {            /* This happens when the picture buffers need to be recreated.             * This is useful on multimonitor displays for instance.             *             * Warning: This only works when the vout creates only 1 picture             * buffer!! */            p_vout->i_changes &= ~VOUT_PICTURE_BUFFERS_CHANGE;            if( !p_vout->b_direct )            {                module_Unneed( p_vout, p_vout->chroma.p_module );            }            vlc_mutex_lock( &p_vout->picture_lock );            p_vout->pf_end( p_vout );            I_OUTPUTPICTURES = I_RENDERPICTURES = 0;            p_vout->b_error = InitThread( p_vout );            vlc_mutex_unlock( &p_vout->picture_lock );        }    }    /*     * Error loop - wait until the thread destruction is requested     */    if( p_vout->b_error )    {        ErrorThread( p_vout );    }    /* End of thread */    EndThread( p_vout );    /* Destroy thread structures allocated by CreateThread */    DestroyThread( p_vout );}/***************************************************************************** * ErrorThread: RunThread() error loop ***************************************************************************** * This function is called when an error occurred during thread main's loop. * The thread can still receive feed, but must be ready to terminate as soon * as possible. *****************************************************************************/static void ErrorThread( vout_thread_t *p_vout ){    /* Wait until a `die' order */    while( !p_vout->b_die )    {        /* Sleep a while */        msleep( VOUT_IDLE_SLEEP );    }}/***************************************************************************** * EndThread: thread destruction

⌨️ 快捷键说明

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