📄 vcdplayer.c
字号:
return READ_STILL_FRAME; } /* Wait time has been processed; continue with next entry. */ vcdplayer_update_entry( p_access, vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld), &itemid.num, "next" ); itemid.type = VCDINFO_ITEM_TYPE_LID; vcdplayer_play( p_access, itemid ); break; } case PSD_TYPE_SELECTION_LIST: /* Selection List (+Ext. for SVCD) */ case PSD_TYPE_EXT_SELECTION_LIST: /* Extended Selection List (VCD2.0) */ { 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, "looped: %d, max_loop %d", p_vcdplayer->i_loop, max_loop); /* Set up for caller process wait time given. */ if (p_vcdplayer->i_still) { *wait_time = vcdinf_get_timeout_time(p_vcdplayer->pxd.psd); dbg_print((INPUT_DBG_PBC|INPUT_DBG_STILL), "playlist wait_time: %d", *wait_time); return READ_STILL_FRAME; } /* Wait time has been processed; continue with next entry. */ /* 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_access, 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", itemid.num); vcdplayer_play( p_access, 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", rand_selection - bsn, rand_lid); vcdplayer_play( p_access, itemid ); return READ_BLOCK; } else if (p_vcdplayer->i_still) { /* Hack: Just go back and do still again */ msleep(1000); return READ_STILL_FRAME; } } break; } case VCDINFO_ITEM_TYPE_NOTFOUND: LOG_ERR( "NOTFOUND in PBC -- not supposed to happen" ); break; case VCDINFO_ITEM_TYPE_SPAREID2: LOG_ERR( "SPAREID2 in PBC -- not supposed to happen" ); break; case VCDINFO_ITEM_TYPE_LID: LOG_ERR( "LID in PBC -- not supposed to happen" ); break; default: ; } /* FIXME: Should handle autowait ... */ return READ_ERROR;}/*! Read block into p_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 (access_t * p_access, uint8_t *p_buf){ /* p_access->handle_events (); */ uint8_t wait_time; vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; 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_access, &wait_time ) : vcdplayer_non_pbc_nav( p_access, &wait_time ); if (READ_STILL_FRAME == read_status) { *p_buf = wait_time; 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 *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; }}/*! Play item assocated with the "default" selection. Return false if there was some problem.*/bool vcdplayer_play_default( access_t * p_access ){ vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; vcdinfo_itemid_t itemid; if (!p_vcdplayer) { dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC), "null p_vcdplayer" ); return VLC_EGENERIC; } dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC), "current: %d" , p_vcdplayer->play_item.num); itemid.type = p_vcdplayer->play_item.type; if (vcdplayer_pbc_is_on(p_vcdplayer)) {#if defined(LIBVCD_VERSION) lid_t lid=vcdinfo_get_multi_default_lid(p_vcdplayer->vcd, p_vcdplayer->i_lid, p_vcdplayer->i_lsn); if (VCDINFO_INVALID_LID != lid) { itemid.num = lid; itemid.type = VCDINFO_ITEM_TYPE_LID; dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num); } else { dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcdplayer->i_lid); return VLC_EGENERIC; }#else vcdinfo_lid_get_pxd(p_vcdplayer->vcd, &(p_vcdplayer->pxd), p_vcdplayer->i_lid); switch (p_vcdplayer->pxd.descriptor_type) { case PSD_TYPE_SELECTION_LIST: case PSD_TYPE_EXT_SELECTION_LIST: if (p_vcdplayer->pxd.psd == NULL) return false; vcdplayer_update_entry( p_access, vcdinfo_get_default_offset(p_vcdplayer->vcd, p_vcdplayer->i_lid), &itemid.num, "default"); break; case PSD_TYPE_PLAY_LIST: case PSD_TYPE_END_LIST: case PSD_TYPE_COMMAND_LIST: LOG_WARN( "There is no PBC 'default' selection here" ); return false; }#endif /* LIBVCD_VERSION (< 0.7.21) */ } else { /* PBC is not on. "default" selection beginning of current selection . */ itemid.num = p_vcdplayer->play_item.num; } /** ??? p_vcdplayer->update_title(); ***/ vcdplayer_play( p_access, itemid ); return VLC_SUCCESS;}/*! Play item assocated with the "next" selection. Return false if there was some problem.*/bool vcdplayer_play_next( access_t * p_access ){ vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo; vcdinfo_itemid_t itemid; if (!p_vcdplayer) return false; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC), "current: %d" , p_vcdplayer->play_item.num); p_vcdinfo = p_vcdplayer->vcd; itemid = p_vcdplayer->play_item; if (vcdplayer_pbc_is_on(p_vcdplayer)) { vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid); switch (p_vcdplayer->pxd.descriptor_type) { case PSD_TYPE_SELECTION_LIST: case PSD_TYPE_EXT_SELECTION_LIST: if (p_vcdplayer->pxd.psd == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_psd_get_next_offset(p_vcdplayer->pxd.psd), &itemid.num, "next"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_PLAY_LIST: if (p_vcdplayer->pxd.pld == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_pld_get_next_offset(p_vcdplayer->pxd.pld), &itemid.num, "next"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_END_LIST: case PSD_TYPE_COMMAND_LIST: LOG_WARN( "There is no PBC 'next' selection here" ); return false; } } else { /* PBC is not on. "Next" selection is play_item.num+1 if possible. */ int max_entry = 0; switch (p_vcdplayer->play_item.type) { case VCDINFO_ITEM_TYPE_ENTRY: case VCDINFO_ITEM_TYPE_SEGMENT: case VCDINFO_ITEM_TYPE_TRACK: switch (p_vcdplayer->play_item.type) { case VCDINFO_ITEM_TYPE_ENTRY: max_entry = p_vcdplayer->i_entries; break; case VCDINFO_ITEM_TYPE_SEGMENT: max_entry = p_vcdplayer->i_segments; break; case VCDINFO_ITEM_TYPE_TRACK: max_entry = p_vcdplayer->i_tracks; break; default: ; /* Handle exceptional cases below */ } if (p_vcdplayer->play_item.num+1 < max_entry) { itemid.num = p_vcdplayer->play_item.num+1; } else { LOG_WARN( "At the end - non-PBC 'next' not possible here" ); return false; } break; case VCDINFO_ITEM_TYPE_LID: { /* Should have handled above. */ LOG_WARN( "Internal inconsistency - should not have gotten here." ); return false; } default: return false; } } /** ??? p_vcdplayer->update_title(); ***/ vcdplayer_play( p_access, itemid ); return VLC_SUCCESS;}/*! Play item assocated with the "prev" selection. Return false if there was some problem.*/bool vcdplayer_play_prev( access_t * p_access ){ vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; vcdinfo_itemid_t itemid; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC), "current: %d" , p_vcdplayer->play_item.num); itemid = p_vcdplayer->play_item; if (vcdplayer_pbc_is_on(p_vcdplayer)) { vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid); switch (p_vcdplayer->pxd.descriptor_type) { case PSD_TYPE_SELECTION_LIST: case PSD_TYPE_EXT_SELECTION_LIST: if (p_vcdplayer->pxd.psd == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_psd_get_prev_offset(p_vcdplayer->pxd.psd), &itemid.num, "prev"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_PLAY_LIST: if (p_vcdplayer->pxd.pld == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_pld_get_prev_offset(p_vcdplayer->pxd.pld), &itemid.num, "prev"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_END_LIST: case PSD_TYPE_COMMAND_LIST: LOG_WARN( "There is no PBC 'prev' selection here" ); return false; } } else { /* PBC is not on. "Prev" selection is play_item.num-1 if possible. */ int min_entry = (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) ? 0 : 1; if (p_vcdplayer->play_item.num > min_entry) { itemid.num = p_vcdplayer->play_item.num-1; } else { LOG_WARN( "At the beginning - non-PBC 'prev' not possible here" ); return false; } } /** ??? p_vcdplayer->update_title(); ***/ vcdplayer_play( p_access, itemid ); return VLC_SUCCESS;}/*! Play item assocated with the "return" selection. Return false if there was some problem.*/bool vcdplayer_play_return( access_t * p_access ){ vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; vcdinfo_itemid_t itemid; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_PBC), "current: %d" , p_vcdplayer->play_item.num); itemid = p_vcdplayer->play_item; if (vcdplayer_pbc_is_on(p_vcdplayer)) { vcdinfo_lid_get_pxd(p_vcdinfo, &(p_vcdplayer->pxd), p_vcdplayer->i_lid); switch (p_vcdplayer->pxd.descriptor_type) { case PSD_TYPE_SELECTION_LIST: case PSD_TYPE_EXT_SELECTION_LIST: if (p_vcdplayer->pxd.psd == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_psd_get_return_offset(p_vcdplayer->pxd.psd), &itemid.num, "return"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_PLAY_LIST: if (p_vcdplayer->pxd.pld == NULL) return false; vcdplayer_update_entry( p_access, vcdinf_pld_get_return_offset(p_vcdplayer->pxd.pld), &itemid.num, "return"); itemid.type = VCDINFO_ITEM_TYPE_LID; break; case PSD_TYPE_END_LIST: case PSD_TYPE_COMMAND_LIST: LOG_WARN( "There is no PBC 'return' selection here" ); return false; } } else { /* PBC is not on. "Return" selection is min_entry if possible. */ p_vcdplayer->play_item.num = (VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type) ? 0 : 1; } /** ??? p_vcdplayer->update_title(); ***/ vcdplayer_play( p_access, itemid ); return VLC_SUCCESS;}/* * Local variables: * c-file-style: "gnu" * tab-width: 8 * indent-tabs-mode: nil * End: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -