從Mplayer.c的main開始
處理參數
mconfig = m_config_new();
m_config_register_options(mconfig,mplayer_opts);
// TODO : add something to let modules register their options
mp_input_register_options(mconfig);
parse_cfgfiles(mconfig);
初始化mpctx架構體,mpctx應該是mplayer context的意思,顧名思義是一個統籌全局的變量。
static MPContext *mpctx = &mpctx_s;
// Not all functions in mplayer.c take the context as an argument yet
static MPContext mpctx_s = {
    .osd_function = OSD_PLAY,
    .begin_skip = MP_NOPTS_VALUE,
    .play_tree_step = 1,
    .global_sub_pos = -1,
    .set_of_sub_pos = -1,
    .file_format = DEMUXER_TYPE_UNKNOWN,
    .loop_times = -1,
    #ifdef HAS_DVBIN_SUPPORT
    .last_dvb_step = 1,
    #endif
};

原型
typedef struct MPContext {
    int osd_show_percentage;
    int osd_function;
    ao_functions_t *audio_out;
    play_tree_t *playtree;
    play_tree_iter_t *playtree_iter;
    int eof;
    int play_tree_step;
    int loop_times;
    stream_t *stream;
    demuxer_t *demuxer;
    sh_audio_t *sh_audio;
    sh_video_t *sh_video;
    demux_stream_t *d_audio;
    demux_stream_t *d_video;
    demux_stream_t *d_sub;
    mixer_t mixer;
    vo_functions_t *video_out;
    // Frames buffered in the vo ready to flip. Currently always 0 or 1.
    // This is really a vo variable but currently there’s no suitable vo
    // struct.
    int num_buffered_frames;
    // AV sync: the next frame should be shown when the audio out has this
    // much (in seconds) buffered data left. Increased when more data is
    // written to the ao, decreased when moving to the next frame.
    // In the audio-only case used as a timer since the last seek
    // by the audio CPU usage meter.
    double delay;

    float begin_skip; ///< start time of the current skip while on edlout mode
                      // audio is muted if either EDL or user activates mute short edl_muted;
                      ///< Stores whether EDL is currently in muted mode. short user_muted;
                      ///< Stores whether user wanted muted mode. int global_sub_size;
                      // this encompasses all subtitle sources int global_sub_pos;
                      // this encompasses all subtitle sources int set_of_sub_pos;
    int set_of_sub_size;
    int global_sub_indices[SUB_SOURCES]; 一些GUI相關的操作,打開字幕流,打開音視頻流 mpctx->stream=open_stream(filename,0,&mpctx->file_format);
    fileformat 檔案還是TV流 DEMUXER_TYPE_PLAYLIST 或 DEMUXER_TYPE_UNKNOWN DEMUXER_TYPE_TV
    current_module 記錄狀態 vobsub open_stream handle_playlist dumpstream
    stream_reset(mpctx->stream);
    stream_seek(mpctx->stream,mpctx->stream->start_pos);
    f=fopen(stream_dump_name,"wb"); dump檔案流
    stream->type==STREAMTYPE_DVD
    //============ Open DEMUXERS ─ DETECT file type ======================
    Demux 分離視頻流和音頻流
    mpctx->demuxer=demux_open(mpctx->stream,mpctx->file_format,audio_id,video_id,dvdsub_id,filename);
    Demux 過程
    demux_open
    get_demuxer_type_from_name
    ……
    mpctx->d_audio=mpctx->demuxer->audio;
    mpctx->d_video=mpctx->demuxer->video;
    mpctx->d_sub=mpctx->demuxer->sub;
    mpctx->sh_audio=mpctx->d_audio->sh;
    mpctx->sh_video=mpctx->d_video->sh;
    分離了之後就開始分別Play audio和video
    這裡只關心play video
    /*========================== PLAY VIDEO ============================*/
    vo_pts=mpctx->sh_video->timer*90000.0;
    vo_fps=mpctx->sh_video->fps;
    if( !mpctx->num_buffered_frames ) {
        double frame_time = update_video(&blit_frame);
        mp_dbg(MSGT_AVSYNC,MSGL_DBG2,”*** ftime=%5.3f ***\n”,frame_time);
        if( mpctx->sh_video->vf_inited < 0 ) {
            mp_msg(MSGT_CPLAYER,MSGL_FATAL, MSGTR_NotInitializeVOPorVO);
            mpctx->eof = 1;
            goto goto_next_file;
        }
        if( frame_time < 0 )
            mpctx->eof = 1;
        else {
            // might return with !eof && !blit_frame if !correct_pts
            mpctx->num_buffered_frames += blit_frame;
            time_frame += frame_time / playback_speed; // for nosound
        }
    }
    關鍵的函數是 update_video
    根據 pts 是否正確調整一下同步並在必要的時候丟幀處理。
    最終呼叫 decode_video 開始解碼(包括generate_video_frame裡)。
    mpi = mpvdec->decode(sh_video, start, in_size, drop_frame);
    mpvdec 是在 main 裡透過 reinit_video_chain 的一系列調用動態選定的解碼程式。
    其實就一架構體。
    它的原型是
    typedef struct vd_functions_s
    {
        vd_info_t *info;
        int (*init)(sh_video_t *sh);
        void (*uninit)(sh_video_t *sh);
        int (*control)(sh_video_t *sh,int cmd,void* arg, …);
        mp_image_t* (*decode)(sh_video_t *sh,void* data,int len,int flags);
        } vd_functions_t;
        這是所有解碼器必須實現的界面。
        int (*init)(sh_video_t *sh);是一個名為init的指標,指向一個接受sh_video_t *類型參數,並返回int類型值的函數位址。
        那些vd_開頭的檔案都是解碼相關的。隨便打開一個vd檔案以上幾個函數和info變量肯定都包含了。
        mpi被mplayer用來存儲解碼後的圖像。在mp_image.h裡定義。
        typedef struct mp_image_s {
        unsigned short flags;
        unsigned char type;
        unsigned char bpp; // bits/pixel. NOT depth! for RGB it will be n*8
        unsigned int imgfmt;
        int width,height; // stored dimensions
        int x,y,w,h; // visible dimensions
        unsigned char* planes[MP_MAX_PLANES];
        int stride[MP_MAX_PLANES];
        char * qscale;
        int qstride;
        int pict_type; // 0->unknown, 1->I, 2->P, 3->B
        int fields;
        int qscale_type; // 0->mpeg1/4/h263, 1->mpeg2
        int num_planes;
        /* these are only used by planar formats Y,U(Cb),V(Cr) */
        int chroma_width;
        int chroma_height;
        int chroma_x_shift; // horizontal
        int chroma_y_shift; // vertical
        /* for private use by filter or vo driver (to store buffer id or dmpi) */
        void* priv;
    } mp_image_t;
    圖像在解碼以後會輸出到顯示器,mplayer本來就是一個視頻播放器器。
    但也有可能作為輸入提供給編碼器進行二次編碼,MP附帶的 mencoder.exe 就是專門用來編碼的。
    在這之前可以定義 filter 對圖像進行處理,以實現各種效果。
    所有以 vf_ 開頭的檔案,都是這樣的 filter。

    圖像的顯示是透過vo,即 video out 來實現的。
    解碼器只負責把解碼完成的幀傳給 vo,怎樣顯示就不用管了。
    這也是平台相關性最大的部分,單獨分出來的好處是不言而喻的。
    像在 Windows下有透過 direcx 實現的 vo,Linux下有輸出到X的vo。
    vo_*檔案是各種不同的vo實現,只是他們不都是以顯示為目的,像 vo_md5sum.c 只是計算一下圖像的md5值。
    在解碼完成以後,即得到 mpi 以後,filter_video 被調用。
    其結果是整個 filter 鏈上的所有 filter 都被調用了一遍。
    包括最後的VO,在vo的put_image裡把圖像輸出到顯示器。
    這個時候需要考慮的是圖像存儲的方法即用哪種色彩空間。

arrow
arrow
    全站熱搜

    BB 發表在 痞客邦 留言(0) 人氣()