summaryrefslogtreecommitdiffstats
path: root/demux/demux_lavf.c
Commit message (Collapse)AuthorAgeFilesLines
* {wscript,demux_lavf}: clean up last bits of !FFMPEG_STRICT_ABIJan Ekström2021-10-261-6/+4
| | | | | | | | | | | | | | | | | The bytes_read struct member in AVIOContext is now officially public, so its usage no longer has to be specified as non-compliance with FFmpeg's ABI/API rules. That said, unfortunately there was a short period of time between August 2021 and October 2021 where the struct member did not exist in FFmpeg's git master, so keep a feature check for it alive for now to enable building with those versions. Thankfully, no release version of FFmpeg will be without this field, so it should be possible to drop this check with time. Finally, simplify the function in case the struct member is not found. After all, there is zero reason to iterate through the AVIO contexts if we cannot get the information we require.
* player: add track-list/N/image sub-propertyGuido Cella2021-10-141-0/+1
| | | | | | | | | | | | | | | | | | | | | | This exposes whether a video track is detected as an image, which is useful for profile conditions, property expansion and lavfi-complex. The lavf demuxer sets image to true when the existing check detects an image. When the lavf demuxer fails, the mf one guesses if the file is an image by its extension, so sh->image is set to true when the mf demuxer succeds and there's only one file. The mkv demuxer just sets image to true for any attached picture. The timeline demuxer just copies the value of image from source to destination. This sets image to true for attached pictures, standalone images and images added with !new_stream in EDL playlists, but it is imperfect since you could concatenate multiple images in an EDL playlist (which should be done with the mf demuxer anyway). This is good enough anyway since the comment of the modified function already says it is "Imperfect and arbitrary".
* demux_lavf: improve image detectionGuido Cella2021-10-141-9/+9
| | | | | | | | | | | | | | | | | | | | This moves the image check to where the number of frames is available of comparison, which allows not detecting jpg and png videos as images, and detecting 1-frame gifs as images. This works with the mjpeg and png videos in the FATE suite, though unfortunately the bmp video is still detected as an image since it has nb_frames = 0. aliaspix streams are also now considered images. Attached pictures are now treated like standalone images, so audio with attached pictures now has mf-fps as container-fps instead of unavailable, which makes it consistent with external cover art, which was already being assigned mf-fps. Unfortunately images in a codec commonly used for videos are never detected, and detection was inaccurate even using the now private codec_info_nb_frames field in AVStream, and mediainfo gets them wrong too, so I guess it's just a lost cause.
* Revert "player: add track-list/N/image sub-property"Jan Ekström2021-10-021-34/+9
| | | | | | | | Unfortunately, this functionality in large part based on a struct member that was made private in FFmpeg/FFmpeg@7489f632815c98ad58c3db71d1a5239b5dae266c in May. Unfortunately, this was not noticed during review. This reverts commit 0862664ac952d21fef531a8923a58ae575268fc5.
* player: add track-list/N/image sub-propertyGuido Cella2021-10-021-9/+34
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This exposes whether a video track is detected as an image. This is useful for profile conditions, property expansion and lavfi-complex, and is more accurate than any detection even Lua scripts can perform, since they can't differentiate between images and videos without container-fps and audio and with duration 1 (which is the duration set by the mf demuxer with the default --mf-fps=1). The lavf demuxer image check is moved to where the number of frames is available for comparison, and is modified to check the number of frames and duration instead of the video codec. This doesn't misdetect videos in a codec commonly used for images (e.g. mjpeg) as images, and can detect images in a codec commonly used for videos (e.g. 1-frame gifs). pix files are also now detected as images, while before they weren't since the condition was checking if the AVInputFormat name ends with _pipe, and alias_pix doesn't. Both nb_frames and codec_info_nb_frames are checked because nb_frames is 0 for some video codecs (hevc, av1, vc1, mpeg1video, vp9 if forcing --demuxer=lavf), and codec_info_nb_frames is 1 for others (mpeg, mpeg4, wmv3). The duration is checked as well because for some uncommon codecs and containers found in FFMpeg's FATE suite, libavformat returns nb_frames = 0 and codec_info_nb_frames = 1. For some of them it even returns duration = 0, so they are blacklisted in order to never be considered images. The extra codecs that would have to be blacklisted without checking the duration are AV_CODEC_ID_4XM, AV_CODEC_ID_BINKVIDEO, AV_CODEC_ID_DSICINVIDEO, AV_CODEC_ID_ESCAPE130, AV_CODEC_ID_MMVIDEO, AV_CODEC_ID_NUV, AV_CODEC_ID_RL2, AV_CODEC_ID_SMACKVIDEO and AV_CODEC_ID_XAN_WC3, while the containers are film-cpk, ivf and ogg. The lower limit for duration is 10 because that's the duration of 1-frame gifs. Streams with codec_info_nb_frames 0 are not considered images because vp9 and av1 have nb_frames = 0 and codec_info_nb_frames = 0, and we can't rely on just the duration to detect them because they could be livestreams without an initial duration, and actually even if we could for these codecs libavformat returns huge negative durations like -9223372036854775808. Some more images in the FATE suite that are really frames cut from a video in an uncommon codec and container, like cine/bayer_gbrg8.cine, could be detected by allowing codec_info_nb_frames = 0, but then any present and future video codec with nb_frames = 0 and codec_info_nb_frames = 0 would need to be added to the blacklist. Some even have duration > 10, so to detect these images the duration check would have to be removed, and all the previously mentioned extra codecs and containers would have to be added added to the blacklists, which means that images that use them (if they exist anywhere) will never be detected. These FATE images aren't detected as such by mediainfo either anyway, nor can a Lua script reliably detect them as images since they have container-fps and duration > 0 and != 1, and you probably will never see files like them anywhere else. For attached pictures the lavf demuxer always set image to true, which is necessary because they have duration > 10. There is a minor change in behavior for which audio with attached pictures now has mf-fps as container-fps instead of unavailable, but this makes it consistent with external cover art, which was already being assigned mf-fps. When the lavf demuxer fails, the mf one guesses if the file is an image by its extension, so sh->image is set to true when the mf demuxer succeds and there's only one file. Even if you add a video's file type to --mf-type and open it with the mf protocol, only the first frame is used, so setting image to true is still accurate. When converting an image to the extensions listed in demux/demux_mf.c, tga and pam files are currently the only ones detected by the mf demuxer rather than lavf. Actually they are detected with the image2 format, but it is blacklisted; see d0fee0ac33a. The mkv demuxer just sets image to true for any attached picture. The timeline demuxer just copies the value of image from source to destination. This sets image to true for attached pictures, standalone images and images added with !new_stream in EDL playlists, but it is imperfect since you could concatenate multiple images in an EDL playlist (which should be done with the mf demuxer anyway). This is good enough anyway since the comment of the modified function already says it is "Imperfect and arbitrary".
* build: address AVCodec, AVInputFormat, AVOutputFormat const warningssfan52021-05-011-2/+2
| | | | FFmpeg recently changed these to be const on their side.
* demux_lavf: fix minor memory leaksrland jon2021-04-201-0/+2
|
* demux_lavf: initialize ReplayGain dataMia Herkt2020-10-231-0/+2
| | | | | | | This was causing undefined behavior when playing streams without RG tags but with RG enabled. Broken in 585f9ff42f3195c. Thanks to uau for bisecting.
* Revert "demux_lavf: always give libavformat the filename when probing"wm42020-08-231-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reverts commit 41243e7c4f98b410195397b6758f9796acd9de57. This fixes image format detection. FFmpeg has an utter called "image2", which is designed to read patterns in filenames (so you can play something like "%*.jpg" for all jpg files in the current directory). "image2" is not what we want; it's just broken with custom I/O like mpv uses it, and we don't want to "accidentally" interpret filenames as pattern. That's why mpv blacklists it. Unfortunately, "image2" is sometimes the format that FFmpeg's probe API returns as best match. Thus demux_lavf fails to detect the file type, and after some more futile attempts, we end up at demux_mf, which uses detection by file extension. (Not sure why. I guess MPlayer did that, and foudn that sufficient.) If the file extension is wrong (which happens a lot because apparently the world is full of idiots who don't manage to get the most simple things right), the image "loads", but decoding obviously fails. There's no easy way around this. The FFmpeg API has no mechanism to exclude a specific format from probing (like image2, which breaks stuff for us). Out of the 5 probe functions the API provides, none can probe a specific format or include or exclude specific formats. The main problem is that AVInputFormat.read_probe is a private symbol. FFmpeg itself has no problem opening such files. It turns out that it works, because even though image2 by itself uses detection by file extension, it uses private API to further probe the exact format. It explicitly excludes itself to prevent recursion. But fortunately, that also means that it's impossible to get the image2 format if no filename is passed to the prober. (No filename, no file extension.) Apparently we pass it in because it helps in corner cases. Until almost 3 years ago, we passed the filename only when normal probing already failed. Restore this by this revert. It makes incorrectly named files work. The revert also makes the (apparently forgotten) comment above the touched line of code true again. Yes, quite possible that this breaks some mp3s again. You can't win with FFmpeg. Thanks FFmpeg for making us fail at opening simple image files and/or the most widely used file format for audio.
* demux_lavf: workaround reading gif from unseekable streamswm42020-07-091-0/+19
| | | | | | | FFmpeg, being the pile of trash as usual, recently broke this. Add our own trash hack to trashily workaround this shit. Fixes: #7893
* options: change option macros and all option declarationswm42020-03-181-24/+23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Change all OPT_* macros such that they don't define the entire m_option initializer, and instead expand only to a part of it, which sets certain fields. This requires changing almost every option declaration, because they all use these macros. A declaration now always starts with {"name", ... followed by designated initializers only (possibly wrapped in macros). The OPT_* macros now initialize the .offset and .type fields only, sometimes also .priv and others. I think this change makes the option macros less tricky. The old code had to stuff everything into macro arguments (and attempted to allow setting arbitrary fields by letting the user pass designated initializers in the vararg parts). Some of this was made messy due to C99 and C11 not allowing 0-sized varargs with ',' removal. It's also possible that this change is pointless, other than cosmetic preferences. Not too happy about some things. For example, the OPT_CHOICE() indentation I applied looks a bit ugly. Much of this change was done with regex search&replace, but some places required manual editing. In particular, code in "obscure" areas (which I didn't include in compilation) might be broken now. In wayland_common.c the author of some option declarations confused the flags parameter with the default value (though the default value was also properly set below). I fixed this with this change.
* demuxer-lavf: udp_multicast rtsp-transport optionmg2020-03-031-1/+4
|
* demux_lavf: don't interpret errors as EOFwm42020-02-281-3/+9
| | | | | | | | | | | | | | | It seems sporadic errors are possible, such as connection timeouts. Before the recent demuxer change, the demuxer thread retried many times even on EOF, so an error was only interpreted as EOF once the decoder queues ran out. Change it to use EOF only. Since this may actually lead to the demuxer thread being "stuck" and retrying forever (depending on libavformat API behavior), I'm also adding a heuristic to prevent this, using a random retry counter. This should not be necessary, but libavformat cannot be trusted. (This retrying forever could be stopped by the user, but obviously it would still heat the CPU for a longer time if the user is not present.)
* demux_lavf: signal no seeking for RTSP streams without durationwm42020-02-201-0/+5
| | | | | | | | | | | | RTSP supports seeking, but at least the libavformat implementation makes this dependent on runtime behavior. So you have to perform a seek, and check if it fails. But even if you do this, the stream is interrupted and restarted, and there seem to be other issues. Assume that RTSP with unknown duration means it's a live stream, and disable seeking in this case, as suggested by the issue reporter. Fixes: #7472
* player: print manifest per-stream bitrate information to terminalwm42020-02-191-2/+0
| | | | | Aka hls-bitrate. In turn, remove the demux_lavf.c hack, which made the track title use this.
* Remove remains of Libav compatibilitywm42020-02-161-2/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Libav seems rather dead: no release for 2 years, no new git commits in master for almost a year (with one exception ~6 months ago). From what I can tell, some developers resigned themselves to the horrifying idea to post patches to ffmpeg-devel instead, while the rest of the developers went on to greener pastures. Libav was a better project than FFmpeg. Unfortunately, FFmpeg won, because it managed to keep the name and website. Libav was pushed more and more into obscurity: while there was initially a big push for Libav, FFmpeg just remained "in place" and visible for most people. FFmpeg was slowly draining all manpower and energy from Libav. A big part of this was that FFmpeg stole code from Libav (regular merges of the entire Libav git tree), making it some sort of Frankenstein mirror of Libav, think decaying zombie with additional legs ("features") nailed to it. "Stealing" surely is the wrong word; I'm just aping the language that some of the FFmpeg members used to use. All that is in the past now, I'm probably the only person left who is annoyed by this, and with this commit I'm putting this decade long problem finally to an end. I just thought I'd express my annoyance about this fucking shitshow one last time. The most intrusive change in this commit is the resample filter, which originally used libavresample. Since the FFmpeg developer refused to enable libavresample by default for drama reasons, and the API was slightly different, so the filter used some big preprocessor mess to make it compatible to libswresample. All that falls away now. The simplification to the build system is also significant.
* demux: stop setting dummy stream on demux_close_stream()wm42019-12-231-3/+7
| | | | | | | | | | | | | | Demuxers can call demux_close_stream() to close the underlying stream if it's not needed anymore. (Useful to release "heavy" resources like FDs and sockets. Plus merely keeping a file open can have visible side effects such as inability to unmount a filesystem or, on Windows, to do anything with the file.) Until now, this set demuxer->stream to a dummy stream, because most code used to assume that the stream field is non-NULL. But this requirement disappeared (in some cases, the stream field is already NULL), so stop doing that. demux_lavf.c, one of the demuxers which calls this function, still had some of this, though.
* demux: add an option to control tag charsetwm42019-12-201-1/+1
| | | | | | Fucking gross that you need this in almost-2020. Fixes: #7255
* demux_lavf: export demuxer_id for more formats which have itwm42019-12-031-5/+8
| | | | | | | | | | | | | | | | | | See previous commit. libavformat exports this information as AVStream.id field. The big problem is that the libavformat field is simply 0 if it's unknown (i.e. the demuxer never sets it). So it needs to remain a whitelist. Just add more formats which are known to have a meaningful ID. I considered exporting IDs for all formats, and then either leaving the values as they are, or filtering duplicate values (and choosing arbitrary but unique different IDs). But then again, I think it's sort of mpv's job to filter FFmpeg's absurd bullshit API, and it should make an effort to hide it rather than to reflect it. See: #7211
* demux_lavf: log packet read errorsAman Gupta2019-11-221-1/+1
| | | | Signed-off-by: Aman Gupta <aman@tmm1.net>
* demux_lavf: fight ffmpeg API some more and get the timeout setwm42019-11-161-2/+29
| | | | | | | | | | | | | | | | | | | | | | | | It sometimes happens that HLS streams freeze because the HTTP server is not responding for a fragment (or something similar, the exact circumstances are unknown). The --timeout option didn't affect this, because it's never set on HLS recursive connections (these download the fragments, while the main connection likely nothing and just wastes a TCP socket). Apply an elaborate hack on top of an existing elaborate hack to somehow get these options set. Of course this could still break easily, but hey, it's ffmpeg, it can't not try to fuck you over. I'm so fucking sick of ffmpeg's API bullshit, especially wrt. HLS. Of course the change is sort of pointless. For HLS, GET requests should just aggressively retried (because they're not "streamed", they're just actual files on a CDN), while normal HTTP connections should probably not be made this fragile (they could be streamed, i.e. they are backed by some sort of real time encoder, and block if there is no data yet). The 1 minute default timeout is too high to save playback if this happens with HLS. Vaguely related to #5793.
* stream_lavf: set --network-timeout to 60 seconds by defaultwm42019-11-141-1/+2
| | | | | | | | | | | Until now, we've made FFmpeg use the default network timeout - which is apparently infinite. I don't know if this was changed at some point, although it seems likely, as I was sure there was a more useful default. For most use cases, a smaller timeout is more useful (for example recording something in the background), so force a timeout of 1 minute. See: #5793
* stream: turn into a ring buffer, make size configurablewm42019-11-061-4/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In some corner cases (see #6802), it can be beneficial to use a larger stream buffer size. Use this as argument to rewrite everything for no reason. Turn stream.c itself into a ring buffer, with configurable size. The latter would have been easily achievable with minimal changes, and the ring buffer is the hard part. There is no reason to have a ring buffer at all, except possibly if ffmpeg don't fix their awful mp4 demuxer, and some subtle issues with demux_mkv.c wanting to seek back by small offsets (the latter was handled with small stream_peek() calls, which are unneeded now). In addition, this turns small forward seeks into reads (where data is simply skipped). Before this commit, only stream_skip() did this (which also mean that stream_skip() simply calls stream_seek() now). Replace all stream_peek() calls with something else (usually stream_read_peek()). The function was a problem, because it returned a pointer to the internal buffer, which is now a ring buffer with wrapping. The new function just copies the data into a buffer, and in some cases requires callers to dynamically allocate memory. (The most common case, demux_lavf.c, required a separate buffer allocation anyway due to FFmpeg "idiosyncrasies".) This is the bulk of the demuxer_* changes. I'm not happy with this. There still isn't a good reason why there should be a ring buffer, that is complex, and most of the time just wastes half of the available memory. Maybe another rewrite soon. It also contains bugs; you're an alpha tester now.
* build: add --enable-ffmpeg-strict-abi optionwm42019-10-211-0/+4
| | | | | | | | | This can be used by distros to disable all known FFmpeg ABI violations. Currently only 1 is known, in demux_lavf.c. In addition to if-defing out the access to the private FFmpeg field, this disables the possibly fragile nested open callbacks, which make sense only if the aforementioned field can be accessed.
* video, demux: rip out unused spherical metadata codewm42019-10-171-12/+0
| | | | | | This was preparation into something that never happened. Spherical video is a shit idea anyway.
* demux: restore some of the DVD/BD/CDDA interaction layerswm42019-10-031-15/+0
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This partially reverts commit a9d83eac40c94f44d19fab7b6955331f10efe301 ("Remove optical disc fancification layers"). Mostly due to the timestamp crap, this was never really going to work. The playback layer is sensitive to timestamps, and derives the playback time directly from the low level packet timestamps. DVD/BD works differently, and libdvdnav/libbluray do not make it easy at all to compensate for this. Which is why it never worked well, but not doing it at all is even more awful. demux_disc.c tried this and rewrote packet timestamps from low level TS to playback time. So restore demux_disc.c, which should bring behavior back to the old often non-working but slightly better state. I did not revert anything that affects components above the demuxer layer. For example, the properties for switching DVD angles or listing disc titles are still gone. (Disc titles could be reimplemented as editions. But not by me.) This commit modifies the reverted code a bit; this can't be avoided, because the internal API changed quite a bit. The old seek resync in demux_lavf.c (which was a hack) is replaced with a hack. SEEK_FORCE and demux_params.external_stream are new additions. Some of this could/should be further cleaned up. If you don't want "proper" DVD/BD support to disappear, you should probably volunteer. Now why am I wasting my time for this? Just because some idiot users are too lazy to rip their ever-wearing out shitty physical discs? Then why should I not be lazy and drop support completely? They won't even be thankful for me maintaining this horrible garbage for no compensation.
* demux_lavf: remove recently added author name from license headerwm42019-10-011-1/+0
| | | | | | | | | | | | | | | | | This was added in 585f9ff42f3195c by @bbarenblat (github handle). We don't do this. This file alone probably has multiple dozen of authors (I didn't count, but it has a history of 15 years). If everyone added their names with each small change, this project would have giant lists of contributing authors on every source file. Neither copyright law nor any of the used licenses require listing authors in the license header. Authorship is recorded in the git log. So don't start with this, and remove this recent case to avoid setting a precedent. Some files still have an author in the header. These cases are grandfathered, and usually are the actual authors of the original code.
* demux_lavf: fix seeking in ogg audio streamswm42019-09-221-0/+3
| | | | | | | | | | | | | | | | | This detected the first packet demuxed after a seek as timestamp discontinuity. Obviously this is non-sense. Since the OGG radio streams for which this feature was introduced are normally unseekable, it's simple to fix this: simply disable it (if in auto mode, the default) as soon as a seek is performed. This code is never called if the stream is considered unseekable, unless the user forced it. There's still a chance this linearization is performed before a seek happens. This will be a bit awkward, but no worse than without this feature, since seeking with timestamp resets is inherently broken in both mpv and libavformat. Fixes: #6974 Fixes: 27fcd4d
* demux_lavf: document intentional FFmpeg API violationwm42019-09-191-0/+4
| | | | | | | | | | | | | | | This field is documented as internal, so an API user should not access it. However, this is the only way to get some read statistics without replacing FFmpeg's entire HLS demuxer. (Using custom I/O as workaround doesn't work: the HLS code uses some weird internal APIs that cannot be provided by FFmpeg API users; I even made the author of the relevant patch to provide a public API, but which was shot down by another FFmpeg developer. So I take this as my right to access this field.) Mention this explicitly, as it affects ABI and API compatibility, and I don't want that anyone claims this was a "mistake". Add some explanations.
* demux: make webm dash work by using init fragment on all demuxerswm42019-09-191-32/+3
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Retarded webshit streaming protocols (well, DASH) chop a stream into small fragments, and move unchanging header parts to an "init" fragment to save some bytes (in the case at hand about 300 bytes for each fragment that is 100KB-200KB, sure was worth it, fucking idiots). Since mpv uses an even more retarded hack to inefficiently emulate DASH through EDL, it opens a new demuxer for every fragment. Thus the fragment needs to be virtually concatenated with the init fragment. (To be fair, I'm not sure whether the alternative, reusing the demuxer and letting it see a stream of byte-wise concatenated fragmenmts, would actually be saner.) demux_lavc.c contained a hack for this. Unfortunately, a certain shitty streaming site by an evil company, that will bestow dytopia upon us soon enough, sometimes serves webm based DASH instead of the expected mp4 DASH. And for some reason, libavformat's mkv demuxer can't handle the init fragment or rejects it for some reason. Since I'd rather eat mushrooms grown in Chernobyl than debugging, hacking, or (god no) contributing to FFmpeg, and since Chernobyl is so far away, make it work with our builtin mkv demuxer instead. This is not hard. We just need to copy the hack in demux_lavf.c to demux_mkv.c. Since I'm not _that_ much of a dumbfuck to actually do this, remove the shitty gross demux_lavf.c hack, and replace it by a slightly less bad generic implementation (stream_concat.c from the previous commit), and use it on all demuxers. Although this requires much more code, this frees demux_lavf.c from a hack, and doesn't require adding a duplicated one to demux_mkv.c, so to the naive eye this seems to be a much better outcome. Regarding the code, for some reason stream_memory_open() is never meant to fail, while stream_concat_open() can in extremely obscure situations, and (currently) not in this case, but we handle failure of it anyway. Yep.
* stream: create memory streams in more straightforward waywm42019-09-191-1/+1
| | | | | | | | | | | | | | | Instead of having to rely on the protocol matching, make a function that creates a stream from a stream_info_t directly. Instead of going through a weird indirection with STREAM_CTRL, add a direct argument for non-text arguments to the open callback. Instead of creating a weird dummy mpv_global, just pass an existing one from all callers. (The latter one is just an artifact from the past, where mpv_global wasn't available everywhere.) Actually I just wanted a function that creates a stream without any of that bullshit. This goal was slightly missed, since you still need this heavy "constructor" just to setup a shitty struct with some shitty callbacks.
* demux: redo timed metadatawm42019-09-191-10/+8
| | | | | | | | | | | | | | | | | |