From d6b04c78471b3eea40e679a558fc53289525364e Mon Sep 17 00:00:00 2001 From: Rocky Bernstein Date: Thu, 23 Dec 2004 04:01:45 +0000 Subject: [PATCH] Fill out more VCD player-independent parts. Modal (track, segment, entry) playing is better. Still frame and menu selection is still quite a mess. --- modules/access/vcdx/access.c | 400 ++++++++------------------------ modules/access/vcdx/vcdplayer.c | 250 +++++++++++++++----- modules/access/vcdx/vcdplayer.h | 8 +- 3 files changed, 293 insertions(+), 365 deletions(-) diff --git a/modules/access/vcdx/access.c b/modules/access/vcdx/access.c index c2770a0577..b7b3d72404 100644 --- a/modules/access/vcdx/access.c +++ b/modules/access/vcdx/access.c @@ -47,6 +47,9 @@ #define FREE_AND_NULL(ptr) if (NULL != ptr) free(ptr); ptr = NULL; +extern void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t *p_itemid ); + /***************************************************************************** * Local prototypes *****************************************************************************/ @@ -58,16 +61,10 @@ static int VCDControl ( access_t *p_access, int i_query, va_list args ); /* Now those which are strictly internal */ -static void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, - track_t track, - const vcdinfo_itemid_t * p_itemid ); static vlc_bool_t VCDEntryPoints ( access_t * ); static vlc_bool_t VCDLIDs ( access_t * ); static vlc_bool_t VCDSegments ( access_t * ); static int VCDTitles ( access_t * ); -static int VCDReadSector ( vlc_object_t *p_this, - const vcdinfo_obj_t *p_vcd, lsn_t i_lsn, - byte_t * p_buffer ); static char *VCDParse ( access_t *, /*out*/ vcdinfo_itemid_t * p_itemid , /*out*/ vlc_bool_t *play_single_item ); @@ -150,14 +147,11 @@ VCDReadBlock( access_t * p_access ) block_t *p_block; const int i_blocks = p_vcd->i_blocks_per_read; int i_read; - byte_t p_last_sector[ M2F2_SECTOR_SIZE ]; i_read = 0; -#if 0 - dbg_print( (INPUT_DBG_CALL), "lsn: %lu", + dbg_print( (INPUT_DBG_LSN), "lsn: %lu", (long unsigned int) p_vcd->i_lsn ); -#endif /* Allocate a block for the reading */ if( !( p_block = block_New( p_access, i_blocks * M2F2_SECTOR_SIZE ) ) ) @@ -170,95 +164,60 @@ VCDReadBlock( access_t * p_access ) for ( i_read = 0 ; i_read < i_blocks ; i_read++ ) { + const lsn_t old_lsn = p_vcd->i_lsn; - if ( p_vcd->i_lsn >= p_vcd->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: %lu, end: %u", - (long unsigned int) p_vcd->i_lsn, - p_vcd->end_lsn); - - read_status = vcdplayer_pbc_is_on( p_vcd ) - ? vcdplayer_pbc_nav( p_access ) - : vcdplayer_non_pbc_nav( p_access ); - - switch (read_status) { - case READ_END: - /* End reached. Return NULL to indicated this. */ - case READ_ERROR: - /* Some sort of error. */ - return NULL; - - case READ_STILL_FRAME: - { - /* Reached the end of a still frame. */ - byte_t * p_buf = (byte_t *) p_block->p_buffer; - - p_buf += (i_read*M2F2_SECTOR_SIZE); - memset(p_buf, 0, M2F2_SECTOR_SIZE); - p_buf += 2; - *p_buf = 0x01; - dbg_print(INPUT_DBG_STILL, "Handled still event"); - - p_vcd->in_still = VLC_TRUE; - var_SetInteger( p_access, "state", PAUSE_S ); - - return p_block; - } - default: - case READ_BLOCK: - break; - } - } - - if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd, - p_vcd->i_lsn, - (byte_t *) p_block->p_buffer - + (i_read*M2F2_SECTOR_SIZE) ) < 0 ) - { - LOG_ERR ("could not read sector %lu", - (long unsigned int) p_vcd->i_lsn ); - /* Try to skip one sector (in case of bad sectors) */ - p_vcd->i_lsn ++; - p_access->info.i_pos += M2F2_SECTOR_SIZE; - return NULL; + switch ( vcdplayer_read(p_access, (byte_t *) p_block->p_buffer + + (i_read*M2F2_SECTOR_SIZE)) ) { + case READ_END: + /* End reached. Return NULL to indicated this. */ + block_Release( p_block ); + return NULL; + case READ_ERROR: + /* Some sort of error. Should we increment lsn? to skip block? + */ + block_Release( p_block ); + return NULL; + case READ_STILL_FRAME: + { + dbg_print(INPUT_DBG_STILL, "Handled still event\n"); + /* Reached the end of a still frame. */ + byte_t * p_buf = (byte_t *) p_block->p_buffer; + + p_buf += (i_read*M2F2_SECTOR_SIZE); + memset(p_buf, 0, M2F2_SECTOR_SIZE); + p_buf += 2; + *p_buf = 0x01; + dbg_print(INPUT_DBG_STILL, "Handled still event"); + + p_vcd->in_still = VLC_TRUE; + var_SetInteger( p_access, "state", PAUSE_S ); + + return p_block; + } + + default: + case READ_BLOCK: + /* Read buffer */ + ; } - p_vcd->i_lsn ++; - p_access->info.i_pos += M2F2_SECTOR_SIZE; + p_access->info.i_pos += (p_vcd->i_lsn - old_lsn) * M2F2_SECTOR_SIZE; /* Update seekpoint */ if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcd->play_item.type ) { unsigned int i_entry = p_vcd->play_item.num+1; - - if (p_vcd->i_lsn >= vcdinfo_get_entry_lba(p_vcd->vcd, i_entry)) + lsn_t i_lsn = vcdinfo_get_entry_lba(p_vcd->vcd, i_entry); + if (p_vcd->i_lsn >= i_lsn ) { const track_t i_track = p_vcd->i_track; p_vcd->play_item.num = i_entry; dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "entry change" ); - VCDSetOrigin( p_access, - vcdinfo_get_entry_lba(p_vcd->vcd, i_entry), - i_track, &(p_vcd->play_item) ); + VCDSetOrigin( p_access, i_lsn, i_track, &(p_vcd->play_item) ); } } } - - if ( i_read != i_blocks ) /* this should not happen */ - { - if ( VCDReadSector( VLC_OBJECT(p_access), p_vcd->vcd, - p_vcd->i_lsn, p_last_sector ) < 0 ) - { - LOG_ERR ("could not read sector %lu", - (long unsigned int) p_vcd->i_lsn ); - } - - p_vcd->i_lsn ++; - return NULL; - } - + return p_block; } @@ -294,10 +253,14 @@ VCDSeek( access_t * p_access, int64_t i_pos ) break; } } - p_vcd->play_item.num = i_entry; - p_vcd->play_item.type = VCDINFO_ITEM_TYPE_ENTRY; - vcdplayer_set_origin(p_access); - VCDUpdateTitle(p_access); + + { + vcdinfo_itemid_t itemid; + itemid.num = i_entry; + itemid.type = VCDINFO_ITEM_TYPE_ENTRY; + VCDSetOrigin(p_access, p_vcd->i_lsn, p_vcd->i_track, + &itemid); + } } dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK), @@ -327,155 +290,6 @@ VCDSeek( access_t * p_access, int64_t i_pos ) } -/***************************************************************************** - VCDPlay: set up internal structures so seeking/reading places an item. - itemid: the thing to play. - user_entry: true if itemid is a user selection (rather than internally- - generated selection such as via PBC) in which case we may have to adjust - for differences in numbering. - *****************************************************************************/ -int -VCDPlay( access_t *p_access, vcdinfo_itemid_t itemid ) -{ - if (!p_access || !p_access->p_sys) return VLC_EGENERIC; - - { - - vcdplayer_t *p_vcd= (vcdplayer_t *)p_access->p_sys; -#if 0 - const vlc_bool_t b_was_still = p_vcd->in_still; -#endif - - dbg_print(INPUT_DBG_CALL, "itemid.num: %d, itemid.type: %d\n", - itemid.num, itemid.type); - - switch (itemid.type) { - case VCDINFO_ITEM_TYPE_TRACK: - - { - track_t i_track = itemid.num; - unsigned int i_entry = - vcdinfo_track_get_entry( p_vcd->vcd, i_track); - - /* Valid MPEG tracks go from 1...i_tracks. */ - - if (i_track == 0 || i_track > p_vcd->i_tracks) { - LOG_ERR ("Invalid track number %d", i_track ); - return VLC_EGENERIC; - } - p_vcd->in_still = VLC_FALSE; - VCDSetOrigin( p_access, - vcdinfo_get_entry_lba(p_vcd->vcd, i_entry), - i_track, &itemid ); - break; - } - - case VCDINFO_ITEM_TYPE_SEGMENT: - { - int i_seg = itemid.num; - - /* Valid segments go from 0...i_segments-1. */ - if (itemid.num >= p_vcd->i_segments) { - LOG_ERR ( "Invalid segment number: %d", i_seg ); - return VLC_EGENERIC; - } else { - vcdinfo_video_segment_type_t segtype = - vcdinfo_get_video_type(p_vcd->vcd, i_seg); - - dbg_print(INPUT_DBG_PBC, "%s (%d), seg_num: %d", - vcdinfo_video_type2str(p_vcd->vcd, i_seg), - (int) segtype, itemid.num); - - 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: - p_vcd->in_still = VLC_TRUE; - break; - default: - p_vcd->in_still = VLC_FALSE; - } - VCDSetOrigin( p_access, p_vcd->p_segments[i_seg], - 0, &itemid ); - } - - } - break; - - case VCDINFO_ITEM_TYPE_LID: - /* LIDs go from 1..i_lids. */ - if (itemid.num == 0 || itemid.num > p_vcd->i_lids) { - LOG_ERR ( "Invalid LID number: %d", itemid.num ); - return VLC_EGENERIC; - } else { - p_vcd->i_lid = itemid.num; - vcdinfo_lid_get_pxd(p_vcd->vcd, &(p_vcd->pxd), itemid.num); - - switch (p_vcd->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_vcd->pxd.psd == NULL) return VLC_EGENERIC; - trans_itemid_num = vcdinf_psd_get_itemid(p_vcd->pxd.psd); - vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid); - p_vcd->loop_count = 1; - p_vcd->loop_item = trans_itemid; - return VCDPlay( p_access, trans_itemid ); - break; - } - - case PSD_TYPE_PLAY_LIST: { - if (p_vcd->pxd.pld == NULL) return VLC_EGENERIC; - p_vcd->pdi = -1; - return vcdplayer_inc_play_item(p_access) - ? VLC_SUCCESS : VLC_EGENERIC; - break; - } - - case PSD_TYPE_END_LIST: - case PSD_TYPE_COMMAND_LIST: - - default: - ; - } - } - return VLC_EGENERIC; - case VCDINFO_ITEM_TYPE_ENTRY: - { - int i_entry = itemid.num; - - /* Entries go from 0..i_entries-1. */ - if (itemid.num >= p_vcd->i_entries) { - LOG_ERR ("Invalid entry number: %d", i_entry ); - return VLC_EGENERIC; - } else { - track_t i_track = vcdinfo_get_track(p_vcd->vcd, i_entry); - p_vcd->in_still = VLC_FALSE; - VCDSetOrigin( p_access, - vcdinfo_get_entry_lba(p_vcd->vcd, i_entry), - i_track, &itemid ); - } - break; - } - - default: - LOG_ERR ("unknown entry type" ); - return VLC_EGENERIC; - } - - p_vcd->play_item = itemid; - - } - - - return VLC_SUCCESS; -} - /***************************************************************************** VCDEntryPoints: Reads the information about the entry points on the disc and initializes area information with that. @@ -526,7 +340,7 @@ VCDEntryPoints( access_t * p_access ) * M2F2_SECTOR_SIZE; dbg_print( INPUT_DBG_MRL, - "%s, lsn %d, byte_offset %ld\n", + "%s, lsn %d, byte_offset %ld", s->psz_name, p_vcd->p_entries[i], (unsigned long int) s->i_byte_offset); TAB_APPEND( p_vcd->p_title[i_track-1]->i_seekpoint, @@ -553,7 +367,7 @@ VCDSegments( access_t * p_access ) p_vcd->i_segments = vcdinfo_get_num_segments(p_vcd->vcd); dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL), - "num LIDs=%d", p_vcd->i_segments); + "Segments: %d", p_vcd->i_segments); if ( 0 == p_vcd->i_segments ) return VLC_FALSE; @@ -652,7 +466,7 @@ VCDLIDs( access_t * p_access ) p_vcd->i_lid = VCDINFO_INVALID_ENTRY; dbg_print( (INPUT_DBG_CALL|INPUT_DBG_MRL), - "num LIDs=%d", p_vcd->i_lids); + "LIDs: %d", p_vcd->i_lids); if ( 0 == p_vcd->i_lids ) return VLC_FALSE; @@ -826,51 +640,57 @@ VCDParse( access_t * p_access, /*out*/ vcdinfo_itemid_t * p_itemid, /* Set's start origin subsequent seeks/reads */ -static void +void VCDSetOrigin( access_t *p_access, lsn_t i_lsn, track_t i_track, const vcdinfo_itemid_t *p_itemid ) { vcdplayer_t *p_vcd= (vcdplayer_t *)p_access->p_sys; - - unsigned int i_title = i_track - 1; /* For now */ dbg_print( (INPUT_DBG_CALL|INPUT_DBG_LSN), "i_lsn: %lu, track: %d", (long unsigned int) i_lsn, i_track ); - p_vcd->i_lsn = i_lsn; - p_vcd->i_track = i_track; - p_vcd->track_lsn = vcdinfo_get_track_lsn(p_vcd->vcd, i_track); - - p_vcd->play_item.num = p_itemid->num; - p_vcd->play_item.type = p_itemid->type; - - vcdplayer_set_origin(p_access); + vcdplayer_set_origin(p_access, i_lsn, i_track, p_itemid); p_access->info.i_pos = ( i_lsn - p_vcd->track_lsn ) * M2F2_SECTOR_SIZE; p_access->info.i_update |= INPUT_UPDATE_TITLE|INPUT_UPDATE_SIZE | INPUT_UPDATE_SEEKPOINT; - if (p_itemid->type == VCDINFO_ITEM_TYPE_ENTRY) { - VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, - "chapter", _("Entry"), "Setting entry/segment"); - p_access->info.i_title = i_track-1; - p_access->info.i_size = p_vcd->p_title[i_title]->i_size; - p_access->info.i_seekpoint = p_itemid->num; - } else if (p_itemid->type == VCDINFO_ITEM_TYPE_SEGMENT) { - VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, + + switch (p_vcd->play_item.type) { + case VCDINFO_ITEM_TYPE_ENTRY: + VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, + "chapter", _("Entry"), "Setting entry/segment"); + p_access->info.i_title = i_track-1; + p_access->info.i_size = p_vcd->p_title[i_track-1]->i_size; + p_access->info.i_seekpoint = p_itemid->num; + break; + + case VCDINFO_ITEM_TYPE_SEGMENT: + VCDUpdateVar( p_access, p_itemid->num, VLC_VAR_SETVALUE, "chapter", _("Segment"), "Setting entry/segment"); - /* The last title entry is the for segments (when segments exist - and they must here. The segment seekpoints are stored after - the entry seekpoints and (zeroed) lid seekpoints. - */ - p_access->info.i_title = p_vcd->i_titles - 1; - p_access->info.i_size = 150 * M2F2_SECTOR_SIZE; - p_access->info.i_seekpoint = p_vcd->i_entries - + p_vcd->i_lids + p_itemid->num; - + /* The last title entry is the for segments (when segments exist + and they must here. The segment seekpoints are stored after + the entry seekpoints and (zeroed) lid seekpoints. + */ + p_access->info.i_title = p_vcd->i_titles - 1; + p_access->info.i_size = 150 * M2F2_SECTOR_SIZE; + p_access->info.i_seekpoint = p_vcd->i_entries + + p_vcd->i_lids + p_itemid->num; + break; + + case VCDINFO_ITEM_TYPE_TRACK: + p_access->info.i_title = i_track-1; + p_access->info.i_size = p_vcd->p_title[i_track-1]->i_size; + p_access->info.i_seekpoint = vcdinfo_track_get_entry(p_vcd->vcd, + i_track); + break; + default: + msg_Warn( p_access, "can't set origin for play type %d", + p_vcd->play_item.type ); } + VCDUpdateTitle( p_access ); @@ -889,7 +709,7 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev ) char *actual_dev; unsigned int i; - dbg_print(INPUT_DBG_CALL, "called with %s\n", psz_dev); + dbg_print(INPUT_DBG_CALL, "called with %s", psz_dev); if( !psz_dev ) return NULL; @@ -945,34 +765,6 @@ vcd_Open( vlc_object_t *p_this, const char *psz_dev ) return p_vcdobj; } -/**************************************************************************** - * VCDReadSector: Read a sector (2324 bytes) - ****************************************************************************/ -static int -VCDReadSector( vlc_object_t *p_this, const vcdinfo_obj_t *p_vcd, - lsn_t i_lsn, byte_t * p_buffer ) -{ - 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; - - if( cdio_read_mode2_sector( vcdinfo_get_cd_image( p_vcd ), - &vcd_sector, i_lsn, VLC_TRUE ) - != 0) - { - msg_Warn( p_this, "Could not read LSN %lu", - (long unsigned int) i_lsn ); - return -1; - } - - memcpy (p_buffer, vcd_sector.data, M2F2_SECTOR_SIZE); - - return( 0 ); -} - /**************************************************************************** Update the "varname" variable to i_num without triggering a callback. ****************************************************************************/ @@ -1016,7 +808,6 @@ E_(VCDOpen) ( vlc_object_t *p_this ) vcdplayer_t *p_vcd; char *psz_source; vcdinfo_itemid_t itemid; - vlc_bool_t b_play_ok; vlc_bool_t play_single_item = VLC_FALSE; p_access->pf_read = NULL; @@ -1105,15 +896,16 @@ E_(VCDOpen) ( vlc_object_t *p_this ) msg_Warn( p_access, "could not read entry LIDs" ); } + /* Do we set PBC (via LID) on? */ + p_vcd->i_lid = + ( VCDINFO_ITEM_TYPE_LID == itemid.type && p_vcd->i_lids > itemid.num ) + ? itemid.num + : VCDINFO_INVALID_ENTRY; + /* Initialize segment information and add that a "Track". */ VCDSegments( p_access ); - b_play_ok = (VLC_SUCCESS == VCDPlay( p_access, itemid )); - - if ( ! b_play_ok ) { - vcdinfo_close( p_vcd->vcd ); - goto err_exit; - } + vcdplayer_play( p_access, itemid ); p_access->psz_demux = strdup( "ps" ); diff --git a/modules/access/vcdx/vcdplayer.c b/modules/access/vcdx/vcdplayer.c index 8e25b69618..fdb53fcb88 100644 --- a/modules/access/vcdx/vcdplayer.c +++ b/modules/access/vcdx/vcdplayer.c @@ -47,6 +47,9 @@ #define sleep(A) Sleep((A)*1000) #endif +extern void VCDSetOrigin ( access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t * p_itemid ); + /*! Return VLC_TRUE if playback control (PBC) is on */ @@ -80,7 +83,7 @@ vcdplayer_get_item_size(access_t * p_access, vcdinfo_itemid_t itemid) case VCDINFO_ITEM_TYPE_NOTFOUND: case VCDINFO_ITEM_TYPE_SPAREID2: default: - LOG_ERR("%s %d\n", _("bad item type"), itemid.type); + LOG_ERR("%s %d", _("bad item type"), itemid.type); return 0; } } @@ -97,7 +100,7 @@ vcdplayer_update_entry( access_t * p_access, uint16_t ofs, vcdinfo_offset_t *off = vcdinfo_get_offset_t(p_vcd->vcd, ofs); if (off != NULL) { *entry = off->lid; - dbg_print(INPUT_DBG_PBC, "%s: LID %d\n", label, off->lid); + dbg_print(INPUT_DBG_PBC, "%s: LID %d", label, off->lid); } else *entry = VCDINFO_INVALID_ENTRY; } @@ -119,10 +122,10 @@ vcdplayer_non_pbc_nav ( access_t *p_access ) switch (p_vcd->play_item.type) { case VCDINFO_ITEM_TYPE_TRACK: case VCDINFO_ITEM_TYPE_ENTRY: { - - dbg_print( INPUT_DBG_LSN, "new track %d, lsn %d", p_vcd->i_track+1, - vcdinfo_get_track_lsn(p_vcd->vcd, p_vcd->i_track+1) ); - return READ_END; + if ( ! vcdplayer_play_next( p_access ) ) + { + return READ_END; + } break; } case VCDINFO_ITEM_TYPE_SPAREID2: @@ -154,7 +157,6 @@ vcdplayer_non_pbc_nav ( access_t *p_access ) return READ_BLOCK; } -#if 1 /*! Set reading to play an entire track. */ @@ -171,14 +173,11 @@ _vcdplayer_set_track(access_t * p_access, track_t i_track) itemid.num = i_track; itemid.type = VCDINFO_ITEM_TYPE_TRACK; p_vcd->in_still = 0; - p_vcd->i_lsn = vcdinfo_get_track_lsn(p_obj, i_track); - p_vcd->play_item = itemid; - p_vcd->i_track = i_track; - p_vcd->track_lsn = p_vcd->i_lsn; - vcdplayer_set_origin(p_access); + VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_obj, i_track), + i_track, &itemid); - dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcd->i_lsn); + dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcd->i_lsn); } } @@ -193,7 +192,7 @@ _vcdplayer_set_entry(access_t * p_access, unsigned int num) unsigned int num_entries = vcdinfo_get_num_entries(p_obj); if (num >= num_entries) { - LOG_ERR("%s %d\n", _("bad entry number"), num); + LOG_ERR("%s %d", _("bad entry number"), num); return; } else { vcdinfo_itemid_t itemid; @@ -201,16 +200,11 @@ _vcdplayer_set_entry(access_t * p_access, unsigned int num) itemid.num = num; itemid.type = VCDINFO_ITEM_TYPE_ENTRY; p_vcd->in_still = 0; - p_vcd->i_lsn = vcdinfo_get_entry_lsn(p_obj, num); - p_vcd->play_item = itemid; - p_vcd->i_track = vcdinfo_get_track(p_obj, num); - p_vcd->track_lsn = vcdinfo_get_track_lsn(p_obj, p_vcd->i_track); - p_vcd->track_end_lsn = p_vcd->track_lsn + - p_vcd->track[p_vcd->i_track-1].size; - vcdplayer_set_origin(p_access); + VCDSetOrigin(p_access, vcdinfo_get_entry_lba(p_obj, num), + vcdinfo_get_track(p_obj, num), &itemid); - dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u\n", + dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u", p_vcd->i_lsn, p_vcd->track_end_lsn); } } @@ -226,27 +220,23 @@ _vcdplayer_set_segment(access_t * p_access, unsigned int num) segnum_t num_segs = vcdinfo_get_num_segments(p_obj); if (num >= num_segs) { - LOG_ERR("%s %d\n", _("bad segment number"), num); + LOG_ERR("%s %d", _("bad segment number"), num); return; } else { vcdinfo_itemid_t itemid; - p_vcd->i_lsn = vcdinfo_get_seg_lsn(p_obj, num); - p_vcd->i_track = 0; - if (VCDINFO_NULL_LSN==p_vcd->i_lsn) { - LOG_ERR("%s %d\n", + LOG_ERR("%s %d", _("Error in getting current segment number"), num); return; } itemid.num = num; itemid.type = VCDINFO_ITEM_TYPE_SEGMENT; - p_vcd->play_item = itemid; - vcdplayer_set_origin(p_access); + VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_obj, num), 0, &itemid); - dbg_print(INPUT_DBG_LSN, "LSN: %u\n", p_vcd->i_lsn); + dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcd->i_lsn); } } @@ -258,7 +248,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_obj = p_vcd->vcd; - dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d\n", + dbg_print(INPUT_DBG_CALL, "called itemid.num: %d, itemid.type: %d", itemid.num, itemid.type); p_vcd->in_still = 0; @@ -270,7 +260,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) = vcdinfo_get_video_type(p_obj, itemid.num); segnum_t num_segs = vcdinfo_get_num_segments(p_obj); - dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d\n", + dbg_print(INPUT_DBG_PBC, "%s (%d), itemid.num: %d", vcdinfo_video_type2str(p_obj, itemid.num), (int) segtype, itemid.num); @@ -293,7 +283,7 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) } case VCDINFO_ITEM_TYPE_TRACK: - dbg_print(INPUT_DBG_PBC, "track %d\n", itemid.num); + dbg_print(INPUT_DBG_PBC, "track %d", itemid.num); if (itemid.num < 1 || itemid.num > p_vcd->i_tracks) return; _vcdplayer_set_track(p_access, itemid.num); break; @@ -301,23 +291,23 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) case VCDINFO_ITEM_TYPE_ENTRY: { unsigned int num_entries = vcdinfo_get_num_entries(p_obj); - dbg_print(INPUT_DBG_PBC, "entry %d\n", itemid.num); + dbg_print(INPUT_DBG_PBC, "entry %d", itemid.num); if (itemid.num >= num_entries) return; _vcdplayer_set_entry(p_access, itemid.num); break; } case VCDINFO_ITEM_TYPE_LID: - LOG_ERR("%s\n", _("Should have converted p_vcd above")); + LOG_ERR("%s", _("Should have converted p_vcd above")); break; case VCDINFO_ITEM_TYPE_NOTFOUND: - dbg_print(INPUT_DBG_PBC, "play nothing\n"); + dbg_print(INPUT_DBG_PBC, "play nothing"); p_vcd->i_lsn = p_vcd->end_lsn; return; default: - LOG_ERR("item type %d not implemented.\n", itemid.type); + LOG_ERR("item type %d not implemented.", itemid.type); return; } @@ -327,11 +317,8 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) that need to be flushed when playing a new selection. */ /* if (p_vcd->flush_buffers) p_vcd->flush_buffers(); */ - } -#endif /* FINISHED */ - /* Set's start origin and size for subsequent seeks. input: p_vcd->i_lsn, p_vcd->play_item @@ -340,15 +327,24 @@ vcdplayer_play_single_item( access_t * p_access, vcdinfo_itemid_t itemid) /* FIXME: add parameters lsn, i_track, p_itemid and set accordingly. */ void -vcdplayer_set_origin(access_t *p_access) +vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t *p_itemid) { vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys; - size_t i_size= vcdplayer_get_item_size(p_access, p_vcd->play_item); - - p_vcd->end_lsn = p_vcd->i_lsn + i_size; - p_vcd->origin_lsn = p_vcd->i_lsn; - - dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN), "end LSN: %u\n", p_vcd->end_lsn); + const size_t i_size= vcdplayer_get_item_size(p_access, *p_itemid); + + p_vcd->play_item.num = p_itemid->num; + p_vcd->play_item.type = p_itemid->type; + p_vcd->i_lsn = i_lsn; + p_vcd->end_lsn = p_vcd->i_lsn + i_size; + p_vcd->origin_lsn = p_vcd->i_lsn; + p_vcd->i_track = i_track; + p_vcd->track_lsn = vcdinfo_get_track_lba(p_vcd->vcd, i_track); + + dbg_print((INPUT_DBG_CALL|INPUT_DBG_LSN), + "lsn %u, end LSN: %u item.num %d, item.type %d", + p_vcd->i_lsn, p_vcd->end_lsn, + p_vcd->play_item.num, p_vcd->play_item.type); } /* @@ -363,7 +359,7 @@ _vcdplayer_inc_play_item(access_t *p_access) vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys; int noi; - dbg_print(INPUT_DBG_CALL, "called pli: %d\n", p_vcd->pdi); + dbg_print(INPUT_DBG_CALL, "called pli: %d", p_vcd->pdi); if ( NULL == p_vcd || NULL == p_vcd->pxd.pld ) return false; @@ -385,13 +381,65 @@ _vcdplayer_inc_play_item(access_t *p_access) 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", + dbg_print(INPUT_DBG_PBC, " play-item[%d]: %s", p_vcd->pdi, vcdinfo_pin2str (trans_itemid_num)); vcdplayer_play_single_item(p_access, trans_itemid); return true; } } +void +vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid) +{ + vcdplayer_t *p_vcd = (vcdplayer_t *)p_access->p_sys; + + dbg_print(INPUT_DBG_CALL, "called itemid.num: %d itemid.type: %d", + itemid.num, itemid.type); + + if (!vcdplayer_pbc_is_on(p_vcd)) { + vcdplayer_play_single_item(p_access, itemid); + } else { + /* PBC on - Itemid.num is LID. */ + + vcdinfo_obj_t *obj = p_vcd->vcd; + + if (obj == NULL) return; + + p_vcd->i_lid = itemid.num; + vcdinfo_lid_get_pxd(obj, &(p_vcd->pxd), itemid.num); + + switch (p_vcd->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_vcd->pxd.psd == NULL) return; + trans_itemid_num = vcdinf_psd_get_itemid(p_vcd->pxd.psd); + vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid); + p_vcd->loop_count = 1; + p_vcd->loop_item = trans_itemid; + vcdplayer_play_single_item(p_access, trans_itemid); + break; + } + + case PSD_TYPE_PLAY_LIST: { + if (p_vcd->pxd.pld == NULL) return; + p_vcd->pdi = -1; + _vcdplayer_inc_play_item(p_access); + break; + } + + case PSD_TYPE_END_LIST: + case PSD_TYPE_COMMAND_LIST: + + default: + ; + } + } +} + /* Handles PBC navigation when reaching the end of a play item. */ vcdplayer_read_status_t vcdplayer_pbc_nav ( access_t * p_access ) @@ -410,7 +458,7 @@ vcdplayer_pbc_nav ( access_t * p_access ) p_vcd->play_item.num++; dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "continuing into next entry: %u", p_vcd->play_item.num); - VCDPlay( p_access, p_vcd->play_item ); + vcdplayer_play( p_access, p_vcd->play_item ); /* p_vcd->update_title(); */ return READ_BLOCK; } @@ -439,7 +487,7 @@ vcdplayer_pbc_nav ( access_t * p_access ) vcdinf_pld_get_next_offset(p_vcd->pxd.pld), &itemid.num, "next" ); itemid.type = VCDINFO_ITEM_TYPE_LID; - VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); break; } case PSD_TYPE_SELECTION_LIST: /* Selection List (+Ext. for SVCD) */ @@ -479,7 +527,7 @@ vcdplayer_pbc_nav ( access_t * p_access ) itemid.num = offset_timeout_LID->lid; itemid.type = VCDINFO_ITEM_TYPE_LID; dbg_print(INPUT_DBG_PBC, "timeout to: %d", itemid.num); - VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); return READ_BLOCK; } else { int num_selections = vcdinf_get_num_selections(p_vcd->pxd.psd); @@ -495,7 +543,7 @@ vcdplayer_pbc_nav ( access_t * p_access ) itemid.type = VCDINFO_ITEM_TYPE_LID; dbg_print(INPUT_DBG_PBC, "random selection %d, lid: %d", rand_selection - bsn, rand_lid); - VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); return READ_BLOCK; } else if (p_vcd->in_still) { /* Hack: Just go back and do still again */ @@ -523,6 +571,83 @@ vcdplayer_pbc_nav ( access_t * p_access ) 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_t +vcdplayer_read (access_t * p_access, uint8_t *p_buf) +{ + + /* p_access->handle_events (); */ + + vcdplayer_t *p_vcd= (vcdplayer_t *)p_access->p_sys; + if ( p_vcd->i_lsn >= p_vcd->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_vcd->i_lsn, p_vcd->end_lsn); + + handle_item_continuation: + read_status = vcdplayer_pbc_is_on( p_vcd ) + ? vcdplayer_pbc_nav( p_access ) + : vcdplayer_non_pbc_nav( p_access ); + + 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_vcd->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_vcd->i_lsn, true)!=0) { + dbg_print(INPUT_DBG_LSN, "read error\n"); + return READ_ERROR; + } + p_vcd->i_lsn++; + + if ( p_vcd->i_lsn >= p_vcd->end_lsn ) { + /* We've run off of the end of p_vcd entry. Do we continue or stop? */ + dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), + "end reached in reading, cur: %u, end: %u\n", + p_vcd->i_lsn, p_vcd->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_vcd->i_lsn >= p_vcd->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; + } +} + /*! 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 @@ -560,7 +685,8 @@ vcdplayer_inc_play_item( access_t *p_access ) vcdinfo_classify_itemid(trans_itemid_num, &trans_itemid); dbg_print(INPUT_DBG_PBC, " play-item[%d]: %s", p_vcd->pdi, vcdinfo_pin2str (trans_itemid_num)); - return VLC_SUCCESS == VCDPlay( p_access, trans_itemid ); + vcdplayer_play( p_access, trans_itemid ); + return VLC_SUCCESS; } } @@ -597,9 +723,9 @@ vcdplayer_play_default( access_t * p_access ) if (VCDINFO_INVALID_LID != lid) { itemid.num = lid; itemid.type = VCDINFO_ITEM_TYPE_LID; - dbg_print(INPUT_DBG_PBC, "DEFAULT to %d\n", itemid.num); + dbg_print(INPUT_DBG_PBC, "DEFAULT to %d", itemid.num); } else { - dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d\n", p_vcd->i_lid); + dbg_print(INPUT_DBG_PBC, "no DEFAULT for LID %d", p_vcd->i_lid); } #else @@ -634,7 +760,8 @@ vcdplayer_play_default( access_t * p_access ) } /** ??? p_vcd->update_title(); ***/ - return VLC_SUCCESS == VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); + return VLC_SUCCESS; } @@ -732,7 +859,8 @@ vcdplayer_play_next( access_t * p_access ) } /** ??? p_vcd->update_title(); ***/ - return VLC_SUCCESS == VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); + return VLC_SUCCESS; } @@ -797,7 +925,8 @@ vcdplayer_play_prev( access_t * p_access ) } /** ??? p_vcd->update_title(); ***/ - return VLC_SUCCESS == VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); + return VLC_SUCCESS; } @@ -855,6 +984,7 @@ vcdplayer_play_return( access_t * p_access ) } /** ??? p_vcd->update_title(); ***/ - return VLC_SUCCESS == VCDPlay( p_access, itemid ); + vcdplayer_play( p_access, itemid ); + return VLC_SUCCESS; } diff --git a/modules/access/vcdx/vcdplayer.h b/modules/access/vcdx/vcdplayer.h index fa423fe438..d592dcfd31 100644 --- a/modules/access/vcdx/vcdplayer.h +++ b/modules/access/vcdx/vcdplayer.h @@ -196,11 +196,17 @@ vcdplayer_play_return( access_t * p_access ); input: p_vcd->i_lsn, p_vcd->play_item changed: p_vcd->origin_lsn, p_vcd->end_lsn */ -void vcdplayer_set_origin(access_t * p_access); +void vcdplayer_set_origin(access_t *p_access, lsn_t i_lsn, track_t i_track, + const vcdinfo_itemid_t *p_itemid); + +void vcdplayer_play(access_t *p_access, vcdinfo_itemid_t itemid); vcdplayer_read_status_t vcdplayer_pbc_nav ( access_t * p_access ); vcdplayer_read_status_t vcdplayer_non_pbc_nav ( access_t * p_access ); +vcdplayer_read_status_t vcdplayer_read (access_t * p_access_t, + uint8_t *p_buf); + #endif /* _VCDPLAYER_H_ */ /* * Local variables: -- 2.39.2