/*! Set reading to play an segment (e.g. still frame) */ static void _vcdplayer_set_segment(access_t * p_access, unsigned int num) { vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; segnum_t i_segs = vcdinfo_get_num_segments(p_vcdinfo); if (num >= i_segs) { LOG_ERR("%s %d", "bad segment number", num); return; } else { vcdinfo_itemid_t itemid; if (VCDINFO_NULL_LSN==p_vcdplayer->i_lsn) { LOG_ERR("%s %d", "Error in getting current segment number", num); return; } itemid.num = num; itemid.type = VCDINFO_ITEM_TYPE_SEGMENT; VCDSetOrigin(p_access, vcdinfo_get_seg_lsn(p_vcdinfo, num), 0, &itemid); dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn); } }
/*! Set reading to play an entire track. */ static void _vcdplayer_set_track(access_t * p_access, track_t i_track) { vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; if (i_track < 1 || i_track > p_vcdplayer->i_tracks) return; else { const vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; vcdinfo_itemid_t itemid; itemid.num = i_track; itemid.type = VCDINFO_ITEM_TYPE_TRACK; p_vcdplayer->in_still = 0; VCDSetOrigin(p_access, vcdinfo_get_track_lsn(p_vcdinfo, i_track), i_track, &itemid); dbg_print(INPUT_DBG_LSN, "LSN: %u", p_vcdplayer->i_lsn); } }
/*! Set reading to play an entry */ static void _vcdplayer_set_entry(access_t * p_access, unsigned int num) { vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_access->p_sys; vcdinfo_obj_t *p_vcdinfo = p_vcdplayer->vcd; const unsigned int i_entries = vcdinfo_get_num_entries(p_vcdinfo); if (num >= i_entries) { LOG_ERR("%s %d", "bad entry number", num); return; } else { vcdinfo_itemid_t itemid; itemid.num = num; itemid.type = VCDINFO_ITEM_TYPE_ENTRY; p_vcdplayer->i_still = 0; VCDSetOrigin(p_access, vcdinfo_get_entry_lsn(p_vcdinfo, num), vcdinfo_get_track(p_vcdinfo, num), &itemid); dbg_print(INPUT_DBG_LSN, "LSN: %u, track_end LSN: %u", p_vcdplayer->i_lsn, p_vcdplayer->track_end_lsn); } }
/**************************************************************************** * VCDSeek ****************************************************************************/ int VCDSeek( access_t * p_access, uint64_t i_pos ) { if (!p_access || !p_access->p_sys) return VLC_EGENERIC; { vcdplayer_t *p_vcdplayer = (vcdplayer_t *)p_vcd_access->p_sys; const input_title_t *t = p_vcdplayer->p_title[p_access->info.i_title]; unsigned int i_entry = VCDINFO_INVALID_ENTRY; int i_seekpoint; /* Next sector to read */ p_access->info.i_pos = i_pos; p_vcdplayer->i_lsn = (i_pos / (uint64_t) M2F2_SECTOR_SIZE) + p_vcdplayer->origin_lsn; switch (p_vcdplayer->play_item.type) { case VCDINFO_ITEM_TYPE_TRACK: case VCDINFO_ITEM_TYPE_ENTRY: break; default: p_vcdplayer->b_valid_ep = false; break; } /* Find entry */ if( p_vcdplayer->b_valid_ep ) { for( i_entry = 0 ; i_entry < p_vcdplayer->i_entries ; i_entry ++ ) { if( p_vcdplayer->i_lsn < p_vcdplayer->p_entries[i_entry] ) { VCDUpdateVar( p_access, i_entry, VLC_VAR_SETVALUE, "chapter", _("Entry"), "Setting entry" ); break; } } { vcdinfo_itemid_t itemid; itemid.num = i_entry; itemid.type = VCDINFO_ITEM_TYPE_ENTRY; VCDSetOrigin(p_access, p_vcdplayer->i_lsn, p_vcdplayer->i_track, &itemid); } } dbg_print( (INPUT_DBG_CALL|INPUT_DBG_EXT|INPUT_DBG_SEEK), "orig %lu, cur: %lu, offset: %"PRIi64", entry %d", (long unsigned int) p_vcdplayer->origin_lsn, (long unsigned int) p_vcdplayer->i_lsn, i_pos, i_entry ); /* Find seekpoint */ for( i_seekpoint = 0; i_seekpoint < t->i_seekpoint; i_seekpoint++ ) { if( i_seekpoint + 1 >= t->i_seekpoint ) break; if( i_pos < t->seekpoint[i_seekpoint + 1]->i_byte_offset ) break; } /* Update current seekpoint */ if( i_seekpoint != p_access->info.i_seekpoint ) { dbg_print( (INPUT_DBG_SEEK), "seekpoint change %lu", (long unsigned int) i_seekpoint ); p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT; p_access->info.i_seekpoint = i_seekpoint; } } p_access->info.b_eof = false; return VLC_SUCCESS; }
/***************************************************************************** VCDRead: reads VCD_BLOCKS_ONCE from the VCD and returns that. NULL is returned if something went wrong. *****************************************************************************/ static block_t * VCDReadBlock( access_t * p_access ) { vcdplayer_t *p_vcdplayer= (vcdplayer_t *)p_access->p_sys; const int i_blocks = p_vcdplayer->i_blocks_per_read; block_t *p_block; int i_read; uint8_t *p_buf; dbg_print( (INPUT_DBG_LSN), "lsn: %lu", (long unsigned int) p_vcdplayer->i_lsn ); /* Allocate a block for the reading */ if( !( p_block = block_Alloc( i_blocks * M2F2_SECTOR_SIZE ) ) ) { msg_Err( p_access, "cannot get a new block of size: %i", i_blocks * M2F2_SECTOR_SIZE ); block_Release( p_block ); return NULL; } p_buf = (uint8_t *) p_block->p_buffer; for ( i_read = 0 ; i_read < i_blocks ; i_read++ ) { vcdplayer_read_status_t read_status = vcdplayer_read(p_access, p_buf); p_access->info.i_pos += M2F2_SECTOR_SIZE; switch ( read_status ) { case READ_END: /* End reached. Return NULL to indicated this. */ /* We also set the postion to the end so the higher level (demux?) doesn't try to keep reading. If everything works out right this shouldn't have to happen. */ #if 0 if( p_access->info.i_pos != p_access->info.i_size ) { msg_Warn( p_access, "At end but pos (%llu) is not size (%llu). Adjusting.", p_access->info.i_pos, p_access->info.i_size ); p_access->info.i_pos = p_access->info.i_size; } #endif 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: /* FIXME The below should be done in an event thread. Until then... */ #if 1 msleep( INT64_C(1000) * *p_buf ); VCDSetOrigin(p_access, p_vcdplayer->origin_lsn, p_vcdplayer->i_track, &(p_vcdplayer->play_item)); // p_vcd->in_still = false; dbg_print(INPUT_DBG_STILL, "still wait time done"); #endif block_Release( p_block ); return NULL; default: case READ_BLOCK: /* Read buffer */ break; } p_buf += M2F2_SECTOR_SIZE; /* Update seekpoint */ if ( VCDINFO_ITEM_TYPE_ENTRY == p_vcdplayer->play_item.type ) { size_t i_entry = p_vcdplayer->play_item.num+1; lsn_t i_lsn = vcdinfo_get_entry_lsn(p_vcdplayer->vcd, i_entry); if ( p_vcdplayer->i_lsn >= i_lsn && i_lsn != VCDINFO_NULL_LSN ) { dbg_print( (INPUT_DBG_LSN|INPUT_DBG_PBC), "entry change to %zu, current LSN %u >= end %u", i_entry, p_vcdplayer->i_lsn, i_lsn); p_vcdplayer->play_item.num = i_entry; VCDSetOrigin( p_access, i_lsn, p_vcdplayer->i_track, &(p_vcdplayer->play_item) ); } } } return p_block; }