Remove obsolete comment about FFmpeg ignoring non-http proxies
which was repeated in ytdl_hook before the feature was added.
Remove unnecessary conditions for not nil. Lua tables will always
return nil for non-existent keys.
This commit allows for video to be shown with the right aspect even when
pixels are not square in the selected drm mode. For example, if drm mode
5 is "640x400", the right aspect on a 4:3 monitor is obtained by mpv
--vo=drm --drm-mode=5 --monitorpixelaspect=5:6 ...
Other vo's seem to make this parameter change the size of the window,
but in the drm vo this is fixed, being as large as the screen.
The last image is stored in vo->priv->last_input to be used when
redrawing a frame is necessary (control: VOCTRL_REDRAW_FRAME). At the
beginning it is NULL, so a redraw request has no effect since
draw_image ignores calls with image=NULL.
When using --force-window the size of the image may change without the
vo structure being re-created. Before this commit, the size of
vo->priv->last_input could become inconsistent with the cropping
rectangle vo->priv->src_rc, which could trigger an assert in
mp_image_crop_rc(). Even if it did not, the last image of a video
remained on the screen when the next file in the playlist had no video
(e.g., it was an mp3 without an embedded cover).
This commit deallocates and resets to NULL the image
vo->priv->last_input when reconfiguring video.
Before this commit, the drm vo drew the osd over the scaled image, and
then copied the result onto the framebuffer, shifted. This made the
frame centered, but forced the osd to be only as large as the image.
This was inconsistent with other vo's, covered the image with the
progress indicator even when a black band was at the top of the screen,
made the progress indicator wrap on narrow videos, etc.
The change is to always use an image as large as the screen. The frame
is copied scaled and shifted to it, and the osd drawn over it. The
result is finally copied to the framebuffer without any shift, since it
is already as large as it.
Technically, cur_frame is an image as large as the screen and
cur_frame_cropped is a dummy reference to it, cropped to the size of
the scaled video. This way, copying the scaled image to
cur_frame_cropped positions the image in the right place in cur_frame,
which can then have the osd added to it and copied to the framebuffer.
Using the GL renderer for color conversion will make sure screenshots
will use the same conversion as normal video rendering. It can do this
for all types of screenshots.
The logic when to write 16 bit PNGs changes. To approximate the old
behavior, we decide by looking whether the source video format has more
than 8 bits per component. We apply this logic even for window
screenshots. Also, 16 bit PNGs now always include an unused alpha
channel. The reason is that FFmpeg has RGB48 and RGBA64 formats, but no
RGB064. RGB48 is 3 bytes and usually not supported by GPUs for
rendering, so we have to use RGBA64, which forces an alpha channel.
Will break for users who use --target-trc and similar options.
I considered creating a new gl_video context, but it could double GPU
memory use, so I didn't.
This uses FBOs instead of glGetTexImage(), because that increases the
chance it could work on GLES (e.g. ANGLE). Untested. No support for the
Vulkan and D3D11 backends yet.
Fixes#5498. Also fixes#5240, because the code for reading back is not
used with the new code path.
The re-ordering of commits e3d93fd and 0870859 ended up swallowing the
change which made the HDR tone mapping algorithm actually check for
RA_CAP_NUM_GROUPS support.
The major changes are as follows:
1. Use `uint32_t` instead of `unsigned int` for the SSBO size
calculation. This doesn't really matter, since a too-big buffer will
still work just fine, but since `uint` is a 32-bit integer by
definition this is the correct way to do it.
2. Pre-divide the frame_sum by the num_wg immediately at the end of a
frame. This change was made to prevent overflow. At 4K screen size,
this code is currently already very at risk of overflow, especially
once I started playing with longer averaging sizes. Pre-dividing this
out makes it just about fit into 32-bit even for worst-case PQ
content. (It's technically also faster and easier this way, so I
should have done it to begin with). Rename `frame_sum` to `frame_avg`
to clearly signal the change in semantics.
3. Implement a scene transition detection algorithm. This basically
compares the current frame's average brightness against the
(averaged) value of the past frames. If it exceeds a threshold, which
I experimentally configured, we reset the peak detection SSBO's state
immediately - so that it just contains the current frame. This
prevents annoying "eye adaptation"-like effects on scene transitions.
4. As a result of the previous change, we can now use a much larger
buffer size by default, which results in a more stable and less
flickery result. I experimented with values between 20 and 256 and
settled on the new value of 64. (I also switched to a power-of-2
array size, because I like powers of two)
Before this commit, auto_loaded and lang were only set for the first
track in auto-loaded external files. Likewise, for the title and
lang arguments to the sub-add and audio-add commands.
Fixes#5432
Currently using the drmprime interop with external mpv intgration can lead
to rendering issues because the current frame is being released too early.
Typically using this with Qt results in one frame shift because Qt
will do waitforvsync and swap, rather than swap and waitforvsync.
This leads to tearing as the frambuffer is released while being
displayed on screen.
In order to avoid releasing the framebuffer that is displayed, We keep
the framebuffer alive for one more frame with triple buffering to make
sure that whatever rendering process is used, the framebuffer will not
be released when it's still on screen.
This was tested on RockChip Rock64
Also a regression of the filter change. The new code is more picky about
EOF states, and it turns out the weird delay queue (used with some hwdec
copy back modes only) accidentally dropped an EOF event. It reset the
avctx before the delay queue was drained, which meant it never returned
the expected AVERROR_EOF status code.
Also don't signal EOF when copy back fails. It should just try to
continue until fallback is performed.
The current peak detection algorithm was very bugged (which contributed
to the excessive cross-frame flicker without long normalization) and
also didn't take into account the frame average brightness level.
The new algorithm both takes into account frame average brightness (in
addition to peak brightness), and also computes the values in a more
stable/correct way. (The old path was basically undefined behavior)
In addition to improving the algorithm, we also switch to hable tone
mapping by default, and try to enable peak computation automatically
whever possible (compute shaders + SSBOs supported). We also make the
desaturation milder, after extensive testing during libplacebo
development.
I also had to compensate a bit for the representational differences
between mpv and libplacebo (libplacebo treats 1.0 as the reference peak,
but mpv treats it as the nominal peak), but it shouldn't have caused any
problems.
This is still not quite the same as libplacebo, since libplacebo also
allows tagging the desired scene average brightness on the output, and
it also supports reading the scene average brightness from static
metadata (MaxFALL) where available. But those changes are a bit more
involved. It's possible we could also read this from metadata in the
future, but we have problems communicating with AVFrames as it is and I
don't want to touch the mpv colorimetry structs for the time being.
The vulkan validation layers warn you if you try requesting a query
result from a timer that hasn't even been started yet, so we have to do
some extra bit of work to keep track of which indices we've seen so far,
and avoid the queries on them.
Instead of enabling every feature under the sun, make an effort to just
whitelist the ones we actually might use. Turns out the extended storage
format support is needed for some of the storage formats we use, in
particular rgba16.
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.)
This is a dataflow issue caused by the filters change. When the fallback
happens, vd_lavc does not return a frame, but also does not accept a new
packet, which confuses lavc_process(). Fix this by immediately retrying
to feed the buffered packet and decode a frame on fallback.
Fixes#5489.
In theory (and practice), this is not needed, because the VS filter get
frame callback will cause the process function to be called again if
there's not enough data. But it's still a bit weird to just add one more
frame on each iteration, so make it cleaner and make it request frames
until the input array is full.
This was obviously nonsense, and a previous "fix" to this code was
nonsense too. What is really needed here is temporarily dropping the
lock while calling destroy_vs()/reinit_vs().
Fixes#5470.
We called mp_pin_out_request_data() if there was input _and_ output.
This is not how it should be: we should request new input only if output
was requested, but we could not produce any output.
On the other hand, the upper half of the process() function will request
new input if output is required, but all input was consumed. But this
requires calling mp_filter_internal_mark_progress(), as otherwise the
general filter logic would not know that we can continue.
If the speed is changed by a large amount, we need to effectively change
the output rate by a large amount, and swr_set_compensation() is
apparently not designed to handle such large changes well. So it's
better to reinitialize the resampler on all large changes.
Also, strictly reinitialize the resampler if the rate changes, otherwise
it could happen that libavresample (which does not automatically
initialize resampling if avresample_set_compensation() is used) would
never apply speed changes properly.
Also document some conditions better that handle corner cases (remove
the inline condition from the if gating the compensation code).
It also appears that we crashed with very large compensation ratios
(when raising audio speed quickly by keeping the "[" key down), and this
commit accidentally mitigates it by not allowing large compensation.
Setting lavfi-complex at runtime will now forcefully reselect the tracks
as needed, even if it was a "proper" track selection via --aid or --vid.
Before this commit, it just failed and complained that the VO/AO was
already "used".
Requested.
This makes it actually somewhat simpler, and doesn't have any
disadvantages. It should also make some new features easier.
Mostly just moves code around.
The somewhat confusing thing is that many filters (including track->dec)
have a public struct, but to free them, you need to free the mp_filter
pointer itself (track->dec->f). The assignment wrote to a dangling
pointer, instead of removing the dangling pointer.
(Other than that, this idiom is actually nice.)
Unknown frames were not freed properly. Although this doesn't really
happen anyway, because we're never going to feed audio frames to a video
filter chain. Since it's theoretically possible, and all other filters
handle this consistently, fix it anyway.
Properly initialize the output frame parameters other than image format
and size. This includes colorspace hints. (We're still not reading them
back from VapourSynth if it sets them, though. Usually it doesn't
anyway.)
VapourSynth can't pass through timestamps, only frame durations. So we
need to remember the timestamp of the very first frame passed to it.
This was accidentally set to 0 instead of NOPTS on init, so inserting
the filter during playback could show strange behavior.
Might be part of #5470.
Similar to the previous commit, and for the same reasons. Unlike with
af_scaletempo, resampling does not have a natural frame size, so we set
an arbitrary size limit on output frames. We add a new option to control
this size, although I'm not sure whether anyone will use it, so mark it
for testing only.
Note that we go through some effort to avoid buffering data in
libswresample itself. One reason is that we might have to reinitialize
the resampler completely when changing speed, which drops the buffered
data. Another is that I'm not sure whether the resampler will do the
right thing when applying dynamic speed changes.
This helps the filter to adapt much faster to speed changes. Before this
commit, the filter just converted and output the full input frame, which
could cause problems with large input frames. This was made worse by
certain filters like dynaudnorm or loudnorm outputting pretty large
frames.
This commit changes the filter from trying to convert all input at once
to only outputting a single internally filtered frame. Internally, this
filter already output data in units of 60ms by default (controlled by
the "stride" sub-option), and concatenated as many output frames as
necessary to consume all input.
Behavior is still kind of bad when inserting the filter. This is because
the large frames can be buffered up after the insertion point, so the
speed change will be performed with a larger latency. The scaletempo
filter can't do anything against this, although it can be fixed by
inserting scaletempo as user filter as part of --af.
--vf=help will now list libavfilter filters, and e.g. --vf=yadif=help
will list libavfilter filter options.
The latter is rather bare, because the AVOption API is really awful
(holy shit how is it so bad), and would require us to handle _every_
option type manually.
Alternatively we could call av_opt_show2(), which ffmpeg uses for help
output in its CLI tools and which is much more detailed. But it's rather
foreign and forces output through av_log(), so I don't really want to
use it.