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

📄 vcdplayer.c

📁 linux下的MPEG1
💻 C
📖 第 1 页 / 共 2 页
字号:
    p_vcdplayer->i_lsn   = vcdinfo_get_seg_lsn(p_vcdinfo, num);    p_vcdplayer->i_track = 0;    if (VCDINFO_NULL_LSN==p_vcdplayer->i_lsn) {      LOG_ERR(p_vcdplayer, "%s %d\n",               _("Error in getting current segment number"), num);      return;    }        itemid.num = num;    itemid.type = VCDINFO_ITEM_TYPE_SEGMENT;    p_vcdplayer->play_item = itemid;    _vcdplayer_set_origin(p_vcdplayer);        dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcdplayer->i_lsn);  }}/* Play entry. *//* Play a single item. */static voidvcdplayer_play_single_item(vcdplayer_t *p_vcdplayer, vcdinfo_itemid_t itemid){  vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;  dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d\n",             itemid.num, itemid.type);  p_vcdplayer->i_still = 0;  switch (itemid.type) {  case VCDINFO_ITEM_TYPE_SEGMENT:     {      vcdinfo_video_segment_type_t segtype         = vcdinfo_get_video_type(p_vcdinfo, itemid.num);      segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo);      dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d\n",                 vcdinfo_video_type2str(p_vcdinfo, itemid.num),                 (int) segtype, itemid.num);      if (itemid.num >= i_segs) return;      _vcdplayer_set_segment(p_vcdplayer, itemid.num);      vcdinfo_get_seg_resolution(p_vcdinfo, itemid.num,                                 &(p_vcdplayer->max_x),                                  &(p_vcdplayer->max_y));            switch (segtype) {      case VCDINFO_FILES_VIDEO_NTSC_STILL:      case VCDINFO_FILES_VIDEO_NTSC_STILL2:      case VCDINFO_FILES_VIDEO_PAL_STILL:      case VCDINFO_FILES_VIDEO_PAL_STILL2:        /* Note that we are reading a still frame but haven't           got to the end.        */        p_vcdplayer->i_still = STILL_READING;        break;      default:        /* */        switch (p_vcdplayer->vcd_format) {        case VCD_TYPE_VCD:        case VCD_TYPE_VCD11:        case VCD_TYPE_VCD2:          /* aspect ratio for VCD's is known to be 4:3 for any              type of VCD's */          p_vcdplayer->set_aspect_ratio(1);          break;        default: ;        }        p_vcdplayer->i_still = 0;      }            break;    }      case VCDINFO_ITEM_TYPE_TRACK:    dbg_print(INPUT_DBG_PBC, "track %d\n", itemid.num);    if (itemid.num < 1 || itemid.num > p_vcdplayer->i_tracks) return;    _vcdplayer_set_track(p_vcdplayer, itemid.num);    break;      case VCDINFO_ITEM_TYPE_ENTRY:     {      unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo);      dbg_print(INPUT_DBG_PBC, "entry %d\n", itemid.num);      if (itemid.num >= i_entries) return;      _vcdplayer_set_entry(p_vcdplayer, itemid.num);      break;    }      case VCDINFO_ITEM_TYPE_LID:    LOG_ERR(p_vcdplayer, "%s\n", _("Should have converted this above"));    break;  case VCDINFO_ITEM_TYPE_NOTFOUND:    dbg_print(INPUT_DBG_PBC, "play nothing\n");    p_vcdplayer->i_lsn = p_vcdplayer->end_lsn;    return;  default:    LOG_ERR(p_vcdplayer, "item type %d not implemented.\n", itemid.type);    return;  }    p_vcdplayer->play_item = itemid;  vcdplayer_update_nav(p_vcdplayer);  /* Some players like xine, have a fifo queue of audio and video buffers     that need to be flushed when playing a new selection. */  /*  if (p_vcdplayer->flush_buffers)      p_vcdplayer->flush_buffers(); */}/*  Get the next play-item in the list given in the LIDs. Note play-item  here refers to list of play-items for a single LID It shouldn't be  confused with a user's list of favorite things to play or the   "next" field of a LID which moves us to a different LID. */static bool_vcdplayer_inc_play_item(vcdplayer_t *p_vcdplayer){  int noi;  dbg_print(INPUT_DBG_CALL, "called pli: %d\n", p_vcdplayer->pdi);  if ( NULL == p_vcdplayer || NULL == p_vcdplayer->pxd.pld  ) return false;  noi = vcdinf_pld_get_noi(p_vcdplayer->pxd.pld);    if ( noi <= 0 ) return false;    /* Handle delays like autowait or wait here? */  p_vcdplayer->pdi++;  if ( p_vcdplayer->pdi < 0 || p_vcdplayer->pdi >= noi ) return false;  else {    uint16_t trans_itemid_num=vcdinf_pld_get_play_item(p_vcdplayer->pxd.pld,                                                        p_vcdplayer->pdi);    vcdinfo_itemid_t trans_itemid;    if (VCDINFO_INVALID_ITEMID == trans_itemid_num) return false;        vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);    dbg_print(INPUT_DBG_PBC, "  play-item[%d]: %s\n",              p_vcdplayer->pdi, vcdinfo_pin2str (trans_itemid_num));    vcdplayer_play_single_item(p_vcdplayer, trans_itemid);    return true;  }}voidvcdplayer_play(vcdplayer_t *p_vcdplayer, vcdinfo_itemid_t itemid){  dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d\n",             itemid.num, itemid.type);  if  (!vcdplayer_pbc_is_on(p_vcdplayer)) {    vcdplayer_play_single_item(p_vcdplayer, itemid);  } else {    /* PBC on - Itemid.num is LID. */    vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd;    if (p_vcdinfo == NULL) return;    p_vcdplayer->i_lid = itemid.num;    vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), itemid.num);        switch (p_vcdplayer->pxd.descriptor_type) {          case PSD_TYPE_SELECTION_LIST:    case PSD_TYPE_EXT_SELECTION_LIST: {      vcdinfo_itemid_t trans_itemid;      uint16_t trans_itemid_num;      if (p_vcdplayer->pxd.psd == NULL) return;      trans_itemid_num  = vcdinf_psd_get_itemid(p_vcdplayer->pxd.psd);      vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid);      p_vcdplayer->i_loop    = 1;      p_vcdplayer->loop_item = trans_itemid;      vcdplayer_play_single_item(p_vcdplayer, trans_itemid);      break;    }          case PSD_TYPE_PLAY_LIST: {      if (p_vcdplayer->pxd.pld == NULL) return;      p_vcdplayer->pdi = -1;      _vcdplayer_inc_play_item(p_vcdplayer);      break;    }          case PSD_TYPE_END_LIST:    case PSD_TYPE_COMMAND_LIST:          default:      ;    }  }}/*    Set's start origin and size for subsequent seeks.     input: p_vcdplayer->i_lsn, p_vcdplayer->play_item   changed: p_vcdplayer->origin_lsn, p_vcdplayer->end_lsn*/static void _vcdplayer_set_origin(vcdplayer_t *p_vcdplayer){  size_t size = _vcdplayer_get_item_size(p_vcdplayer, p_vcdplayer->play_item);  p_vcdplayer->end_lsn    = p_vcdplayer->i_lsn + size;  p_vcdplayer->origin_lsn = p_vcdplayer->i_lsn;  dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN), "end LSN: %u\n",             p_vcdplayer->end_lsn);}#define RETURN_NULL_STILL                       \  p_vcdplayer->i_still = 127;                   \  memset (p_buf, 0, M2F2_SECTOR_SIZE);          \  p_buf[0] = 0;  p_buf[1] = 0; p_buf[2] = 0x01; \  return READ_STILL_FRAME/* Handles PBC navigation when reaching the end of a play item. */static vcdplayer_read_status_tvcdplayer_pbc_nav (vcdplayer_t *p_vcdplayer, uint8_t *p_buf){  /* We are in playback control. */  vcdinfo_itemid_t itemid;  /* The end of an entry is really the end of the associated      sequence (or track). */    if ( (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) &&        (p_vcdplayer->i_lsn < p_vcdplayer->track_end_lsn) ) {    /* Set up to just continue to the next entry */    p_vcdplayer->play_item.num++;    dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),                "continuing into next entry: %u\n", p_vcdplayer->play_item.num);    vcdplayer_play_single_item(p_vcdplayer, p_vcdplayer->play_item);    p_vcdplayer->update_title();    return READ_BLOCK;  }    switch (p_vcdplayer->pxd.descriptor_type) {  case PSD_TYPE_END_LIST:    return READ_END;    break;  case PSD_TYPE_PLAY_LIST: {    int wait_time = vcdinf_get_wait_time(p_vcdplayer->pxd.pld);        dbg_print(INPUT_DBG_PBC, "playlist wait_time: %d\n", wait_time);        if (_vcdplayer_inc_play_item(p_vcdplayer))      return READ_BLOCK;    /* This needs to be improved in libvcdinfo when I get around to it.     */    if (-1 == wait_time) wait_time = STILL_INDEFINITE_WAIT;    /* Set caller to handle wait time given. */    if (STILL_READING == p_vcdplayer->i_still && wait_time > 0) {      p_vcdplayer->i_still = wait_time;      return READ_STILL_FRAME;    }    break;  }  case PSD_TYPE_SELECTION_LIST:     /* Selection List (+Ext. for SVCD) */  case PSD_TYPE_EXT_SELECTION_LIST: /* Extended Selection List (VCD2.0) */    {      int wait_time         = vcdinf_get_timeout_time(p_vcdplayer->pxd.psd);      uint16_t timeout_offs = vcdinf_get_timeout_offset(p_vcdplayer->pxd.psd);      uint16_t max_loop     = vcdinf_get_loop_count(p_vcdplayer->pxd.psd);      vcdinfo_offset_t *offset_timeout_LID =         vcdinfo_get_offset_t(p_vcdplayer->vcd, timeout_offs);            dbg_print(INPUT_DBG_PBC, "wait_time: %d, looped: %d, max_loop %d\n",                 wait_time, p_vcdplayer->i_loop, max_loop);            /* Set caller to handle wait time given. */      if (STILL_READING == p_vcdplayer->i_still && wait_time > 0) {        p_vcdplayer->i_still = wait_time;        return READ_STILL_FRAME;      }            /* Handle any looping given. */      if ( max_loop == 0 || p_vcdplayer->i_loop < max_loop ) {        p_vcdplayer->i_loop++;        if (p_vcdplayer->i_loop == 0x7f) p_vcdplayer->i_loop = 0;        vcdplayer_play_single_item(p_vcdplayer, p_vcdplayer->loop_item);        if (p_vcdplayer->i_still) p_vcdplayer->force_redisplay();        return READ_BLOCK;      }            /* Looping finished and wait finished. Move to timeout         entry or next entry, or handle still. */            if (NULL != offset_timeout_LID) {        /* Handle timeout_LID */        itemid.num  = offset_timeout_LID->lid;        itemid.type = VCDINFO_ITEM_TYPE_LID;        dbg_print(INPUT_DBG_PBC, "timeout to: %d\n", itemid.num);        vcdplayer_play(p_vcdplayer, itemid);        return READ_BLOCK;      } else {        int i_selections = vcdinf_get_num_selections(p_vcdplayer->pxd.psd);        if (i_selections > 0) {          /* Pick a random selection. */          unsigned int bsn=vcdinf_get_bsn(p_vcdplayer->pxd.psd);          int rand_selection=bsn +            (int) ((i_selections+0.0)*rand()/(RAND_MAX+1.0));          lid_t rand_lid=vcdinfo_selection_get_lid(p_vcdplayer->vcd,                                                    p_vcdplayer->i_lid,                                                   rand_selection);          itemid.num = rand_lid;          itemid.type = VCDINFO_ITEM_TYPE_LID;          dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d\n",                     rand_selection - bsn, rand_lid);          vcdplayer_play(p_vcdplayer, itemid);          return READ_BLOCK;        } else if (p_vcdplayer->i_still > 0) {          /* Hack: Just go back and do still again */          RETURN_NULL_STILL ;        }      }            break;    }  case VCDINFO_ITEM_TYPE_NOTFOUND:      LOG_ERR(p_vcdplayer, "NOTFOUND in PBC -- not supposed to happen\n");    break;  case VCDINFO_ITEM_TYPE_SPAREID2:      LOG_ERR(p_vcdplayer, "SPAREID2 in PBC -- not supposed to happen\n");    break;  case VCDINFO_ITEM_TYPE_LID:      LOG_ERR(p_vcdplayer, "LID in PBC -- not supposed to happen\n");    break;      default:    ;  }  /* FIXME: Should handle autowait ...  */  itemid.num  = p_vcdplayer->next_entry;  itemid.type = VCDINFO_ITEM_TYPE_LID;  vcdplayer_play(p_vcdplayer, itemid);  return READ_BLOCK;}/* Handles navigation when NOT in PBC reaching the end of a play item.    The navigations rules here we are sort of made up, but the intent    is to do something that's probably right or helpful.*/static vcdplayer_read_status_tvcdplayer_non_pbc_nav (vcdplayer_t *p_vcdplayer, uint8_t *p_buf){  /* Not in playback control. Do we advance automatically or stop? */  switch (p_vcdplayer->play_item.type) {  case VCDINFO_ITEM_TYPE_TRACK:  case VCDINFO_ITEM_TYPE_ENTRY:    if (p_vcdplayer->autoadvance         && p_vcdplayer->next_entry != VCDINFO_INVALID_ENTRY) {      p_vcdplayer->play_item.num=p_vcdplayer->next_entry;      vcdplayer_update_nav(p_vcdplayer);    } else       return READ_END;    break;  case VCDINFO_ITEM_TYPE_SPAREID2:      RETURN_NULL_STILL ;  case VCDINFO_ITEM_TYPE_NOTFOUND:      LOG_ERR(p_vcdplayer, "NOTFOUND outside PBC -- not supposed to happen\n");    return READ_END;    break;  case VCDINFO_ITEM_TYPE_LID:      LOG_ERR(p_vcdplayer, "LID outside PBC -- not supposed to happen\n");    return READ_END;    break;  case VCDINFO_ITEM_TYPE_SEGMENT:    /* Hack: Just go back and do still again */    RETURN_NULL_STILL ;  }  return READ_BLOCK;}/*!  Read i_len bytes into buf and return the status back.  This routine is a bit complicated because on reaching the end of   a track or entry we may automatically advance to the item, or   interpret the next item in the playback-control list.*/vcdplayer_read_status_tvcdplayer_read (vcdplayer_t *p_vcdplayer, uint8_t *p_buf,                 const off_t i_len) {  if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) {    vcdplayer_read_status_t read_status;        /* We've run off of the end of this entry. Do we continue or stop? */    dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),               "end reached, cur: %u, end: %u\n",                p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);  handle_item_continuation:    read_status = vcdplayer_pbc_is_on(p_vcdplayer)       ? vcdplayer_pbc_nav(p_vcdplayer, p_buf)       : vcdplayer_non_pbc_nav(p_vcdplayer, p_buf);    if (READ_STILL_FRAME == read_status) {      *p_buf = p_vcdplayer->i_still;      return READ_STILL_FRAME;    }    if (READ_BLOCK != read_status) return read_status;  }  /* Read the next block.          Important note: we probably speed things up by removing "data"    and the memcpy to it by extending vcd_image_source_read_mode2    to allow a mode to do what's below in addition to its     "raw" and "block" mode. It also would probably improve the modularity    a little bit as well.  */  {    CdIo_t *p_img = vcdinfo_get_cd_image(p_vcdplayer->vcd);    typedef struct {      uint8_t subheader	[CDIO_CD_SUBHEADER_SIZE];      uint8_t data	[M2F2_SECTOR_SIZE];      uint8_t spare     [4];    } vcdsector_t;    vcdsector_t vcd_sector;    do {      if (cdio_read_mode2_sector(p_img, &vcd_sector, 				 p_vcdplayer->i_lsn, true)!=0) {        dbg_print(INPUT_DBG_LSN, "read error\n");	p_vcdplayer->i_lsn++;        return READ_ERROR;      }      p_vcdplayer->i_lsn++;      if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn ) {        /* We've run off of the end of this entry. Do we continue or stop? */        dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC),                    "end reached in reading, cur: %u, end: %u\n",                    p_vcdplayer->i_lsn, p_vcdplayer->end_lsn);        break;      }            /* Check header ID for a padding sector and simply discard         these.  It is alleged that VCD's put these in to keep the         bitrate constant.      */    } while((vcd_sector.subheader[2]&~0x01)==0x60);    if ( p_vcdplayer->i_lsn >= p_vcdplayer->end_lsn )       /* We've run off of the end of this entry. Do we continue or stop? */      goto handle_item_continuation;          memcpy (p_buf, vcd_sector.data, M2F2_SECTOR_SIZE);    return READ_BLOCK;  }}/* Do if needed */void vcdplayer_send_button_update(vcdplayer_t *p_vcdplayer, const int mode){  /* dbg_print(INPUT_DBG_CALL, "Called\n"); */  return;}/*  * Local variables: *  c-file-style: "gnu" *  tab-width: 8 *  indent-tabs-mode: nil * End: */

⌨️ 快捷键说明

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