summaryrefslogtreecommitdiffstats
Commit message (Collapse)AuthorAgeFilesLines
* demux: move timestamp helper macros to common.hwm42019-09-192-12/+12
| | | | These are probably generally useful.
* manpage: document accidental feature/bugwm42019-09-191-5/+19
| | | | | | | | | | | | | | | | Clarify existing semantics for the --start/--end/--length options. De-emphasize the difference between absolute and relative timestamps, since they've not been different by default since mpv 0.14. Document a bug, that also happens to work as a feature: if the option value begins with spaces, the code for checking for relative timestamps is inactive, and they're always considered absolute. The check is done on the first character of the string - so even a negative timestamp will be treated as absolute.) Yes, this is useful in extremely rare situations, such as when you really want send a specific timestamp (even a negative one) to the demuxer.
* player: partially fix seek_to_last_frame in backward modewm42019-09-191-4/+9
| | | | | | | | | | | | | | | | | | | | | | | | | | | | Another shitty obscure feature that usually nobody notices. Unsurprisingly, it doesn't go well with backward playback mode. If you use --keep-open in forward playback mode, and seek past the end of the file, it tries to seek to the very last frame. The demuxer will seek to the last "keyframe" before the end (i.e. some frames to go in most cases), and trying to hr-seek to the file duration often won't cut it, so this requires some special code. The function at hand seeks "close" to the end, and then stops hr-seek when the last frame us encountered (simple enough and very effective). In backward playback mode, start and end are reversed, and we need to seek "close" to the start of the file instead. Simple enough to do, and it works. One problem is that command.c has some weird logic to make going beyond the last chapter either end playback (--keep-open=no), or jump to the last frame. Now this will jump to the first frame, which is weird, but let's ignore this. Another problem is that seeking before playback start position hits EOF in backward playback mode, which is a demuxer bug, and has nothing to do with this code. But it triggers this code, so seeking before the start will show the "last" frame. (My description is a mess with directions. Figure it out yourself.)
* player: fix --loop with backward playbackwm42019-09-194-10/+19
| | | | | | | | | | | 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: remove some duplication between normal looping and ab-loopswm42019-09-191-14/+19
| | | | | | Not sure if this is better or worse. Some minor behavior changes.
* player: modify/simplify AB-loop behaviorwm42019-09-197-83/+86
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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: replace a magic numer by another magic numberwm42019-09-191-1/+1
| | | | | | | | | | | | | | | | | This code attempts to seek to the last frame by seeking close to the end, and then decoding until the last frame has been reached. To do so it sets hrseek_lastframe, which for video enables some logic to "catch" this last frame, and completely ignores hrseek_pts. But audio still may use hrseek_pts I don't know if the original author (me) was thinking, if anything, when setting this variable to 1e99, essentially a random, number. It's very large, and a timestamp like this will never happen, so it does its job. But it's random. Use INFINITY instead. It will skip all audio samples in the audio code correctly. This change doesn't fix anything, but it does get rid of the random looking number.
* player: simplify/fix --start/--end handling with --rebase-start-time=nowm42019-09-192-27/+10
| | | | | | | | | | | | | | | | | | | | | | 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.
* player: minor --end simplificationwm42019-09-191-4/+1
|
* options: remove --chapterwm42019-09-195-33/+3
| | | | | | | | | Has been deprecated for almost 3 years. Manpage didn't mention the deprecation, but CLI and release notes did. It wouldn't be much effort to keep this option working, but I just don't see the damn point. --start/--end can specify chapters using special syntax, which is equivalent.
* player: fix --end for backwards playbackwm42019-09-192-0/+4
| | | | | | | | We need to transform the timestamp returned by get_play_end_pts(). I considered making it return the transformed timestamp directly. There are 4 callers; 2 need a transformed timestamps, 2 don't. So I guess it doesn't matter.
* osd: simplify AB-loop rendering on progress barwm42019-09-191-9/+10
| | | | | | This adds the stops using the same logic get_play_end_pts() and handle_loop_file(). It did that before, it just looks slightly different now. It also won't try to add MP_NOPTS_VALUE as stop value.
* player: make a function staticwm42019-09-192-2/+1
|
* demux, f_decoder_wrapper: fix coverart in backward modewm42019-09-192-13/+17
| | | | | | | | | | | | Shitty ancient hack that wastes my time all the time. demux.c: always return the coverart packet as soon as possible, and don't let the backward demux state machine possibly stop it. f_decoder_wrapper.c: mess with some shit until it somehow starts to work. I think the old code tried to let it cleverly fall through so the packet was processed "normally"; just make it run the "usual" code instead.
* player: fix --hr-seek-demuxer-offset with backward playbackwm42019-09-191-1/+1
|
* demux_lavf: implement bad hack for backward playback of wavwm42019-09-192-15/+67
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit generally fixes backward playing in wav, at least in most PCM cases. libavformat's wav demuxer (and actually all other raw PCM based demuxers) have a specific behavior that breaks backward demuxing. The same thing also breaks persistent seek ranges in the demuxer cache, although that's less critical (it just means some cached data gets discarded). The backward demuxing issue is fatal, will log the message "Demuxer not cooperating.", and then typically stop doing anything. Unlike modern media formats, these formats don't organize media data in packets, but just wrap a monolithic byte stream that is described by a header. This is good enough for PCM, which uses fixed frames (a single sample for all audio channels), and for which it would be too expensive to have per frame headers. libavformat (and mpv) is heavily packet based, and using a single packet for each PCM frame causes too much overhead. So they typically "bundle" multiple frames into a single packet. This packet size is obviously arbitrary, and in libavformat's case hardcoded in its source code. The problem is that seeking doesn't respect this arbitrary packet boundary. Seeking is sample accurate. You can essentially seek inside a packet. The resulting packets will not be aligned with previously demuxed packets. This is normally OK. Backward seeking (and some other demuxer layer features) expect that demuxing an earlier demuxed file position eventually results in the same packets, regardless of the seeks that were done to get there. I like to call this "deterministic" demuxing. Backward demuxing in particular requires this to avoid overlaps, which would make it rather hard to get continuous output. Fix this issue by detecting wav and hopefully other raw audio formats with a heuristic (even PCM needs to be detected as heuristic). Then, if a seek is requested, align the seek timestamps on the guessed number of samples in the audio packets returned by the demuxer. The heuristic excludes files with multiple streams. (Except "attachment" video streams, which could be an ID3 tag. Yes, FFmpeg allows ID3 tags on WAV files.) Such files will inherently use the packet concept in some way. We don't know how the demuxer chooses the internal packet size, but we assume that it's fixed and aligned to PCM frame sizes. The frame size is most likely given by block_align (the native wav frame size, according to Microsoft). We possibly need to explicitly read and discard a packet if the seek is done without reading anything before that. We ignore any subsequent packet sizes; we need to avoid the very last packet, which likely has a different size. This hack should be rather benign. In the worst case, it will "round" the seek target a little, but the maximum rounding amount is bounded. Maybe we _could_ round up if SEEK_FORWARD is specified, but I didn't bother. An earlier commit fixed the same issue for mpv's demux_raw. An alternative, and probably much better solution would be clipping decoded data by timestamp. demux.c could allow the type of overlap the wav demuxer introduces, and instruct the decoder to clip the output against the last decoded timestamp. There's already an infrastructure for this (demux_packet.end field) used by EDL/ordered chapters. Although this sounds like a good solution, mpv unfortunately uses floats for timestamps. The rounding errors break sample accuracy. Even if you used integers, you'd need a timebase that is sample accurate (not always easy, since EDL can merge tracks with different sample rates).
* demux: add an explicit start state for backward demuxingwm42019-09-191-20/+48
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Yay, more subtle state on top of this nightmarish, fragile state machine. But this is what happens when you subvert the laws of nature. This simple checks where playback should "resume" from when no packets were returned to the decoder yet after the seek that initiated backward playback. The main purpose is to process the first returned keyframe range in the same way like all other ranges. This ensures that things like preroll are included properly. Before this commit, it could for example have happened that the start of the first audio frame was slightly broken, because no preroll was included. Since the audio frame is reversed before sending it to the audio output, it would have added an audible discontinuity before the second frame was played; all subsequent frames would have been fine. (Although I didn't test and confirm this particular issue.) In future, this could be useful for certain other things. At least the condition for delaying the backstep seek becomes simpler and more explicit. Move the code that attempts to start demuxing up in dequeue_packet. Before, it was not called when the stream was in back_restarting state. This commit makes streams be in back_restarting state at initialization, so the demuxer would never have started reading. Likewise, we need to call back_demux_see_packets() right after seek in case the seek was within the cache. (We don't bother with checking whether it was a cached seek; nothing happens if it was a normal one.) There is nothing else that would process these cached packets explicitly, although coincidences could sporadically trigger it. The check for back_restart_next in find_backward_restart_pos() now decides whether to use this EOF special code. Since the backward playback start state also sets this variable, we don't need some of the complex checks in dequeue_packet() anymore either.
* manpage: deinterlacing with backwards playback probably workswm42019-09-191-3/+1
| | | | | | | | | | | | | | | | | | | | | | | As well as other filtering. I was writing this with the assumption that timestamps go backwards (which I first planned to do). But in fact, timestamps go forward, frame durations are positive, and adding a frame duration to a timestamp yields the correct result. The only strange thing is that timestamps are negative. Also, media of course goes backwards. In other possible implementation, filters would see normal forward playback, interrupted by seeks or discontinuities. It turns out the current implementation of providing a continuous backward media stream is probably better for filters. Even deinterlacing seems to work. libavcodec always outputs fields in as interleaved frames (i.e. fields are not reversed), and making up timestamps for the new frames (when doubling the framerate) works exactly like like in the forward case. Actually the previous paragraph was a lie, and libavcodec does not output fields as interleaved frames in rare cases. Sometimes AVFrame contains single fields. In this case you'd need to inverse the field dominance for deinterlacing filters to work correctly.
* manpage: backward encoding actually appears to workwm42019-09-191-1/+2
| | | | | | | | | | | | The way backward playback is implemented doesn't break basic assumptions about timestamps after the decoder, so I guess all the encoding mode needs to do is to adjust for the start offset, which it already does. Though I might be wrong and my test was possibly flawed. Stream recording on the other hand will fail immediately with --record-file, and --stream-record will probably yield unexpected results if any backstep seeks are done.
* demux: add a special case for backward demuxing of opuswm42019-09-192-2/+6
| | | | | | | | | | | Make --audio-backward-overlap default to 2 for Opus. I have no idea why this is needed. It seems to fix backward decoding though (going purely by listening). Normally, this should not be needed, since initial padding is completely contained within the first packet (normally, and in the case I tested). So the 2nd packet/frame should be fine, but for some unknown reason it works only with the 3rd.
* demux: use no overlapping packets for lossless audiowm42019-09-194-3/+14
| | | | | | Worthless optimization, but at least it justifies that the --audio-backward-overlap option has an "auto" choice. Tested with PCM and FLAC.
* manpage: document why Vorbis backward playback does not workwm42019-09-191-0/+7
| | | | | | | The only reasonable solution to this is probably to make discarding of preroll frames based on timestmaps, instead of frame/packet count. But then you get issues with video and its dumb timestamp reordering. So for now, fuck it.
* demux: remove some redundant pointer indirectionswm42019-09-191-13/+13
| | | | | | In all of these cases ds->in should be the same as the local variable in, and neither ds->in nor in ever change, i.e. a cosmetic simplification.
* demux: change backward-overlap to keyframe ranges instead of packetswm42019-09-192-39/+41
| | | | | | | | | This seems more useful in general. This change also happens to fix a miscounting of preroll packets when some of them were "rounded" away, and which could make it stuck. Also a simple intra-refresh encode with x264 (and muxed to mkv by it) seems to work now. I guess I misinterpreted earlier results.
* demux: fix typoswm42019-09-191-2/+2
|
* demux: redo backstep seek handling slightly againwm42019-09-191-2/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Backstepping still could get "stuck" if the demuxer didn't seek far back enough. This commit fixes getting stuck if playing backwards from the end, and audio has ended much earlier than the video. In commit "demux: fix initial backward demuxing state in some cases", I claimed that the backward seek semantics ("snapping" backward in normal seeking, unrelated to backward playing) would take care of this. Unfortunately, this is not always quite true. In theory, a seek to any position (that does not use SEEK_FORWARD, i.e. backward snapping) should return a packet for every stream. But I have a mkv sample, where audio ends much earlier than video. Its mkvmerge created index does not have entries for audio packets, so the video index is used. This index has its last entry somewhere close after the end of audio. So no audio packets will be returned. With a "too small" back_seek_size, the demuxer will retry a seek target that ends up in this place forever. (This does not happen if you use --index=recreate. It also doesn't happen with libavformat, which always prefers its own index, while mpv's internal mkv demuxer strictly prefers the index from the file if it can be read.) Fix this by adding the back_seek_size every time we fail to see enough packets. This way the seek step can add up until it works. To prevent that back_seek_pos just "runs away" towards negative infinity by subtracting back_seek_size every time we back step to undo forward reading (e.g. if --no-cache is used), readjust the back_seek_pos to the lowest known resume position. (If the cache is active, kf_seek_pts can be used, but to work in all situations, the code needs to grab the minimum PTS in the keyframe range.)
* demux: set SEEK_HR for backstep seeks, move a hr-seek detail to playloopwm42019-09-192-14/+9
| | | | | | Just rearranging shit. Setting SEEK_HR for backstep seeks actually doesn't have much meaning, but disables the weird audio snapping for "keyframe" seeks, and I don't know it's late.
* demux: rename a variablewm42019-09-191-8/+8
| | | | | It's "better". This is all what's left from an attempt to make the code slightly nicer.
* demux: remove minor code duplicationwm42019-09-191-16/+14
| | | | | | | | | | | | | | | | | | This code used to be simpler, but now it's enough that it should be factored into a single function. Both uses of the new function are annoyingly different. The first use is the special case when a decoder tries to read packets, but the demuxer doesn't see any (like mp4 files with sparse video packets, which actually turned out to be chapter thumbnail "tracks"). Then the other stream queues will overflow, and the stream with no packets is marked EOF to avoid stalling playback. The second case is when the demxuer returns global EOF. It would be more awkward to have the loop iterating the streams in the function, because then you'd need a weird parameter to control the behavior.
* demux: fix initial backward demuxing state in some caseswm42019-09-192-67/+95
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Just "mpv file.mkv --play-direction=backward" did not work, because backward demuxing from the very end was not implemented. This is another corner case, because the resume mechanism so far requires a packet "position" (dts or pos) as reference. Now "EOF" is another possible reference. Also, the backstep mechanism could cause streams to find different playback start positions, basically leading to random playback start (instead of what you specified with --start). This happens only if backstep seeks are involved (i.e. no cached data yet), but since this is usually the case at playback start, it always happened. It was racy too, because it depended on the order the decoders on other threads requested new data. The comment below "resume_earlier" has some more blabla. Some other details are changed. I'm giving up on the "from_cache" parameter, and don't try to detect the situation when the demuxer does not seek properly. Instead, always seek back, hopefully some more. Instead of trying to adjust the backstep seek target by a random value of 1.0 seconds. Instead, always rely on the random value provided by the user via --demuxer-backward-playback-step. If the demuxer should really get "stuck" and somehow miss the seek target badly, or the user sets the option value to 0, then the demuxer will not make any progress and just eat CPU. (Although due to backward seek semantics used for backstep seeks, even a very small seek step size will work. Just not 0.) It seems this also fixes backstepping correctly when the initial seek ended at the last keyframe range. (The explanation above was about the case when it ends at EOF. These two cases are different. In the former, you just need to step to the previous keyframe range, which was broken because it didn't always react correctly to reaching EOF. In the latter, you need to do a separate search for the last keyframe.)
* sd_lavc: implement --sub-pos for bitmap subtitleswm42019-09-192-0/+20
| | | | | | | | | | | | | Simple enough to do. May have mixed results. Typically, bitmap subtitles will have a tight bounding box around the rendered text. But if for example there is text on the top and bottom, it may be a single big bitmap with a large transparent area between top and bottom. In particular, DVD subtitles are really just a single screen-sized RLE-encoded bitmap, though libavcodec will crop off transparent areas. Like with sd_ass, you can't move subtitles _down_ if they are already in their origin position. This could probably be improved, but I don't want to deal with that right now.
* demux_lavf: also fix cache seeking with large codec delaywm42019-09-191-0/+2
| | | | | | | | | Fixes the same thing as the previous commit did with demux_mkv. I'm not sure if this is correct or a good idea (well, it works with my sample file). There are some shady things in this, but describing them would require too many expletives.
* demux, demux_mkv: fix seeking in cache with large codec delaywm42019-09-193-1/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | In this scenario, the demuxer will output timestamps offset by the codec delay (e.g. negative timestamps at the start; mkv simulates those), and the trimming in the decoder (often libavcodec, but ad_lavc.c in our case) will adjust the timestamps back (e.g. stream actually starts at 0). This offset needs to be taken into account when seeking. This worked in the uncached case. (demux_mkv.c is a bit tricky in that the index is already in the offset space, so it compensates even though the seek call does not reference codec_delay.) But in the cached case, seeks backwards did not seek enough, and forward they seeked too much. Fix this by adding the codec delay to the index search. We need to get "earlier" packets, so e.g. seeking to position 0 really gets the initial packets with negative timestamps. This also adjusts the seek range start. This is also pretty obvious: if the beginning of the file is cached, the seek range should start at 0, not a negative value. We compare 0-based timestamps to it later on. Not sure if this is the best approach. I also could have thought about/checked some corner cases harder. But fuck this shit. Not fixing duration (who cares) or end trimming, which would reduce the seek range and duration (who cares).
* demux_mkv: stop setting per-packet initial padding from codec delaywm42019-09-191-2/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | This is a bad approach, and should be handled by a codec parameter field (in mp_codec_params or AVCodecParameters). It's bad because it's overly complicated, and has potential to break demuxer cache assumptions: packets that were "intended" for seek resuming may suddenly appear in the middle of a stream, when you seek back and play a cached part again. (In general it was fine though, because seek range joining tends to remove the first audio packet of the next range when trying to find an overlap.) demux_mkv.c does not try to export its codec_delay field through the codec parameters mentioned above. In the only case I spotted this element, the codec itself (opus) set this field within libavcodec. And I think that's actually how it should be. On the other hand, a file could in theory set this field via mkv headers if the codec is too stupid to have such a field internally. But I don't really care until I see such a file. The end trimming is still sort of needed (though not sure if anything uses it, other than the opus/mkv test sample I was using). The decoder can't know whether something is the last packet, until it's too late. The codec_delay field is still needed to offset timestamps.
* ad_lavc: skip fully skipped frameswm42019-09-191-1/+5
| | | | | | | | | | | Fixes stupid messages with a opus/mkv test file that had an absurdly huge codec delay. This file fully skips several frames at the start. ad_lavc.c trimmed these frames to 0 samples and returned them. The next layer (f_decoder_wrapper.c) saw discontinuous PTS values, because the PTS values increased by a frame, but amounted to 0 audio samples. This was harmless, but logged PTS discontinuity errors.
* manpage: document that backward playback from the end does not workwm42019-09-191-0/+8
| | | | | | | | | | | | | | | | | | | | | | | | | | Not specifying a --start or using --start=100% with --play-direction=backward usually does not work. The demuxer gets no packets and immediately enters EOF state, which then hangs because backward playback mode neither considers this mode, nor propagates the EOF. As far as demuxer implementations are concerned, this behavior is OK and even wanted. Seekin