关于mplayer dvd seek定位函数dvd

    技术2024-08-09  61

    环境:mplayer,及它下面的stream说明:1。本文只是阅读它的代码,没有进行调试跟踪,可能有出入不对的地方.

    2。希望读者对dvd的逻辑结构有些了解,如vts, pgc, chapter, cell它们的关系.dvd如何通过时间来定位的,可通过dvd_seek_to_time来分析,看看它是如何通过时间来定位的。也就是把时间转换成sector, DVDReadBlocks中的参数offset Block它的定位就有点象物理学中的千分尺(游标卡尺),先通过时间查到所属dvd的cell,再在cell中找到时间偏移量,这时才确定dvd_read_sector所需要的cur_pack. <<DVDReadBlocks(d->title, d->cur_pack, 1, data)>>static int dvd_seek_to_time(stream_t *stream, ifo_handle_t *vts_file, double sec){    unsigned int i, j, k, timeunit, ac_time, tmap_sector=0, cell_sector=0, vobu_sector=0;    int t=0;    double tm, duration;    off_t pos = -1;    dvd_priv_t *d = stream->priv;    vts_tmapt_t *vts_tmapt = vts_file->vts_tmapt;

        if(!vts_file->vts_tmapt || sec < 0)        return 0;  //pgc时间长度。(从opes_s源代码来看,mplay是以pgc为单元来处理播放的)

        duration = (double) mp_get_titleset_length(d->vts_file, d->tt_srpt, d->cur_title-1) / 1000.0f;    if(sec > duration)      return 0;//在pgc中找到vobu的sector,用于找到所属的cell

        i=d->cur_pgc_idx;    timeunit = vts_tmapt->tmap[i].tmu;    for(j = 0; j < vts_tmapt->tmap[i].nr_of_entries; j++) {      ac_time = timeunit * (j + 1);      if(ac_time >= sec)        break;      tmap_sector = vts_tmapt->tmap[i].map_ent[j] & 0x7fffffff;    }    //search enclosing cell//定位cell,当前tmap_sector所属的dvd cell    for(i=0; i<d->cur_pgc->nr_of_cells; i++) {      if(tmap_sector >= d->cur_pgc->cell_playback[i].first_sector &&         tmap_sector <= d->cur_pgc->cell_playback[i].last_sector) {        cell_sector = d->cur_pgc->cell_playback[i].first_sector;        break;      }    }// 让查询指针指向cell的起始位置

        pos = ((off_t)cell_sector)<<11;    stream_seek(stream, pos);    do {      stream_skip(stream, 2048);      t = mp_dvdtimetomsec(&d->dsi_pack.dsi_gi.c_eltm);    } while(!t);    tm = dvd_get_current_time(stream, 0);// 让查询指针指向cell的偏移位置(tmap_sector与cell_sector在同一时刻是不同的值)

        pos = ((off_t)tmap_sector)<<11;    stream_seek(stream, pos);    //now get current time in terms of the cell+cell time offset    memset(&d->dsi_pack.dsi_gi.c_eltm, 0, sizeof(dvd_time_t));//找到sec在cell中对应的位置stream->pos.    while(tm <= sec) {        if(!stream_skip(stream, 2048))          break;        tm = dvd_get_current_time(stream, 0);    };//后面这段个人还不太理解它的作用,下面猜测可能:1。与关键帧相关以确定画面是在一个关键位置上2。tmap_sector与cell_sector对应关系的转换3. 有关文档参考:http://www.mpucoder.com/DVD/ifo.html#vam    tmap_sector = stream->pos >> 11;

        //search closest VOBU sector    k=(vts_file->vts_vobu_admap->last_byte + 1 - VOBU_ADMAP_SIZE)/4; //entries in the vobu admap    for(i=1; i<k; i++) {      if(vts_file->vts_vobu_admap->vobu_start_sectors[i] > tmap_sector)        break;    }    vobu_sector = vts_file->vts_vobu_admap->vobu_start_sectors[i-1];    pos = ((off_t)vobu_sector) << 11;    stream_seek(stream, pos);

        return 1;}这个函数多次调用stream_seek,stream_skip,从它们源代码来看,最终会调用fill_buffer->dvd_read_sector->DVDReadBlocks来定位的。以上理解有不对不处或需要补充的,请留言。

    最新回复(0)