Many informative comments courtesy of Peter J. Creath.
External accessible routines renamed to their libcdio name.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: paranoia.c,v 1.16 2005/10/08 09:08:10 rocky Exp $
|
||||
$Id: paranoia.c,v 1.17 2005/10/14 01:20:55 rocky Exp $
|
||||
|
||||
Copyright (C) 2004, 2005 Rocky Bernstein <rocky@panix.com>
|
||||
Copyright (C) 1998 Monty xiphmont@mit.edu
|
||||
@@ -235,7 +235,7 @@ do_const_sync(c_block_t *A,
|
||||
ret=i_paranoia_overlap(cv(A), iv(B), posA, posB,
|
||||
cs(A), is(B), begin, end);
|
||||
else
|
||||
if((flagB[posB]&2)==0)
|
||||
if((flagB[posB]&FLAGS_UNREAD)==0)
|
||||
ret=i_paranoia_overlap2(cv(A), iv(B), flagA, flagB,
|
||||
posA, posB, cs(A), is(B),
|
||||
begin, end);
|
||||
@@ -1162,7 +1162,40 @@ paranoia_seek(cdrom_paranoia_t *p, off_t seek, int mode)
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* returns last block read, -1 on error */
|
||||
|
||||
|
||||
/* ===========================================================================
|
||||
* read_c_block() (internal)
|
||||
*
|
||||
* This funtion reads many (p->readahead) sectors, encompassing at least
|
||||
* the requested words.
|
||||
*
|
||||
* It returns a c_block which encapsulates these sectors' data and sector
|
||||
* number. The sectors come come from multiple low-level read requests.
|
||||
*
|
||||
* This function reads many sectors in order to exhaust any caching on the
|
||||
* drive itself, as caching would simply return the same incorrect data
|
||||
* over and over. Paranoia depends on truly re-reading portions of the
|
||||
* disc to make sure the reads are accurate and correct any inaccuracies.
|
||||
*
|
||||
* Which precise sectors are read varies ("jiggles") between calls to
|
||||
* read_c_block, to prevent consistent errors across multiple reads
|
||||
* from being misinterpreted as correct data.
|
||||
*
|
||||
* The size of each low-level read is determined by the underlying driver
|
||||
* (p->d->nsectors), which allows the driver to specify how many sectors
|
||||
* can be read in a single request. Historically, the Linux kernel could
|
||||
* only read 8 sectors at a time, with likely dropped samples between each
|
||||
* read request. Other operating systems may have different limitations.
|
||||
*
|
||||
* This function is called by paranoia_read_limited(), which breaks the
|
||||
* c_block of read data into runs of samples that are likely to be
|
||||
* contiguous, verifies them and stores them in verified fragments, and
|
||||
* eventually merges the fragments into the verified root.
|
||||
*
|
||||
* This function returns the last c_block read or NULL on error.
|
||||
*/
|
||||
|
||||
static c_block_t *
|
||||
i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
void(*callback)(long, paranoia_cb_mode_t))
|
||||
@@ -1186,6 +1219,16 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
long dynoverlap=(p->dynoverlap+CD_FRAMEWORDS-1)/CD_FRAMEWORDS;
|
||||
long anyflag=0;
|
||||
|
||||
|
||||
/* Calculate the first sector to read. This calculation takes
|
||||
* into account the need to jitter the starting point of the read
|
||||
* to reveal consistent errors as well as the low reliability of
|
||||
* the edge words of a read.
|
||||
*
|
||||
* ???: Document more clearly how dynoverlap and MIN_SECTOR_BACKUP
|
||||
* are calculated and used.
|
||||
*/
|
||||
|
||||
/* What is the first sector to read? want some pre-buffer if
|
||||
we're not at the extreme beginning of the disc */
|
||||
|
||||
@@ -1233,12 +1276,28 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
sofar=0;
|
||||
firstread=-1;
|
||||
|
||||
|
||||
/* Issue each of the low-level reads until we've read enough sectors
|
||||
* to exhaust the drive's cache.
|
||||
*
|
||||
* p->readahead = total number of sectors to read
|
||||
* p->d->nsectors = number of sectors to read per request
|
||||
*
|
||||
* The driver determines this latter number, which is the maximum
|
||||
* number of sectors the kernel can reliably read per request. In
|
||||
* old Linux kernels, there was a hard limit of 8 sectors per read.
|
||||
* While this limit has since been removed, certain motherboards
|
||||
* can't handle DMA requests larger than 64K. And other operating
|
||||
* systems may have similar limitations. So the method of splitting
|
||||
* up reads is still useful.
|
||||
*/
|
||||
|
||||
/* actual read loop */
|
||||
|
||||
while(sofar<totaltoread){
|
||||
long secread=sectatonce;
|
||||
long adjread=readat;
|
||||
long thisread;
|
||||
long secread=sectatonce; /* number of sectors to read this request */
|
||||
long adjread=readat; /* first sector to read for this request */
|
||||
long thisread; /* how many sectors were read this request */
|
||||
|
||||
/* don't under/overflow the audio session */
|
||||
if(adjread<p->current_firstsector){
|
||||
@@ -1254,8 +1313,21 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
|
||||
if (firstread<0) firstread = adjread;
|
||||
|
||||
/* Issue the low-level read to the driver.
|
||||
*/
|
||||
|
||||
thisread = cdda_read(p->d, buffer+sofar*CD_FRAMEWORDS, adjread, secread);
|
||||
|
||||
|
||||
/* If the low-level read returned too few sectors, pad the result
|
||||
* with null data and mark it as invalid (FLAGS_UNREAD). We pad
|
||||
* because we're going to be appending further reads to the current
|
||||
* c_block.
|
||||
*
|
||||
* ???: Why not re-read? It might be to keep you from getting
|
||||
* hung up on a bad sector. Or it might be to avoid interrupting
|
||||
* the streaming as much as possible.
|
||||
*/
|
||||
if ( thisread < secread) {
|
||||
|
||||
if (thisread<0) thisread=0;
|
||||
@@ -1273,6 +1345,20 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
}
|
||||
if(thisread!=0)anyflag=1;
|
||||
|
||||
|
||||
/* Because samples are likely to be dropped between read requests,
|
||||
* mark the samples near the the boundaries of the read requests
|
||||
* as suspicious (FLAGS_EDGE). This means that any span of samples
|
||||
* against which these adjacent read requests are compared must
|
||||
* overlap beyond the edges and into the more trustworthy data.
|
||||
* Such overlapping spans are accordingly at least MIN_WORDS_OVERLAP
|
||||
* words long (and naturally longer if any samples were dropped
|
||||
* between the read requests).
|
||||
*
|
||||
* (EEEEE...overlapping span...EEEEE)
|
||||
* (read 1 ...........EEEEE) (EEEEE...... read 2 ......EEEEE) ...
|
||||
* dropped samples --^
|
||||
*/
|
||||
if(flags && sofar!=0){
|
||||
/* Don't verify across overlaps that are too close to one
|
||||
another */
|
||||
@@ -1281,6 +1367,12 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
flags[sofar*CD_FRAMEWORDS+i]|=FLAGS_EDGE;
|
||||
}
|
||||
|
||||
|
||||
/* Move the read cursor ahead by the number of sectors we attempted
|
||||
* to read.
|
||||
*
|
||||
* ???: Again, why not move it ahead by the number actually read?
|
||||
*/
|
||||
p->lastread=adjread+secread;
|
||||
|
||||
if(adjread+secread-1==p->current_lastsector)
|
||||
@@ -1290,13 +1382,24 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
|
||||
sofar+=secread;
|
||||
readat=adjread+secread;
|
||||
} else
|
||||
} else /* secread <= 0 */
|
||||
if(readat<p->current_firstsector)
|
||||
readat+=sectatonce; /* due to being before the readable area */
|
||||
else
|
||||
break; /* due to being past the readable area */
|
||||
}
|
||||
|
||||
|
||||
/* Keep issuing read requests until we've read enough sectors to
|
||||
* exhaust the drive's cache.
|
||||
*/
|
||||
|
||||
} /* end while */
|
||||
|
||||
|
||||
/* If we managed to read any sectors at all (anyflag), create a new
|
||||
* c_block containing the read data. Otherwise, free our buffers and
|
||||
* return NULL.
|
||||
*/
|
||||
if (anyflag) {
|
||||
new->vector=buffer;
|
||||
new->begin=firstread*CD_FRAMEWORDS-p->dyndrift;
|
||||
@@ -1311,11 +1414,20 @@ i_read_c_block(cdrom_paranoia_t *p,long beginword,long endword,
|
||||
return(new);
|
||||
}
|
||||
|
||||
/* The returned buffer is *not* to be freed by the caller. It will
|
||||
persist only until the next call to paranoia_read() for this p */
|
||||
|
||||
/** ==========================================================================
|
||||
* cdio_paranoia_read(), cdio_paranoia_read_limited()
|
||||
*
|
||||
* These functions "read" the next sector of audio data and returns
|
||||
* a pointer to a full sector of verified samples (2352 bytes).
|
||||
*
|
||||
* The returned buffer is *not* to be freed by the caller. It will
|
||||
* persist only until the next call to paranoia_read() for this p
|
||||
*/
|
||||
|
||||
int16_t *
|
||||
paranoia_read(cdrom_paranoia_t *p, void(*callback)(long, paranoia_cb_mode_t))
|
||||
cdio_paranoia_read(cdrom_paranoia_t *p,
|
||||
void(*callback)(long, paranoia_cb_mode_t))
|
||||
{
|
||||
return paranoia_read_limited(p, callback, 20);
|
||||
}
|
||||
@@ -1324,7 +1436,7 @@ paranoia_read(cdrom_paranoia_t *p, void(*callback)(long, paranoia_cb_mode_t))
|
||||
breaking any old apps using the nerw libs. cdparanoia 9.8 will
|
||||
need the updated libs, but nothing else will require it. */
|
||||
int16_t *
|
||||
paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
cdio_paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
void(*callback)(long int, paranoia_cb_mode_t),
|
||||
int max_retries)
|
||||
{
|
||||
@@ -1338,6 +1450,16 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
p->root.returnedlimit=beginword;
|
||||
lastend=re(root);
|
||||
|
||||
|
||||
/* Since paranoia reads and verifies chunks of data at a time
|
||||
* (which it needs to counteract dropped samples and inaccurate
|
||||
* seeking), the requested samples may already be in memory,
|
||||
* in the verified "root".
|
||||
*
|
||||
* The root is where paranoia stores samples that have been
|
||||
* verified and whose position has been accurately determined.
|
||||
*/
|
||||
|
||||
/* First, is the sector we want already in the root? */
|
||||
while(rv(root)==NULL ||
|
||||
rb(root)>beginword ||
|
||||
@@ -1347,13 +1469,36 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
|
||||
/* Nope; we need to build or extend the root verified range */
|
||||
|
||||
/* We may have already read the necessary samples and placed
|
||||
* them into verified fragments, but not yet merged them into
|
||||
* the verified root. We'll check that before we actually
|
||||
* try to read data from the drive.
|
||||
*/
|
||||
|
||||
if(p->enable&(PARANOIA_MODE_VERIFY|PARANOIA_MODE_OVERLAP)){
|
||||
|
||||
/* We need to make sure our memory consumption doesn't grow
|
||||
* to the size of the whole CD. But at the same time, we
|
||||
* need to hang onto some of the verified data (even perhaps
|
||||
* data that's already been returned by paranoia_read()) in
|
||||
* order to verify and accurately position future samples.
|
||||
*
|
||||
* Therefore, we free some of the verified data that we
|
||||
* no longer need.
|
||||
*/
|
||||
i_paranoia_trim(p,beginword,endword);
|
||||
recover_cache(p);
|
||||
|
||||
if(rb(root)!=-1 && p->root.lastsector)
|
||||
i_end_case(p, endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
|
||||
callback);
|
||||
else
|
||||
|
||||
/* Merge as many verified fragments into the verified root
|
||||
* as we need to satisfy the pending request. We may
|
||||
* not have all the fragments we need, in which case we'll
|
||||
* read data from the CD further below.
|
||||
*/
|
||||
i_stage2(p, beginword,
|
||||
endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
|
||||
callback);
|
||||
@@ -1361,6 +1506,9 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
i_end_case(p,endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS),
|
||||
callback); /* only trips if we're already done */
|
||||
|
||||
/* If we were able to fill the verified root with data already
|
||||
* in memory, we don't need to read any more data from the drive.
|
||||
*/
|
||||
if(!(rb(root)==-1 || rb(root)>beginword ||
|
||||
re(root)<endword+(MAX_SECTOR_OVERLAP*CD_FRAMEWORDS)))
|
||||
break;
|
||||
@@ -1368,13 +1516,35 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
/* Hmm, need more. Read another block */
|
||||
|
||||
{
|
||||
/* Read many sectors, encompassing at least the requested words.
|
||||
*
|
||||
* The returned c_block encapsulates these sectors' data and
|
||||
* sector number. The sectors come come from multiple low-level
|
||||
* read requests, and words which were near the boundaries of
|
||||
* those read requests are marked with FLAGS_EDGE.
|
||||
*/
|
||||
c_block_t *new=i_read_c_block(p,beginword,endword,callback);
|
||||
|
||||
if(new){
|
||||
if(p->enable&(PARANOIA_MODE_OVERLAP|PARANOIA_MODE_VERIFY)){
|
||||
|
||||
/* If we need to verify these samples, send them to
|
||||
* stage 1 verification, which will add verified samples
|
||||
* to the set of verified fragments. Verified fragments
|
||||
* will be merged into the verified root during stage 2
|
||||
* overlap analysis.
|
||||
*/
|
||||
if(p->enable&PARANOIA_MODE_VERIFY)
|
||||
i_stage1(p,new,callback);
|
||||
|
||||
/* If we're only doing overlapping reads (no stage 1
|
||||
* verification), consider each low-level read in the
|
||||
* c_block to be a verified fragment. We exclude the
|
||||
* edges from these fragments to enforce the requirement
|
||||
* that we overlap the reads by the minimum amount.
|
||||
* These fragments will be merged into the verified
|
||||
* root during stage 2 overlap analysis.
|
||||
*/
|
||||
else{
|
||||
/* just make v_fragments from the boundary information. */
|
||||
long begin=0,end=0;
|
||||
@@ -1394,6 +1564,11 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
|
||||
}else{
|
||||
|
||||
/* If we're not doing any overlapping reads or verification
|
||||
* of data, skip over the stage 1 and stage 2 verification and
|
||||
* promote this c_block directly to the current "verified" root.
|
||||
*/
|
||||
|
||||
if(p->root.vector)i_cblock_destructor(p->root.vector);
|
||||
free_elem(new->e,0);
|
||||
p->root.vector=new;
|
||||
@@ -1407,6 +1582,9 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
|
||||
/* Are we doing lots of retries? **************************************/
|
||||
|
||||
/* ???: To be studied
|
||||
*/
|
||||
|
||||
/* Check unaddressable sectors first. There's no backoff here;
|
||||
jiggle and minimum backseek handle that for us */
|
||||
|
||||
@@ -1438,15 +1616,25 @@ paranoia_read_limited(cdrom_paranoia_t *p,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Having read data from the drive and placed it into verified
|
||||
* fragments, we now loop back to try to extend the root with
|
||||
* the newly loaded data. Alternatively, if the root already
|
||||
* contains the needed data, we'll just fall through.
|
||||
*/
|
||||
|
||||
} /* end while */
|
||||
p->cursor++;
|
||||
|
||||
/* Return a pointer into the verified root. Thus, the caller
|
||||
* must NOT free the returned pointer!
|
||||
*/
|
||||
return(rv(root)+(beginword-rb(root)));
|
||||
}
|
||||
|
||||
/* a temporary hack */
|
||||
void
|
||||
paranoia_overlapset(cdrom_paranoia_t *p, long int overlap)
|
||||
cdio_paranoia_overlapset(cdrom_paranoia_t *p, long int overlap)
|
||||
{
|
||||
p->dynoverlap=overlap*CD_FRAMEWORDS;
|
||||
p->stage1.offpoints=-1;
|
||||
|
||||
Reference in New Issue
Block a user