summaryrefslogtreecommitdiffstats
path: root/filters/filter.c
Commit message (Collapse)AuthorAgeFilesLines
* filter: add filter priority thingwm42020-08-281-6/+27
| | | | | | | This is a kind of bad hack (with bad implementation) to paint over other problems of the filter system. The main problem is that some filters might be left with pending frames if the filter runner is "paused", which we don't want. To be used in a later commit.
* filter: add a helperwm42020-08-271-0/+5
| | | | | Not used yet; probably will, just dumping this to get it out of my sight.
* filter: reduce redundant re-iterationswm42020-04-101-8/+29
| | | | | | | | | | | | | | | | | | | | | | | | | | | When the player core requests new frames from the filter, this is called external/recursive filtering, which acts slightly differently from when filters request new data internally. Mainly this is so the external user doesn't have to call mp_filter_graph_run() just to get a frame. This causes a number of complications, and the short version is that until now, mp_filter_graph_run() has unnecessarily returned true in the current common case, which made the playloop run too often for no reason. The problem is that when a mp_pin is read externally, updating the same mp_pin during recursive filtering flagged external_pending when the result was written, which made mp_filter_graph_run() return true, which made the playloop call mp_filter_graph_run() again. This is redundant because the caller is obviously checking the new state of the mp_pin immediately. The only situation in which external_pending really must be set is if _another_ pin is changed. In theory, we could also unset it if the set of "external" pins that are not in a signaled state becomes empty, but we don't track that in a convenient way. This commit removes the redundant signaling, and avoids running the playloop an additional time for each video and audio frame (as it actually was planned from the beginning, but duh).
* filter: process asynchronous wakeups during filteringwm42020-04-101-4/+5
| | | | | | | | | | | | | If a filter receives an asynchronous wakeup during filtering, then process newly pending filters resulting from that as well, before returning to the user. Might possibly skip some redundant playloop cycles. There is an explicit comment in the code about how this shouldn't be done, but I think it makes no sense. Filters have no business trying to interrupt the mainloop, and mp_filter_graph_interrupt() provides a proper mechanism to do this (though intended to be used by the filter user, not filters).
* filter: minor cosmetic naming issuewm42020-03-081-8/+12
| | | | | Just putting some more lipstick on the pig, maybe it looks a bit nicer now.
* filter: add functions to suspend filtering temporarilywm42020-03-051-1/+41
| | | | | | | | | | | | | | Filtering is integrated into an event loop, which is something the filter API user provides. To make interacting with the event loop easier, and in particular to avoid filtering to block event handling, add functions the event loop code can suspend filtering. While we cannot actually suspend a single filter, it's pretty easy to suspend the filter graph run loop itself, which is responsible for selecting which filter to run next. This commit shouldn't change behavior at all, but the functions will be used in later commits.
* filter: decide how multi-threading is supposed to workwm42020-02-291-0/+11
| | | | | | | | | | Instead of vague ideas about making different filter graphs on different threads interact directly, this have no direct support. Instead, helpers are required (such as added with the next commit). Document it. Different root filters (i.e. separate filter graphs) are now considered to be part of separate threads, so assert() if they're found to accidentally interact.
* filter: fix possibly lost async wakeupswm42020-02-291-5/+5
| | | | | | | | | | | mp_filter_mark_async_progress() can asynchronously mark a filter for processing, without waking up the filter thread. (It's some sort of idiotic micro-optimization I guess?) But since it sets async_pending without doing the wakeup, a mp_filter_wakeup() after this will do nothing, and the wakeup is lost. Fix it by checking for the needed wakeup separately. Fortunately, nothing used this function yet, so there is no impact.
* filter: hide warning when disconnecting pins drops frameswm42018-04-291-2/+2
| | | | | | | | | | Sometimes this hints that there's a bug, but sometimes it's normal. Since the code for --end/--frames puts frames that should not be shown anymore back into the pin, using those options will show this warning when playback ends. This is a minor annoyance. We could change how it's done (e.g. set an explicit flag somewhere), but that seems bothersome, so just change the message from warning to verbose.
* filter: fix potential NULL pointer derefwm42018-02-161-1/+1
| | | | | | The rest of the function should be executed only if both are set. It seems like in practice this didn't happen yet with only one of them unset, but in theory it's possible. Found by Coverity.
* filter: simplify/fix external filter graph usagewm42018-02-131-34/+37
| | | | | | | | | | | | | | | | There was the following problem: if a filter graph had asynchronous filters, and the filter graph user did not call mp_filter_run() (and only accessed the mp_pins), then filtering could stall, because using mp_pin_out_request_data() only recursively invoked filtering if the data_requested flag wasn't already set. The latter can happen if a request was tried earlier but failed, and then an asynchronous filter actually produced output that would satisfy the request. Obviously, it has to invoke filtering again to get the requested frame. Fix this by organizing the code differently, and making sure to invoke mp_filter_run() on every request (if there's nothing to do, it doesn't do anything anyway). Simplify it a bit by removing things which are not needed, like connecting filter graphs with different root filters.
* filter: adjust root log prefixwm42018-02-131-2/+3
| | | | | | | | | | Avoids that the audio decoder shows up with a "[root/ad]" log prefix. This is an annoying consequence of mp_log_new(): if a log parent doesn't have a prefix with "!", it'll add the prefix to all mp_logs created from it. This should probably be fixed in the mp_log code itself, but doing so would be a big deal as we'd have to make sure all the other log prefixes are what we want. So work it around for now.
* filter: don't randomly lose async wakeup notificationswm42018-02-051-5/+4
| | | | | | | | | | | | Another "what was I thinking" thing - destroying filters explicitly skipped async wakeups for no reason. These were notifications for filters that are not going to be destroyed too, and so their wakeup will be lost, leading to stalled playback. This is completely unnecessary and the special code can be removed. Fixes #5488. (This case destroyed all audio filters due to AO init failure, which could make clear out the f_demux_in.c wakeup for video, and "freeze" playback.)
* filter: add/use a convenience functionwm42018-02-031-0/+6
| | | | | I guess this is generally useful for filters which buffer data internally.
* video: rewrite filtering glue codewm42018-01-301-0/+790
Get rid of the old vf.c code. Replace it with a generic filtering framework, which can potentially handle more than just --vf. At least reimplementing --af with this code is planned. This changes some --vf semantics (including runtime behavior and the "vf" command). The most important ones are listed in interface-changes. vf_convert.c is renamed to f_swscale.c. It is now an internal filter that can not be inserted by the user manually. f_lavfi.c is a refactor of player/lavfi.c. The latter will be removed once --lavfi-complex is reimplemented on top of f_lavfi.c. (which is conceptually easy, but a big mess due to the data flow changes). The existing filters are all changed heavily. The data flow of the new filter framework is different. Especially EOF handling changes - EOF is now a "frame" rather than a state, and must be passed through exactly once. Another major thing is that all filters must support dynamic format changes. The filter reconfig() function goes away. (This sounds complex, but since all filters need to handle EOF draining anyway, they can use the same code, and it removes the mess with reconfig() having to predict the output format, which completely breaks with libavfilter anyway.) In addition, there is no automatic format negotiation or conversion. libavfilter's primitive and insufficient API simply doesn't allow us to do this in a reasonable way. Instead, filters can use f_autoconvert as sub-filter, and tell it which formats they support. This filter will in turn add actual conversion filters, such as f_swscale, to perform necessary format changes. vf_vapoursynth.c uses the same basic principle of operation as before, but with worryingly different details in data flow. Still appears to work. The hardware deint filters (vf_vavpp.c, vf_d3d11vpp.c, vf_vdpaupp.c) are heavily changed. Fortunately, they all used refqueue.c, which is for sharing the data flow logic (especially for managing future/past surfaces and such). It turns out it can be used to factor out most of the data flow. Some of these filters accepted software input. Instead of having ad-hoc upload code in each filter, surface upload is now delegated to f_autoconvert, which can use f_hwupload to perform this. Exporting VO capabilities is still a big mess (mp_stream_info stuff). The D3D11 code drops the redundant image formats, and all code uses the hw_subfmt (sw_format in FFmpeg) instead. Although that too seems to be a big mess for now. f_async_queue is unused.