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

📄 video_output.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
        picture_t *p_picture = NULL;        picture_t *p_filtered_picture;        mtime_t display_date = 0;        picture_t *p_directbuffer;        input_thread_t *p_input;        int i_index;#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        /* Update statistics */        p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );        if( p_input )        {            vlc_mutex_lock( &p_input->p->counters.counters_lock );            stats_UpdateInteger( p_vout, p_input->p->counters.p_lost_pictures,                                 i_lost , NULL);            stats_UpdateInteger( p_vout,                                 p_input->p->counters.p_displayed_pictures,                                 i_displayed , NULL);            i_displayed = i_lost = 0;            vlc_mutex_unlock( &p_input->p->counters.counters_lock );            vlc_object_release( p_input );        }        /*         * 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++ )        {            picture_t *p_pic = PP_RENDERPICTURE[i_index];            if( p_pic->i_status == READY_PICTURE &&                ( p_picture == NULL || p_pic->date < display_date ) )            {                p_picture = p_pic;                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++ )                {                    picture_t *p_pic = PP_RENDERPICTURE[i_index];                    if( p_pic->i_status == READY_PICTURE &&                        p_pic != p_last_picture &&                        ( p_picture == p_last_picture || p_pic->date < display_date ) )                    {                        p_picture = p_pic;                        display_date = p_picture->date;                    }                }            }            /* If we found better than the last picture, destroy it */            if( p_last_picture && p_picture != p_last_picture )            {                DropPicture( p_vout, p_last_picture );                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 &&                b_drop_late )            {                /* Picture is late: it will be destroyed and the thread                 * will directly choose the next picture */                DropPicture( p_vout, p_picture );                i_lost++;                msg_Warn( p_vout, "late picture skipped (%"PRId64")",                                  current_date - display_date );                continue;            }            if( display_date >                current_date + p_vout->i_pts_delay + VOUT_BOGUS_DELAY )            {                /* Picture is waaay too early: it will be destroyed */                DropPicture( p_vout, p_picture );                i_lost++;                msg_Warn( p_vout, "vout warning: early picture skipped "                          "(%"PRId64")", display_date - current_date                          - p_vout->i_pts_delay );                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++;        p_filtered_picture = NULL;        if( p_picture )            p_filtered_picture = filter_chain_VideoFilter( p_vout->p_vf2_chain,                                                           p_picture );        if( p_filtered_picture && p_vout->b_snapshot )        {            p_vout->b_snapshot = false;            vout_Snapshot( p_vout, p_filtered_picture );        }        /*         * Check for subpictures to display         */        if( display_date > 0 )        {            p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_PARENT );            p_subpic = spu_SortSubpictures( p_vout->p_spu, display_date,                                            p_input ? var_GetBool( p_input, "state" ) == PAUSE_S : false );            if( p_input )                vlc_object_release( p_input );        }        /*         * Perform rendering         */        i_displayed++;        p_directbuffer = vout_RenderPicture( p_vout, p_filtered_picture, p_subpic );        /*         * Call the plugin-specific rendering method if there is one         */        if( p_filtered_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 );        vlc_object_unlock( p_vout );        /* 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_object_lock( p_vout );        /* Note: vlc_object_alive() could be false here, and we         * could be dead */        vlc_mutex_lock( &p_vout->change_lock );        /*         * Display the previously rendered picture         */        if( p_filtered_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 = false;        }        /* Drop the filtered picture if created by video filters */        if( p_filtered_picture != NULL && p_filtered_picture != p_picture )            DropPicture( p_vout, p_filtered_picture );        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. */            // FIXME pf_end            p_vout->b_error = 1;            break;        }        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;            assert( !p_vout->b_direct );            ChromaDestroy( p_vout );            vlc_mutex_lock( &p_vout->picture_lock );            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;            }            vlc_mutex_unlock( &p_vout->picture_lock );            /* Need to reinitialise the chroma plugin. Since we might need             * resizing too and it's not sure that we already had it,             * recreate the chroma plugin chain from scratch. */            /* dionoea */            if( ChromaCreate( p_vout ) )            {                msg_Err( p_vout, "WOW THIS SUCKS BIG TIME!!!!!" );                p_vout->b_error = 1;            }            if( p_vout->b_error )                break;        }        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 )                ChromaDestroy( p_vout );            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 );            if( p_vout->b_error )                msg_Err( p_vout, "InitThread after VOUT_PICTURE_BUFFERS_CHANGE failed\n" );            vlc_mutex_unlock( &p_vout->picture_lock );            if( p_vout->b_error )                break;        }        /* Check for "video filter2" changes */        vlc_mutex_lock( &p_vout->vfilter_lock );        if( p_vout->psz_vf2 )        {            es_format_t fmt;            es_format_Init( &fmt, VIDEO_ES, p_vout->fmt_render.i_chroma );            fmt.video = p_vout->fmt_render;            filter_chain_Reset( p_vout->p_vf2_chain, &fmt, &fmt );            if( filter_chain_AppendFromString( p_vout->p_vf2_chain,                                               p_vout->psz_vf2 ) < 0 )                msg_Err( p_vout, "Video filter chain creation failed" );            free( p_vout->psz_vf2 );            p_vout->psz_vf2 = NULL;        }        vlc_mutex_unlock( &p_vout->vfilter_lock );    }    /*     * Error loop - wait until the thread destruction is requested     */    if( p_vout->b_error )        ErrorThread( p_vout );    /* End of thread */    CleanThread( p_vout );    EndThread( p_vout );    vlc_mutex_unlock( &p_vout->change_lock );    vlc_object_unlock( p_vout );    return NULL;}/***************************************************************************** * 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( vlc_object_alive( p_vout ) )        vlc_object_wait( p_vout );}/***************************************************************************** * CleanThread: clean up after InitThread ***************************************************************************** * This function is called after a sucessful * initialization. It frees all resources allocated by InitThread. * XXX You have to enter it with change_lock taken. *****************************************************************************/static void CleanThread( vout_thread_t *p_vout ){    int     i_index;                                        /* index in heap */    if( !p_vout->b_direct )        ChromaDestroy( p_vout );    /* Destroy all remaining pictures */    for( i_index = 0; i_index < 2 * VOUT_MAX_PICTURES + 1; i_index++ )    {        if ( p_vout->p_picture[i_index].i_type == MEMORY_PICTURE )        {            free( p_vout->p_picture[i_index].p_data_orig );        }    }    /* Destroy translation tables */    if( !p_vout->b_error )        p_vout->pf_end( p_vout );}/***************************************************************************** * EndThread: thread destruction ***************************************************************************** * This function is called when the thread ends. * It frees all resources not allocated by InitThread. * XXX You have to enter it with change_lock taken.

⌨️ 快捷键说明

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