summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* command: put seek ranges at the end of outputwm42019-09-191-12/+12
| | | | | | | | | | | | | | | | | | This is a minor benign hack that reorders the MPV_FORMAT_NODE output. The order of members is not supposed to matter, but it's how the OSD renders them as raw output. Normally this isn't used, but demuxer-cache-state is a "prominent" case. Moving the seek ranges to the end avoids that the more important other fields are not cut off by going out of the screen on the bottom. Also output the seek ranges in reverse. The order doesn't matter either (as declared by input.rst). Currently, the demuxer orders them by least recent use. Reversing it makes the most recently used range (the current range) show up on top. In other words, this commit does basically nothing but fudge stuff in a cosmetic way to make debugging easier for me, and you've wasted your time reading this commit message and the diff. Good.
* manpage: remove double fw-bytes documentationwm42019-09-191-6/+3
| | | | | It was documented two times, with different text. Merge them and reword it a little.
* demux, command: export bof/eof flagswm42019-09-194-0/+15
| | | | | Export these flags with demuxer-cache-state. Useful for debugging, but any client API users could also make use of it.
* command: make demuxer-cache-state property observablewm42019-09-191-1/+1
| | | | The update is throttled by the normal playloop cache update mechanism.
* playloop: update cache properties in idle statewm42019-09-191-3/+4
| | | | | | | | | This will properly notify observed properties if the player hasn't started actual playback yet, such as with --demuxer-cache-wait. This also happens to cause the main loop more often, which triggers MPV_EVENT_IDLE, and fixes the OSC display. (See previous commit message.)
* player: send MPV_EVENT_TICK during init for the sake of the oscwm42019-09-191-1/+4
| | | | | | | | | | | | | | | | | | | | The OSC's (osc.lua) event handling is fundamentally broken. It waits for MPV_EVENT_TICK to update the UI, and MPV_EVENT_TICK has become entirely meaningless, except as a hack for the OSC. There are many situations where the OSC doesn't properly update because the TICK event it expects isn't sent. Fix one of them: it doesn't update the cache state if the VO window is forced and --demuxer-cache-wait is used. Make it so that the tick event is sent even if playback initialization is taking time. This is still slightly broken, because it works only if the mainloop is actually run, which depends on random circumstances (such as moving the mouse over the VO window). The next commit will add another such circumstance which will make it appear to work, although it's still conceptually broken. If we "fixed" it and strictly woke up the player if the idle timer ran out, we'd send tick events all the time, even if nothing is going on, which we don't want. Fucking shitshow.
* demux: remove logic duplication from packet read functionswm42019-09-191-68/+57
| | | | | | | | | | | | | | | | | There were 3 packet reading functions: the "old" demux_read_packet() that blocked (leftover from MPlayer times, but was still used until recently by some obscure code), the "new" demux_read_packet_async(), and the special demux_read_any_packet(), that is used by pseudo-demuxers like demux_edl. The first two could be used both in threaded and un-threaded mode. This made 5 cases in total. Some bits of logic was spread across all of them. Unify the logic. A recent commit made demux_read_packet() private, and the code for it in threaded mode disappears. The difference between threaded and un-threaded is minimized. It's possible that this commit causes random regression. Enjoy.
* sub: remove only user of demux_read_packet()wm42019-09-193-6/+25
| | | | | | | | | | | | | | | | | | | There are 3 packet reading functions in the demux API, which all function completely differently. One of them, demux_read_packet(), has only 1 caller, which is in dec_sub.c. Change this caller to use demux_read_packet_async() instead. Since it really wants to do a blocking call, setup some proper waiting. This uses mp_dispatch_queue, because even though it's overkill, it needs the least code. In practice, waiting actually never happens. This code is only called on code paths where everything is already read into memory (libavformat's subtitle demuxers simply behave this way). It's still a bit of a "coincidence", so implement it properly anyway. If suubtitle decoder init fails, we still need to unset the demuxer wakeup callback. Add a sub_destroy() call to the failure path. This also happens to fix a missed pthread_mutex_destroy() call (in practice this was a nop, or a memory leak on BSDs).
* f_decoder_wrapper: move cover art retrievalwm42019-09-191-5/+5
| | | | | This is basically a refactor in preparation for future changes and shouldn't have much influence on actual behavior.
* 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).
* demux: adjust reader_head on range joiningwm42019-09-191-0/+8
| | | | | | | | | | | | | | | | | | | I'm not sure about this, but it looks like a bug. If a stream didn't have packets, but the joined range does, the stream should obviously read the packets added by the joined range. Until now, due to reader_head being NULL, reading was only resumed if a _new_ packet was added by actual demuxing (in add_packet_locked()), which means the stream would suddenly skip ahead, past the original end of the joined range. Change it so that it will pick up the new range. Also, clear the skip_to_keyframe flag. Nothing useful can come from this flag being set; in the first place, the first packet of a range (that isn't the current range) should start with a keyframe. Some code probably enforced it (although it's fuzzy). Completely untested.
* demux: don't process obscure skipped packetswm42019-09-191-0/+5
| | | | | | | | | | When doing a seek to the end of the cache, ds->skip_to_keyframe can be set to true. Then some packets passed to add_packet_locked() may have to be skipped. In some aspects, the skipped packet was still treated as if it was going to be returned to the reader. It almost doesn't matter though: it only caused a redundant wakeup_ds() call, and could pass the packet to the stream recorder. Fix it anyway.
* demux: factor out a some packet queue codewm42019-09-191-11/+22
| | | | | Might be helpful for later. The "duplicated" ds->reader_head check above the function call is redundant, but leaving it also for later.
* demux: fix typos in commentswm42019-09-191-2/+2
| | | | How does this happen?
* player: add --demuxer-cache-wait optionwm42019-09-196-0/+35
|
* packet: reorder fieldswm42019-09-191-5/+6
| | | | Saves 8 bytes on 64 bit platforms.
* sd_lavc: fix some obscure UBwm42019-09-191-4/+4
| | | | | | | | UB-sanitizer complains that we shift bits into the sign (when a is used). Change it to unsigned, which in theory is more correct and silences the warning. Doesn't matter in practice, both the "bug" and the fix have 0 impact.
* demux_edl: fix assertion failure on exit in obscure ytdl caseswm42019-09-191-0/+1
| | | | | | | | | | | | | | | | | | | | | | If a DASH-hack EDL has an init fragment is set, it opens the init fragment as such to get the track layout (including codec etc.) and avoids opening actual fragments until actual playback. It does not get added to the source array, so it leaks on exit, which triggers an obscure (but very justified) assertion in thread_tools.c:106. Fix the leak by adding the additional demuxer instance to the sources arrays, which gets it freed. This is a regression from when I rewrote some of the timeline handling. I decided that in order to make memory management slightly simpler, freeing a timeline should only free elements in the sources array. That is OK; I just didn't re-test with pseudo-DASH that has init fragments, and just hit a video that uses that by accidents. These videos are rather scarce (apparently) so it happened only now. The real solution would probably be adding demuxer reference counting. This EDL memory management is just too messy, and throwing refcounting at such problems is an effective and popular fix. Then you'd get debugging nightmares with incorrect refcounts too, though.
* demux_mkv: fix seeking in broken mjpeg fileswm42019-09-191-1/+3
|
* DOCS/edl-mpv.rst: make clear the DASH stuff is for internal use onlywm42019-09-191-0/+7
| | | | | | | ytdl_hook.lua essentially uses these headers to implement parts of DASH. Hopefully the FFmpeg DASH demuxer gets usable at some point, and/or mpv gets a proper DASH demuxer. In any case, these EDL hacks could get removed as soon as they get unnecessary and too annoying.
* 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-196-6/+29
| | | | | | | | | | | | | 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-197-131/+160
| | | | | | | | | | | | | | | | | | | | | 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.
* ytdl_hook: use no_clip for separate audio streamswm42019-09-191-1/+1
| | | | | | | | | | | | I noticed that some ytdl streams have a start time other than 0. There's currently no mechanism inside of the EDL stuff that determines this start time correctly, so it can happen that if the start time is high, demux_timeline.c tries to clip off the entire video and audio, resulting in failure of playback. As a counter measure, use the no_clip header, which entirely disables clipping against time ranges in demux_timeline.c. (It's basically a hack.)
* demux_edl: add no_clipwm42019-09-194-8/+17
| | | | | | 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.
* video: fix player not exiting if no video frame was renderedwm42019-09-191-2/+3
| | | | | | | | | | | | E.g. "mpv null:// --demuxer=rawvideo" will "hang" by waiting for video EOF forever. It's not signalled correctly because of the last-frame corner case, which attempts to wait until the current frame is finally displayed (which is signalled by whether a new frame can be queued, see commit 1a339fa09d for some details). If no frame was ever queued, the VO is not configured, and vo_is_ready_for_frame() never returns true. Fix this by using vo_has_frame(), which seems to be exactly the correct thing we need.
* stream: log positions on seek failureswm42019-09-191-1/+2
|
* ytdl_hook: fix pseudo-DASH if no init fragment is presentwm42019-09-191-5/+11
| | | | | | | | | | | | | | Init fragments are not a necessity for DASH, but this code assumed so. Maybe the check was to prevent worse. But using normal EDL here leads to very shitty behavior where it tries to open hundreds or thousands of fragments, each with its own demuxer and HTTP connection. (This behavior is fine for normal uses of EDLs, but completely unacceptable when emulating fragmented streaming protocols. I'm not sure why the normal EDL code is needed here, but I think someone claimed some obscure sites just need it.) This happens in the same situation as the one described in the previous commit.
* ytdl_hook: audio can use fragmented DASH toowm42019-09-191-1/+1
| | | | | | | | | | | | | | Otherwise we'd just use the base URL as media URL, which would fail with a 404 error. Not sure if there's a deeper reason why the audio path was explicitly different from the video one. But this actually works now for a video that returned fragmented DASH audio with the default format selection. (This affects streams on that well known site of a big evil Silicon Valley company. Typically happens after live stream gets converted to a normal video, though after some time passes, this fragmented version is deleted, and replaced by a non-fragmented one. I've observed this several times and this seems to be the "normal" behavior.)
* 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: fix typo in a commentwm42019-09-191-2/+2
|
* demux: fix SEEK_FORWARD into end of cached rangewm42019-09-191-0/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes that there were weird delay ("buffering") when seeking into the last part of a seekable range. The exact case which triggers it if SEEK_FORWARD is used, and the seek pts is after the second-last keyframe, but before the end of the range. In that case, find_seek_target() returned NULL, and the cache layer waited until the _next_ keyframe the underlying demuxer returned until resuming playback. find_seek_target() returned NULL, because the last keyframe had kf_seek_pts unset. This field contains the lowest PTS in the packet range from the keyframe until the next keyframe (or EOF). For normal seeks, this is needed because keyframes don't necessarily have the minimum PTS in the packet range, so it needs to be computed by waiting for all packets until the next keyframe (or EOF). Strictly speaking, this behavior was correct, but it meant that the caller would set ds->skip_to_keyframe, which waits for the next newly demuxed keyframe. No packets were returned to the decoder until this happened, usually resulting in the frontend entering "buffering" mode. What it really needs to do is returning the last keyframe in the cache. In this situation, the seek target points in the middle of the last completely cached packet range (as delimited by keyframes), and SEEK_FORWARD is supposed to skip to the next keyframe. This is in line with the basic assumptions the packet cache makes (e.g. the keyframe flag means it's possible to start decoding, and the frames decoded from it and following packets will strictly have PTS values above the previous keyframe range). This means in this situation the kf_seek_pts value doesn't matter either. So fix this situation by explicitly detecting it and then returning the last cached keyframe. Should the search loop look at all packets, instead of only keyframe ones? This would mean it can know that it's within the last keyframe range (without looking at queue->seek_end). Maybe this would be a bit more natural for the SEEK_FORWARD case, but due to PTS reordering it doesn't sound like a useful thing to do. Should skip_to_keyframe be checked by the code that sets kf_seek_pts to a known value? This wouldn't help too much; the frontend would still go into "buffering" mode for no reason until the packet range is completed, although it would resume from the correct range. Should a NULL return always unconditionally use keyframe_latest? This makes sense because the seek PTS is usually already in the cached range, so this is the only case that should happen. But there are scary special cases, like sparse subtitle streams, or other uses of find_seek_target() which could be out of range now or in future. Basically, don't "risk" it. One other potential problem with this is that the "adjust seek target" code will be disabled in this case. It checks kf_seek_pts, and if it's unset, the adjustment is not done. Maybe this could be changed to use the queue's seek_end time, but I'm not sure if this is fully kosher. On the other hand, I think the main use for this adjustment is with backwards seeks, so this shouldn't matter. A previous commit dealing with audio/video stream merging mentioned how seeking forward entered "buffering" mode for unknown reasons; this commit fixes this issue.
* demux_timeline: report network speed of slave connectionswm42019-09-193-1/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: slightly cleanup network speed reportingwm42019-09-193-8/+32
| | | | | | | | | | | | It was an ugly hack, and the next commit will make it even uglier. Slightly reduce the ugliness to prevent death of too many brain cells, though it's still an ugly hack. The cleanup is really minor, but I guess the following commit would be much worse otherwise. In particular, this commit checks accesses (instead of having a public field with evil access rules), which should avoid misunderstandings and incorrect use. Strictly speaking, the added field is redundant, but the next commit complicates it a bit.
* ytdl_hook: disable EDL-generated useless chapters when merging streamswm42019-09-191-1/+2
| | | | (Yes, a bit odd how this header is needed only for the first stream.)
* demux_edl: add a special header to disable chapter generationwm42019-09-192-11/+29
| | | | A bit of a hack.
* demux_edl: explicitly error on unknown header typeswm42019-09-191-0/+2
| | | | | | I think this is better. On the other hand, this is a behavior change. The EDL "spec" says that unknown fields are igored. But strictly speaking, unknown headers are not "fields", but unknown entities.
* demux_edl: minor cleanup to header parsingwm42019-09-191-31/+35
| | | | | | | EDL "headers" were always an afterthought, and kind of hacked on top of the existing code. Improve it slightly, and make it follow the conventions of the normal parsing. Basically use the same code structure for them, just that they use different field names.
* ytdl_hook: merge separate audio tracks via EDLwm42019-09-191-5/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This merges separate audio and video tracks into one virtual stream, which helps the mpv caching layer. See previous EDL commit for details. It's apparently active for most of evil Silicon Valley giant's streaming videos. Initial tests seem to work fine, except it happens pretty often that playback goes into buffering immediately even when seeking within a cached range, because there is not enough forward cache data yet to fully restart playback. (Or something like this.) The audio stream title used to be derived from track.format_note; this commit stops doing so. It seemed pointless anyway. If really necessary, it could be restored by adding new EDL headers. Note that we explicitly don't do this with subtitle tracks. Subtitle tracks still have a chance with on-demand loading or loading in the background while video is already playing; merging them with EDL would prevent this. Currently, subtitles are still added in a "blocking" manner, but in theory this could be loosened. For example, the Lua API already provides a way to run processes asynchronously, which could be used to add subtitles during playback. EDL will probably be never flexible enough to provide this. Also, subtitles are downloaded at once, rather than streamed like audio and video. Still missing: disabling EDL's pointless chapter generation, and propagating download speed statistics through the EDL wrapper.
* loadfile, ytdl_hook: don't reject EDL-resolved URLs through playlistwm42019-09-193-1/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* demux, demux_edl: add extension for tracks sourced from separate streamswm42019-09-195-159/+315
| | | | | | | | | | | | | | | | | | | | | | | | |