This used global variables for the asynchronous interrupt callback.
Pick the simple and dumb solution and stuff the callback into
mpv_global. Do this because interrupt checking should also work in the
connect phase, and currently stream creation equates connecting.
Ideally, this would be passed to the stream on creation instead, or
connecting would be separated from creation. But since I don't know yet
which is better, and since moving stream/demuxer into their own thread
is something that will happen later, go with the mpv_global solution.
This is the only function which actually used the time argument of
stream_check_interrupt(). Considering that the whole player freezes
anyway, this is not worth the complication.
Also generally reduce the maximum wait time due to timeout. Introduce
exponential backoff, which makes the first reconnect retries faster, but
still waits up to 500ms in the later retries.
Fix all include statements of the form:
#include "libav.../..."
These come from MPlayer times, when FFmpeg was somehow part of the
MPlayer build tree, and this form was needed to prefer the local files
over system FFmpeg.
In some cases, the include statement wasn't needed or could be replaced
with mpv defined symbols.
This was accidentally completely destroyed with commit 24f1878e. I
didn't notice it when testing, because forward seeking still worked
mostly.
The issue was that dvd_seek_to_time() actually called stream_seek(),
which was supposed to call the byte-level seek function dvd_seek(). So
we have to restore this function, and replace all generic stream calls
with stream_dvd.c internal ones. This also affects stream->pos (now a
random number as far as stream_dvd.c is concerned) and stream_skip().
I hate tabs.
This replaces all tabs in all source files with spaces. The only
exception is old-makefile. The replacement was made by running the
GNU coreutils "expand" command on every file. Since the replacement was
automatic, it's possible that some formatting was destroyed (but perhaps
only if it was assuming that the end of a tab does not correspond to
aligning the end to multiples of 8 spaces).
This was broken at some unknown point (even before the recent cache
changes). There are several problems:
- stream_dvd returning a random stream position, confusing the cache
layer (cached data and stream data lost their 1:1 corrospondence by
position)
- this also confused the mechanism added with commit a9671524, which
basically triggered random seeking (although this was not the only
problem)
- demux_lavf requesting seeks in the stream layer, which resulted in
seeks in the cache or the real stream
Fix this by completely removing byte-based seeking from stream_dvd. This
already works fine for stream_dvdnav and stream_bluray. Now all these
streams do time-based seeks, and pretend to be infinite streams of data,
and the rest of the player simply doesn't care about the stream byte
positions.
resize_cache() checks the size itself and clamps the size to the valid
range if necessary, so we don't need these checks. In fact, the checks
are different. Also, output the cache size after clamping, instead of
before.
Use NtQueryVolumeInformationFile instead of GetDriveType for detecting
remote filesystems on Windows. This has the advantage of working
directly on the file handle instead of needing a path and it works
unmodified in Cygwin where the previous code wouldn't understand Cygwin
paths or symlinks.
There is some risk in using NtQueryVolumeInformationFile, since it's an
internal function and its behaviour could change at any time or it could
be removed in a future version of Windows, however it's documented[1] in
the WDK and it's used successfully by Cygwin, so it should be fine. If
it's removed, the code should fail gracefully by treating all files as
local.
[1]: http://msdn.microsoft.com/en-us/library/windows/hardware/ff567070.aspx
Signed-off-by: wm4 <wm4@nowhere>
Merge the cache_read function into cache_fill_buffer, since there's
not much reason to keep them separate. Also, simply call read_buffer()
to see if there's any readable data, instead of checking for the
condition manually.
The only tricky part is keeping the cache contents, which is made simple
by allocating the new cache while still keeping the old cache around,
and then copying the old data.
To explain the "Don't use this when playing DVD or Bluray." comment: the
cache also associates timestamps to blocks of bytes, but throws away the
timestamps on seek. Thus you will experience strange behavior after
resizing the cache until the old cached region is exhausted.
The only difference is that the MP_DBG message is not printed anymore if
the current user read position is outside of the current cache range.
(In order to handle seek_limit==0 gracefully in the normal case of
linear reading, change the comparison from ">=" to ">".)
Until now, this could never happen, because new data was simply always
appended to the end of the cache. But for making stream cache resizing
easier, doing it this way seems advantageous. It also makes it harder to
make the internal state inconsistent. (Before this change it could
happen that cache and stream position went out of sync if the read
position was adjusted "inappropriately".)
Until now, cache_read() (which calls read_buffer()) could return short
reads. This was a simplification allowed by the stream interface. But
for cache resizing, it will be more practical to make read_buffer() do
a full read.
Seems like a good idea. One possible bad effect would be slowing down
uncached controls, but they're already slow. The good thing is that
many controls make intrusive changes to the stream (at least controls
which do write accesses), so the cached parameters should be updated.
There are two kind of encryption for Blu-ray disc, AACS and BD+,
and both of them can be checked through BLURAY_DISC_INFO object.
This commit makes the bluray and bdnav streams refuse playback
if AACS/BD+ is detected and decryption is failed.
The angles should be set and queried only if a valid title is
selected. Also, in navigation mode, there are some limitations
which make it impossible to query current title/angle.
This commit introduces new stream protocols: bdnav(and others).
bdnav stream shares lots of codes with original bluray stream, so
it's not separated in different source file.
Major difference from bluray is that bdnav does not support longest
title because there is no way to query that information.
bdnav://menu and bdnav://first correspond to top menu title and
first play title respectively, though they often point same title.
Also, binary position based seeking has been removed, because it
didn't have no point.
This was actually supposed to be removed with pull reuqest #671, but
I accidentally re-added it with a rebasing mistake.
This probably also coincidentally fixes compilation with older
libbluray (issue #672).
Use bd_get_playlist_info() instead of bd_get_title_info(). The
previous implementation couldn't query current playlist and this
made it impossible to call bd_get_playlist_info() which is more
desirable than bd_get_title_info() because, for Blu-rays, playlist
is the unit of playback not title. This commit fixes that.
The cost of calling bd_get_title_info() is quite expensive and
requires lots of CPU usage. Using BD_EVENT_PLAYLIST and
BD_EVENT_TITLE, it's possible to cache BLURAY_TITLE_INFO object for
current title and BD_EVENT_ANGLE handler caches current angle. In
my test case, with this commit, CPU usage can be saved about 15-20%.
demux_mf.c explicitly checks for the stream type to check whether images
are opened via pattern (mf://..., i.e. stream_mf.c) or directly. Of
course the stream type is not set to STREAMTYPE_MF if the stream is
wrapped through the cache, so it tried to open the pattern directly as
file, which failed.
Fix this by disabling caching for mf://. The cache doesn't make sense
here anyway, because each file is opened and closed every frame (perhaps
to avoid memory bloat).
This cd_info_t struct was practically unused. The only thing it did was
storing the track name of the form "Track %d" in a very roundabout way.
Remove it. (It made more sense when there was still CDDB support.)
Don't use an integer division to get the time, since that would round on
second boundaries. Also round up the time by sector size. Seeking rounds
down due to alignment constraints, but if we round up the time, we can
make it land on the exact destination sector.
This fixes that the track change code printed the previous track when
seeking by chapter.
dvdnav.c did not handle event in regular sequence. Usually this
does not make any trouble except around MP_NAV_EVENT_RESET_ALL.
Those events should be handled in regular sequence. If they're
mixed, it can make wrong result.
For instance, MP_NAV_EVENT_HIGHLIGHT right after
MP_NAV_EVENT_RESET_ALL should not be ignored but it might be
because MP_NAV_EVENT_RESET_ALL makes the demuxer reloaded and osd
hidden.
Stream-level chapters (like DVD etc.) did potentially not have
timestamps for each chapter, so STREAM_CTRL_SEEK_TO_CHAPTER and
STREAM_CTRL_GET_CURRENT_CHAPTER were needed to navigate chapters. We've
switched everything to use timestamps and that seems to work, so we can
simplify the code and remove this old mechanism.
Report the time for each chapter (tracks are treated as chapters). This
allows us to get rid of the "old" chapter mechanism, and also behaves
better with the frontend.
This makes assumptions about the audio formats, but that format is
hardcoded anyway in the rawaudio demuxer defaults (and always was).
The title for stream_bluray DID start from 1 and I misunderstood
that it started from 0 because mpv accepted bd://0 as a proper
argument. In fact, 0 title was an alias for the longest title but
it was not handled as a special value. This commit fixes these
behavious. 'disc-title' property for Blu-ray now starts from 0 and
the default title can be specified by 'longest' title just like
stream_dvdnav: bd://longest. Of course, 'longest' can be omitted.
This commit makes 'disc-title' property writable using
STREAM_CTRL_SET_CURRENT_TITLE. This commit also contains
implementation of STREAM_CTRL_SET_CURRENT_TITLE for stream_bluray.
Currently, 'disc-title' is writable only for stream_dvdnav and
stream_bluray and stream_dvd is not supported.
This commit makes 'disc-title' properties for DVDs start from 0.
There was an inconsistency around 'disc-title' property between
DVDs (from 1) and Blu-rays (from 0). This fixes#648.
Signed-off-by: wm4 <wm4@nowhere>
This commit provides impelmentation of STREAM_CTRL_GET_NUM_TITLES
for dvdnav stream. Other streams for DVD or Blu-ray are already
provide STREAM_CTRL_GET_NUM_TITLES.
Detected 'protocols' are AFP, nfs, smb and webdav. This can be extended on
request.
This is currently only implemented for BSD systems (using fstatfs). This
addresses issue #558 on the above platforms.
Note that this still happens in the stream level, so we can't have
nice highlevel behavior restricting seeking. Instead, if a seek leads
to the demuxer requesting data outside of the cached range, the seek
will simply fail. This might confuse the demuxer, and the resulting
behavior is not necessarily useful.
Note that this also doesn't try to skip data on a forward seek. This
would just freeze the stream with slow unseekable streams.
One nice thing is that stream.h has a separate function for merely
skipping data (separate from seeking forward), which is pretty useful
in this case: we want skipping of data to work, even if we reject
seeking forward by skipping data as too expensive. This probably is
or will be useful for demux_mkv.c.
This is probably ok. Probing could hit this case very often, since it'll
mean running this function on potentially binary data, but on the other
hand, probing usually uses a memory stream (to limit the amount of data
read), and memory streams have s->log silenced (details see
open_memory_stream()).
This simplifies the implementation and should make it more robust. For
example, we return an error if a line is longer than the provided buffer
(instead of splitting the line).
The code is much shorter, because now finding the new line and reading
characters is done in one go.
Doesn't affect the generated code, but avoids confusion
in both humans and newer Coverity versions.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@36623 b3059339-0415-0410-9bf9-f77b7e298cf2
The struct we need to copy is actually a cdrom_msf0, not cdrom_msf.
Even though the kernel for no good reason reads it in as a
cdrom_msf struct, but only uses the part shared with cdrom_msf0 -
this is probably a kernel bug.
git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@36622 b3059339-0415-0410-9bf9-f77b7e298cf2
Starting a network stream could stall by executing uncacheable stream
control requests (STREAM_CTRL_GET_LANG and STREAM_CTRL_GET_DVD_INFO).
Being uncacheable means the player has to wait until the cache is done
reading the current block of data. These requests can't be cached
because they're too complicated, so the only way to avoid them is
special casing the DVD and Bluray streams (which are the only things
which need these requests), and not doing them in other cases.
(This is kind of inelegant, but so is the rest of the DVD/BD code.)
This fixes two things:
1. Dropping files on the VO window will auto-load subtitles (since most
drag & drop code prefixes the filenames with 'file://', and the
subtitle auto-load code considers 'file://' non-local)
2. Fix behavior of the %x screenshot filename template (similar problem)
One could force all that code to special-case 'file://' URLs, but just
replacing the filename on playback start is simpler.
Streams like CDDA have special requirements in what quantities data can
be read: you can only read a sector at once, not more and not less. The
stream_peek() function didn't respect that and set less (used internal
buffer size of 2048 bytes, instead of CD sector size of 2352 bytes), so
no data was read and EOF was accidentally set, making playback with
cdda:// fail.
This is a regression since commit 9a723f, but that commit merely exposed
the issue (the redundant seek would clear the EOF flag).
There's a single mp_msg() in path.c, but all path lookup functions seem
to depend on it, so we get a rat-tail of stuff we have to change. This
is probably a good thing though, because we can have the path lookup
functions also access options, so we could allow overriding the default
config path, or ignore the MPV_HOME environment variable, and such
things.
Also take the chance to consistently add talloc_ctx parameters to the
path lookup functions.
Also, this change causes a big mess on configfiles.c. It's the same
issue: everything suddenly needs a (different) context argument. Make it
less wild by providing a mp_load_auto_profiles() function, which
isolates most of it to configfiles.c.
The TV code pretends to be part of stream/, but it's actually demuxer
code too. The audio_in code is shared between the TV code and
stream_radio.c, so stream_radio.c needs a small hack until stream.c is
converted.
Always pass around mp_log contexts in the option parser code. This of
course affects all users of this API as well.
In stream.c, pass a mp_null_log, because we can't do it properly yet.
This will be fixed later.
In my opinion, config.h inclusions should be kept to a minimum. MPlayer
code really liked including config.h everywhere, though, even in often
used header files. Try to reduce this.
Since m_option.h and options.h are extremely often included, a lot of
files have to be changed.
Moving path.c/h to options/ is a bit questionable, but since this is
mainly about access to config files (which are also handled in
options/), it's probably ok.
The tmsg stuff was for the internal gettext() based translation system,
which nobody ever attempted to use and thus was removed. mp_gtext() and
set_osd_tmsg() were also for this.
mp_dbg was once enabled in debug mode only, but since we have log level
for enabling debug messages, it seems utterly useless.
Before this, they were displayed forever. Since some dvd screens seem
not to allow escaping from the still frame using the menu, this could
get you stuck forever.
On dvdnav, caching kind of works but not really. (Not our fault, at
least not fully. It's due to libdvdnav being slightly misdesigned; see
previous commit for some explanations.)
The TV code is implemented in the demuxer, and the stream implementation
is just a wrapper, so caching makes no sense here.
No idea why this was disabled. It was in the original MPlayer code,
which doesn't make much sense to me, because using the MPlayer stream
cache seems 100% broken due to design issues.
EOF is a special case. Normally, the reader will block until the cache
thread has new data. Obviously we don't want to do this on EOF, because
we'd potentially block forever. On the other hand, EOF will put the
cache thread into a waiting state, so if EOF recovers, this will happen
at a "later" point. This is bad if there is some kind of external event
that ends the EOF condition. In this case, a steram_read() call would
still return EOF. Make it so that the reader waits at least for one
iteration of the cache trying to rad a new block.
Also adjust some debug messages to not print file positions in hex.
There was already something similar in the code that did the actual
seek, but I think seeking to the same position could still trigger an
actual seek due to weid interaction with the buffer.
This readds a more or less completely new dvdnav implementation, though
it's based on the code from before commit 41fbcee. Note that this is
rather basic, and might be broken or not quite usable in many cases.
Most importantly, navigation highlights are not correctly implemented.
This would require changes in the FFmpeg dvdsub decoder (to apply a
different internal CLUT), so supporting it is not really possible right
now. And in fact, I don't think I ever want to support it, because it's
a very small gain for a lot of work. Instead, mpv will display fake
highlights, which are an approximate bounding box around the real
highlights.
Some things like mouse input or switching audio/subtitles stream using
the dvdnav VM are not supported.
Might be quite fragile on transitions: if dvdnav initiates a transition,
and doesn't give us enough mpeg data to initialize video playback, the
player will just quit.
This is added only because some users seem to want it. I don't intend to
make mpv a good DVD player, so the very basic minimum will have to do.
How about you just convert your DVD to proper video files?
Uncompressed rar archives can be transparently opened, but the filename
the player doesn't have the direct filename (but something starting
with rar://... instead). This will lead to external subtitles not
being loaded.
This doesn't handle multi-volume rar files, but in that cases just use
the --autosub-match=fuzzy option.
Fixes#397 on github.
This is needed so that new processes (created with fork+exec) don't
inherit open files, which can be important for a number of reasons.
Since O_CLOEXEC is relatively new (POSIX.1-2008, before that Linux
specific), we #define it to 0 in io.h to prevent compilation errors on
older/crappy systems. At least this is the plan.
input.c creates a pipe. For that, add a mp_set_cloexec() function (which
is based on Weston's code in vo_wayland.c, but more correct). We could
use pipe2() instead, but that is Linux specific. Technically, we have a
race condition, but it won't matter.
pthreads should be available anywhere. Even if not, for environment
without threads a pthread wrapper could be provided that can't actually
start threads, thus disabling features that require threads.
Make pthreads mandatory in order to simplify build dependencies and to
reduce ifdeffery. (Admittedly, there wasn't much complexity, but maybe
we will use pthreads more in the future, and then it'd become a real
bother.)
This used to be needed to access the generic stream header from the
specific headers, which in turn was needed because the decoders had
access only to the specific headers. This is not the case anymore, so
this can finally be removed again.
Also move the "format" field from the specific headers to sh_stream.
The priv struct is now allocated by talloc in stream.c. It doesn't need
to be manually freed, and using free() instead of talloc_free() probably
crashes.
Slightly simplifies memory management. This might make adding a demuxer
cache wrapper easier at a later point, because you can just copy the
complete stream header, without worrying that the wrapper will free the
individual stream header fields.
This used to be needed for teletext support. Teletext commit has been
removed (see commit ebaaa41f), and it appears this code is inactive.
It was just forgotten with the removal. Get rid of it completely.
Untested. (Like all changes to the TV code.)
Signed-off-by: wm4 <wm4@nowhere>
Significant modifications over the original patch by not overriding
syscalls with macros ("#define open v4l2open") for fallback, but the
other way around ("#define v4l2open open"). As consequence, the calls
have to be replaced throughout the file.
Untested, although the original patch probably was tested.
Apparently this is not portable to FreeBSD. It turns out that we
(probably) don't use any symbols defined by this header directly, so
the includes are not needed.
This member was redundant. sh_audio->sample_format indicates the sample
size already.
The TV code is a bit strange: the redundant sample size was part of the
internal TV interface. Assume it's really redundant and not something
else. The PCM decoder ignores the sample size anyway.
The configure followed 5 different convetions of defines because the next guy
always wanted to introduce a new better way to uniform it[1]. For an
hypothetic feature 'hurr' you could have had:
* #define HAVE_HURR 1 / #undef HAVE_DURR
* #define HAVE_HURR / #undef HAVE_DURR
* #define CONFIG_HURR 1 / #undef CONFIG_DURR
* #define HAVE_HURR 1 / #define HAVE_DURR 0
* #define CONFIG_HURR 1 / #define CONFIG_DURR 0
All is now uniform and uses:
* #define HAVE_HURR 1
* #define HAVE_DURR 0
We like definining to 0 as opposed to `undef` bcause it can help spot typos
and is very helpful when doing big reorganizations in the code.
[1]: http://xkcd.com/927/ related
Never check s->seek (except in init), because it'd have to check
s->flags anyway. Also, for fast skippable streams (like pipes), don't
set the bit that indicates support for seek forward.
Make sure s->end_pos is always 0 for unseekable streams. Lots of code
outside of stream.c uses this to check seeking support.
This one really did bite me hard (see previous commit), so enable it by
default.
Fix some cases of shadowing throughout the codebase. None of these
change behavior, and all of these were correct code, and just tripped up
the warning.
It's true that ALSA uses alloca() in some of its API functions, but
since this is hidden behind macros in the ALSA headers, we have no
reason to include alloca.h ourselves.
Might help with portability (FreeBSD).
Now that talloc has been removed, the license can be switched back to
GPLv2+. Actually, there never was a GPLv2+ licensed MPlayer (fork or
not) until now, but removal of some GPLv2-only code makes this possible
now. Rewrite the Copyright file to explain the reasons for the licenses
MPlayer and forks use. The old Copyright file didn't contain anything
interesting anymore, and all information it contained is available at
other places in the source tree.
The reason for the license change itself is that it should improve
interoperability with differently licensed code in general.
This essentially reverts commit 1752808.
The problem with DVD/BD and playback resume is that most often, the
filename is just "dvd://", while the actual path to the DVD disk image
is given with --dvd-device. But playback resume works on the filename
only.
Add a pretty bad hack that includes the path to the disk image if the
filename starts with dvd://, and the same for BD respectively. (It's a
bad hack, but I want to go to bed, so here we go. I might revert or
improve it later, depending on user feedback.)
We have to cleanup the global variable mess around the dvd_device.
Ideally, this should go into MPOpts, but it isn't yet. Make the code
paths in mplayer.c take MPOpts anyway.
By default, libavformat uses UDP for rtsp playback. This doesn't work
very well. Apparently the reason is that the buffer sizes libavformat
chooses for UDP are way too small, and switching to TCP gets rid of this
issue entirely (thanks go to Reimar Döffinger for figuring this out).
In theory, you can set buffer sizes as libavformat options, but that
doesn't seem to help.
Add an option to select the rtsp transport, and make TCP the default.
Also remove an outdated comment from stream.c.
Mainly for debugging. Usually, we just set options for all possible
protocols, and we can't really know whether a certain protocol is used
beforehand. That's also the reason why avio_open2() takes a dictionary,
instead of letting the user set options directly with av_opt_set(). Or
in other words, we don't know whether an option that could be set is an
error or not, thus we print the messages only at verbose level.
I have a sample where some final chapters are missing. This was causing a
segmentation fault when trying to fetch chapter times for them.
This makes the code ignore those chapters.
MPlayer handles this correctly, because MPlayer still has the FourCC
codec dispatch (codecs.conf). We need to handle this case specially,
because the libavformat rawvideo decoder will of course not eat mjpeg.
mjpeg is the only supported format, though. (Even MPlayer needs to
convert between V4L2 formats and MPlayer FourCCs, and mjpeg is the only
non-raw format.)
Until now, stream_peek() read only the bare minimum it had to read from
the stream. But this could cause problems, such as being very
inefficient when peeking a lot, or conflicting with ability to seek
back. (The latter issue can be caused by peeking a few bytes, and then
doing a stream_read() with a size that is 1 byte longer: this would read
the peeked data, then call stream_fill_buffer(), which throws away the
previously peeked bytes - so you can't seek back anymore. This is
mitigated by a hack in demux_open(): it peeks a full buffer, to avoid
that peeking/reading during demuxer probing [or before that, in a stream
filter] can cause the buffer to be dropped.)
Apparently, it is popular to store large files in uncompressed rar
archives. Extracting files is not practical, and some media players
suport playing directly from uncompressed rar (at least VLC and some
DirectShow components).
Storing or accessing files this way is completely idiotic, but it is
a common practice, and the ones subjected to this practice can't do
much to change this (at least that's what I assume/hope). Also, it's
a feature request, so we say yes.
This code is mostly taken from VLC (commit f6e7240 from their git tree).
We also copy the way this is done: opening a rar file by itself yields
a playlist, which contains URLs to the actual entries in the rar file.
Compressed entries are simply skipped.
Add a stream filter concept, in which streams can be opened on top of
an underlying "source" stream. Change the open code to make this
easier, and also to account for some mechanisms that will be needed
for this.
The following commit will add stream_rar, which contains such a stream
filter.
This is really not needed. While we really can't take a loaded buffer
over to the cache, there's no reason why the cache couldn't read this
buffer normally.
On the other hand, this code could cause trouble when probing from a
stream before the cache has been enabled.
The way the url_options field was handled was not entirely sane: it's
actually a flexible array member, so it points to garbage for streams
which do not initialize this member (it just points to the data right
after the struct, which is garbage in theory and practice). This was
not actually a problem, since the field is only used if priv_size is
set (due to how this stuff is used). But it doesn't allow setting
priv_size only, which might be useful in some cases.
Also, make the protocols array not a fixed size array. Most stream
implementations have only 1 protocol prefix, but stream_lavf.c has
over 10 (whitelists ffmpeg protocols). The high size of the fixed
size protocol array wastes space, and it is _still_ annoying to
add new prefixes to stream_lavf (have to bump the maximum length),
so make it arbitrary length.
The two changes (plus some more cosmetic changes) arte conflated into
one, because it was annoying going over all the stream implementations.
Modeled after the old playlist_parser.c, but actually new code, and it
works a bit differently.
Demuxers (and sometimes streams) are the component that should be used
to open files and to determine the file format. This was already done
for subtitles, but playlists still use a separate code path.
Instead of always skipping in STREAM_BUFFER_SIZE blocks, allow an
arbitrary size. This allows - in theory - faster forward seeking in
pipes.
(Maybe not a very significant change, but it reduces the number of
things that depend on STREAM_BUFFER_SIZE for no good reason. Though
we still use that value as minimum read size.)
stream_file.c contains some code meant for forward seeking with pipes.
This simply reads data until the seek position is reached. Move this
code to stream.c. This stops stream_file from doing strange things
(messing with stream internals), and removes the code duplication too.
We also make stream_seek_long() use the new skip code. This is shorter
and much easier to follow than the old code, which basically did strange
things.