Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1409ceacf | ||
|
|
44f62ff6f3 | ||
|
|
55c3055784 | ||
|
|
58fbe50d68 | ||
|
|
6a0036ea03 | ||
|
|
2e4fdf01f5 | ||
|
|
a2259b3fd3 | ||
|
|
aeeb7a92f2 | ||
|
|
1e2f3191a7 | ||
|
|
51d030308e | ||
|
|
4cd8aab84f | ||
|
|
3795154155 | ||
|
|
461198e149 | ||
|
|
7b1f12adba | ||
|
|
cf1645aebb | ||
|
|
1b20ec4864 | ||
|
|
ee529da760 | ||
|
|
c9e6e7cc04 | ||
|
|
cb1d1e7a62 | ||
|
|
e6d4ec62ae | ||
|
|
e7e2a6c8f7 | ||
|
|
6643ebaa28 | ||
|
|
98d33db5da | ||
|
|
ca8dc9147b | ||
|
|
df8b99490c | ||
|
|
c78142a973 | ||
|
|
a8e6caf56b | ||
|
|
e6cca1e43b | ||
|
|
d7538d3597 | ||
|
|
f3eb5b143c | ||
|
|
9993fd8888 | ||
|
|
d9c3a51d87 | ||
|
|
619fa761af | ||
|
|
717d729dcb | ||
|
|
4eb5b62e5a | ||
|
|
b9e32d0d3d | ||
|
|
28e2b95f58 | ||
|
|
491f633a20 | ||
|
|
eb5e45855a | ||
|
|
59e55bb0e1 | ||
|
|
9f46be7373 | ||
|
|
3623fb38ee | ||
|
|
1ad9e322e3 | ||
|
|
cad63810c5 | ||
|
|
da17c64c76 | ||
|
|
57f32f7ca8 | ||
|
|
3d85137495 | ||
|
|
4aff0076a0 | ||
|
|
70f8ea228d | ||
|
|
3196f4cdd7 | ||
|
|
4fa0853c34 | ||
|
|
6598b55c35 | ||
|
|
848d7979e5 | ||
|
|
13301daf6a | ||
|
|
763a38f889 | ||
|
|
ed1e4de452 | ||
|
|
0e2fe55fde | ||
|
|
22cfb48b52 | ||
|
|
4a07120f83 | ||
|
|
d06ff691ed | ||
|
|
34cee2a77d | ||
|
|
8f5eb7b780 | ||
|
|
b991c072f6 | ||
|
|
3c2777994b | ||
|
|
80741f27f3 | ||
|
|
3d18ab77b3 | ||
|
|
8d2baaa318 | ||
|
|
2758bc462d | ||
|
|
2687b43dd0 | ||
|
|
bb40daf367 | ||
|
|
cc1f926441 | ||
|
|
67f653324a | ||
|
|
6e2c29b786 | ||
|
|
e565217f22 | ||
|
|
144c67efaf | ||
|
|
96d7e80ddf | ||
|
|
dde72c5c54 | ||
|
|
577d03da0c | ||
|
|
fc510f0da8 | ||
|
|
8d5775a8d2 | ||
|
|
cf8ff2fd87 | ||
|
|
852c924a60 | ||
|
|
1685d198b9 | ||
|
|
1e2d28f567 | ||
|
|
89973ebca1 | ||
|
|
3f4e528f73 | ||
|
|
6f7c9f516e | ||
|
|
33e0074603 | ||
|
|
b6ed94fa7c | ||
|
|
a419703549 | ||
|
|
5171da86e3 | ||
|
|
7bd670949c | ||
|
|
421b2be348 | ||
|
|
b659476ed9 |
No files matched your search
@@ -0,0 +1,139 @@
|
||||
Coding style
|
||||
============
|
||||
|
||||
mpv uses C99 with K&R formatting, with some exceptions.
|
||||
|
||||
General formatting
|
||||
------------------
|
||||
|
||||
- Use the K&R indent style.
|
||||
- Use 4 spaces of indentation, never use tabs (except in Makefiles).
|
||||
- Add a single space between keywords and binary operators. There are some other
|
||||
cases where spaces should be added. Example:
|
||||
|
||||
```C
|
||||
if ((a * b) > c) {
|
||||
// code
|
||||
some_function(a, b, c);
|
||||
}
|
||||
```
|
||||
- Break lines on 80 columns. There is a hard limit of 85 columns. You may ignore
|
||||
this limit if there's a strong case that not breaking the line will increase
|
||||
readability. Going over 85 columns might provoke endless discussions about
|
||||
whether such a limit is needed or not, so avoid it.
|
||||
- If the body of an if/for/while statement has more than 1 physical lines, then
|
||||
always add braces, even if they're technically redundant.
|
||||
|
||||
Bad:
|
||||
|
||||
```C
|
||||
if (a)
|
||||
// do something if b
|
||||
if (b)
|
||||
do_something();
|
||||
```
|
||||
|
||||
Good:
|
||||
|
||||
```C
|
||||
if (a) {
|
||||
// do something if b
|
||||
if (b)
|
||||
do_something();
|
||||
}
|
||||
```
|
||||
- If the body of an if statement uses braces, the else branch should also
|
||||
use braces (and reverse).
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
if (a) {
|
||||
// do something
|
||||
something();
|
||||
something_else();
|
||||
} else {
|
||||
one_line();
|
||||
}
|
||||
```
|
||||
- If an if condition spans multiple physical lines, then put the opening brace
|
||||
for the if body on the next physical line. (Also, preferably always add a
|
||||
brace, even if technically none is needed.)
|
||||
|
||||
Example:
|
||||
|
||||
```C
|
||||
if (very_long_condition_a &&
|
||||
very_long_condition_b)
|
||||
{
|
||||
code();
|
||||
}
|
||||
```
|
||||
- Remove any trailing whitespace.
|
||||
- If the file you're editing uses formatting different from from what is
|
||||
described here, it's probably an old file from times when nobody followed a
|
||||
consistent style. You're free to use the existing style, or the new style, or
|
||||
to send a patch to reformat the file to the new style before making functional
|
||||
changes.
|
||||
|
||||
General coding
|
||||
--------------
|
||||
|
||||
- Use C99. Also freely make use of C99 features if it's appropriate, such as
|
||||
stdbool.h.
|
||||
- Don't use GNU-only features. In some cases they may be warranted, if they
|
||||
are optional (such as attributes enabling printf-like format string checks).
|
||||
But in general, standard C99 should be used.
|
||||
- The same applies to libc functions. We have to be Windows-compatible too. Use
|
||||
functions guaranteed by C99 or POSIX only, unless your use is guarded by a
|
||||
configure check.
|
||||
- Prefer fusing declaration and initialization, rather than putting declarations
|
||||
on the top of a block. Obvious data flow is more important than avoiding
|
||||
mixing declarations and statements, which is just a C90 artifact.
|
||||
- tech-overview.txt might help to get an overview how mpv is structured.
|
||||
- If you add features that require intrusive changes, discuss them on the dev
|
||||
channel first. There might be a better way to add a feature and it can avoid
|
||||
wasted work.
|
||||
|
||||
Sending patches
|
||||
---------------
|
||||
|
||||
- Make a github pull request, or send a link to a plaintext patch created with
|
||||
``git format-patch``. diffs posted as pastebins (especially if the http link
|
||||
returns HTML) just cause extra work for everyone, because they lack commit
|
||||
message and authorship information.
|
||||
- Write informative commit messages. Use present tense to describe the
|
||||
situation with the patch applied, and past tense for the situation before
|
||||
the change.
|
||||
- The subject line (the first line in a commit message) should contain a
|
||||
prefix identifying the sub system, followed by a short description what
|
||||
impact this commit has. This subject line shouldn't be longer than 72
|
||||
characters, because it messes up the output of many git tools otherwise.
|
||||
|
||||
For example, you fixed a crash in af_volume.c:
|
||||
|
||||
Bad: ``fixed the bug (wtf?)``
|
||||
Good: ``af_volume: fix crash due to null pointer access``
|
||||
|
||||
Having a prefix gives context, and is especially useful when trying to find
|
||||
a specific change by looking at the history, or when running ``git blame``.
|
||||
- The body of the commit message (everything else after the subject line) should
|
||||
be as informative as possible and contain everything that isn't obvious. Don't
|
||||
hesitate to dump as much information as you can - it doesn't cost you
|
||||
anything. Put some effort into it. If someone finds a bug months or years
|
||||
later, and finds that it's caused by your commit (even though your commit was
|
||||
supposed to fix another bug), it would be bad if there wasn't enough
|
||||
information to test the original bug. The old bug might be reintroduced while
|
||||
fixing the new bug.
|
||||
|
||||
The commit message should be wrapped on 72 characters per line, because git
|
||||
tools usually do not break text automatically. On the other hand, you do not
|
||||
need to break text that would be unnatural to break (like data for test cases,
|
||||
or long URLs).
|
||||
|
||||
Important: put an empty line between the subject line and the commit message.
|
||||
If this is missing, it will break display in common git tools.
|
||||
- Try to separate cosmetic and functional changes. It's ok to make a few
|
||||
additional cosmetic changes in the same file you're working on, but don't do
|
||||
something like reformatting a whole file and hiding an actual functional
|
||||
change in the same commit.
|
||||
+1
-1
@@ -134,9 +134,9 @@ What works
|
||||
* Deinterlacing/Inverse Telecine with any of mpv's filters for that
|
||||
* Audio file converting: mpv -o outfile.mp3 infile.flac -no-video -oac
|
||||
libmp3lame -oacopts ab=320k
|
||||
* inverse telecine filters (confirmed working: detc, pullup, filmdint)
|
||||
|
||||
What does not work yet
|
||||
======================
|
||||
|
||||
* 3-pass encoding (ensuring constant total size and bitrate constraints while
|
||||
having VBR audio; mencoder calls this "frameno")
|
||||
|
||||
+4
-4
@@ -266,7 +266,7 @@ Available filters are:
|
||||
Filter for internal use only. Converts between signed/unsigned formats
|
||||
and formats with different endian.
|
||||
|
||||
``volume[=volumedb[:softclip[:s16]]]``
|
||||
``volume[=<volumedb>[:...]]``
|
||||
Implements software volume control. Use this filter with caution since it
|
||||
can reduce the signal to noise ratio of the sound. In most cases it is
|
||||
best to use the *Master* volume control of your sound card or the volume
|
||||
@@ -279,14 +279,14 @@ Available filters are:
|
||||
Sets the desired gain in dB for all channels in the stream from -200dB
|
||||
to +60dB, where -200dB mutes the sound completely and +60dB equals a
|
||||
gain of 1000 (default: 0).
|
||||
``<softclip>``
|
||||
``softclip``
|
||||
Turns soft clipping on. Soft-clipping can make the
|
||||
sound more smooth if very high volume levels are used. Enable this
|
||||
option if the dynamic range of the loudspeakers is very low.
|
||||
|
||||
*WARNING*: This feature creates distortion and should be considered a
|
||||
last resort.
|
||||
``<s16>``
|
||||
``s16``
|
||||
Force S16 sample format if set. Lower quality, but might be faster
|
||||
in some situations.
|
||||
|
||||
@@ -296,7 +296,7 @@ Available filters are:
|
||||
Would amplify the sound by 10.1dB and hard-clip if the sound level
|
||||
is too high.
|
||||
|
||||
``pan=n[:<matrix>]``
|
||||
``pan=n:[<matrix>]``
|
||||
Mixes channels arbitrarily. Basically a combination of the volume and the
|
||||
channels filter that can be used to down-mix many channels to only a few,
|
||||
e.g. stereo to mono, or vary the "width" of the center speaker in a
|
||||
|
||||
+25
-1
@@ -18,7 +18,12 @@ normal driver parameters.
|
||||
|
||||
.. note::
|
||||
|
||||
See ``--ao=help`` for a list of compiled-in audio output drivers.
|
||||
See ``--ao=help`` for a list of compiled-in audio output drivers. The
|
||||
driver ``--ao=alsa`` is preferred. ``--ao=pulse`` is preferred on systems
|
||||
where PulseAudio is used. On Windows, ``--ao=wasapi`` is preferred,
|
||||
though it might cause trouble sometimes, in which case ``--ao=dsound``
|
||||
should be used. On BSD systems, ``--ao=oss`` or `--ao=sndio`` may work
|
||||
(the latter being experimental). On OSX systems, use ``--ao=coreaudio``.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
@@ -118,6 +123,9 @@ Available audio output drivers are:
|
||||
``openal``
|
||||
Experimental OpenAL audio output driver
|
||||
|
||||
.. note:: This driver is not very useful. Playing multi-channel audio with
|
||||
it is slow.
|
||||
|
||||
``pulse``
|
||||
PulseAudio audio output driver
|
||||
|
||||
@@ -130,6 +138,10 @@ Available audio output drivers are:
|
||||
PortAudio audio output driver. This works on all platforms, and has
|
||||
extensive MS Windows support.
|
||||
|
||||
.. note:: This driver is not very useful. It was added in the hope of
|
||||
providing portable audio API across all platforms, but turned
|
||||
out semi-broken and underfeatured.
|
||||
|
||||
``device``
|
||||
Specify the subdevice to use. Giving ``help`` as device name lists all
|
||||
devices found by PortAudio. Devices can be given as numeric values,
|
||||
@@ -138,6 +150,8 @@ Available audio output drivers are:
|
||||
``dsound`` (Windows only)
|
||||
DirectX DirectSound audio output driver
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``device=<devicenum>``
|
||||
Sets the device number to use. Playing a file with ``-v`` will show a
|
||||
list of available devices.
|
||||
@@ -147,6 +161,10 @@ Available audio output drivers are:
|
||||
1.2, but may require the ``SDL_AUDIODRIVER`` environment variable to be set
|
||||
appropriately for your system.
|
||||
|
||||
.. note:: This driver is for compatibility with extremely foreign
|
||||
environments, such as systems where none of the other drivers
|
||||
are available.
|
||||
|
||||
``buflen=<length>``
|
||||
Sets the audio buffer length in seconds. Is used only as a hint by the
|
||||
sound system. Playing a file with ``-v`` will show the requested and
|
||||
@@ -186,6 +204,10 @@ Available audio output drivers are:
|
||||
``rsound``
|
||||
Audio output to an RSound daemon
|
||||
|
||||
.. note:: Completely useless, unless you intend to run RSound. Not to be
|
||||
confused with RoarAudio, which is something completely
|
||||
different.
|
||||
|
||||
``host=<name/path>``
|
||||
Set the address of the server (default: localhost). Can be either a
|
||||
network hostname for TCP connections or a Unix domain socket path
|
||||
@@ -197,6 +219,8 @@ Available audio output drivers are:
|
||||
``sndio``
|
||||
Audio output to the OpenBSD sndio sound system
|
||||
|
||||
.. note:: Experimental. There are known bugs and issues.
|
||||
|
||||
(Note: only supports mono, stereo, 4.0, 5.1 and 7.1 channel
|
||||
layouts.)
|
||||
|
||||
|
||||
+18
-11
@@ -1152,7 +1152,9 @@ OPTIONS
|
||||
You can get the list of allowed codecs with ``mpv --vd=help``. Remove the
|
||||
prefix, e.g. instead of ``lavc:h264`` use ``h264``.
|
||||
|
||||
By default this is set to ``h264,vc1,wmv3``.
|
||||
By default this is set to ``h264,vc1,wmv3``. Note that the hardware
|
||||
acceleration special codecs like ``h264_vdpau`` are not relevant anymore,
|
||||
and in fact have been removed from Libav in this form.
|
||||
|
||||
This is usually only needed with broken GPUs, where a codec is reported
|
||||
as supported, but decoding causes more problems than it solves.
|
||||
@@ -1556,10 +1558,10 @@ OPTIONS
|
||||
``--osd-level=<0-3>``
|
||||
Specifies which mode the OSD should start in.
|
||||
|
||||
:0: subtitles only
|
||||
:1: volume + seek (default)
|
||||
:2: volume + seek + timer + percentage
|
||||
:3: volume + seek + timer + percentage + total time
|
||||
:0: OSD completely disabled (subtitles only)
|
||||
:1: enabled (shows up only on user interaction)
|
||||
:2: enabled + current time visible by default
|
||||
:3: enabled + ``--osd-status-msg`` (current time and status by default)
|
||||
|
||||
``--osd-margin-x=<size>, --sub-text-margin-x=<size>``
|
||||
Left and right screen margin for the OSD/subs in scaled pixels (see
|
||||
@@ -1646,20 +1648,25 @@ OPTIONS
|
||||
file is dumped.
|
||||
|
||||
``--playlist=<filename>``
|
||||
Play files according to a playlist file (ASX, Winamp, SMIL, or
|
||||
one-file-per-line format).
|
||||
Play files according to a playlist file (Supports some common formats.If
|
||||
no format is detected, t will be treated as list of files, separated by
|
||||
newline characters. Note that XML playlist formats are not supported.)
|
||||
|
||||
.. warning::
|
||||
|
||||
The way mpv parses and uses playlist files is not safe against
|
||||
maliciously constructed files. Such files may trigger harmful actions.
|
||||
The way mpv uses playlist files is not safe against maliciously
|
||||
constructed files. Such files may trigger harmful actions.
|
||||
This has been the case for all mpv and MPlayer versions, but
|
||||
unfortunately this fact was not well documented earlier, and some people
|
||||
have even misguidedly recommended use of ``--playlist`` with untrusted
|
||||
sources. Do NOT use ``--playlist`` with random internet sources or files
|
||||
you do not trust!
|
||||
|
||||
FIXME: This needs to be clarified and documented thoroughly.
|
||||
The main problem is that playlists can point to arbitrary network
|
||||
addresses (including local addresses inside of your LAN), and thus
|
||||
can't be considered secure. Playlists also can contain entries using
|
||||
other protocols, such as local files, or (most severely), special
|
||||
protocols like ``avdevice://``, which are inherently unsafe.
|
||||
|
||||
``--priority=<prio>``
|
||||
(Windows only.)
|
||||
@@ -1780,7 +1787,7 @@ OPTIONS
|
||||
libquvi 0.9.x:
|
||||
|
||||
The following explanations are relevant:
|
||||
`<http://quvi.sourceforge.net/doc/0.9/glossary_termino.html#m_stream_id>`_
|
||||
`<http://quvi.sourceforge.net/r/api/0.9/glossary_termino.html#m_stream_id>`_
|
||||
|
||||
The ``quvi-format`` property can be used at runtime to cycle through the
|
||||
list of formats. Unfortunately, this is slow. On libquvi 0.4.x, this
|
||||
|
||||
+12
-10
@@ -98,10 +98,12 @@ Available filters are:
|
||||
:2: Rotate by 90 degrees counterclockwise.
|
||||
:3: Rotate by 90 degrees counterclockwise and flip.
|
||||
|
||||
``scale[=w:h[:interlaced[:chr_drop[:par[:par2[:noup[:arnd]]]]]]]``
|
||||
``scale[=w:h:param:param2:chr-drop:noup:arnd``
|
||||
Scales the image with the software scaler (slow) and performs a YUV<->RGB
|
||||
colorspace conversion (see also ``--sws``).
|
||||
|
||||
All parameters are optional.
|
||||
|
||||
``<w>,<h>``
|
||||
scaled width/height (default: original width/height)
|
||||
|
||||
@@ -114,15 +116,7 @@ Available filters are:
|
||||
:-(n+8): Like -n above, but rounding the dimension to the closest
|
||||
multiple of 16.
|
||||
|
||||
``<chr_drop>``
|
||||
chroma skipping
|
||||
|
||||
:0: Use all available input lines for chroma.
|
||||
:1: Use only every 2. input line for chroma.
|
||||
:2: Use only every 4. input line for chroma.
|
||||
:3: Use only every 8. input line for chroma.
|
||||
|
||||
``<par>[:<par2>]`` (see also ``--sws``)
|
||||
``<param>[:<param2>]`` (see also ``--sws``)
|
||||
Set some scaling parameters depending on the type of scaler selected
|
||||
with ``--sws``::
|
||||
|
||||
@@ -137,6 +131,14 @@ Available filters are:
|
||||
|
||||
--sws=9 (lanczos): filter length (1-10)
|
||||
|
||||
``<chr-drop>``
|
||||
chroma skipping
|
||||
|
||||
:0: Use all available input lines for chroma (default).
|
||||
:1: Use only every 2. input line for chroma.
|
||||
:2: Use only every 4. input line for chroma.
|
||||
:3: Use only every 8. input line for chroma.
|
||||
|
||||
``<noup>``
|
||||
Disallow upscaling past the original dimensions.
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ normal driver parameters.
|
||||
|
||||
See ``--vo=help`` for a list of compiled-in video output drivers.
|
||||
|
||||
The recommended output drivers are ``--vo=vdpau`` and ``--vo=opengl-hq``.
|
||||
All other drivers are just for compatibility or special purposes.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``--vo=opengl,xv,``
|
||||
@@ -32,6 +35,8 @@ Available video output drivers are:
|
||||
the most compatible VO on X, but may be low-quality, and has issues with
|
||||
OSD and subtitle display.
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``adaptor=<number>``
|
||||
Select a specific XVideo adaptor (check xvinfo results).
|
||||
``port=<number>``
|
||||
@@ -172,6 +177,9 @@ Available video output drivers are:
|
||||
``direct3d_shaders`` (Windows only)
|
||||
Video output driver that uses the Direct3D interface.
|
||||
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
proper OpenGL drivers.
|
||||
|
||||
``prefer-stretchrect``
|
||||
Use ``IDirect3DDevice9::StretchRect`` over other methods if possible.
|
||||
|
||||
@@ -228,11 +236,15 @@ Available video output drivers are:
|
||||
Same as ``direct3d_shaders``, but with the options ``disable-textures``
|
||||
and ``disable-shaders`` forced.
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``corevideo`` (Mac OS X 10.6 and later)
|
||||
Mac OS X CoreVideo video output driver. Uses the CoreVideo APIs to fill
|
||||
PixelBuffers and generate OpenGL textures from them (useful as a fallback
|
||||
for ``opengl``).
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``opengl``
|
||||
OpenGL video output driver. It supports extended scaling methods, dithering
|
||||
and color management.
|
||||
@@ -519,6 +531,8 @@ Available video output drivers are:
|
||||
implementation, even if you do not get any error message. Use ``glxinfo``
|
||||
or a similar tool to display the supported OpenGL extensions.
|
||||
|
||||
.. note:: This driver is for compatibility with old systems.
|
||||
|
||||
``(no-)ati-hack``
|
||||
ATI drivers may give a corrupted image when PBOs are used (when using
|
||||
``force-pbo``). This option fixes this, at the expense of using a bit
|
||||
@@ -692,6 +706,9 @@ Available video output drivers are:
|
||||
hardware acceleration. Should work on all platforms supported by SDL 2.0.
|
||||
For tuning, refer to your copy of the file ``SDL_hints.h``.
|
||||
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
proper graphics drivers, or which support GLES only.
|
||||
|
||||
``sw``
|
||||
Continue even if a software renderer is detected.
|
||||
|
||||
@@ -704,6 +721,9 @@ Available video output drivers are:
|
||||
hardware decoding to save power on laptops, or possibly preventing video
|
||||
tearing with some setups.
|
||||
|
||||
.. note:: This driver is for compatibility with crappy systems. You can
|
||||
use vaapi hardware decoding with ``--vo=opengl`` too.
|
||||
|
||||
``scaling=<algorithm>``
|
||||
default
|
||||
Driver default (mpv default as well).
|
||||
@@ -744,6 +764,8 @@ Available video output drivers are:
|
||||
``caca``
|
||||
Color ASCII art video output driver that works on a text console.
|
||||
|
||||
.. note:: This driver is a joke.
|
||||
|
||||
``image``
|
||||
Output each frame into an image file in the current directory. Each file
|
||||
takes the frame number padded with leading zeros as name.
|
||||
@@ -789,6 +811,9 @@ Available video output drivers are:
|
||||
``wayland`` (Wayland only)
|
||||
Wayland shared memory video output as fallback for ``opengl``.
|
||||
|
||||
.. note:: This driver is for compatibility with systems that don't provide
|
||||
working OpenGL drivers.
|
||||
|
||||
``default-format``
|
||||
Use the default RGB32 format instead of an auto-detected one.
|
||||
|
||||
|
||||
@@ -45,13 +45,24 @@ Essential dependencies (incomplete list):
|
||||
- gcc or clang
|
||||
- X development headers (xlib, X extensions, libvdpau, libGL, libXv, ...)
|
||||
- Audio output development headers (libasound, pulseaudio)
|
||||
- fribidi, freetype, fontconfig development headers (for libass)
|
||||
- libass
|
||||
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libpostproc)
|
||||
- libjpeg
|
||||
- FFmpeg libraries (libavutil libavcodec libavformat libswscale libavresample)
|
||||
At least FFmpeg 1.2.4 or Libav 9.10 is required. (If FFmpeg was compiled
|
||||
without libavresample, at least FFmpeg 2.0 is required.)
|
||||
- libjpeg (for screenshots)
|
||||
- libquvi if you want to play Youtube videos directly
|
||||
|
||||
Libass dependencies:
|
||||
|
||||
- gcc or clang, yasm on x86 and x86_64
|
||||
- fribidi, freetype, fontconfig development headers (for libass)
|
||||
|
||||
FFmpeg dependencies:
|
||||
|
||||
- gcc or clang, yasm on x86 and x86_64
|
||||
- OpenSSL (has to be explicitly enabled when compiling ffmpeg)
|
||||
- libx264/libmp3lame/libfdk-aac if you want to use encoding (has to be
|
||||
explicitly enabled when compiling ffmpeg)
|
||||
- Libav also works, but some features will not work. (See section below.)
|
||||
|
||||
Most of the above libraries are available in suitable versions on normal
|
||||
Linux distributions. However FFmpeg is an exception (distro versions may be
|
||||
@@ -71,6 +82,22 @@ Generally, mpv should work with the latest release as well as the git version
|
||||
of both FFmpeg and Libav. But FFmpeg is preferred, and some mpv features work
|
||||
with FFmpeg only. See the [wiki article][ffmpeg_vs_libav] about the issue.
|
||||
|
||||
|
||||
Release cycle
|
||||
-------------
|
||||
|
||||
Every few months, a new release is cut off of the master branch. Currently,
|
||||
these releases are assigned a version number ``0.X.0``. Only the latest release
|
||||
is maintained. As part of the maintenance process, minor releases are made,
|
||||
which are assigned ``0.X.Y`` version numbers. Minor releases contain bug fixes
|
||||
only. They never merge the master branch, and no features are added to it. The
|
||||
goal of releases is to provide stability and an unchanged base for the sake of
|
||||
Linux distributions. If you want the newest features, just use the master
|
||||
branch. (The master branch is stable most of the time, except sometimes, when
|
||||
it's not.)
|
||||
|
||||
Releases other than the latest release are unsupported and unmaintained.
|
||||
|
||||
Bug reports
|
||||
-----------
|
||||
|
||||
@@ -84,8 +111,8 @@ For small changes you can just send us pull requests through GitHub. For bigger
|
||||
changes come and talk to us on IRC before you start working on them. It will
|
||||
make code review easier for both parties later on.
|
||||
|
||||
Contacts
|
||||
--------
|
||||
Contact
|
||||
-------
|
||||
|
||||
These forms of contact are meant to ask questions about mpv usage, give
|
||||
feedback on mpv and discuss it's development.
|
||||
|
||||
+35
-6
@@ -23,6 +23,11 @@ Note that you can control the mpv instance by writing to the command fifo:
|
||||
|
||||
echo "cycle fullscreen" > /tmp/umpv-fifo-*
|
||||
|
||||
Note: you can supply custom options with the UMPV_OPTIONS environment variable.
|
||||
The environment variable will be split on whitespace, and each item is
|
||||
passed as option to mpv _if_ the script starts mpv. If mpv is not started
|
||||
by the script (i.e. mpv is already running), the options will be ignored.
|
||||
|
||||
Warning:
|
||||
|
||||
The script attempts to make sure the FIFO is safely created (i.e. not world-
|
||||
@@ -38,13 +43,33 @@ import errno
|
||||
import subprocess
|
||||
import fcntl
|
||||
import stat
|
||||
import string
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print("error: needs at least one file as argument.")
|
||||
if len(sys.argv) < 1:
|
||||
sys.exit(1)
|
||||
files = sys.argv[1:]
|
||||
|
||||
# this is about the same method mpv uses to decide this
|
||||
def is_url(filename):
|
||||
parts = filename.split(":", 1)
|
||||
if len(parts) < 2:
|
||||
return False
|
||||
# protocol prefix has no special characters => it's an URL
|
||||
prefix = parts[0]
|
||||
for c in prefix:
|
||||
if string.ascii_letters.find(c) < 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
# make them absolute; also makes them safe against interpretation as options
|
||||
files = [os.path.abspath(f) for f in files]
|
||||
def make_abs(filename):
|
||||
if not is_url(filename):
|
||||
return os.path.abspath(filename)
|
||||
return filename
|
||||
files = [make_abs(f) for f in files]
|
||||
|
||||
opts_env = os.getenv("UMPV_OPTIONS")
|
||||
opts_env = opts_env.split() if opts_env else []
|
||||
|
||||
FIFO = "/tmp/umpv-fifo-" + os.getenv("USER")
|
||||
|
||||
@@ -87,7 +112,11 @@ else:
|
||||
pass
|
||||
else:
|
||||
raise e
|
||||
os.mkfifo(FIFO, 0600)
|
||||
os.mkfifo(FIFO, int("0600", 8))
|
||||
|
||||
subprocess.check_call(["mpv", "--really-quiet", "--force-window",
|
||||
"--input-file=" + FIFO, "--"] + files)
|
||||
opts = ["mpv", "--really-quiet", "--force-window", "--input-file=" + FIFO]
|
||||
opts.extend(opts_env)
|
||||
opts.append("--")
|
||||
opts.extend(files)
|
||||
|
||||
subprocess.check_call(opts)
|
||||
+7
-2
@@ -173,10 +173,15 @@ void mp_audio_realloc(struct mp_audio *mpa, int samples)
|
||||
}
|
||||
|
||||
// Like mp_audio_realloc(), but only reallocate if the audio grows in size.
|
||||
// If the buffer is reallocated, also preallocate.
|
||||
void mp_audio_realloc_min(struct mp_audio *mpa, int samples)
|
||||
{
|
||||
if (samples > mp_audio_get_allocated_size(mpa))
|
||||
mp_audio_realloc(mpa, samples);
|
||||
if (samples > mp_audio_get_allocated_size(mpa)) {
|
||||
size_t alloc = ta_calc_prealloc_elems(samples);
|
||||
if (alloc > INT_MAX)
|
||||
abort(); // oom
|
||||
mp_audio_realloc(mpa, alloc);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the size allocated for the data, in number of samples. If the allocated
|
||||
|
||||
+1
-1
@@ -485,5 +485,5 @@ void mp_chmap_print_help(struct mp_log *log)
|
||||
std_layout_names[n][0], std_layout_names[n][1]);
|
||||
}
|
||||
for (int n = 0; n < MP_NUM_CHANNELS; n++)
|
||||
mp_info(log, " unknown%d\n", n);
|
||||
mp_info(log, " unknown%d\n", n + 1);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
|
||||
struct mp_audio *in = arg;
|
||||
struct mp_audio orig_in = *in;
|
||||
|
||||
if (AF_FORMAT_IS_AC3(in->format) || in->nch < s->cfg_min_channel_num)
|
||||
if (AF_FORMAT_IS_SPECIAL(in->format) || in->nch < s->cfg_min_channel_num)
|
||||
return AF_DETACH;
|
||||
|
||||
mp_audio_set_format(in, s->in_sampleformat);
|
||||
|
||||
+11
-8
@@ -18,6 +18,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libavutil/common.h>
|
||||
|
||||
@@ -245,8 +246,9 @@ char *mixer_get_volume_restore_data(struct mixer *mixer)
|
||||
{
|
||||
if (!mixer->driver[0])
|
||||
return NULL;
|
||||
return talloc_asprintf(NULL, "%s:%f:%f:%d", mixer->driver, mixer->vol_l,
|
||||
mixer->vol_r, mixer->muted_by_us);
|
||||
return talloc_asprintf(NULL, "%s:%f:%f:%d:%f", mixer->driver, mixer->vol_l,
|
||||
mixer->vol_r, mixer->muted_by_us,
|
||||
mixer->opts->softvol_max);
|
||||
}
|
||||
|
||||
static void probe_softvol(struct mixer *mixer)
|
||||
@@ -307,19 +309,20 @@ static void restore_volume(struct mixer *mixer)
|
||||
force_mute = opts->mixer_init_mute;
|
||||
|
||||
// Set parameters from playback resume.
|
||||
char *restore_data = mixer->opts->mixer_restore_volume_data;
|
||||
if (restore && restore_data && restore_data[0]) {
|
||||
char *data = mixer->opts->mixer_restore_volume_data;
|
||||
if (restore && data && data[0]) {
|
||||
char drv[40];
|
||||
float v_l, v_r;
|
||||
float v_l, v_r, s;
|
||||
int m;
|
||||
if (sscanf(restore_data, "%39[^:]:%f:%f:%d", drv, &v_l, &v_r, &m) == 4) {
|
||||
if (strcmp(mixer->driver, drv) == 0) {
|
||||
if (sscanf(data, "%39[^:]:%f:%f:%d:%f", drv, &v_l, &v_r, &m, &s) == 5) {
|
||||
float diff = fabs(mixer->opts->softvol_max - s);
|
||||
if (strcmp(mixer->driver, drv) == 0 && diff < 0.01) {
|
||||
force_vol_l = v_l;
|
||||
force_vol_r = v_r;
|
||||
force_mute = !!m;
|
||||
}
|
||||
}
|
||||
talloc_free(restore_data);
|
||||
talloc_free(mixer->opts->mixer_restore_volume_data);
|
||||
mixer->opts->mixer_restore_volume_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -431,6 +431,32 @@ static bool ca_bitmap_from_ch_tag(struct ao *ao, AudioChannelLayout *layout,
|
||||
}
|
||||
}
|
||||
|
||||
static void ca_log_layout(struct ao *ao, AudioChannelLayout layout)
|
||||
{
|
||||
if (!mp_msg_test(ao->log, MSGL_V))
|
||||
return;
|
||||
|
||||
AudioChannelDescription *descs = layout.mChannelDescriptions;
|
||||
|
||||
MP_VERBOSE(ao, "layout: tag: <%d>, bitmap: <%d>, "
|
||||
"descriptions <%d>\n",
|
||||
layout.mChannelLayoutTag,
|
||||
layout.mChannelBitmap,
|
||||
layout.mNumberChannelDescriptions);
|
||||
|
||||
for (int i = 0; i < layout.mNumberChannelDescriptions; i++) {
|
||||
AudioChannelDescription d = descs[i];
|
||||
MP_VERBOSE(ao, " - description %d: label <%d, %d>, flags: <%u>, "
|
||||
"coords: <%f, %f, %f>\n", i,
|
||||
d.mChannelLabel,
|
||||
ca_label_to_mp_speaker_id(d.mChannelLabel),
|
||||
d.mChannelFlags,
|
||||
d.mCoordinates[0],
|
||||
d.mCoordinates[1],
|
||||
d.mCoordinates[2]);
|
||||
}
|
||||
}
|
||||
|
||||
void ca_bitmaps_from_layouts(struct ao *ao,
|
||||
AudioChannelLayout *layouts, size_t n_layouts,
|
||||
uint32_t **bitmaps, size_t *n_bitmaps)
|
||||
@@ -440,6 +466,7 @@ void ca_bitmaps_from_layouts(struct ao *ao,
|
||||
|
||||
for (int i=0; i < n_layouts; i++) {
|
||||
uint32_t bitmap = 0;
|
||||
ca_log_layout(ao, layouts[i]);
|
||||
|
||||
switch (layouts[i].mChannelLayoutTag) {
|
||||
case kAudioChannelLayoutTag_UseChannelBitmap:
|
||||
|
||||
+1
-1
@@ -179,7 +179,7 @@ static void uninit(struct ao *ao, bool cut_audio)
|
||||
struct encode_lavc_context *ectx = ao->encode_lavc_ctx;
|
||||
|
||||
if (!encode_lavc_start(ectx)) {
|
||||
MP_WARN(ao, "not even ready to encode audio at end -> dropped");
|
||||
MP_WARN(ao, "not even ready to encode audio at end -> dropped\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -522,6 +522,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
|
||||
.glog = log,
|
||||
.filename = talloc_strdup(demuxer, stream->url),
|
||||
.metadata = talloc_zero(demuxer, struct mp_tags),
|
||||
.initializing = true,
|
||||
};
|
||||
demuxer->params = params; // temporary during open()
|
||||
stream_seek(stream, stream->start_pos);
|
||||
@@ -554,6 +555,7 @@ static struct demuxer *open_given_type(struct mpv_global *global,
|
||||
"File is not seekable, but there's a cache: enabling seeking.\n");
|
||||
demuxer->seekable = true;
|
||||
}
|
||||
demuxer->initializing = false;
|
||||
return demuxer;
|
||||
}
|
||||
|
||||
@@ -724,6 +726,8 @@ int demux_info_add_bstr(demuxer_t *demuxer, struct bstr opt, struct bstr param)
|
||||
if (oldval) {
|
||||
if (bstrcmp0(param, oldval) == 0)
|
||||
return 0;
|
||||
}
|
||||
if (!demuxer->initializing) {
|
||||
MP_INFO(demuxer, "Demuxer info %.*s changed to %.*s\n",
|
||||
BSTR_P(opt), BSTR_P(param));
|
||||
}
|
||||
@@ -740,6 +744,8 @@ int demux_info_print(demuxer_t *demuxer)
|
||||
if (!info || !info->num_keys)
|
||||
return 0;
|
||||
|
||||
demux_info_update(demuxer);
|
||||
|
||||
mp_info(demuxer->glog, "Clip info:\n");
|
||||
for (n = 0; n < info->num_keys; n++) {
|
||||
mp_info(demuxer->glog, " %s: %s\n", info->keys[n], info->values[n]);
|
||||
|
||||
@@ -170,6 +170,7 @@ typedef struct demuxer {
|
||||
// File format allows PTS resets (even if the current file is without)
|
||||
bool ts_resets_possible;
|
||||
bool warned_queue_overflow;
|
||||
bool initializing;
|
||||
|
||||
struct sh_stream **streams;
|
||||
int num_streams;
|
||||
|
||||
+1
-1
@@ -97,8 +97,8 @@ static const struct format_hack format_hacks[] = {
|
||||
// for webradios
|
||||
{"aac", "audio/aacp", 25, 0.5},
|
||||
{"aac", "audio/aac", 25, 0.5},
|
||||
{"mp3", "audio/mpeg", 25, 0.5},
|
||||
// some mp3 files don't detect correctly
|
||||
{"mp3", "audio/mpeg", 24, 0.5},
|
||||
{"mp3", NULL, 24, .max_probe = true},
|
||||
{0}
|
||||
};
|
||||
|
||||
+5
-3
@@ -1173,6 +1173,7 @@ typedef struct {
|
||||
char *id;
|
||||
int fourcc;
|
||||
int extradata;
|
||||
bool parse;
|
||||
} videocodec_info_t;
|
||||
|
||||
static const videocodec_info_t vinfo[] = {
|
||||
@@ -1185,11 +1186,11 @@ static const videocodec_info_t vinfo[] = {
|
||||
{MKV_V_MPEG4_AVC, MP_FOURCC('a', 'v', 'c', '1'), 1},
|
||||
{MKV_V_THEORA, MP_FOURCC('t', 'h', 'e', 'o'), 1},
|
||||
{MKV_V_VP8, MP_FOURCC('V', 'P', '8', '0'), 0},
|
||||
{MKV_V_VP9, MP_FOURCC('V', 'P', '9', '0'), 0},
|
||||
{MKV_V_VP9, MP_FOURCC('V', 'P', '9', '0'), 0, true},
|
||||
{MKV_V_DIRAC, MP_FOURCC('d', 'r', 'a', 'c'), 0},
|
||||
{MKV_V_PRORES, MP_FOURCC('p', 'r', '0', '0'), 0},
|
||||
{MKV_V_HEVC, MP_FOURCC('H', 'E', 'V', 'C'), 1},
|
||||
{NULL, 0, 0}
|
||||
{0}
|
||||
};
|
||||
|
||||
static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
|
||||
@@ -1273,6 +1274,7 @@ static int demux_mkv_open_video(demuxer_t *demuxer, mkv_track_t *track)
|
||||
extradata = track->private_data;
|
||||
extradata_size = track->private_size;
|
||||
}
|
||||
track->parse = vi->parse;
|
||||
if (!vi->id) {
|
||||
MP_WARN(demuxer, "Unknown/unsupported "
|
||||
"CodecID (%s) or missing/bad CodecPrivate\n"
|
||||
@@ -1336,7 +1338,7 @@ static struct mkv_audio_tag {
|
||||
bool parse;
|
||||
} mkv_audio_tags[] = {
|
||||
{ MKV_A_MP2, 0, 0x0055 },
|
||||
{ MKV_A_MP3, 0, 0x0055 },
|
||||
{ MKV_A_MP3, 0, 0x0055, true },
|
||||
{ MKV_A_AC3, 1, 0x2000 },
|
||||
{ MKV_A_EAC3, 1, MP_FOURCC('E', 'A', 'C', '3') },
|
||||
{ MKV_A_DTS, 0, 0x2001 },
|
||||
|
||||
+1
-1
@@ -271,7 +271,7 @@ bool mp_input_is_abort_cmd(struct mp_cmd *cmd)
|
||||
if (cmd->id == MP_CMD_COMMAND_LIST) {
|
||||
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
|
||||
{
|
||||
if (mp_input_is_abort_cmd(cmd))
|
||||
if (mp_input_is_abort_cmd(sub))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -27,8 +27,7 @@ SOURCES_AUDIO_INPUT-$(ALSA) += stream/ai_alsa1x.c
|
||||
SOURCES_AUDIO_INPUT-$(OSS) += stream/ai_oss.c
|
||||
SOURCES_AUDIO_INPUT-$(SNDIO) += stream/ai_sndio.c
|
||||
SOURCES-$(AUDIO_INPUT) += $(SOURCES_AUDIO_INPUT-yes)
|
||||
SOURCES-$(CDDA) += stream/stream_cdda.c \
|
||||
stream/cdinfo.c
|
||||
SOURCES-$(CDDA) += stream/stream_cdda.c
|
||||
SOURCES-$(DVBIN) += stream/dvb_tune.c \
|
||||
stream/stream_dvb.c
|
||||
SOURCES-$(DVDREAD) += stream/stream_dvd.c \
|
||||
@@ -344,6 +343,7 @@ DIRS = . \
|
||||
player/timeline \
|
||||
demux \
|
||||
misc \
|
||||
options \
|
||||
osdep \
|
||||
osdep/ar \
|
||||
player \
|
||||
|
||||
@@ -86,6 +86,9 @@ static char *term_smkx = NULL;
|
||||
#endif
|
||||
|
||||
static keycode_st *keys_push(char *p, int code) {
|
||||
if (strlen(p) > 8)
|
||||
return NULL;
|
||||
|
||||
if (getch2_keys.len == getch2_keys.cap) {
|
||||
getch2_keys.cap *= 2;
|
||||
if (getch2_keys.cap == 0)
|
||||
@@ -515,7 +518,7 @@ static int setsigaction(int signo, void (*handler) (int),
|
||||
else
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
sa.sa_flags = flags;
|
||||
sa.sa_flags = flags | SA_RESTART;
|
||||
return sigaction(signo, &sa, NULL);
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -750,11 +750,9 @@ static int mp_property_chapter_metadata(m_option_t *prop, int action, void *arg,
|
||||
{
|
||||
struct demuxer *demuxer = mpctx->master_demuxer;
|
||||
int chapter = get_current_chapter(mpctx);
|
||||
if (!demuxer || chapter < 0)
|
||||
if (!demuxer || chapter < 0 || chapter >= demuxer->num_chapters)
|
||||
return M_PROPERTY_UNAVAILABLE;
|
||||
|
||||
assert(chapter < demuxer->num_chapters);
|
||||
|
||||
return tag_property(prop, action, arg, demuxer->chapters[chapter].metadata);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,8 +110,8 @@ static void mp_load_per_file_config(struct MPContext *mpctx)
|
||||
const char *file = mpctx->filename;
|
||||
|
||||
if (snprintf(cfg, sizeof(cfg), "%s.conf", file) >= sizeof(cfg)) {
|
||||
MP_WARN(mpctx, "Filename is too long, "
|
||||
"can not load file or directory specific config files\n");
|
||||
MP_VERBOSE(mpctx, "Filename is too long, "
|
||||
"can not load file or directory specific config files\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -140,7 +140,10 @@ void mp_handle_nav(struct MPContext *mpctx)
|
||||
case MP_NAV_EVENT_RESET_ALL: {
|
||||
mpctx->stop_play = PT_RELOAD_DEMUXER;
|
||||
MP_VERBOSE(nav, "reload\n");
|
||||
break;
|
||||
// return immediately.
|
||||
// other events should be handled after reloaded.
|
||||
talloc_free(ev);
|
||||
return;
|
||||
}
|
||||
case MP_NAV_EVENT_RESET: {
|
||||
nav->nav_still_frame = 0;
|
||||
@@ -237,6 +240,8 @@ void mp_nav_get_highlight(struct osd_state *osd, struct mp_osd_res res,
|
||||
talloc_free(sub->bitmap);
|
||||
sub->bitmap = talloc_array(sub, uint32_t, sizes[0] * sizes[1]);
|
||||
memset(sub->bitmap, 0x80, talloc_get_size(sub->bitmap));
|
||||
nav->subsize[0] = sizes[0];
|
||||
nav->subsize[1] = sizes[1];
|
||||
}
|
||||
|
||||
sub->x = nav->highlight[0];
|
||||
|
||||
+10
-12
@@ -64,6 +64,14 @@
|
||||
#include "command.h"
|
||||
#include "screenshot.h"
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
|
||||
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE (0x0001)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_X11
|
||||
#include "video/out/x11_common.h"
|
||||
#endif
|
||||
@@ -76,18 +84,6 @@
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
#include <windows.h>
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
|
||||
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE (0x0001)
|
||||
#endif
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_PERMANENT
|
||||
#define BASE_SEARCH_PATH_PERMANENT (0x8000)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
const char mp_help_text[] =
|
||||
"Usage: mpv [options] [url|path/]filename\n"
|
||||
"\n"
|
||||
@@ -405,8 +401,10 @@ static int mpv_main(int argc, char *argv[])
|
||||
m_config_set_option0(mpctx->mconfig, "vo", "lavc");
|
||||
m_config_set_option0(mpctx->mconfig, "ao", "lavc");
|
||||
m_config_set_option0(mpctx->mconfig, "fixed-vo", "yes");
|
||||
m_config_set_option0(mpctx->mconfig, "keep-open", "no");
|
||||
m_config_set_option0(mpctx->mconfig, "force-window", "no");
|
||||
m_config_set_option0(mpctx->mconfig, "gapless-audio", "yes");
|
||||
m_config_set_option0(mpctx->mconfig, "resume-playback", "no");
|
||||
mp_input_enable_section(mpctx->input, "encode", MP_INPUT_EXCLUSIVE);
|
||||
}
|
||||
#endif
|
||||
|
||||
+5
-1
@@ -106,6 +106,10 @@ double get_start_time(struct MPContext *mpctx)
|
||||
struct demuxer *demuxer = mpctx->demuxer;
|
||||
if (!demuxer)
|
||||
return 0;
|
||||
// We reload the demuxer on menu transitions; don't make it use the first
|
||||
// timestamp it finds as start PTS.
|
||||
if (mpctx->nav_state)
|
||||
return 0;
|
||||
return demuxer_get_start_time(demuxer);
|
||||
}
|
||||
|
||||
@@ -134,7 +138,7 @@ void update_window_title(struct MPContext *mpctx, bool force)
|
||||
{
|
||||
if (!mpctx->video_out && !mpctx->ao) {
|
||||
talloc_free(mpctx->last_window_title);
|
||||
mpctx->last_window_title = false;
|
||||
mpctx->last_window_title = NULL;
|
||||
return;
|
||||
}
|
||||
char *title = mp_property_expand_string(mpctx, mpctx->opts->wintitle);
|
||||
|
||||
+1
-1
@@ -66,7 +66,7 @@ static const char av_desync_help_text[] =
|
||||
" Experiment with different values for --autosync, 30 is a good start.\n"
|
||||
" If you have PulseAudio, try --ao=alsa .\n"
|
||||
"- Slow video output.\n"
|
||||
" Try a different -vo driver (-vo help for a list) or try -framedrop!\n"
|
||||
" Try a different --vo driver (--vo=help for a list) or try --framedrop!\n"
|
||||
"- Playing a video file with --vo=opengl with higher FPS than the monitor.\n"
|
||||
" This is due to vsync limiting the framerate.\n"
|
||||
"- Playing from a slow network source.\n"
|
||||
|
||||
@@ -201,7 +201,7 @@ static void build_timeline(struct MPContext *mpctx, struct tl_parts *parts)
|
||||
part->filename);
|
||||
}
|
||||
|
||||
// Unkown length => use rest of the file. If duration is unknown, make
|
||||
// Unknown length => use rest of the file. If duration is unknown, make
|
||||
// something up.
|
||||
if (part->length < 0)
|
||||
part->length = (len < 0 ? 1 : len) - part->offset;
|
||||
|
||||
+1
-1
@@ -514,7 +514,7 @@ static int cache_control(stream_t *cache, int cmd, void *arg)
|
||||
if (r != STREAM_ERROR)
|
||||
goto done;
|
||||
|
||||
MP_VERBOSE(s, "[cache] blocking for STREAM_CTRL %d\n", cmd);
|
||||
MP_VERBOSE(s, "blocking for STREAM_CTRL %d\n", cmd);
|
||||
|
||||
s->control = cmd;
|
||||
s->control_arg = arg;
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef MPLAYER_CDD_H
|
||||
#define MPLAYER_CDD_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
struct mp_log;
|
||||
|
||||
typedef struct cd_track {
|
||||
char *name;
|
||||
unsigned int track_nb;
|
||||
unsigned int min;
|
||||
unsigned int sec;
|
||||
unsigned int msec;
|
||||
unsigned long frame_begin;
|
||||
unsigned long frame_length;
|
||||
struct cd_track *prev;
|
||||
struct cd_track *next;
|
||||
} cd_track_t;
|
||||
|
||||
typedef struct {
|
||||
char *artist;
|
||||
char *album;
|
||||
char *genre;
|
||||
unsigned int nb_tracks;
|
||||
unsigned int min;
|
||||
unsigned int sec;
|
||||
unsigned msec;
|
||||
cd_track_t *first;
|
||||
cd_track_t *last;
|
||||
cd_track_t *current;
|
||||
} cd_info_t;
|
||||
|
||||
cd_info_t* cd_info_new(void);
|
||||
void cd_info_free(cd_info_t *cd_info);
|
||||
cd_track_t* cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length);
|
||||
cd_track_t* cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb);
|
||||
|
||||
void cd_info_debug(cd_info_t *cd_info, struct mp_log *log);
|
||||
|
||||
#endif /* MPLAYER_CDD_H */
|
||||
-154
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* CD Info
|
||||
*
|
||||
* Copyright (C) 2002 Bertrand Baudet <bertrand_baudet@yahoo.com>
|
||||
*
|
||||
* This file is part of MPlayer.
|
||||
*
|
||||
* MPlayer is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* MPlayer is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with MPlayer; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "common/msg.h"
|
||||
#include "cdd.h"
|
||||
|
||||
/*******************************************************************************************************************
|
||||
*
|
||||
* xmcd parser, cd info list
|
||||
*
|
||||
*******************************************************************************************************************/
|
||||
|
||||
cd_info_t*
|
||||
cd_info_new(void) {
|
||||
cd_info_t *cd_info = NULL;
|
||||
|
||||
cd_info = malloc(sizeof(cd_info_t));
|
||||
if( cd_info==NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(cd_info, 0, sizeof(cd_info_t));
|
||||
|
||||
return cd_info;
|
||||
}
|
||||
|
||||
void
|
||||
cd_info_free(cd_info_t *cd_info) {
|
||||
cd_track_t *cd_track, *cd_track_next;
|
||||
if( cd_info==NULL ) return;
|
||||
free(cd_info->artist);
|
||||
free(cd_info->album);
|
||||
free(cd_info->genre);
|
||||
|
||||
cd_track_next = cd_info->first;
|
||||
while( cd_track_next!=NULL ) {
|
||||
cd_track = cd_track_next;
|
||||
cd_track_next = cd_track->next;
|
||||
free(cd_track->name);
|
||||
free(cd_track);
|
||||
}
|
||||
}
|
||||
|
||||
cd_track_t*
|
||||
cd_info_add_track(cd_info_t *cd_info, char *track_name, unsigned int track_nb, unsigned int min, unsigned int sec, unsigned int msec, unsigned long frame_begin, unsigned long frame_length) {
|
||||
cd_track_t *cd_track;
|
||||
|
||||
if( cd_info==NULL || track_name==NULL ) return NULL;
|
||||
|
||||
cd_track = malloc(sizeof(cd_track_t));
|
||||
if( cd_track==NULL ) {
|
||||
return NULL;
|
||||
}
|
||||
memset(cd_track, 0, sizeof(cd_track_t));
|
||||
|
||||
cd_track->name = malloc(strlen(track_name)+1);
|
||||
if( cd_track->name==NULL ) {
|
||||
free(cd_track);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(cd_track->name, track_name);
|
||||
cd_track->track_nb = track_nb;
|
||||
cd_track->min = min;
|
||||
cd_track->sec = sec;
|
||||
cd_track->msec = msec;
|
||||
cd_track->frame_begin = frame_begin;
|
||||
cd_track->frame_length = frame_length;
|
||||
|
||||
if( cd_info->first==NULL ) {
|
||||
cd_info->first = cd_track;
|
||||
}
|
||||
if( cd_info->last!=NULL ) {
|
||||
cd_info->last->next = cd_track;
|
||||
}
|
||||
|
||||
cd_track->prev = cd_info->last;
|
||||
|
||||
cd_info->last = cd_track;
|
||||
cd_info->current = cd_track;
|
||||
|
||||
cd_info->nb_tracks++;
|
||||
|
||||
return cd_track;
|
||||
}
|
||||
|
||||
cd_track_t*
|
||||
cd_info_get_track(cd_info_t *cd_info, unsigned int track_nb) {
|
||||
cd_track_t *cd_track=NULL;
|
||||
|
||||
if( cd_info==NULL ) return NULL;
|
||||
|
||||
cd_track = cd_info->first;
|
||||
while( cd_track!=NULL ) {
|
||||
if( cd_track->track_nb==track_nb ) {
|
||||
return cd_track;
|
||||
}
|
||||
cd_track = cd_track->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void cd_info_debug(cd_info_t *cd_info, struct mp_log *log)
|
||||
{
|
||||
cd_track_t *current_track;
|
||||
mp_info(log, "================ CD INFO === start =========\n");
|
||||
if( cd_info==NULL ) {
|
||||
mp_info(log, "cd_info is NULL\n");
|
||||
return;
|
||||
}
|
||||
mp_info(log, " artist=[%s]\n", cd_info->artist);
|
||||
mp_info(log, " album=[%s]\n", cd_info->album);
|
||||
mp_info(log, " genre=[%s]\n", cd_info->genre);
|
||||
mp_info(log, " nb_tracks=%d\n", cd_info->nb_tracks);
|
||||
mp_info(log, " length= %2d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
|
||||
|
||||
mp_info(log, "ID_CDDB_INFO_ARTIST=%s\n", cd_info->artist);
|
||||
mp_info(log, "ID_CDDB_INFO_ALBUM=%s\n", cd_info->album);
|
||||
mp_info(log, "ID_CDDB_INFO_GENRE=%s\n", cd_info->genre);
|
||||
mp_info(log, "ID_CDDB_INFO_LENGTH_MSF=%02d:%02d.%02d\n", cd_info->min, cd_info->sec, cd_info->msec);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACKS=%d\n", cd_info->nb_tracks);
|
||||
|
||||
current_track = cd_info->first;
|
||||
while( current_track!=NULL ) {
|
||||
mp_info(log, " #%2d %2d:%02d.%02d @ %7ld\t[%s] \n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec, current_track->frame_begin, current_track->name);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACK_%d_NAME=%s\n", current_track->track_nb, current_track->name);
|
||||
mp_info(log, "ID_CDDB_INFO_TRACK_%d_MSF=%02d:%02d.%02d\n", current_track->track_nb, current_track->min, current_track->sec, current_track->msec);
|
||||
current_track = current_track->next;
|
||||
}
|
||||
mp_info(log, "================ CD INFO === end =========\n");
|
||||
}
|
||||
+8
-2
@@ -396,16 +396,22 @@ stream_t *open_output_stream(const char *filename, struct mpv_global *global)
|
||||
static int stream_reconnect(stream_t *s)
|
||||
{
|
||||
#define MAX_RECONNECT_RETRIES 5
|
||||
#define RECONNECT_SLEEP_MS 1000
|
||||
#define RECONNECT_SLEEP_MAX_MS 500
|
||||
if (!s->streaming)
|
||||
return 0;
|
||||
if (!(s->flags & MP_STREAM_SEEK_FW))
|
||||
return 0;
|
||||
int64_t pos = s->pos;
|
||||
int sleep_ms = 5;
|
||||
for (int retry = 0; retry < MAX_RECONNECT_RETRIES; retry++) {
|
||||
MP_WARN(s, "Connection lost! Attempting to reconnect (%d)...\n", retry + 1);
|
||||
|
||||
if (stream_check_interrupt(retry ? RECONNECT_SLEEP_MS : 0))
|
||||
if (retry) {
|
||||
mp_sleep_us(sleep_ms * 1000);
|
||||
sleep_ms = MPMIN(sleep_ms * 2, RECONNECT_SLEEP_MAX_MS);
|
||||
}
|
||||
|
||||
if (stream_check_interrupt(0))
|
||||
return 0;
|
||||
|
||||
s->eof = 1;
|
||||
|
||||
@@ -187,6 +187,7 @@ static int bluray_stream_control(stream_t *s, int cmd, void *arg)
|
||||
return STREAM_UNSUPPORTED;
|
||||
|
||||
*((double *) arg) = BD_TIME_TO_MP(ti->duration);
|
||||
bd_free_title_info(ti);
|
||||
return STREAM_OK;
|
||||
}
|
||||
|
||||
|
||||
+16
-68
@@ -46,8 +46,6 @@
|
||||
#include "libavutil/common.h"
|
||||
#include "compat/mpbswap.h"
|
||||
|
||||
#include "cdd.h"
|
||||
|
||||
#include "common/msg.h"
|
||||
|
||||
typedef struct {
|
||||
@@ -56,7 +54,6 @@ typedef struct {
|
||||
int sector;
|
||||
int start_sector;
|
||||
int end_sector;
|
||||
cd_info_t *cd_info;
|
||||
|
||||
// options
|
||||
int speed;
|
||||
@@ -132,8 +129,8 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
#else
|
||||
cdtext_t *text = cdio_get_cdtext(p->cd->p_cdio);
|
||||
#endif
|
||||
int header = 0;
|
||||
if (text) {
|
||||
MP_INFO(s, "CD-Text (%s):\n", track ? "track" : "CD");
|
||||
for (int i = 0; i < sizeof(cdtext_name) / sizeof(cdtext_name[0]); i++) {
|
||||
const char *name = cdtext_name[i];
|
||||
#ifdef OLD_API
|
||||
@@ -141,8 +138,12 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
#else
|
||||
const char *value = cdtext_get_const(text, i, track);
|
||||
#endif
|
||||
if (name && value)
|
||||
if (name && value) {
|
||||
if (!header)
|
||||
MP_INFO(s, "CD-Text (%s):\n", track ? "track" : "CD");
|
||||
header = 1;
|
||||
MP_INFO(s, " %s: '%s'\n", name, value);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -151,17 +152,8 @@ static bool print_cdtext(stream_t *s, int track)
|
||||
|
||||
static void print_track_info(stream_t *s, int track)
|
||||
{
|
||||
cdda_priv* p = (cdda_priv*)s->priv;
|
||||
cd_track_t *cd_track = cd_info_get_track(p->cd_info, track);
|
||||
if( cd_track!=NULL ) {
|
||||
MP_INFO(s, "\n%s\n", cd_track->name);
|
||||
MP_INFO(s, "ID_CDDA_TRACK=%d\n",
|
||||
cd_track->track_nb);
|
||||
}
|
||||
if (print_cdtext(s, track)) {
|
||||
// hack for term OSD overwriting the last line of CDTEXT
|
||||
MP_INFO(s, "\n");
|
||||
}
|
||||
MP_INFO(s, "Switched to track %d\n", track);
|
||||
print_cdtext(s, track);
|
||||
}
|
||||
|
||||
static void cdparanoia_callback(long int inpos, paranoia_cb_mode_t function)
|
||||
@@ -242,7 +234,6 @@ static void close_cdda(stream_t *s)
|
||||
cdda_priv *p = (cdda_priv *)s->priv;
|
||||
paranoia_free(p->cdp);
|
||||
cdda_close(p->cd);
|
||||
cd_info_free(p->cd_info);
|
||||
free(p);
|
||||
}
|
||||
|
||||
@@ -273,37 +264,18 @@ static int control(stream_t *stream, int cmd, void *arg)
|
||||
*(unsigned int *)arg = end_track + 1 - start_track;
|
||||
return STREAM_OK;
|
||||
}
|
||||
case STREAM_CTRL_SEEK_TO_CHAPTER:
|
||||
case STREAM_CTRL_GET_CHAPTER_TIME:
|
||||
{
|
||||
int r;
|
||||
unsigned int track = *(unsigned int *)arg;
|
||||
int track = *(double *)arg;
|
||||
int start_track = get_track_by_sector(p, p->start_sector);
|
||||
int end_track = get_track_by_sector(p, p->end_sector);
|
||||
int seek_sector;
|
||||
if (start_track == -1 || end_track == -1)
|
||||
track += start_track + 1;
|
||||
if (track > end_track)
|
||||
return STREAM_ERROR;
|
||||
track += start_track;
|
||||
if (track > end_track) {
|
||||
seek(stream, (p->end_sector + 1) * CDIO_CD_FRAMESIZE_RAW);
|
||||
// seeking beyond EOF should not be an error,
|
||||
// the cache cannot handle changing stream pos and
|
||||
// returning error.
|
||||
return STREAM_OK;
|
||||
}
|
||||
seek_sector = track == 0 ? p->start_sector
|
||||
: p->cd->disc_toc[track].dwStartSector;
|
||||
r = seek(stream, seek_sector * CDIO_CD_FRAMESIZE_RAW);
|
||||
if (r)
|
||||
return STREAM_OK;
|
||||
break;
|
||||
}
|
||||
case STREAM_CTRL_GET_CURRENT_CHAPTER:
|
||||
{
|
||||
int start_track = get_track_by_sector(p, p->start_sector);
|
||||
int cur_track = get_track_by_sector(p, p->sector);
|
||||
if (start_track == -1 || cur_track == -1)
|
||||
return STREAM_ERROR;
|
||||
*(unsigned int *)arg = cur_track - start_track;
|
||||
int64_t sector = p->cd->disc_toc[track].dwStartSector;
|
||||
int64_t pos = sector * (CDIO_CD_FRAMESIZE_RAW + 1) - 1;
|
||||
// Assume standard audio CD: 44.1khz, 2 channels, s16 samples
|
||||
*(double *)arg = pos / (44100.0 * 2 * 2);
|
||||
return STREAM_OK;
|
||||
}
|
||||
}
|
||||
@@ -317,10 +289,7 @@ static int open_cdda(stream_t *st, int m)
|
||||
int mode = p->paranoia_mode;
|
||||
int offset = p->toc_offset;
|
||||
cdrom_drive_t *cdd = NULL;
|
||||
cd_info_t *cd_info;
|
||||
unsigned int audiolen = 0;
|
||||
int last_track;
|
||||
int i;
|
||||
|
||||
if (m != STREAM_READ) {
|
||||
return STREAM_UNSUPPORTED;
|
||||
@@ -355,29 +324,9 @@ static int open_cdda(stream_t *st, int m)
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
cd_info = cd_info_new();
|
||||
MP_INFO(st, "Found audio CD with %d tracks.\n",
|
||||
(int)cdda_tracks(cdd));
|
||||
for (i = 0; i < cdd->tracks; i++) {
|
||||
char track_name[80];
|
||||
long sec = cdda_track_firstsector(cdd, i + 1);
|
||||
long off = cdda_track_lastsector(cdd, i + 1) - sec + 1;
|
||||
|
||||
sprintf(track_name, "Track %d", i + 1);
|
||||
cd_info_add_track(cd_info, track_name, i + 1,
|
||||
(unsigned int)(off / (60 * 75)),
|
||||
(unsigned int)((off / 75) % 60),
|
||||
(unsigned int)(off % 75), sec, off);
|
||||
audiolen += off;
|
||||
}
|
||||
cd_info->min = (unsigned int)(audiolen / (60 * 75));
|
||||
cd_info->sec = (unsigned int)((audiolen / 75) % 60);
|
||||
cd_info->msec = (unsigned int)(audiolen % 75);
|
||||
|
||||
priv = malloc(sizeof(cdda_priv));
|
||||
memset(priv, 0, sizeof(cdda_priv));
|
||||
priv->cd = cdd;
|
||||
priv->cd_info = cd_info;
|
||||
|
||||
if (p->toc_bias)
|
||||
offset -= cdda_track_firstsector(cdd, 1);
|
||||
@@ -411,7 +360,6 @@ static int open_cdda(stream_t *st, int m)
|
||||
if (priv->cdp == NULL) {
|
||||
cdda_close(cdd);
|
||||
free(priv);
|
||||
cd_info_free(cd_info);
|
||||
return STREAM_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+37
-30
@@ -298,42 +298,47 @@ static void handle_cmd(stream_t *s, struct mp_nav_cmd *ev)
|
||||
|
||||
}
|
||||
|
||||
static inline bool set_event_type(struct priv *priv, int type,
|
||||
struct mp_nav_event *event)
|
||||
{
|
||||
if (!(priv->next_event & (1 << type)))
|
||||
return false;
|
||||
priv->next_event &= ~(1 << type);
|
||||
event->event = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void fill_next_event(stream_t *s, struct mp_nav_event **ret)
|
||||
{
|
||||
struct priv *priv = s->priv;
|
||||
struct mp_nav_event e = {0};
|
||||
for (int n = 0; n < 30; n++) {
|
||||
if (priv->next_event & (1 << n)) {
|
||||
priv->next_event &= ~(1 << n);
|
||||
e.event = n;
|
||||
switch (e.event) {
|
||||
case MP_NAV_EVENT_HIGHLIGHT: {
|
||||
dvdnav_highlight_event_t hlev = priv->hlev;
|
||||
e.u.highlight.display = hlev.display;
|
||||
e.u.highlight.sx = hlev.sx;
|
||||
e.u.highlight.sy = hlev.sy;
|
||||
e.u.highlight.ex = hlev.ex;
|
||||
e.u.highlight.ey = hlev.ey;
|
||||
e.u.highlight.palette = hlev.palette;
|
||||
break;
|
||||
}
|
||||
case MP_NAV_EVENT_MENU_MODE:
|
||||
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
||||
break;
|
||||
case MP_NAV_EVENT_STILL_FRAME:
|
||||
e.u.still_frame.seconds = priv->still_length;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (!set_event_type(priv, MP_NAV_EVENT_RESET_ALL, &e))
|
||||
for (int n = 0; n < 30 && !set_event_type(priv, n, &e); n++) ;
|
||||
switch (e.event) {
|
||||
case MP_NAV_EVENT_NONE:
|
||||
return;
|
||||
case MP_NAV_EVENT_HIGHLIGHT: {
|
||||
dvdnav_highlight_event_t hlev = priv->hlev;
|
||||
e.u.highlight.display = hlev.display;
|
||||
e.u.highlight.sx = hlev.sx;
|
||||
e.u.highlight.sy = hlev.sy;
|
||||
e.u.highlight.ex = hlev.ex;
|
||||
e.u.highlight.ey = hlev.ey;
|
||||
e.u.highlight.palette = hlev.palette;
|
||||
break;
|
||||
}
|
||||
if (e.event) {
|
||||
*ret = talloc(NULL, struct mp_nav_event);
|
||||
**ret = e;
|
||||
case MP_NAV_EVENT_MENU_MODE:
|
||||
e.u.menu_mode.enable = !dvdnav_is_domain_vts(priv->dvdnav);
|
||||
break;
|
||||
case MP_NAV_EVENT_STILL_FRAME:
|
||||
e.u.still_frame.seconds = priv->still_length;
|
||||
break;
|
||||
}
|
||||
*ret = talloc(NULL, struct mp_nav_event);
|
||||
**ret = e;
|
||||
|
||||
MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
|
||||
LOOKUP_NAME(mp_nav_event_types, e.event));
|
||||
}
|
||||
MP_VERBOSE(s, "DVDNAV: player event '%s'\n",
|
||||
LOOKUP_NAME(mp_nav_event_types, e.event));
|
||||
}
|
||||
|
||||
static int fill_buffer(stream_t *s, char *buf, int max_len)
|
||||
@@ -414,6 +419,8 @@ static int fill_buffer(stream_t *s, char *buf, int max_len)
|
||||
priv->had_initial_vts = true;
|
||||
break;
|
||||
}
|
||||
// clear all previous events
|
||||
priv->next_event = 0;
|
||||
priv->next_event |= 1 << MP_NAV_EVENT_RESET;
|
||||
priv->next_event |= 1 << MP_NAV_EVENT_RESET_ALL;
|
||||
if (dvdnav_current_title_info(dvdnav, &tit, &part) == DVDNAV_STATUS_OK)
|
||||
|
||||
@@ -33,6 +33,7 @@ mf_stream_open (stream_t *stream, int mode)
|
||||
{
|
||||
stream->type = STREAMTYPE_MF;
|
||||
stream->demuxer = "mf";
|
||||
stream->allow_caching = false;
|
||||
|
||||
return STREAM_OK;
|
||||
}
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ void mp_ass_set_style(ASS_Style *style, double res_y,
|
||||
void mp_ass_add_default_styles(ASS_Track *track, struct MPOpts *opts)
|
||||
{
|
||||
if (opts->ass_styles_file && opts->ass_style_override)
|
||||
ass_read_styles(track, opts->ass_styles_file, opts->sub_cp);
|
||||
ass_read_styles(track, opts->ass_styles_file, NULL);
|
||||
|
||||
if (track->n_styles == 0) {
|
||||
if (!track->PlayResY) {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#define MP_ASS_FONT_PLAYRESY 288
|
||||
|
||||
#define MP_ASS_RGBA(r, g, b, a) \
|
||||
(((r) << 24U) | ((g) << 16) | ((b) << 8) | (0xFF - (a)))
|
||||
(((unsigned)(r) << 24) | ((g) << 16) | ((b) << 8) | (0xFF - (a)))
|
||||
|
||||
// m_color argument
|
||||
#define MP_ASS_COLOR(c) MP_ASS_RGBA((c).r, (c).g, (c).b, (c).a)
|
||||
|
||||
@@ -52,11 +52,9 @@ struct sub_bitmap {
|
||||
int x, y;
|
||||
int dw, dh;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t color;
|
||||
} libass;
|
||||
};
|
||||
struct {
|
||||
uint32_t color;
|
||||
} libass;
|
||||
};
|
||||
|
||||
struct sub_bitmaps {
|
||||
|
||||
+2
-2
@@ -424,10 +424,10 @@ static void mangle_colors(struct sd *sd, struct sub_bitmaps *parts)
|
||||
int r = (color >> 24u) & 0xff;
|
||||
int g = (color >> 16u) & 0xff;
|
||||
int b = (color >> 8u) & 0xff;
|
||||
int a = color & 0xff;
|
||||
int a = 0xff - (color & 0xff);
|
||||
int c[3] = {r, g, b};
|
||||
mp_map_int_color(vs_rgb2yuv, 8, c);
|
||||
mp_map_int_color(vs2rgb, 8, c);
|
||||
sb->libass.color = (c[0] << 24u) | (c[1] << 16) | (c[2] << 8) | a;
|
||||
sb->libass.color = MP_ASS_RGBA(c[0], c[1], c[2], a);
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ will be replaced with TA calls, and the talloc wrapper will be removed.
|
||||
|
||||
Documentation for the talloc API is here:
|
||||
|
||||
http://git.samba.org/?p=samba.git;a=blob;f=lib/talloc/talloc.h;hb=HEAD
|
||||
http://talloc.samba.org/talloc/doc/html/modules.html
|
||||
|
||||
There are some minor differences with mpv's talloc bridge. mpv calls abort()
|
||||
on allocation failures, and the talloc_set_destructor() signature is slightly
|
||||
|
||||
@@ -91,5 +91,6 @@ void mp_buffer_ref(struct FrameBuffer *buffer);
|
||||
void mp_buffer_unref(struct FrameBuffer *buffer);
|
||||
bool mp_buffer_is_unique(struct FrameBuffer *buffer);
|
||||
void mp_buffer_pool_free(struct FramePool **pool);
|
||||
bool mp_buffer_check(struct FrameBuffer *buffer);
|
||||
|
||||
#endif
|
||||
@@ -204,6 +204,16 @@ void mp_buffer_ref(struct FrameBuffer *buf)
|
||||
pool_unlock();
|
||||
}
|
||||
|
||||
bool mp_buffer_check(struct FrameBuffer *buf)
|
||||
{
|
||||
pool_lock();
|
||||
bool ok = buf->refcount > 0;
|
||||
if (ok)
|
||||
buf->refcount++;
|
||||
pool_unlock();
|
||||
return ok;
|
||||
}
|
||||
|
||||
void mp_buffer_unref(struct FrameBuffer *buf)
|
||||
{
|
||||
FramePool *pool = buf->pool;
|
||||
|
||||
+12
-1
@@ -706,7 +706,16 @@ static struct mp_image *image_from_decoder(struct dec_video *vd)
|
||||
mp_image_copy_attributes(mpi, &new);
|
||||
} else if (ctx->do_dr1 && pic->opaque) {
|
||||
struct FrameBuffer *fb = pic->opaque;
|
||||
mp_buffer_ref(fb); // initial reference for mpi
|
||||
// initial reference for mpi
|
||||
if (!new.planes[0] || !mp_buffer_check(fb)) {
|
||||
// Decoder returned an unreferenced buffer! Taking this would just
|
||||
// lead to an eventual double-free. Nothing we can do about this.
|
||||
// So just say "fuck you" in a nice way.
|
||||
MP_FATAL(vd,
|
||||
"Impossible condition detected! This version of Libav/FFmpeg is not\n"
|
||||
"supported anymore. Please update.\n");
|
||||
return NULL;
|
||||
}
|
||||
mpi = mp_image_new_external_ref(&new, fb, fb_ref, fb_unref,
|
||||
fb_is_unique, NULL);
|
||||
} else {
|
||||
@@ -752,6 +761,8 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
|
||||
|
||||
// Note: potentially resets ctx->pic as it is transferred to mpi
|
||||
struct mp_image *mpi = image_from_decoder(vd);
|
||||
if (!mpi)
|
||||
return 0;
|
||||
assert(mpi->planes[0]);
|
||||
mp_image_set_params(mpi, ¶ms);
|
||||
|
||||
|
||||
@@ -115,6 +115,8 @@ static const vf_info_t *const filter_list[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
static void vf_uninit_filter(vf_instance_t *vf);
|
||||
|
||||
static bool get_desc(struct m_obj_desc *dst, int index)
|
||||
{
|
||||
if (index >= MP_ARRAY_SIZE(filter_list) - 1)
|
||||
@@ -270,6 +272,17 @@ static vf_instance_t *vf_open_filter(struct vf_chain *c, const char *name,
|
||||
return vf_open(c, name, args);
|
||||
}
|
||||
|
||||
void vf_remove_filter(struct vf_chain *c, struct vf_instance *vf)
|
||||
{
|
||||
assert(vf != c->first && vf != c->last); // these are sentinels
|
||||
struct vf_instance *prev = c->first;
|
||||
while (prev && prev->next != vf)
|
||||
prev = prev->next;
|
||||
assert(prev); // not inserted
|
||||
prev->next = vf->next;
|
||||
vf_uninit_filter(vf);
|
||||
}
|
||||
|
||||
struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name,
|
||||
char **args)
|
||||
{
|
||||
@@ -439,6 +452,7 @@ static void update_formats(struct vf_chain *c, struct vf_instance *vf,
|
||||
MP_INFO(c, "Using conversion filter.\n");
|
||||
struct vf_instance *conv = vf_open(c, "scale", NULL);
|
||||
if (conv) {
|
||||
conv->autoinserted = true;
|
||||
conv->next = vf->next;
|
||||
vf->next = conv;
|
||||
update_formats(c, conv, vf->last_outfmts);
|
||||
@@ -492,6 +506,12 @@ int vf_reconfig(struct vf_chain *c, const struct mp_image_params *params)
|
||||
{
|
||||
struct mp_image_params cur = *params;
|
||||
int r = 0;
|
||||
for (struct vf_instance *vf = c->first; vf; ) {
|
||||
struct vf_instance *next = vf->next;
|
||||
if (vf->autoinserted)
|
||||
vf_remove_filter(c, vf);
|
||||
vf = next;
|
||||
}
|
||||
c->first->fmt_in = *params;
|
||||
uint8_t unused[IMGFMT_END - IMGFMT_START];
|
||||
update_formats(c, c->first, unused);
|
||||
|
||||
@@ -75,6 +75,7 @@ typedef struct vf_instance {
|
||||
void (*uninit)(struct vf_instance *vf);
|
||||
|
||||
char *label;
|
||||
bool autoinserted;
|
||||
|
||||
struct mp_image_params fmt_in, fmt_out;
|
||||
|
||||
@@ -134,6 +135,7 @@ struct mp_image *vf_output_queued_frame(struct vf_chain *c);
|
||||
void vf_seek_reset(struct vf_chain *c);
|
||||
struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name,
|
||||
char **args);
|
||||
void vf_remove_filter(struct vf_chain *c, struct vf_instance *vf);
|
||||
int vf_append_filter_list(struct vf_chain *c, struct m_obj_settings *list);
|
||||
struct vf_instance *vf_find_by_label(struct vf_chain *c, const char *label);
|
||||
void vf_print_filter_chain(struct vf_chain *c, int msglevel);
|
||||
|
||||
@@ -469,7 +469,6 @@ int vf_open(vf_instance_t *vf)
|
||||
vf->filter = filter;
|
||||
vf->uninit = uninit;
|
||||
|
||||
vf->priv = malloc (sizeof (vf_eq2_t));
|
||||
eq2 = vf->priv;
|
||||
eq2->log = vf->log;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* Parts based on the MPlayer VA-API patch (see vo_vaapi.c).
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
|
||||
+2
-1
@@ -267,7 +267,8 @@ static int encode_video(struct vo *vo, AVFrame *frame, AVPacket *packet)
|
||||
frame->pts * (double) vc->stream->codec->time_base.num /
|
||||
(double) vc->stream->codec->time_base.den, size);
|
||||
|
||||
encode_lavc_write_stats(vo->encode_lavc_ctx, vc->stream);
|
||||
if (got_packet)
|
||||
encode_lavc_write_stats(vo->encode_lavc_ctx, vc->stream);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -301,12 +301,6 @@ static struct mp_image *get_screenshot(struct priv *p)
|
||||
return img;
|
||||
}
|
||||
|
||||
static bool redraw_frame(struct priv *p)
|
||||
{
|
||||
p->output_surface = p->visible_surface;
|
||||
return render_to_screen(p, p->output_surfaces[p->output_surface]);
|
||||
}
|
||||
|
||||
static void free_subpicture(struct priv *p, struct vaapi_osd_image *img)
|
||||
{
|
||||
if (img->image.image_id != VA_INVALID_ID)
|
||||
@@ -528,7 +522,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
|
||||
return get_equalizer(p, eq->name, eq->valueptr);
|
||||
}
|
||||
case VOCTRL_REDRAW_FRAME:
|
||||
redraw_frame(p);
|
||||
p->output_surface = p->visible_surface;
|
||||
return true;
|
||||
case VOCTRL_SCREENSHOT: {
|
||||
struct voctrl_screenshot_args *args = data;
|
||||
|
||||
+56
-77
@@ -50,6 +50,8 @@
|
||||
#include "osdep/timer.h"
|
||||
#include "bitmap_packer.h"
|
||||
|
||||
// Returns x + a, but wrapped around to the range [0, m)
|
||||
// a must be within [-m, m], x within [0, m)
|
||||
#define WRAP_ADD(x, a, m) ((a) < 0 \
|
||||
? ((x)+(a)+(m) < (m) ? (x)+(a)+(m) : (x)+(a)) \
|
||||
: ((x)+(a) < (m) ? (x)+(a) : (x)+(a)-(m)))
|
||||
@@ -76,8 +78,6 @@ struct vdpctx {
|
||||
|
||||
VdpPresentationQueueTarget flip_target;
|
||||
VdpPresentationQueue flip_queue;
|
||||
uint64_t last_vdp_time;
|
||||
uint64_t last_sync_update;
|
||||
|
||||
VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES];
|
||||
VdpOutputSurface screenshot_surface;
|
||||
@@ -160,53 +160,6 @@ struct vdpctx {
|
||||
|
||||
static bool status_ok(struct vo *vo);
|
||||
|
||||
static int change_vdptime_sync(struct vo *vo, int64_t *t)
|
||||
{
|
||||
struct vdpctx *vc = vo->priv;
|
||||
struct vdp_functions *vdp = vc->vdp;
|
||||
VdpStatus vdp_st;
|
||||
VdpTime vdp_time;
|
||||
vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
|
||||
CHECK_VDP_ERROR(vo, "Error when calling vdp_presentation_queue_get_time");
|
||||
uint64_t t1 = *t;
|
||||
uint64_t t2 = mp_time_us();
|
||||
uint64_t old = vc->last_vdp_time + (t1 - vc->last_sync_update) * 1000ULL;
|
||||
if (vdp_time > old) {
|
||||
if (vdp_time > old + (t2 - t1) * 1000ULL)
|
||||
vdp_time -= (t2 - t1) * 1000ULL;
|
||||
else
|
||||
vdp_time = old;
|
||||
} else if (!vdp_time) {
|
||||
/* Some drivers do not return timestamps. */
|
||||
vdp_time = old;
|
||||
}
|
||||
MP_DBG(vo, "adjusting VdpTime offset by %f µs\n",
|
||||
(int64_t)(vdp_time - old) / 1000.);
|
||||
vc->last_vdp_time = vdp_time;
|
||||
vc->last_sync_update = t1;
|
||||
*t = t2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint64_t sync_vdptime(struct vo *vo)
|
||||
{
|
||||
struct vdpctx *vc = vo->priv;
|
||||
|
||||
uint64_t t = mp_time_us();
|
||||
if (t - vc->last_sync_update > 5000000)
|
||||
change_vdptime_sync(vo, &t);
|
||||
uint64_t now = (t - vc->last_sync_update) * 1000ULL + vc->last_vdp_time;
|
||||
// Make sure nanosecond inaccuracies don't make things inconsistent
|
||||
now = FFMAX(now, vc->recent_vsync_time);
|
||||
return now;
|
||||
}
|
||||
|
||||
static uint64_t convert_to_vdptime(struct vo *vo, uint64_t t)
|
||||
{
|
||||
struct vdpctx *vc = vo->priv;
|
||||
return (t - vc->last_sync_update) * 1000LL + vc->last_vdp_time;
|
||||
}
|
||||
|
||||
static int render_video_to_output_surface(struct vo *vo,
|
||||
VdpOutputSurface output_surface,
|
||||
VdpRect *output_rect,
|
||||
@@ -485,12 +438,6 @@ static int win_x11_init_vdpau_flip_queue(struct vo *vo)
|
||||
CHECK_VDP_WARNING(vo, "Error setting colorkey");
|
||||
}
|
||||
|
||||
VdpTime vdp_time;
|
||||
vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
|
||||
CHECK_VDP_ERROR(vo, "Error when calling vdp_presentation_queue_get_time");
|
||||
vc->last_vdp_time = vdp_time;
|
||||
vc->last_sync_update = mp_time_us();
|
||||
|
||||
vc->vsync_interval = 1;
|
||||
if (vc->composite_detect && vo_x11_screen_is_composited(vo)) {
|
||||
MP_INFO(vo, "Compositing window manager detected. Assuming timing info "
|
||||
@@ -708,6 +655,12 @@ static int initialize_vdpau_objects(struct vo *vo)
|
||||
&vc->rgb_surfaces[n]);
|
||||
CHECK_VDP_ERROR(vo, "Allocating RGB surface");
|
||||
}
|
||||
} else {
|
||||
if (create_vdp_mixer(vo, vc->vdp_chroma_type) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vc->black_pixel == VDP_INVALID_HANDLE) {
|
||||
vdp_st = vdp->output_surface_create(vc->vdp_device, OUTPUT_RGBA_FORMAT,
|
||||
1, 1, &vc->black_pixel);
|
||||
CHECK_VDP_ERROR(vo, "Allocating clearing surface");
|
||||
@@ -716,9 +669,6 @@ static int initialize_vdpau_objects(struct vo *vo)
|
||||
(const void*[]){data},
|
||||
(uint32_t[]){4}, NULL);
|
||||
CHECK_VDP_ERROR(vo, "Initializing clearing surface");
|
||||
} else {
|
||||
if (create_vdp_mixer(vo, vc->vdp_chroma_type) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
forget_frames(vo, false);
|
||||
@@ -1019,6 +969,15 @@ static int update_presentation_queue_status(struct vo *vo)
|
||||
&status, &vtime);
|
||||
CHECK_VDP_WARNING(vo, "Error calling "
|
||||
"presentation_queue_query_surface_status");
|
||||
if (mp_msg_test(vo->log, MSGL_TRACE)) {
|
||||
VdpTime current;
|
||||
vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, ¤t);
|
||||
CHECK_VDP_WARNING(vo, "Error when calling "
|
||||
"vdp_presentation_queue_get_time");
|
||||
MP_TRACE(vo, "Vdpau time: %"PRIu64"\n", (uint64_t)current);
|
||||
MP_TRACE(vo, "Surface %d status: %d time: %"PRIu64"\n",
|
||||
(int)surface, (int)status, (uint64_t)vtime);
|
||||
}
|
||||
if (status == VDP_PRESENTATION_QUEUE_STATUS_QUEUED)
|
||||
break;
|
||||
if (vc->vsync_interval > 1) {
|
||||
@@ -1040,12 +999,13 @@ static int update_presentation_queue_status(struct vo *vo)
|
||||
return num_queued;
|
||||
}
|
||||
|
||||
static inline uint64_t prev_vs2(struct vdpctx *vc, uint64_t ts, int shift)
|
||||
// Return the timestamp of the vsync that must have happened before ts.
|
||||
static inline uint64_t prev_vsync(struct vdpctx *vc, uint64_t ts)
|
||||
{
|
||||
uint64_t offset = ts - vc->recent_vsync_time;
|
||||
// Fix negative values for 1<<shift vsyncs before vc->recent_vsync_time
|
||||
offset += (uint64_t)vc->vsync_interval << shift;
|
||||
offset %= vc->vsync_interval;
|
||||
int64_t diff = (int64_t)(ts - vc->recent_vsync_time);
|
||||
int64_t offset = diff % vc->vsync_interval;
|
||||
if (offset < 0)
|
||||
offset += vc->vsync_interval;
|
||||
return ts - offset;
|
||||
}
|
||||
|
||||
@@ -1067,18 +1027,36 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
|
||||
if (vc->vsync_interval == 1)
|
||||
duration = -1; // Make sure drop logic is disabled
|
||||
|
||||
/* If the presentation time may not be before our last timestamp sync. */
|
||||
if (pts_us && pts_us < vc->last_sync_update)
|
||||
pts_us = vc->last_sync_update;
|
||||
VdpTime vdp_time = 0;
|
||||
vdp_st = vdp->presentation_queue_get_time(vc->flip_queue, &vdp_time);
|
||||
CHECK_VDP_WARNING(vo, "Error when calling vdp_presentation_queue_get_time");
|
||||
|
||||
uint64_t now = sync_vdptime(vo);
|
||||
uint64_t pts = pts_us ? convert_to_vdptime(vo, pts_us) : now;
|
||||
int64_t rel_pts_ns = (pts_us - mp_time_us()) * 1000;
|
||||
if (!pts_us || rel_pts_ns < 0)
|
||||
rel_pts_ns = 0;
|
||||
|
||||
uint64_t now = vdp_time;
|
||||
uint64_t pts = now + rel_pts_ns;
|
||||
uint64_t ideal_pts = pts;
|
||||
uint64_t npts = duration >= 0 ? pts + duration : UINT64_MAX;
|
||||
|
||||
#define PREV_VS2(ts, shift) prev_vs2(vc, ts, shift)
|
||||
// Only gives accurate results for ts >= vc->recent_vsync_time
|
||||
#define PREV_VSYNC(ts) PREV_VS2(ts, 0)
|
||||
/* This should normally never happen.
|
||||
* - The last queued frame can't have a PTS that goes more than 50ms in the
|
||||
* future. This is guaranteed by the playloop, which currently actually
|
||||
* roughly queues 50ms ahead, plus the flip queue offset. Just to be sure
|
||||
* give some additional room by doubling the time.
|
||||
* - The last vsync can never be in the future.
|
||||
*/
|
||||
int64_t max_pts_ahead = (vo->flip_queue_offset + 0.050) * 2 * 1e9;
|
||||
if (vc->last_queue_time > now + max_pts_ahead ||
|
||||
vc->recent_vsync_time > now)
|
||||
{
|
||||
vc->last_queue_time = 0;
|
||||
vc->recent_vsync_time = 0;
|
||||
MP_WARN(vo, "Inconsistent timing detected.\n");
|
||||
}
|
||||
|
||||
#define PREV_VSYNC(ts) prev_vsync(vc, ts)
|
||||
|
||||
/* We hope to be here at least one vsync before the frame should be shown.
|
||||
* If we are running late then don't drop the frame unless there is
|
||||
@@ -1107,7 +1085,7 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
|
||||
*/
|
||||
uint64_t vsync = PREV_VSYNC(pts);
|
||||
if (pts < vsync + vsync_interval / 4
|
||||
&& (vsync - PREV_VS2(vc->last_queue_time, 16)
|
||||
&& (vsync - PREV_VSYNC(vc->last_queue_time)
|
||||
> pts - vc->last_ideal_time + vsync_interval / 2
|
||||
|| vc->dropped_frame && vsync > vc->dropped_time))
|
||||
pts -= vsync_interval / 2;
|
||||
@@ -1122,19 +1100,20 @@ static void flip_page_timed(struct vo *vo, int64_t pts_us, int duration)
|
||||
|
||||
int num_flips = update_presentation_queue_status(vo);
|
||||
vsync = vc->recent_vsync_time + num_flips * vc->vsync_interval;
|
||||
now = sync_vdptime(vo);
|
||||
pts = FFMAX(pts, now);
|
||||
pts = FFMAX(pts, vsync + (vsync_interval >> 2));
|
||||
vsync = PREV_VSYNC(pts);
|
||||
if (npts < vsync + vsync_interval)
|
||||
return;
|
||||
pts = vsync + (vsync_interval >> 2);
|
||||
vdp_st =
|
||||
vdp->presentation_queue_display(vc->flip_queue,
|
||||
vc->output_surfaces[vc->surface_num],
|
||||
vo->dwidth, vo->dheight, pts);
|
||||
VdpOutputSurface frame = vc->output_surfaces[vc->surface_num];
|
||||
vdp_st = vdp->presentation_queue_display(vc->flip_queue, frame,
|
||||
vo->dwidth, vo->dheight, pts);
|
||||
CHECK_VDP_WARNING(vo, "Error when calling vdp_presentation_queue_display");
|
||||
|
||||
MP_TRACE(vo, "Queue new surface %d: Vdpau time: %"PRIu64" "
|
||||
"pts: %"PRIu64"\n", (int)frame, now, pts);
|
||||
|
||||
vc->last_queue_time = pts;
|
||||
vc->queue_time[vc->surface_num] = pts;
|
||||
vc->last_ideal_time = ideal_pts;
|
||||
|
||||
+1
-1
@@ -228,8 +228,8 @@ shmemerror:
|
||||
|
||||
static void freeMyXImage(struct priv *p, int foo)
|
||||
{
|
||||
struct vo *vo = p->vo;
|
||||
#if HAVE_SHM && HAVE_XEXT
|
||||
struct vo *vo = p->vo;
|
||||
if (p->Shmem_Flag) {
|
||||
XShmDetach(vo->x11->display, &p->Shminfo[foo]);
|
||||
XDestroyImage(p->myximage[foo]);
|
||||
|
||||
@@ -330,9 +330,16 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam,
|
||||
// Window dragging hack
|
||||
ReleaseCapture();
|
||||
SendMessage(hWnd, WM_NCLBUTTONDOWN, HTCAPTION, 0);
|
||||
mp_input_put_key(vo->input_ctx, MP_MOUSE_BTN0 |
|
||||
MP_KEY_STATE_UP);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (mouse_button & MP_KEY_STATE_DOWN)
|
||||
SetCapture(w32->window);
|
||||
else
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
return DefWindowProcW(hWnd, message, wParam, lParam);
|
||||
|
||||
+14
-54
@@ -54,10 +54,10 @@ static int lookupkey(int key);
|
||||
|
||||
static void hide_cursor(struct vo_wayland_state * wl);
|
||||
static void show_cursor(struct vo_wayland_state * wl);
|
||||
static void shedule_resize(struct vo_wayland_state *wl,
|
||||
uint32_t edges,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
static void schedule_resize(struct vo_wayland_state *wl,
|
||||
uint32_t edges,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
|
||||
static void vo_wayland_fullscreen (struct vo *vo);
|
||||
|
||||
@@ -112,43 +112,6 @@ static const struct mp_keymap keymap[] = {
|
||||
|
||||
/** Wayland listeners **/
|
||||
|
||||
static void display_handle_error(void *data,
|
||||
struct wl_display *display,
|
||||
void *object_id,
|
||||
uint32_t code,
|
||||
const char *message)
|
||||
{
|
||||
struct vo_wayland_state *wl = data;
|
||||
const char * error_type_msg = "";
|
||||
|
||||
switch (code) {
|
||||
case WL_DISPLAY_ERROR_INVALID_OBJECT:
|
||||
error_type_msg = "Invalid object";
|
||||
break;
|
||||
case WL_DISPLAY_ERROR_INVALID_METHOD:
|
||||
error_type_msg = "Invalid method";
|
||||
break;
|
||||
case WL_DISPLAY_ERROR_NO_MEMORY:
|
||||
error_type_msg = "No memory";
|
||||
break;
|
||||
}
|
||||
|
||||
MP_ERR(wl, "%s: %s\n", error_type_msg, message);
|
||||
}
|
||||
|
||||
static void display_handle_delete_id(void *data,
|
||||
struct wl_display *display,
|
||||
uint32_t id)
|
||||
{
|
||||
struct vo_wayland_state *wl = data;
|
||||
MP_DBG(wl, "Object %u deleted\n", id);
|
||||
}
|
||||
|
||||
static const struct wl_display_listener display_listener = {
|
||||
display_handle_error,
|
||||
display_handle_delete_id
|
||||
};
|
||||
|
||||
static void ssurface_handle_ping(void *data,
|
||||
struct wl_shell_surface *shell_surface,
|
||||
uint32_t serial)
|
||||
@@ -163,7 +126,7 @@ static void ssurface_handle_configure(void *data,
|
||||
int32_t height)
|
||||
{
|
||||
struct vo_wayland_state *wl = data;
|
||||
shedule_resize(wl, edges, width, height);
|
||||
schedule_resize(wl, edges, width, height);
|
||||
}
|
||||
|
||||
static void ssurface_handle_popup_done(void *data,
|
||||
@@ -566,16 +529,16 @@ static void show_cursor (struct vo_wayland_state *wl)
|
||||
wl_surface_commit(wl->cursor.surface);
|
||||
}
|
||||
|
||||
static void shedule_resize(struct vo_wayland_state *wl,
|
||||
uint32_t edges,
|
||||
int32_t width,
|
||||
int32_t height)
|
||||
static void schedule_resize(struct vo_wayland_state *wl,
|
||||
uint32_t edges,
|
||||
int32_t width,
|
||||
int32_t height)
|
||||
{
|
||||
int32_t minimum_size = 150;
|
||||
int32_t x, y;
|
||||
float temp_aspect = width / (float) MPMAX(height, 1);
|
||||
|
||||
MP_DBG(wl, "shedule resize: %dx%d\n", width, height);
|
||||
MP_DBG(wl, "schedule resize: %dx%d\n", width, height);
|
||||
|
||||
if (width < minimum_size)
|
||||
width = minimum_size;
|
||||
@@ -644,8 +607,6 @@ static bool create_display (struct vo_wayland_state *wl)
|
||||
return false;
|
||||
}
|
||||
|
||||
wl_display_add_listener(wl->display.display, &display_listener, wl);
|
||||
|
||||
wl->display.registry = wl_display_get_registry(wl->display.display);
|
||||
wl_registry_add_listener(wl->display.registry, ®istry_listener, wl);
|
||||
|
||||
@@ -817,7 +778,7 @@ static void vo_wayland_ontop (struct vo *vo)
|
||||
MP_DBG(wl, "going ontop\n");
|
||||
vo->opts->ontop = 1;
|
||||
wl_shell_surface_set_toplevel(wl->window.shell_surface);
|
||||
shedule_resize(wl, 0, wl->window.width, wl->window.height);
|
||||
schedule_resize(wl, 0, wl->window.width, wl->window.height);
|
||||
}
|
||||
|
||||
static void vo_wayland_border (struct vo *vo)
|
||||
@@ -853,7 +814,7 @@ static void vo_wayland_fullscreen (struct vo *vo)
|
||||
MP_DBG(wl, "leaving fullscreen\n");
|
||||
wl->window.is_fullscreen = false;
|
||||
wl_shell_surface_set_toplevel(wl->window.shell_surface);
|
||||
shedule_resize(wl, 0, wl->window.p_width, wl->window.p_height);
|
||||
schedule_resize(wl, 0, wl->window.p_width, wl->window.p_height);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -960,7 +921,6 @@ int vo_wayland_control (struct vo *vo, int *events, int request, void *arg)
|
||||
return VO_TRUE;
|
||||
case VOCTRL_FULLSCREEN:
|
||||
vo_wayland_fullscreen(vo);
|
||||
*events |= VO_EVENT_RESIZE;
|
||||
return VO_TRUE;
|
||||
case VOCTRL_ONTOP:
|
||||
vo_wayland_ontop(vo);
|
||||
@@ -981,7 +941,7 @@ int vo_wayland_control (struct vo *vo, int *events, int request, void *arg)
|
||||
case VOCTRL_SET_WINDOW_SIZE: {
|
||||
int *s = arg;
|
||||
if (!wl->window.is_fullscreen)
|
||||
shedule_resize(wl, 0, s[0], s[1]);
|
||||
schedule_resize(wl, 0, s[0], s[1]);
|
||||
return VO_TRUE;
|
||||
}
|
||||
case VOCTRL_SET_CURSOR_VISIBILITY:
|
||||
@@ -1019,7 +979,7 @@ bool vo_wayland_config (struct vo *vo, uint32_t d_width,
|
||||
|
||||
if (vo->opts->fullscreen) {
|
||||
if (wl->window.is_fullscreen)
|
||||
shedule_resize(wl, 0, wl->window.fs_width, wl->window.fs_height);
|
||||
schedule_resize(wl, 0, wl->window.fs_width, wl->window.fs_height);
|
||||
else
|
||||
vo_wayland_fullscreen(vo);
|
||||
}
|
||||
|
||||
@@ -1054,9 +1054,9 @@ static void vo_x11_set_wm_icon(struct vo_x11_state *x11)
|
||||
for (int n = 0; n < num_icons; n++) {
|
||||
*cur++ = icon_w[n];
|
||||
*cur++ = icon_h[n];
|
||||
uint32_t *src = icon_data[n];
|
||||
for (int i = 0; i < icon_h[n] * icon_w[n]; i++)
|
||||
*cur++ = src[i];
|
||||
uint8_t *s = icon_data[n];
|
||||
for (int i = 0; i < icon_h[n] * icon_w[n]; i++, s += 4)
|
||||
*cur++ = s[0] | (s[1] << 8) | (s[2] << 16) | ((unsigned)s[3] << 24);
|
||||
}
|
||||
|
||||
XChangeProperty(x11->display, x11->window, x11->XA_NET_WM_ICON,
|
||||
|
||||
@@ -8,7 +8,20 @@ __all__ = ["check_pthreads", "check_iconv", "check_lua", "check_oss_4front",
|
||||
|
||||
pthreads_program = load_fragment('pthreads.c')
|
||||
|
||||
def check_pthread_flag(ctx, dependency_identifier):
|
||||
checks = [
|
||||
check_cc(fragment = pthreads_program, cflags = '-pthread'),
|
||||
check_cc(fragment = pthreads_program, cflags = '-pthread',
|
||||
linkflags = '-pthread') ]
|
||||
|
||||
for fn in checks:
|
||||
if fn(ctx, dependency_identifier):
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_pthreads(ctx, dependency_identifier):
|
||||
if check_pthread_flag(ctx, dependency_identifier):
|
||||
return True
|
||||
platform_cflags = {
|
||||
'linux': '-D_REENTRANT',
|
||||
'freebsd': '-D_THREAD_SAFE',
|
||||
|
||||
@@ -3,7 +3,7 @@ __cdrom_devices_map__ = {
|
||||
'cygwin': 'D:',
|
||||
'darwin': '/dev/disk1',
|
||||
'freebsd': '/dev/cd0',
|
||||
'openbsd': '/dev/rcd0r',
|
||||
'openbsd': '/dev/rcd0c',
|
||||
'default': '/dev/cdrom'
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ __dvd_devices_map__ = {
|
||||
'cygwin': 'D:',
|
||||
'darwin': '/dev/rdiskN',
|
||||
'freebsd': '/dev/cd0',
|
||||
'openbsd': '/dev/rcd0r',
|
||||
'openbsd': '/dev/rcd0c',
|
||||
'default': '/dev/dvd'
|
||||
}
|
||||
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
int main(void)
|
||||
{
|
||||
struct v4l2_ext_controls ext;
|
||||
return ext.controls->value;
|
||||
return !!&ext.controls->value;
|
||||
}
|
||||
@@ -6,7 +6,7 @@ def __get_version__(ctx):
|
||||
cwd=ctx.srcnode.abspath())
|
||||
process.wait()
|
||||
(version, err) = process.communicate()
|
||||
return version.strip().decode("utf-8")
|
||||
return version.strip().decode('utf-8').encode('ascii', 'ignore')
|
||||
|
||||
def __get_build_date__():
|
||||
import time
|
||||
|
||||
@@ -716,6 +716,7 @@ radio_and_tv_features = [
|
||||
}, {
|
||||
'name': '--tv-v4l2',
|
||||
'desc': 'Video4Linux2 TV interface',
|
||||
'deps': [ 'tv' ],
|
||||
'func': check_cc(header_name=['sys/time.h', 'linux/videodev2.h'])
|
||||
}, {
|
||||
'name': '--libv4l2',
|
||||
@@ -818,7 +819,7 @@ def configure(ctx):
|
||||
ctx.load('detections.devices')
|
||||
|
||||
if ctx.env.DEST_OS in ('freebsd', 'openbsd'):
|
||||
ctx.env.CFLAGS += ['-I/usr/local/include']
|
||||
ctx.env.CFLAGS += ['-I.', '-I..', '-I/usr/local/include']
|
||||
ctx.env.LINKFLAGS += ['-L/usr/local/lib']
|
||||
|
||||
if ctx.env.DEST_OS == 'netbsd':
|
||||
|
||||
@@ -239,7 +239,6 @@ def build(ctx):
|
||||
( "stream/ai_sndio.c", "sndio" ),
|
||||
( "stream/audio_in.c", "audio-input" ),
|
||||
( "stream/cache.c" ),
|
||||
( "stream/cdinfo.c", "cdda"),
|
||||
( "stream/cookies.c" ),
|
||||
( "stream/dvb_tune.c", "dvbin" ),
|
||||
( "stream/frequencies.c", "tv" ),
|
||||
|
||||
Reference in new issue
Block a user