summaryrefslogtreecommitdiffstats
path: root/demux/demux_timeline.c
Commit message (Collapse)AuthorAgeFilesLines
* some shitytdl_sub_delayloadwm42020-02-151-30/+57
|
* stream, demux: redo origin policy thingwm42019-12-201-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* demux: do not make up demuxer_idwm42019-12-031-1/+1
| | | | | | | | | | | | | | | | | | The demuxer_id (exported in as "src-id" property) is supposed to be the native stream ID, as it exists in the file, or -1 if that does not exist (actually any negative value), or if it is unknown. Until now, an ID was made up if it was missing. That seems like strange non-sense, and I can't find the reason why it was done. But it was probably for convenience by the EDL stuff or so. Stop doing this. Fortunately, the src-id property was documented as being unavailable if the ID is not known. Even the code for this was present, it was just inactive until now. Extend input.rst with some explanations. Also fixing 3 other places where negative demuxer_id was ignored or avoided.
* demux_timeline, demux_edl: correctly enable cache in pseudo-DASH modewm42019-10-081-0/+3
| | | | | | | | | | | | | | | | | | In pseudo-DASH mode, we may have no real streams opened until the demuxer layer is fully loaded and playback actually starts. The only hint that the stream is from network is, at that point, the init segment, which is only opened as stream, and then separately as demuxer (which is dumb but happened to fit the internal architecture better). So just propagate the flags from the init segment stream. Seems like an annoyance, but doesn't hurt that much I guess. (Until someone gets the idea to pass the init segment data inline or so, but nothing does that.) The sample link in the linked issue will probably soon switch to another format, because that service always does this after recent uploads or so. Fixes: #7038
* demux: propagate streaming flag through demux_timelinewm42019-09-201-1/+4
| | | | | | | | | | | | | | Before this commit, EDL or CUE files did not properly enable the cache if they were on "slow" media (stream->streaming==true). This happened because the stream is unset for demux_timeline, so the streaming flag could not be queried anymore. Fix this by adding this flag to struct demuxer, and propagate it exactly like the is_network flag. is_network is not used for checking the cache options anymore, and its main function seems to be something else. Normal http streams set the streaming flag already. This should fix #6958.
* demux: refactor cache range init/deinitwm42019-09-191-6/+2
| | | | | | | | | | | | | | | | | | | | Remove the duplicated creation of the first range. Explicitly destroy ranges, including the last one on final deinit. It looks like this also fixes a leak of removed range structs, which was never noticed because they're so small, and were freed on final deinit due to having the demuxer as talloc parent. This improves upon the previous commit too (that change should have been part of it I guess). Sub-demuxers (demux_timeline only) now automatically don't use the cache (like it was intended by the previous commit). The cache is "initialized" (or disabled) last in the recursive call chain, which is messy, but this sub demuxer stuff FUCKING SUCKS, as mentioned in the previous commit message. This would be no problem if the caching layer and actual demuxer implementations were separate. Most of this change has no purpose. Might make (de-)initialization of further cache exerpiments simpler.
* demux_timeline: add heuristic to fix shifted seeks with separate audiowm42019-09-191-11/+80
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | If you have a EDL stream with separate sources for audio and video stream (like ytdl_hook now creates), you can get the problem that the video stream seeks to a different position than audio due to different key frame granularity. In particular, if you seek backward, the video might undershoot the seek target by a lot. Then video will resume from an earlier position than audio, and the player plays silence. This is annoying. Fix this by explicitly implementing a heuristic to detect separate audio/video streams, determining where a video seek ends up, and then seeking the audio stream to the video destination. This also makes sure to not seek audio with SEEK_FORWARD, so it will always seek before the video position. Non-precise seeks still skip audio to the video target, so this helps with ensuring that audio is present at the final seek target. The implementation is very annoying, because the only way to determine the seek target is to actually read a packet. Thus a 1-packet queue needs to be added. In theory, we could get the seek target from the index of the video file (especially if it's mp4), but libavformat does not have public API that exports this index, so we're stuck with this roundabout generic method. Note that this is only for non-precise seeks. If precise seeks are done, the problem is handled by the frontend by skipping unwanted video frames. But non-precise seeking should still work. (Personally I prefer non-precise seek mode by default because they're still significantly faster.) It also needs to be said that this is the 4th implementation of this seek adjustment thing in mpv. The 1st implementation is in the frontend (look for MPContext.seek_slave). This works only if the external audio stream is known as such on the frontend level. The 2nd implementation is in the demuxer level packet cache (top of execute_cache_seek()). This is similar to code that any demuxer needs to handle non-precise seeks sufficiently nicely. The 3rd is in demux_mkv.c. Since mkv is an interleaved format, this implementation mostly consists on trying to pick index entries for video packets if a video stream is selected. Maybe these "redundant" implementations could be avoided by exposing separate streams through the demuxer API (and making them individually seekable) or something like this, but this is messy and not without problems for multiple reasons. So for now this commit is the best way to fix the observed behavior.
* demux_edl, cue, mkv: slightly nicer file format indicationwm42019-09-191-2/+2
| | | | | | | | | | | | | Instead of just using "edl/" for the file format, report mkv_oc if it's generated from ordered chapters, "cue/" if from .cue, "multi/" if it's from EDL but only for adding separate streams, "dash/" if it's from EDL but only using the DASH hack, and "edl/" for everything else. The EDL variants are mostly special-cased to the variants the ytdl wrapper usually generates. This has no effect other than what the command.c file-format property returns.
* demux_edl, cue, mkv: clean up timeline stuff slightlywm42019-09-191-13/+24
| | | | | | | | | | | | | | | | | | | | | Remove the singly linked list hack, replace it with a slightly more proper data structure. This probably gets rid of a few minor bugs along the way, caused by the awkward nonsensical sharing/duplication of some fields. Another change (because I'm touching everything related to timeline anyway) is that I'm removing the special semantics for parts[num_parts]. This is now strictly out of bounds, and instead of using the start time of the next/beyond-last part, there is an end time field now. Unfortunately, this also requires touching the code for cue and mkv ordered chapters. From some superficial testing, they still seem to mostly work. One observable change is that the "no_chapters" header is per-stream now, which is arguably more correct, and getting the old behavior would require adding code to handle it as special-case, so just adjust ytdl_hook.lua to the new behavior.
* demux_edl: add no_clipwm42019-09-191-6/+7
| | | | | | Used by the next commit. It mostly exposes part of mp4_dash functionality. It actually makes little sense other than for ytdl special-use. See next commit.
* demux_timeline: include "dash" hint in reported file formatwm42019-09-191-1/+2
|
* demux_timeline: disable end-of-segment handling in DASH modewm42019-09-191-2/+2
| | | | | | | | Normal EDL needs to clip packets coming from the underlying demuxer to the segment range (including complicated stuff due to frame reordering). This is unwanted In pseudo-DASH mode. A broken or subtly incorrect manifest would lead to "bad stuff" happening. The intention of the pseudo-DASH mode is to literally concatenate fragments.
* demux_timeline: report network speed of slave connectionswm42019-09-191-1/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | demux_timeline doesn't do any transport accesses itself. The slave demuxers do this (these will actually access the stream layer and perform e.g. network accesses). As a consequence, demux_timeline always reported 0 bytes read, and network speed display didn't work. Fix this by awkwardly reporting the amount of read bytes upwards. This is not very nice, and requires explicit calls whenever the slave "might" have read data. Due to the way the reporting is done, it only works if the slaves do not run demuxer threads, which makes things even less nice. (Fortunately they don't anyway, because it would be a waste of resources.) Some identifiers contain the word "hack" as a warning. Some of the stupidity comes from the fact that demux.c itself resets the stats randomly in order to calculate the bytes_per_second value, which is useless for a slave, but of course is still done, because demux.c itself is not aware of whether it's on the slave or top-level layer. Unfortunately, this must do. In theory, the demuxer thread/cache layer should be separated from demuxer implementations. This would get rid of all the awkwardness and nonsense. For example, the only threading involved would be the caching layer, completely separate from demuxers themselves. It'd be the only thing calculates speed rates for the player frontend, too (instead of doing it for each demuxer, even if unused).
* demux, demux_edl: add extension for tracks sourced from separate streamswm42019-09-191-137/+241
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit adds an extension to mpv EDL, which basically allows you to do the same as --audio-file, --external-file, etc. in a single EDL file. This is a relatively quick & dirty implementation. The dirty part lies in the fact that several shortcuts are taken. For example, struct timeline now forms a singly linked list, which is really weird, but also means the other timeline using demuxers (cue, mkv) don't need to be touched. Also, memory management becomes even worse (weird object ownership rules that are just fragile WTFs). There are some other dubious small changes, mostly related to the weird representation of separate streams. demux_timeline.c contains the actual implementation of the separate stream handling. For the most part, most things that used to be on the top level are now in struct virtual_source, of which one for each separate stream exists. This is basically like running multiple demux_edl.c in parallel. Some changes could strictly speaking be split into a separate commit, such as the stream_map type change. Mostly untested. Seems to work for the intended purpose. Potential for regressions for other timeline uses (like ordered chapters) is probably low. One thing which could definitely break and which I didn't test is the pseudo-DASH fragmented EDL code, of which ytdl can trigger various forms in obscure situations. (Uh why don't we have a test suite.) Background: The intention is to use this for the ytdl wrapper. A certain streaming site from a particularly brain damaged and plain evil Silicon Valley company usually provides streams as separate audio and video streams. The ytdl wrapper simply does use audio-add (i.e. adding it as external track, like with --audio-file), which works mostly fine. Unfortunately, mpv manages caching completely separately for external files. This has the following potential problems: 1. Seek ranges are rendered incorrectly. They always use the "main" stream, in this case the video stream. E.g. clicking into a cached range on the OSC could trigger a low level seek if the audio stream is actually not cached at the target position. 2. The stream cache bloats unnecessarily. Each stream may allocate the full configured maximum cache size, which is not what the user intends to do. Cached ranges are not pruned the same way, which creates disjoint cache ranges, which only use memory and won't help with fast seeking or playback. 3. mpv will try to aggressively read from both streams. This is done from different threads, with no regard which stream is more important. So it might happen that one stream starves the other one, especially if they have different bitrates. 4. Every stream will use a separate thread, which is an unnecessary waste of system resources. In theory, the following solutions are available (this commit works towards D): A. Centrally manage reading and caching of all streams. A single thread would do all I/O, and decide from which stream it should read next. As long as the total TCP/socket buffering is not too high, this should be effective to avoid starvation issues. This can also manage the cached ranges better. It would also get rid of the quite useless additional demuxer threads. This solution is conceptually simple, but requires refactoring the entire demuxer middle layer. B. Attempt to coordinate the demuxer threads. This would maintain a shared cache and readahead state to solve the mentioned problems explicitly. While this sounds simple and like an incremental change, it's probably hard to implement, creates more messy special cases, solution A. seems just a better and simpler variant of this. (On the other hand, A. requires refactoring more code.) C. Render an intersection of the seek ranges across all streams. This fixes only problem 1. D. Merge all streams in a dedicated wrapper demuxer. The general demuxer layer remains unchanged, and reading from separate streams is handled as special case. This effectively achieves the same as A. In particular, caching is simply handled by the usual demuxer cache layer, which sees the wrapper demuxer as a single stream of interleaved packets. One implementation variant of this is to reuse the EDL infrastructure, which this commit does. All in all, solution A would be preferable, because it's cleaner and works for all external streams in general. Some previous commit tried to prepare for implementing solution A. This could still happen. But it could take years until this is finally seriously started and finished. In any case, this commit doesn't block or complicate such attempts, which is also why it's the way to go. It's worth mentioning that original mplayer handles external files by creating a wrapper demuxer. This is like a less ideal mixture of A. and D. (The similarity with A. is that extending the mplayer approach to be fully dynamic and without certain disadvantages caused by the wrapper would end up with A. anyway. The similarity with D. is that due to the wrapper, no higher level code needs to be changed.)
* demux: get rid of ->control callbackwm42019-09-191-8/+3
| | | | | | | | The only thing left is the notification for track switching. Just get rid of that. There's probably no real reason to get rid of control(), but why not. I think I was actually trying to do some real work but fuck that.
* demux_timeline: fix off by one error, rearrange weird codewm42019-09-191-4/+4
| | | | | | | | | | This code set pkt->stream to a value which I'm not sure whether it's correct. A recent commit overwrote it with a value that is definitely correct. There appears to be an off by one error. No fucking clue whether this was somehow correct, but applying an apparent fix does not seem to break anything, so whatever.
* demux: return packets directly from demuxer instead of using sh_streamwm42019-09-191-8/+9
| | | | | | | Preparation for other potential changes to separate demuxer cache/thread and actual demuxers. Most things are untested, but it seems to work somewhat.
* demux: get rid of free_demuxer[_and_stream]()wm42018-05-241-2/+2
| | | | | | | Them being separate is just dumb. Replace them with a single demux_free() function, and free its stream by default. Not freeing the stream is only needed in 1 special case (demux_disc.c), use a special flag to not free the stream in this case.
* demux: add a "cancel" fieldwm42018-05-241-1/+1
| | | | | Instead of relying on demuxer->stream->cancel. This is better because the stream is potentially closed and replaced.
* demux_timeline: disable pointless packet cache for sub-demuxerswm42017-12-101-0/+7
| | | | | | | | | | | | | | | | | It seems like there's nothing stopping from sub-demuxers from keeping packets in the cache, even if it's completely pointless. The top-most demuxer (demux_timeline) already takes care of caching, so sub-demuxers only waste space and time with this. Add a function that can disable the packet cache even at runtime and after packets are read. (It's not clear whether it really can happen that packets are read before demux_timeline gets the sub-demuxers, but there's no reason to make it too fragile.) Call it on all sub-demuxers. For this to work, it seems we have to move the code for setting the seekable_cache flag to before demux_timeline is potentially initialized, because otherwise the cache would be reenabled if the demuxer triggering timeline support is a timeline segment itself (e.g. ordered chapters).
* demux_timeline: don't use segments for DASHwm42017-10-261-1/+1
| | | | | Recent regression. Crashes because it sets the segmented flag, without actually setting the fields required for segmentation.
* demux_timeline: trust attached picture flagwm42017-10-251-0/+1
| | | | | | Fully fixes behavior of the files mentioned in the previous commit. Will probably lead to worse behavior if someone tries to fix real video and cover art tracks, but that's a broken fringe case anyway.
* demux: get rid of demux_packet.new_segment fieldwm42017-10-241-6/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | The new_segment field was used to track the decoder data flow handler of timeline boundaries, which are used for ordered chapters etc. (anything that sets demuxer_desc.load_timeline). This broke seeking with the demuxer cache enabled. The demuxer is expected to set the new_segment field after every seek or segment boundary switch, so the cached packets basically contained incorrect values for this, and the decoders were not initialized correctly. Fix this by getting rid of the flag completely. Let the decoders instead compare the segment information by content, which is hopefully enough. (In theory, two segments with same information could perhaps appear in broken-ish corner cases, or in an attempt to simulate looping, and such. I preferred the simple solution over others, such as generating unique and stable segment IDs.) We still add a "segmented" field to make it explicit whether segments are used, instead of doing something silly like testing arbitrary other segment fields for validity. Cached seeking with timeline stuff is still slightly broken even with this commit: the seek logic is not aware of the overlap that segments can have, and the timestamp clamping that needs to be performed in theory to account for the fact that a packet might contain a frame that is always clipped off by segment handling. This can be fixed later.
* demux_timeline: change virtual_stream array to array of pointerswm42017-10-241-8/+9
| | | | | | Needed for a failed thing, leaving it anyway because it causes no harm and might be less awkward if struct virtual_stream is possibly extended anyway in the future.
* demux: drop redundant SEEK_BACKWARD flagwm42017-10-231-3/+3
| | | | | | | | | | | | | Seems like most code dealing with this was for setting it in redundant cases. Now SEEK_BACKWARD is redundant, and SEEK_FORWARD is the odd one out. Also fix that SEEK_FORWARD was not correctly unset in try_seek_cache(). In demux_mkv_seek(), make the arbitrary decision that a video stream is not required for the subtitle prefetch logic to be active. We might want subtitles with long duration even with audio only playback, or if the file is used as external subtitle.
* demux: get rid of DEMUXER_CTRL_GET_TIME_LENGTHwm42017-06-201-8/+3
| | | | | | | | | | | | Similar purpose as f34e1a0deea45e. Somehow this is much more natural too, and needs less code. This breaks runtime updates to duration. This could easily be fixed, but no important demuxer does this anyway. Only demux_raw and demux_disc might (the latter for BD/DVD). For the latter it might actually have some importance when changing titles at runtime (I guess?), but guess what, I don't care.
* demux: replace custom return codes with CONTROL_ oneswm42017-06-191-3/+3
| | | | | | | | This is more uniform, and potentially gets rid of some past copyrights. It might be that this subtly changes caching behavior (it seems before this, it synced to the demuxer if the length was unknown, which is not what we want.)
* demux_timeline: more silencingwm42017-02-041-1/+1
|
* ytdl_hook, edl: implement pseudo-DASH supportwm42017-02-041-18/+80
| | | | | | | | | We use the metadata provided by youtube-dl to sort-of implement fragmented DASH streaming. This is all a bit hacky, but hopefully a makeshift solution until libavformat has proper mechanisms. (Although in danger of being one of those temporary hacks that become permanent.)
* demux_timeline: move code aroundwm42017-02-041-41/+41
| | | | Cosmetic preparation for later changes.
* player: different way to auto-enable the demuxer cachewm42017-02-021-0/+2
| | | | | | | | | | | | | | | Instead of enabling it only when a stream-cache is enabled, also try to enable it independently from that if the demuxer is marked as is_network. Also add some code to the EDL code, so EDLs containing network streams are automatically cached this way. Extend the OSD info line so that it shows the demuxer cache in this case (more or less). I didn't find where or whether options.rst describes how the demuxer cache is enabled, so no changes there.
* demux_timeline: always signal new segment after a seekwm42016-11-091-3/+1
| | | | | | | | This is needed to put the decoders into the correct state. In particular, decoders will not initialize the current segment without this flag. The intention of not setting the flag for seeks within the segments were to avoid costly decoder reinits, but it seems this is better handled explicitly in the decoder wrappers.
* demux_timeline: enable refresh seeks in some situationswm42016-08-071-0/+5
| | | | | | | | | | | | | Play a trick to make the packet pos field monotonically increasing over segment boundaries if the source demuxers return monotonically increasing pos values. This allows the demuxer to uniquely identify packets with the pos field, and can do refresh seeks using that. Normally, the packet pos field is used as a fallback for determining the playback position if the demuxer returns no proper duration. But demux_timeline.c always will, and the packet pos fields usually make no sense in relation to the returned file size anyway if the timeline source demuxers originate from separate streams.
* player: improve instant track switchingwm42016-08-061-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | When switching tracks, we normally have the problem that data gets lost due to readahead buffering. (Which in turn is because we're stubborn and instruct the demuxers to discard data on unselected streams.) The demuxer layer has a hack that re-reads discarded buffered data if a stream is enabled mid-stream, so track switching will seem instant. A somewhat similar problem is when all tracks of an external files were disabled - when enabling the first track, we have to seek to the target position. Handle these with the same mechanism. Pass the "current time" to the demuxer's stream switch function, and let the demuxer figure out what to do. The demuxer will issue a refresh seek (if possible) to update the new stream, or will issue a "normal" seek if there was no active stream yet. One case that changes is when a video/audio stream is enabled on an external file with only a subtitle stream active, and the demuxer does not support rrefresh seeks. This is a fuzzy case, because subtitles are sparse, and the demuxer might have skipped large amounts of data. We used to seek (and send the subtitle decoder some subtitle packets twice). This case is sort of obscure and insane, and the fix would be questionable, so we simply don't care. Should mostly fix #3392.
* demux_timeline: restore mkv edition switchingwm42016-07-141-0/+3
|
* demux_timeline: request subtitle prefetching on crossing segmentswm42016-03-251-1/+1
| | | | | | | | | | | SEEK_HR is interpreted by demux_mkv.c, and enables subtitle preroll by prefetching additional subtitle pakcets which might overlap with the seek destination. This should make the case work when segment boundaries fall into the middle of subtitle events. This still usually leaves a flicker of at least 1 frame on start, because dec_sub.c does not ensure that enough subtitles are read before rendering after a segment switch. (Probably a WONTFIX.)
*