kopia lustrzana https://gitlab.com/sane-project/website
425 wiersze
19 KiB
HTML
425 wiersze
19 KiB
HTML
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
|
|
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
|
<HTML>
|
|
<HEAD>
|
|
<TITLE>sane-devel: snapscan</TITLE>
|
|
<META NAME="Author" CONTENT="Christian Nassau (nassau@math.uni-frankfurt.de)">
|
|
<META NAME="Subject" CONTENT="snapscan">
|
|
</HEAD>
|
|
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
|
|
<H1>snapscan</H1>
|
|
<!-- received="Wed Jan 10 01:57:02 2001" -->
|
|
<!-- isoreceived="20010110095702" -->
|
|
<!-- sent="Wed, 10 Jan 2001 11:21:03 +0100" -->
|
|
<!-- isosent="20010110102103" -->
|
|
<!-- name="Christian Nassau" -->
|
|
<!-- email="nassau@math.uni-frankfurt.de" -->
|
|
<!-- subject="snapscan" -->
|
|
<!-- id="200101101021.LAA02078@siegel.math.uni-frankfurt.de" -->
|
|
<STRONG>From:</STRONG> Christian Nassau (<A HREF="mailto:nassau@math.uni-frankfurt.de?Subject=Re:%20snapscan&In-Reply-To=<200101101021.LAA02078@siegel.math.uni-frankfurt.de>"><EM>nassau@math.uni-frankfurt.de</EM></A>)<BR>
|
|
<STRONG>Date:</STRONG> Wed Jan 10 2001 - 02:21:03 PST
|
|
<P>
|
|
<!-- next="start" -->
|
|
<LI><STRONG>Next message:</STRONG> <A HREF="0110.html">Christian Nassau: "Re: What is interfering during xscanimage/xsane?"</A>
|
|
<UL>
|
|
<LI><STRONG>Previous message:</STRONG> <A HREF="0108.html">Christian Nassau: "sanei_scsi_cmd / snapscan / Prisa640S"</A>
|
|
<!-- nextthread="start" -->
|
|
<LI><STRONG>Next in thread:</STRONG> <A HREF="0116.html">Henning Meier-Geinitz: "Re: snapscan"</A>
|
|
<LI><STRONG>Reply:</STRONG> <A HREF="0116.html">Henning Meier-Geinitz: "Re: snapscan"</A>
|
|
<!-- reply="end" -->
|
|
<LI><STRONG>Messages sorted by:</STRONG>
|
|
<A HREF="date.html#109">[ date ]</A>
|
|
<A HREF="index.html#109">[ thread ]</A>
|
|
<A HREF="subject.html#109">[ subject ]</A>
|
|
<A HREF="author.html#109">[ author ]</A>
|
|
</UL>
|
|
<HR NOSHADE><P>
|
|
<!-- body="start" -->
|
|
<P>
|
|
Subject: snapscan / SCSISource_Get(..) / Prisa640S
|
|
<BR>
|
|
<P>Dear snapscan folks,
|
|
<BR>
|
|
<P>Opening Apology:
|
|
<BR>
|
|
* I've been working on the snapscan backend for the last two
|
|
<BR>
|
|
* weeks or so, and wrote this e-mail simultaneously.
|
|
<BR>
|
|
* In the middle of it, it turned out that I had some
|
|
<BR>
|
|
* serious misunderstandings in my mind, which sheds a new light
|
|
<BR>
|
|
* on the beginning. I didn't revise the beginning since
|
|
<BR>
|
|
* it contains some hopefully interesting observations
|
|
<BR>
|
|
* nonetheless.
|
|
<BR>
|
|
<P>Sorry, but I think we've got to begin with some
|
|
<BR>
|
|
generalities.
|
|
<BR>
|
|
<P>As a backend, we're sandwiched between two channels of limited
|
|
<BR>
|
|
capacity: the scanner (with a limited transfer speed) and the
|
|
<BR>
|
|
frontend (with a limited capability to accept data). What
|
|
<BR>
|
|
should we do then? I think we
|
|
<BR>
|
|
<P> - should respect the scanner's limitations (so that our reader
|
|
<BR>
|
|
process doesn't waste processor time), but we
|
|
<BR>
|
|
<P> - must ignore the frontend's limitations (as long as possible)
|
|
<BR>
|
|
(sounds cruel, but the alternative is to run the scanner
|
|
<BR>
|
|
in "stop-and-go" mode at a lower speed, which (at best) makes
|
|
<BR>
|
|
a strange, unpleasant sound, and in practice means that
|
|
<BR>
|
|
the scanner has to stop from time to time)
|
|
<BR>
|
|
<P>(here the term "frontend" includes any post-processing the backend
|
|
<BR>
|
|
wants to make, like inversion, chroma correction, etc..)
|
|
<BR>
|
|
<P>Currently, the reader is (at least partially) frontend-driven:
|
|
<BR>
|
|
<P> - in "blocking mode" it only tries to get as many bytes as the
|
|
<BR>
|
|
frontend requested. So it actually tries to simulate nonblocking
|
|
<BR>
|
|
mode.
|
|
<BR>
|
|
<P> - in nonblocking mode the child passes it's data through a pipe
|
|
<BR>
|
|
to the parent, where it can be requested by the frontend.
|
|
<BR>
|
|
I assume that writing to a pipe can be quite slow if too much
|
|
<BR>
|
|
data is already waiting to be read. This is also confirmed by
|
|
<BR>
|
|
the results of my debugging sessions.
|
|
<BR>
|
|
<P> (I timed these write instructions and found that towards the end
|
|
<BR>
|
|
some instructions take 4 or 5 times longer than usual.
|
|
<BR>
|
|
Also, setting READER_WRITE_SIZE to 26128980 (= size of entire
|
|
<BR>
|
|
scan area) allowed the scanner to run without stopping, the
|
|
<BR>
|
|
reason presumably being that SCSISource_get(..) then runs
|
|
<BR>
|
|
uninterrupted. (it is called only once)
|
|
<BR>
|
|
<P> An interesting test:
|
|
<BR>
|
|
"scanimage <device> > /dev/null"
|
|
<BR>
|
|
made my scanner stop from time to time, but
|
|
<BR>
|
|
"scanimage <device> -x 10 > /dev/null"
|
|
<BR>
|
|
ran uninterrupted. I assume that the scanner's intended speed
|
|
<BR>
|
|
(4.2 ms/line) should not depend on the width of the scan region,
|
|
<BR>
|
|
so this problem should be related to the amount of data that
|
|
<BR>
|
|
is generated. I found it helpful to determine exactly
|
|
<BR>
|
|
the width at which the behaviour changes, and to inspect
|
|
<BR>
|
|
the resulting debugging messages. I once found that
|
|
<BR>
|
|
- x=55 made scanner stop 3 times (towards the end)
|
|
<BR>
|
|
- x=54 made scanimage lock (had to abort it)
|
|
<BR>
|
|
- x=53 ran uninterrupted, but with an ugly sound indicating
|
|
<BR>
|
|
that it was constantly about to stop
|
|
<BR>
|
|
<P>(** I've just added a discussion of blocking/non-blocking mode
|
|
<BR>
|
|
at the end of this mail **)
|
|
<BR>
|
|
<P>By the way: the estimates done in SCSISource_get(..) have a
|
|
<BR>
|
|
systematic leak: if the expected number of bytes is larger
|
|
<BR>
|
|
than ps->absolute_max (which is approx. = SCANNER_BUF_SZ) the
|
|
<BR>
|
|
bytes that are available but don't fit into the buffer
|
|
<BR>
|
|
are forgotten when the routine is called the next time.
|
|
<BR>
|
|
The same applies to the bytes that are available, but don't
|
|
<BR>
|
|
form a full scan line. I have a modified version which
|
|
<BR>
|
|
corrects this. (I'm always referring to this version,
|
|
<BR>
|
|
which still makes the scanner stop from time to time, but
|
|
<BR>
|
|
does no longer let the expectation go down to 0 bytes.)
|
|
<BR>
|
|
<P>Isn't a SCANNER_BUF_SZ of 31744 *much* too small, and/or tuned
|
|
<BR>
|
|
to the scsi restrictions of old kernel versions? One should
|
|
<BR>
|
|
be more flexible and let the frontend suggest an appropriate
|
|
<BR>
|
|
value, and choose SCSIBUFFERMAX by default. I also suspect a
|
|
<BR>
|
|
memory leak somewhere: after changing SCANNER_BUF_SZ to a larger
|
|
<BR>
|
|
value I got segfaults, which disappeared after I declared
|
|
<BR>
|
|
snapscan_scanner.buf to be u_char[SCANNER_BUF_SZ+4096]. This
|
|
<BR>
|
|
really should be investigated.
|
|
<BR>
|
|
<P>And I wonder what measure_transferrate is doing: for some reason
|
|
<BR>
|
|
it seems to be simulating the postprocessing overhead, presumably
|
|
<BR>
|
|
to be included in the transferrate estimate. As I've said
|
|
<BR>
|
|
above, I think that is "dead wrong", an absolute no-no !
|
|
<BR>
|
|
<P>But, maybe I don't understand what the READ_TRANSTIME instruction
|
|
<BR>
|
|
is supposed to do: are *we* reading the scanners transfer speed
|
|
<BR>
|
|
from the inquiry result, or is *the scanner* estimating our
|
|
<BR>
|
|
capability to accept data, by timing the two scsi read instructions
|
|
<BR>
|
|
that we're sending? That would also explain why we have to send
|
|
<BR>
|
|
a request for 0 bytes to the scanner. It would be helpful to put
|
|
<BR>
|
|
some explanations into snapscan's source code.
|
|
<BR>
|
|
<P>**** YES! Tests show that the scanner seems to be timing our
|
|
<BR>
|
|
capability to accept data, and to adjust the ms/line value
|
|
<BR>
|
|
accordingly! This puts everything in a different perspective:
|
|
<BR>
|
|
<P> - I can get uninterrupted scans by simulating a heavy system
|
|
<BR>
|
|
load with usleep(1000) in the measure_transferrate routine
|
|
<BR>
|
|
<P> - I cannot do it by opening a pipe and simulating a write/read
|
|
<BR>
|
|
cycle. The following extract of a debugging session (of a
|
|
<BR>
|
|
real scan) indicates that writing a small amount to a newly
|
|
<BR>
|
|
opened file is probably not representative for the average
|
|
<BR>
|
|
transfer time
|
|
<BR>
|
|
...
|
|
<BR>
|
|
write_msecs=0.68
|
|
<BR>
|
|
write_msecs=0.06
|
|
<BR>
|
|
write_msecs=1.51
|
|
<BR>
|
|
write_msecs=0.03
|
|
<BR>
|
|
write_msecs=0.70
|
|
<BR>
|
|
write_msecs=0.05
|
|
<BR>
|
|
write_msecs=0.69
|
|
<BR>
|
|
write_msecs=0.68
|
|
<BR>
|
|
write_msecs=0.07
|
|
<BR>
|
|
write_msecs=1.54
|
|
<BR>
|
|
write_msecs=0.04
|
|
<BR>
|
|
write_msecs=0.73
|
|
<BR>
|
|
write_msecs=0.07
|
|
<BR>
|
|
write_msecs=1.16
|
|
<BR>
|
|
write_msecs=0.05
|
|
<BR>
|
|
write_msecs=0.69
|
|
<BR>
|
|
write_msecs=0.06
|
|
<BR>
|
|
write_msecs=0.69
|
|
<BR>
|
|
write_msecs=0.03
|
|
<BR>
|
|
write_msecs=11.83
|
|
<BR>
|
|
write_msecs=103.50
|
|
<BR>
|
|
write_msecs=0.08
|
|
<BR>
|
|
write_msecs=0.72
|
|
<BR>
|
|
write_msecs=0.07
|
|
<BR>
|
|
write_msecs=0.70
|
|
<BR>
|
|
write_msecs=0.03
|
|
<BR>
|
|
write_msecs=1.57
|
|
<BR>
|
|
write_msecs=0.07
|
|
<BR>
|
|
write_msecs=0.68
|
|
<BR>
|
|
write_msecs=0.05
|
|
<BR>
|
|
write_msecs=0.69
|
|
<BR>
|
|
...
|
|
<BR>
|
|
<P> - It seems what we should do is this:
|
|
<BR>
|
|
|
|
<BR>
|
|
If we want fast scans, the reader child should be asked
|
|
<BR>
|
|
to get all of the data as fast as it can and either
|
|
<BR>
|
|
- write the data to a pipe, or
|
|
<BR>
|
|
- write the data to a shared memory region
|
|
<BR>
|
|
in both cases we increase the memory requirements of our backend.
|
|
<BR>
|
|
If we use memory for data transfer one buffer certainly won't
|
|
<BR>
|
|
suffice, since reading from it would block data acquisition.
|
|
<BR>
|
|
What about a circle of three shared memory regions?
|
|
<BR>
|
|
Ummh, postprocessing (like chroma correction) may need to
|
|
<BR>
|
|
access two buffers for reading, which then leaves
|
|
<BR>
|
|
only one for writing, which could be a bit delicate...
|
|
<BR>
|
|
maybe we should allow N buffers, and determine N later...
|
|
<BR>
|
|
<P> Let me stress this again: the child's execution *must not*
|
|
<BR>
|
|
depend on the sane_read requests coming from the frontend
|
|
<BR>
|
|
(or, essentially equivalently, on the calls to SCSI_source_get).
|
|
<BR>
|
|
<P> The child should get all the data at a speed that is negotiated
|
|
<BR>
|
|
in the measure_transferrate routine! If we use memory (rather
|
|
<BR>
|
|
than pipes), one buffer does *not* suffice!
|
|
<BR>
|
|
<P>Using shared memory would be the best solution, since the data
|
|
<BR>
|
|
could be postprocessed in place, without having to copy it
|
|
<BR>
|
|
through a source chain. One could use the mm-library for the
|
|
<BR>
|
|
implementation of shared memory resources, but I don't know
|
|
<BR>
|
|
how good and/or portable that is.
|
|
<BR>
|
|
<P>I have actually begun to work on a modified snapscan-clone
|
|
<BR>
|
|
that uses shared memory. Unfortunately, this invalidates the
|
|
<BR>
|
|
entire SourceChain architecture of the current version,
|
|
<BR>
|
|
and inversion and chroma-correction have to be reimplemented.
|
|
<BR>
|
|
I'll make this code available when (and if) it works.
|
|
<BR>
|
|
<P>Christian
|
|
<BR>
|
|
<P>PS:
|
|
<BR>
|
|
*** Remarks on blocking/non-blocking mode
|
|
<BR>
|
|
<P>There seems to be some confusion or unclarity what one
|
|
<BR>
|
|
should mean by these terms. Note that the SANE specs
|
|
<BR>
|
|
don't say anything about it!
|
|
<BR>
|
|
<P>I would like to actually distinguish *three* different modes:
|
|
<BR>
|
|
<P>-- blocking mode (aka *strongly* blocking mode):
|
|
<BR>
|
|
all of the data is fetched from the scanner (in the
|
|
<BR>
|
|
first call to sane_read), then handed over to the frontend
|
|
<BR>
|
|
in digestable pieces
|
|
<BR>
|
|
<P>-- simulated non-blocking mode:
|
|
<BR>
|
|
program runs in strongly blocking mode but asks
|
|
<BR>
|
|
only for a convenient amount of data,
|
|
<BR>
|
|
data is then handed out to the frontend
|
|
<BR>
|
|
<P>-- non-blocking mode
|
|
<BR>
|
|
program runs in strongly blocking mode (for
|
|
<BR>
|
|
the full image), but as a background process
|
|
<BR>
|
|
<P><P><P><P>
|
|
<BR>
|
|
<P><P><P><P><PRE>
|
|
--
|
|
Source code, list archive, and docs: <A HREF="http://www.mostang.com/sane/">http://www.mostang.com/sane/</A>
|
|
To unsubscribe: echo unsubscribe sane-devel | mail <A HREF="mailto:majordomo@mostang.com?Subject=Re:%20snapscan&In-Reply-To=<200101101021.LAA02078@siegel.math.uni-frankfurt.de>">majordomo@mostang.com</A>
|
|
</PRE>
|
|
<P><!-- body="end" -->
|
|
<HR NOSHADE>
|
|
<UL>
|
|
<!-- next="start" -->
|
|
<LI><STRONG>Next message:</STRONG> <A HREF="0110.html">Christian Nassau: "Re: What is interfering during xscanimage/xsane?"</A>
|
|
<LI><STRONG>Previous message:</STRONG> <A HREF="0108.html">Christian Nassau: "sanei_scsi_cmd / snapscan / Prisa640S"</A>
|
|
<!-- nextthread="start" -->
|
|
<LI><STRONG>Next in thread:</STRONG> <A HREF="0116.html">Henning Meier-Geinitz: "Re: snapscan"</A>
|
|
<LI><STRONG>Reply:</STRONG> <A HREF="0116.html">Henning Meier-Geinitz: "Re: snapscan"</A>
|
|
<!-- reply="end" -->
|
|
<LI><STRONG>Messages sorted by:</STRONG>
|
|
<A HREF="date.html#109">[ date ]</A>
|
|
<A HREF="index.html#109">[ thread ]</A>
|
|
<A HREF="subject.html#109">[ subject ]</A>
|
|
<A HREF="author.html#109">[ author ]</A>
|
|
</UL>
|
|
<!-- trailer="footer" -->
|
|
<HR NOSHADE>
|
|
<P>
|
|
<SMALL>
|
|
<EM>
|
|
This archive was generated by <A HREF="http://www.hypermail.org/">hypermail 2b29</A>
|
|
: <EM>Wed Jan 10 2001 - 01:57:25 PST</EM>
|
|
</EM>
|
|
</SMALL>
|
|
</BODY>
|
|
</HTML>
|