summaryrefslogtreecommitdiffstats
path: root/player/loadfile.c
Commit message (Collapse)AuthorAgeFilesLines
* playlist: change from linked list to an arraywm42019-12-281-12/+10
| | | | | | | | | | | | | | | | | | | Although a linked list was ideal at first, there are cases where it sucks, and became increasingly awkward (with the mpv command API preferring integer indexes to access the list). In future, we probably want to add more playlist-related functionality, so better change it to an array now. An array isn't always ideal either. Since playlist entries are still separate objects (because in some cases you need a stable "iterator" to it), but you still need to efficiently get the next/previous playlist entry, there's a pl_index field, that needs to be maintained. E.g. adding an entry at the start of the playlist => update the pl_index field for all other entries. Well, it's not really worth to do something more complicated to avoid these things. This commit is probably buggy as shit. It's not like I bothered to test everything. That's _your_ role.
* stream, demux: redo origin policy thingwm42019-12-201-11/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | mpv has a very weak and very annoying policy that determines whether a playlist should be used or not. For example, if you play a remote playlist, you usually don't want it to be able to read local filesystem entries. (Although for a media player the impact is small I guess.) It's weak and annoying as in that it does not prevent certain cases which could be interpreted as bad in some cases, such as allowing playlists on the local filesystem to reference remote URLs. It probably barely makes sense, but we just want to exclude some other "definitely not a good idea" things, all while playlists generally just work, so whatever. The policy is: - from the command line anything is played - local playlists can reference anything except "unsafe" streams ("unsafe" means special stream inputs like libavfilter graphs) - remote playlists can reference only remote URLs - things like "memory://" and archives are "transparent" to this This commit does... something. It replaces the weird stream flags with a slightly clearer "origin" value, which is now consequently passed down and used everywhere. It fixes some deviations from the described policy. I wanted to force archives to reference only content within them, but this would probably have been more complicated (or required different abstractions), and I'm too lazy to figure it out, so archives are now "transparent" (playlists within archives behave the same outside). There may be a lot of bugs in this. This is unfortunately a very noisy commit because: - every stream open call now needs to pass the origin - so does every demuxer open call (=> params param. gets mandatory) - most stream were changed to provide the "origin" value - the origin value needed to be passed along in a lot of places - I was too lazy to split the commit Fixes: #7274
* player: loadfile overrides previous stop commandwm42019-12-061-1/+1
| | | | | | | | | | | | | | | | Both the "stop" and "loadfile" commands are asynchronous. "stop" starts terminating playback, which used to be done in the same playloop iteration, but now it may take longer, so a "loadfile" command can be received while this is going on. (Possible that it used to work if the second command was issued at least in the next playloop iteration.) Make the "loadfile" override the "stop" mode, so the next file will be played, instead of quitting or going into idle mode. Unlike the referenced bug report claims, this has nothing to do with IPC. Fixes: #7225
* player: change m_config to use new option handling mechanismswm42019-11-291-5/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Instead of making m_config a special-case, it more or less uses the underlying m_config_cache/m_config_shadow APIs properly. This makes the player core a (relatively) equivalent user of the core option API. In particular, this means that other threads can change core options with m_config_cache_write_opt() calls (before this commit, this merely led to diverging option values). An important change is that before this commit, mpctx->opts contained the "master copy" of all option data. Now it's just another copy of the option data, and the shadow copy is considered the master. This is why whenever mpctx->opts is written, the change needs to be copied to the master (thus why this commits add a bunch of m_config_notify... calls). If another thread (e.g. a VO) changes an option, async_change_cb is now invoked, which funnels the change notification through the player's layers. The new self_notification parameter on mp_option_change_callback is so that m_config_notify... doesn't trigger recursion, and it's used in cases where the change was already "processed". It's still needed to trigger libmpv property updates. (I considered using an extra m_config_cache for that, but it'd only cause problems with no advantages.) I think the recent changes actually forgot to send libmpv property updates in some cases. This should fix this anyway. In some cases, property updates are reworked, and the potential for bugs should be lower (probably). The primary point of this change is to allow external updates, for example by a VO writing the fullscreen option if the window state is changed by the window manager (rather than mpv changing it). This is not used yet, but the following commits will.
* player: remove mechanisms for better logging with repl.luawm42019-11-181-0/+3
| | | | | | | | | | | | | | | | | | | | | | As preparation for making repl.lua part of the core (maybe), add some mechanisms which are supposed to improve its behavior. Add a silent mode. Calling mpv_request_log_messages() with the log level name prefixed with "silent:" will disable logging from the API user's perspective. But it will keep the log buffer, and record new messages, without returning them to the user. If logging is enabled again by requesting the same log level without "silent:" prefix, the buffered log messages are returned to the user at once. This is not documented, because it's far too messy and special as that I'd want anyone to rely on this behavior, but it will be perfectly fine for an internal script. Another thing is that we record early startup messages. The goal is to make the repl.lua script show option and config parsing file errors. This works only with the special "terminal-default" log level. In addition, reduce the "terminal-default" capacity to only 100 log messages. If this is going to be enabled by default, it shouldn't use too much resources.
* options: remove M_SETOPT_RUNTIMEwm42019-11-101-1/+1
| | | | | | | Used to contain flags for "save" setting of options at runtime. Now there is nothing special needed anymore and it's 0. So drop it completely, and remove anything that distinguishes between runtime and initialization time.
* player: avoid duplicate track auto selectionStephan Hilb2019-10-181-1/+14
| | | | | | | | | Since a track may not be selected twice, it makes sense e.g. for secondary subtitles to select the next best match and avoid the duplicate selection. This allows for example `--slang=en,ja --secondary-sid=auto` to select 'en' as primary and 'ja' as secondary without needing to know the actual sid for 'ja'.
* player: don't load external files when reading from stdinckath2019-10-061-1/+1
|
* loadfile: make prefetching actually workwm42019-09-291-1/+3
| | | | | | | | | | | | | | | | Looks like this didn't actually work. Prefetching will do nothing if there isn't a thread to "drive" it, and the demuxer thread needs to be explicitly enabled. (I guess I did the worst possible job in verifying whether this actually worked when I implemented it. On the other hand, the user didn't confirm back whether it worked, so who cares.) Like in the previous commit, bad factoring makes everything worse. It duplicates logic and implementation of enable_demux_thread(), since the opener thread cannot access the mpctx->opts field freely. But it's deep night, so fuck it. Fixes: c1f1a0845e03885e Fixes: #6753
* loadfile: don't always accidentally always prefetchingwm42019-09-291-11/+15
| | | | | | | | | | | | | | demux_start_prefetch() was called unconditionally in two cases. This is completely wrong. I'm not sure what part of my brain died off that something this obviously wrong went in. The prefetch case is a bit more complicated. It's a different thread, so you can't access just access mpctx->opts there. So add an explicit field for this, which is the simplest way to get this done. (Even if it's bad factoring.) Fixes: c1f1a0845e03885eebe63 Fixes: 556e204a112ee286972e5
* recorder: don't use a magic index for mp_recorder_get_sink()wm42019-09-291-1/+1
| | | | | | | | | | | | | | | | | | | Although this was sort of elegant, it just seems to complicate things slightly. Originally, the API meant that you cache mp_recorder_sink yourself (which would avoid the mess of passing an index around), but that too seems slightly roundabout. In a later change, I want to change the set of streams passed to mp_recorder_create(), and then I'd have to keep track of the index for each stream, which would suck. With this commit, I can just pass the unambiguous sh_stream to it, and it will be guaranteed to match the correct stream. The disadvantages are barely worth discussing. It's a new linear search per packet, but usually only 2 to 4 streams are active at a time. Also, in theory a user could want to write 2 streams using the same sh_stream (same metadata, just writing different packets or so), but in practice this is never done.
* player: use track title if exists instead of filenamethewisenerd2019-09-211-1/+5
|
* loadfile: restore playlist prefetchingwm42019-09-201-4/+11
| | | | | | | | | | | | | | | | | | | | | | | With the stream cache gone, this function had almost no use anymore (other than opening the stream). Improve this by triggering demuxer cache readahead. This enables all streams. At this point we can't know yet what streams the user's options would select (at least not without great additional effort). Generally this is what you want, and the stream cache would have read the same amount of data. In addition, this will work much better for files that e.g. need to seek to the end when opening (typically mp4, and mkv files produced by newer mkvmerge versions). Remove the deselection call from add_stream_track(). This should be fine, as streams normally start out as deselected anyway. In the prefetch case, some code in play_current_file() actually deselects it. Streams that appear during demuxing are disabled by default, so this doesn't break this logic either. Fixes: #6753
* demux, command: add a third stream recording mechanismwm42019-09-191-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | That's right, and it's probably not the end of it. I'll just claim that I have no idea how to create a proper user interface for this, so I'm creating multiple partially-orthogonal, of which some may work better in each of its special use cases. Until now, there was --record-file. You get relatively good control about what is muxed, and it can use the cache. But it sucks that it's bound to playback. If you pause while it's set, muxing stops. If you seek while it's set, the output will be sort-of trashed, and that's by design. Then --stream-record was added. This is a bit better (especially for live streams), but you can't really control well when muxing stops or ends. In particular, it can't use the cache (it just dumps whatever the underlying demuxer returns). Today, the idea is that the user should just be able to select a time range to dump to a file, and it should not affected by the user seeking around in the cache. In addition, the stream may still be running, so there's some need to continue dumping, even if it's redundant to --stream-record. One notable thing is that it uses the async command shit. Not sure whether this is a good idea. Maybe not, but whatever. Also, a user can always use the "async" prefix to pretend it doesn't. Much of this was barely tested (especially the reinterleaving crap), let's just hope it mostly works. I'm sure you can tolerate the one or other crash?
* demux: redo timed metadatawm42019-09-191-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The old implementation didn't work for the OGG case. Discard the old shit code (instead of fixing it), and write new shit code. The old code was already over a year old, so it's about time to rewrite it for no reason anyway. While it's true that the old code appears to be broken, the main reason to rewrite this is to make it simpler. While the amount of code seems to be about the same, both the concept and the actual tag handling are simpler. The result is probably a bit more correct. The packet struct shrinks by 8 byte. That fact that it wasted 8 bytes per packet for a rather obscure use case was the reason I started this at all (and when I found that OGG updates didn't work). While these 8 bytes aren't going to hurt, the packet struct was getting too bloated. If you buffer a lot of data, these extra fields will add up. Still quite some effort for 8 bytes. Fortunately, it's not like there are any managers that need to be convinced whether it's worth doing. The freedom to waste time on dumb shit. The old implementation attached the current metadata to each packet. When the decoder read the packet, the packet's metadata was made current. The new implementation stores metadata as separate list, and requires that the player frontend tells it the current playback time, which will be used to find the currently valid metadata. In both cases, the objective was to correctly update metadata even if a lot of data is buffered ahead (and to update them correctly when seeking within the demuxer cache). The new implementation is actually slightly more correct, because it uses the playback time for the metadata lookup. Consider if you have an audio filter which buffers 15 seconds (unfortunately such a filter exists), then the old code would update the current title 15 seconds too early, while the new one does it correctly. The new code also simplifies mixing the 3 metadata sources (global, per stream, ICY). We assume these aren't mixed in a meaningful way. The old code tried to be a bit more "exact". I didn't bother to look how the old code did this, but the new code simply always "merges" with the previous metadata, so if a newer tag removes a field, it's going to stick around anyway. I tried to keep it simple. Other approaches include making metadata a special sh_stream with metadata packets. This would have been conceptually clean, but the implementation would probably have been unnatural (and doesn't match well with libavformat's API anyway). It would have been nice to make the metadata updates chapter points (makes a lot of sense for the intended use case, web radio current song information), but I don't think it would have been a good idea to make chapters suddenly so dynamic. (Still an idea to keep in mind; the new code actually makes it easier to work towards this.) You could mention how subtitles are timed metadata, and actually are implemented as sparse packet streams in some formats. mp4 implements chapters as special subtitle stream, AFAIK. (Ironically, this is very not-ideal for files. It would be useful for streaming like web radio, but mp4 is extremely bad for streaming by design for other reasons.) bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla
* demux: really disable cache for sub-demuxerswm42019-09-191-1/+4
| | | | | | | | | | | | | | | | | | It seems the so called demuxer cache wasn't really disabled for sub-demuxers (timeline stuff). This was relatively harmless, since the actual packet data was shared anyway via refcounting. But with the addition of a mmap cache backend, this may change a lot. So strictly disable any caching for sub-demuxers. This assumes that users of sub-demuxers (only demux_timeline.c by now?) strictly use demux_read_any_packet(), since demux_read_packet_async() will require some minor read-ahead if a low level packet read returned a packet for a different stream. This requires some awkward messing with this fucking heap of trash. The thing that is really wrong here is that the demuxer API mixes different concepts, and sub-demuxers get the same API as decoders, and use the cache code.
* player: fix --loop with backward playbackwm42019-09-191-1/+1
| | | | | | | | | | | Obviously should seek back to the end of the file when it loops. Also remove some minor code duplication around start times. This isn't the correct solution by the way. Rather than hoping we know a reasonable start/end time, this stuff should instruct the demuxer to seek to the exact location. It'll work with 99% of all normal files, but add an appropriate comment (that basically says the function is bullshit) to get_start_time() anyway.
* player: modify/simplify AB-loop behaviorwm42019-09-191-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This changes the behavior of the --ab-loop-a/b options. In addition, it makes it work with backward playback mode. The most obvious change is that the both the A and B point need to be set now before any looping happens. Unlike before, unset points don't implicitly use the start or end of the file. I think the old behavior was a feature that was explicitly added/wanted. Well, it's gone now. This is because of 2 reasons: 1. I never liked this feature, and it always got in my way (as user). 2. It's inherently annoying with backward playback mode. In backward playback mode, the user wants to set A/B in the wrong order. The ab-loop command will first set A, then B, so if you use this command during backward playback, A will be set to a higher timestamps than B. If you switch back to forward playback mode, the loop would stop working. I want the loop to just continue to work, and the chosen solution conflicts with the removed feature. The order issue above _could_ be fixed by also switching the AB-loop user option values around on direction switch. But there are no other instances of option changes magically affecting other options, and doing this would probably lead to unexpected misery (dying from corner cases and such). Another solution is sorting the A/B points by timestamps after copying them from the user options. Then A/B options set in backward mode will work in forward mode. This is the chosen solution. If you sort the points, you don't know anymore whether the unset point is supposed to signify the end or the start of the file. The AB-loop code is slightly better abstracted now, so it should be easy to restore the removed feature. It would still require coming up with a solution for backwards playback, though. A minor change is that if one point is set and the other is unset, I'm rendering both the chapter markers and the marker for the set point. Why? I don't know. My test file had chapters, and I guess I decided this looked better. This commit also fixes some subtle and obvious issues that I already forgot about when I wrote this commit message. It cleans up some minor code duplication and nonsense too. Regarding backward playback, the code uses an unsanitary mix of internal ("transformed") and user timestamps. So the play_dir variable appears more than usual. To mention one unfixed issue: if you set an AB-loop that is completely past the end of the file, it will get stuck in an infinite seeking loop once playback reaches the end of the file. Fixing this reliably seemed annoying, so the fix is "just don't do this". It's not a hard freeze anyway.
* player: simplify/fix --start/--end handling with --rebase-start-time=nowm42019-09-191-7/+0
| | | | | | | | | | | | | | | | | | | | | | The get_play_start_pts() function was supposed to return "rebased" (relative to 0) timestamps. This was roundabout, because one of 2 callers just added the offset back, and the other caller actually expected an absolute timestamp. Change rel_time_to_abs() (whose return value get_play_start_pts() returns without further changes) to return absolute times. This should fix that absolute and relative times passed to --start and --end were treated the same, which can't be right. It probably also fixes --end if --rebase-start-time=no is used (which can't have been correct either). All in all I'm not sure why --rebase-start-time=no or absolute vs. relative times in --start/--end even exist, when they were incorrectly implemented for years. Untested, because no sample file and I don't care. However, if anyone cares, and I got it wrong, I hope it's simple to fix.
* Implement backwards playbackwm42019-09-191-0/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | See manpage additions. This is a huge hack. You can bet there are shit tons of bugs. It's literally forcing square pegs into round holes. Hopefully, the manpage wall of text makes it clear enough that the whole shit can easily crash and burn. (Although it shouldn't literally crash. That would be a bug. It possibly _could_ start a fire by entering some sort of endless loop, not a literal one, just something where it tries to do work without making progress.) (Some obvious bugs I simply ignored for this initial version, but there's a number of potential bugs I can't even imagine. Normal playback should remain completely unaffected, though.) How this works is also described in the manpage. Basically, we demux in reverse, then we decode in reverse, then we render in reverse. The decoding part is the simplest: just reorder the decoder output. This weirdly integrates with the timeline/ordered chapter code, which also has special requirements on feeding the packets to the decoder in a non-straightforward way (it doesn't conflict, although a bugmessmass breaks correct slicing of segments, so EDL/ordered chapter playback is broken in backward direction). Backward demuxing is pretty involved. In theory, it could be much easier: simply iterating the usual demuxer output backward. But this just doesn't fit into our code, so there's a cthulhu nightmare of shit. To be specific, each stream (audio, video) is reversed separately. At least this means we can do backward playback within cached content (for example, you could play backwards in a live stream; on that note, it disables prefetching, which would lead to losing new live video, but this could be avoided). The fuckmess also meant that I didn't bother trying to support subtitles. Subtitles are a problem because they're "sparse" streams. They need to be "passively" demuxed: you don't try to read a subtitle packet, you demux audio and video, and then look whether there was a subtitle packet. This means to get subtitles for a time range, you need to know that you demuxed video and audio over this range, which becomes pretty messy when you demux audio and video backwards separately. Backward display is the most weird (and potentially buggy) part. To avoid that we need to touch a LOT of timing code, we negate all timestamps. The basic idea is that due to the navigation, all comparisons and subtractions of timestamps keep working, and you don't need to touch every single of them to "reverse" them. E.g.: bool before = pts_a < pts_b; would need to be: bool before = forward ? pts_a < pts_b : pts_a > pts_b; or: bool before = pts_a * dir < pts_b * dir; or if you, as it's implemented now, just do this after decoding: pts_a *= dir; pts_b *= dir; and then in the normal timing/renderer code: bool before = pts_a < pts_b; Consequently, we don't need many changes in the latter code. But some assumptions inhererently true for forward playback may have been broken anyway. What is mainly needed is fixing places where values are passed between positive and negative "domains". For example, seeking and timestamp user display always uses positive timestamps. The main mess is that it's not obvious which domain a given variable should or does use. Well, in my tests with a single file, it suddenly started to work when I did this. I'm honestly surprised that it did, and that I didn't have to change a single line in the timing code past decoder (just something minor to make external/cached text subtitles display). I committed it immediately while avoiding thinking about it. But there really likely are subtle problems of all sorts. As far as I'm aware, gstreamer also supports backward playback. When I looked at this years ago, I couldn't find a way to actually try this, and I didn't revisit it now. Back then I also read talk slides from the person who implemented it, and I'm not sure if and which ideas I might have taken from it. It's possible that the timestamp reversal is inspired by it, but I didn't check. (I think it claimed that it could avoid large changes by changing a sign?) VapourSynth has some sort of reverse function, which provides a backward view on a video. The function itself is trivial to implement, as VapourSynth aims to provide random access to video by frame numbers (so you just request decreasing frame numbers). From what I remember, it wasn't exactly fluid, but it worked. It's implemented by creating an index, and seeking to the target on demand, and a bunch of caching. mpv could use it, but it would either require using VapourSynth as demuxer and decoder for everything, or replacing the current file every time something is supposed to be played backwards. FFmpeg's libavfilter has reversal filters for audio and video. These require buffering the entire media data of the file, and don't really fit into mpv's architecture. It could be used by playing a libavfilter graph that also demuxes, but that's like VapourSynth but worse.
* player: don't print "Playing:" message if there's only 1 filewm42019-09-191-1/+4
| | | | | | | | This is just redundant and slightly annoying, at least for normal command line usage. If there are multiple entries, still print it (because you want to know where you are). Also still print it if the player was redirected (because you want to know where you got redirected to).
* player: add --demuxer-cache-wait optionwm42019-09-191-0/+13
|
* loadfile, ytdl_hook: don't reject EDL-resolved URLs through playlistwm42019-09-191-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The ytdl wrapper can resolve web links to playlists. This playlist is passed as big memory:// blob, and will contain further quite normal web links. When playback of one of these playlist entries starts, ytdl is called again and will resolve the web link to a media URL again. This didn't work if playlist entries resolved to EDL URLs. Playback was rejected with a "potentially unsafe URL from playlist" error. This was completely weird and unexpected: using the playlist entry directly on the command line worked fine, and there isn't a reason why it should be different for a playlist entry (both are resolved by the ytdl wrapper anyway). Also, if the only EDL URL was added via audio-add or sub-add, the URL was accessed successfully. The reason this happened is because the playlist entries were marked as STREAM_SAFE_ONLY, and edl:// is not marked as "safe". Playlist entries passed via command line directly are not marked, so resolving them to EDL worked. Fix this by making the ytdl hook set load-unsafe-playlists while the playlist is parsed. (After the playlist is parsed, and before the first playlist entry is played, file-local options are reset again.) Further, extend the load-unsafe-playlists option so that the playlist entries are not marked while the playlist is loaded. Since playlist entries are already verified, this should change nothing about the actual security situation. There are now 2 locations which check load_unsafe_playlists. The old one is a bit redundant now. In theory, the playlist loading code might not be the only code which sets these flags, so keeping the old code is somewhat justified (and in any case it doesn't hurt to keep it). In general, the security concept sucks (and always did). I can for example not answer the question whether you can "break" this mechanism with various combinations of archives, EDL files, playlists files, compromised sites, and so on. You probably can, and I'm fully aware that it's probably possible, so don't blame me.
* stream_libarchive: remove base filename stuffwm42019-09-191-8/+1
| | | | | | | | Apparently this was so that when playing a video file from a .rar file, it would load external subtitles with the same name (instead of looking for mpv's rar:// mangled URL). This was requested on github almost 5 years ago. Seems like a weird feature, and I don't care. Drop it, because it complicates some in progress change.
* Merge branch 'master' into pr6360Jan Ekström2019-03-111-1/+1
|\ | | | | | | | | | | Manual changes done: * Merged the interface-changes under the already master'd changes. * Moved the hwdec-related option changes to video/decode/vd_lavc.c.
| * player: do not rebase start time for subtitle streamszc622019-02-281-1/+1