Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
76d771a6fa | ||
|
|
19caba0794 | ||
|
|
391546c52f | ||
|
|
a8af6a7852 | ||
|
|
960aca3386 | ||
|
|
e72a327d74 | ||
|
|
87f955f3e9 | ||
|
|
5536ebe82f | ||
|
|
ef8b37ca2a | ||
|
|
d4a5513847 | ||
|
|
d42212cd67 | ||
|
|
674cc1d3a9 | ||
|
|
c47bb9ca42 | ||
|
|
938dad0b88 | ||
|
|
82b5361946 | ||
|
|
f99f48684b | ||
|
|
25864a5539 | ||
|
|
524d9585fd | ||
|
|
95a72baf92 | ||
|
|
48112a74ed | ||
|
|
8427cdc717 | ||
|
|
b695ca1e27 | ||
|
|
801feb6420 | ||
|
|
de6a452039 | ||
|
|
4b764b6cc6 | ||
|
|
7b7c31b190 | ||
|
|
70a66b461d | ||
|
|
844e8f2b51 | ||
|
|
3f4ed8920f | ||
|
|
7ad2999b5f | ||
|
|
14fdbe07ac | ||
|
|
61ed9a8747 | ||
|
|
0801345d68 | ||
|
|
5bd0fe5daf | ||
|
|
cab3c5fbb8 | ||
|
|
99ceae8cc3 | ||
|
|
ebe04ab692 | ||
|
|
808aa08cc0 | ||
|
|
2065e0ba36 | ||
|
|
3c43a022af | ||
|
|
02513cd5df | ||
|
|
4d986d2a98 | ||
|
|
ada6f96811 | ||
|
|
321b3952b0 | ||
|
|
d49b49ff96 | ||
|
|
f088abb2bf | ||
|
|
4a3975bf7e | ||
|
|
a064143899 | ||
|
|
f264d52099 | ||
|
|
74a3c169b5 | ||
|
|
34d9787fcf | ||
|
|
1c0b80d518 | ||
|
|
a9bafeb589 | ||
|
|
3a33db3d92 |
No files matched your search
+1
-1
@@ -147,7 +147,7 @@ Available filters are:
|
||||
0 no matrix decoding (default)
|
||||
==== ===================================
|
||||
|
||||
``equalizer=[g1:g2:g3:...:g10]``
|
||||
``equalizer=g1:g2:g3:...:g10``
|
||||
10 octave band graphic equalizer, implemented using 10 IIR band-pass
|
||||
filters. This means that it works regardless of what type of audio is
|
||||
being played back. The center frequencies for the 10 bands are:
|
||||
|
||||
@@ -103,6 +103,13 @@ OPTIONS
|
||||
Override movie aspect ratio, in case aspect information is incorrect or
|
||||
missing in the file being played. See also ``--no-aspect``.
|
||||
|
||||
Two values have special meaning:
|
||||
|
||||
:0: disable aspect ratio handling, pretend the video has square pixels
|
||||
:-1: use the video stream or container aspect (default)
|
||||
|
||||
But note that handling of these special values might change in the future.
|
||||
|
||||
.. admonition:: Examples
|
||||
|
||||
- ``--aspect=4:3`` or ``--aspect=1.3333``
|
||||
@@ -1746,6 +1753,15 @@ OPTIONS
|
||||
|
||||
Also see ``--really-quiet`` and ``--msglevel``.
|
||||
|
||||
``--quvi-fetch-subtitles=<yes|no>``
|
||||
Toggles fetching of subtitles from streaming sites with libquvi. Disabled
|
||||
by default, because it's unreliable and slow. Note that when enabled,
|
||||
subtitles will always be fetched, even if subtitles are explicitly
|
||||
disabled with ``--no-sub`` (because you might want to enable subtitles
|
||||
at runtime).
|
||||
|
||||
Supported when using libquvi 0.9.x.
|
||||
|
||||
``--quvi-format=<best|default|...>``
|
||||
Video format/quality that is directly passed to libquvi (default: ``best``).
|
||||
This is used when opening links to streaming sites like YouTube. The
|
||||
|
||||
+15
-13
@@ -3,20 +3,18 @@
|
||||
"""
|
||||
This script emulates "unique application" functionality on Linux. When starting
|
||||
playback with this script, it will try to reuse an already running instance of
|
||||
mpv (but only if that was started with umpv).
|
||||
mpv (but only if that was started with umpv). Other mpv instances (not started
|
||||
by umpv) are ignored, and the script doesn't know about them.
|
||||
|
||||
This script only uses mpv instances started with umpv. Other instances are
|
||||
ignored, and don't exist for the script.
|
||||
|
||||
This only takes filenames as arguments. If mpv is already running, they are
|
||||
appended to mpv's internal playlist. If the file does not exist or is otherwise
|
||||
not playable, mpv will skip the playlist entry when attempting to play it (from
|
||||
the GUI perspective, it's silently ignored).
|
||||
This only takes filenames as arguments. Custom options can't be used; the script
|
||||
interprets them as filenames. If mpv is already running, the files passed to
|
||||
umpv are appended to mpv's internal playlist. If a file does not exist or is
|
||||
otherwise not playable, mpv will skip the playlist entry when attempting to
|
||||
play it (from the GUI perspective, it's silently ignored).
|
||||
|
||||
If mpv isn't running yet, this script will start mpv and let it control the
|
||||
current terminal. If you play an audio-only file, mpv will not open a window
|
||||
(that is its normal behavior; but it might not be what a user expects if this
|
||||
script is used in a GUI setting).
|
||||
current terminal. It will not write output to stdout/stderr, because this
|
||||
will typically just fill ~/.xsession-errors with garbage.
|
||||
|
||||
mpv will terminate if there are no more files to play, and running the umpv
|
||||
script after that will start a new mpv instance.
|
||||
@@ -28,7 +26,10 @@ Note that you can control the mpv instance by writing to the command fifo:
|
||||
Warning:
|
||||
|
||||
The script attempts to make sure the FIFO is safely created (i.e. not world-
|
||||
readable, not trying to open a bogus
|
||||
writable), and checks that it's really a FIFO. This is important for security,
|
||||
because the FIFO allows anyone with write access to run arbitrary commands
|
||||
in mpv's context using the "run" input command. If you are worried about
|
||||
security, you should verify that the code handles these concerns correctly.
|
||||
"""
|
||||
|
||||
import sys
|
||||
@@ -88,4 +89,5 @@ else:
|
||||
raise e
|
||||
os.mkfifo(FIFO, 0600)
|
||||
|
||||
subprocess.check_call(["mpv", "--input-file=" + FIFO] + files)
|
||||
subprocess.check_call(["mpv", "--really-quiet", "--force-window",
|
||||
"--input-file=" + FIFO, "--"] + files)
|
||||
+18
-18
@@ -345,26 +345,28 @@ static int af_count_filters(struct af_stream *s)
|
||||
// (So we know what conversion filter with what format to insert next.)
|
||||
static char *af_find_conversion_filter(int srcfmt, int *dstfmt)
|
||||
{
|
||||
#define NUM_FMT 64
|
||||
#define NUM_FILT 32
|
||||
#define NUM_NODES (NUM_FMT * NUM_FILT)
|
||||
#define MAX_NODES (64 * 32)
|
||||
int num_fmt = 0, num_filt = 0;
|
||||
for (int n = 0; filter_list[n]; n++)
|
||||
assert(n < NUM_FILT);
|
||||
num_filt = n + 1;
|
||||
for (int n = 0; af_fmtstr_table[n].format; n++)
|
||||
assert(n < NUM_FMT);
|
||||
num_fmt = n + 1;
|
||||
|
||||
bool visited[NUM_NODES] = {0};
|
||||
unsigned char distance[NUM_NODES];
|
||||
short previous[NUM_NODES] = {0};
|
||||
for (int n = 0; n < NUM_NODES; n++) {
|
||||
int num_nodes = num_fmt * num_filt;
|
||||
assert(num_nodes < MAX_NODES);
|
||||
|
||||
bool visited[MAX_NODES] = {0};
|
||||
unsigned char distance[MAX_NODES];
|
||||
short previous[MAX_NODES] = {0};
|
||||
for (int n = 0; n < num_nodes; n++) {
|
||||
distance[n] = 255;
|
||||
if (af_fmtstr_table[n % NUM_FMT].format == srcfmt)
|
||||
if (af_fmtstr_table[n % num_fmt].format == srcfmt)
|
||||
distance[n] = 0;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
int next = -1;
|
||||
for (int n = 0; n < NUM_NODES; n++) {
|
||||
for (int n = 0; n < num_nodes; n++) {
|
||||
if (!visited[n] && (next < 0 || (distance[n] < distance[next])))
|
||||
next = n;
|
||||
}
|
||||
@@ -372,13 +374,13 @@ static char *af_find_conversion_filter(int srcfmt, int *dstfmt)
|
||||
return NULL;
|
||||
visited[next] = true;
|
||||
|
||||
int fmt = next % NUM_FMT;
|
||||
int fmt = next % num_fmt;
|
||||
if (af_fmtstr_table[fmt].format == *dstfmt) {
|
||||
// Best match found
|
||||
for (int cur = next; cur >= 0; cur = previous[cur] - 1) {
|
||||
if (distance[cur] == 1) {
|
||||
*dstfmt = af_fmtstr_table[cur % NUM_FMT].format;
|
||||
return (char *)filter_list[cur / NUM_FMT]->name;
|
||||
*dstfmt = af_fmtstr_table[cur % num_fmt].format;
|
||||
return (char *)filter_list[cur / num_fmt]->name;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
@@ -392,7 +394,7 @@ static char *af_find_conversion_filter(int srcfmt, int *dstfmt)
|
||||
if (i != fmt && af->test_conversion(af_fmtstr_table[fmt].format,
|
||||
af_fmtstr_table[i].format))
|
||||
{
|
||||
int other = n * NUM_FMT + i;
|
||||
int other = n * num_fmt + i;
|
||||
int ndist = distance[next] + 1;
|
||||
if (ndist < distance[other]) {
|
||||
distance[other] = ndist;
|
||||
@@ -403,9 +405,7 @@ static char *af_find_conversion_filter(int srcfmt, int *dstfmt)
|
||||
}
|
||||
}
|
||||
assert(0);
|
||||
#undef NUM_FMT
|
||||
#undef NUM_FILT
|
||||
#undef NODE_N
|
||||
#undef MAX_NODES
|
||||
}
|
||||
|
||||
static bool af_is_conversion_filter(struct af_instance *af)
|
||||
|
||||
@@ -153,13 +153,13 @@ static int af_open(struct af_instance* af){
|
||||
int j,k;
|
||||
|
||||
int nch = s->nch;
|
||||
if(AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch))
|
||||
if(nch && AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch))
|
||||
return AF_ERROR;
|
||||
|
||||
// Read pan values
|
||||
char *cp = s->matrixstr;
|
||||
j = 0; k = 0;
|
||||
while(k < AF_NCH){
|
||||
while(cp && k < AF_NCH){
|
||||
sscanf(cp, "%f%n" , &s->level[j][k], &n);
|
||||
MP_VERBOSE(af, "[pan] Pan level from channel %i to"
|
||||
" channel %i = %f\n",k,j,s->level[j][k]);
|
||||
|
||||
+1
-1
@@ -112,7 +112,7 @@ enum af_format {
|
||||
// Planar variants
|
||||
AF_FORMAT_U8P = (AF_INTP|AF_FORMAT_US|AF_FORMAT_8BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_S16P = (AF_INTP|AF_FORMAT_SI|AF_FORMAT_16BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_S32P = (AF_INTP|AF_FORMAT_US|AF_FORMAT_32BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_S32P = (AF_INTP|AF_FORMAT_SI|AF_FORMAT_32BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_FLOATP = (AF_FLTP|AF_FORMAT_32BIT|AF_FORMAT_NE),
|
||||
AF_FORMAT_DOUBLEP = (AF_FLTP|AF_FORMAT_64BIT|AF_FORMAT_NE),
|
||||
|
||||
|
||||
@@ -36,10 +36,6 @@
|
||||
#include "misc/ring.h"
|
||||
#include "ao.h"
|
||||
|
||||
#ifndef BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE
|
||||
#define BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE 0x00000001
|
||||
#endif
|
||||
|
||||
#ifndef PKEY_Device_FriendlyName
|
||||
DEFINE_PROPERTYKEY(PKEY_Device_FriendlyName,
|
||||
0xa45c254e, 0xdf1c, 0x4efd, 0x80, 0x20,
|
||||
@@ -136,17 +132,6 @@ static int fill_VistaBlob(wasapi_state *state)
|
||||
{
|
||||
if (!state)
|
||||
return 1;
|
||||
HMODULE hkernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
if (!hkernel32)
|
||||
return 1;
|
||||
WINBOOL (WINAPI *pSetDllDirectory)(LPCWSTR lpPathName) =
|
||||
(WINBOOL (WINAPI *)(LPCWSTR))GetProcAddress(hkernel32, "SetDllDirectoryW");
|
||||
WINBOOL (WINAPI *pSetSearchPathMode)(DWORD Flags) =
|
||||
(WINBOOL (WINAPI *)(DWORD))GetProcAddress(hkernel32, "SetSearchPathMode");
|
||||
if (pSetSearchPathMode)
|
||||
pSetDllDirectory(L""); /* Attempt to use safe search paths */
|
||||
if (pSetSearchPathMode)
|
||||
pSetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
|
||||
state->VistaBlob.hAvrt = LoadLibraryW(L"avrt.dll");
|
||||
if (!state->VistaBlob.hAvrt)
|
||||
goto exit_label;
|
||||
@@ -160,8 +145,6 @@ static int fill_VistaBlob(wasapi_state *state)
|
||||
exit_label:
|
||||
if (state->VistaBlob.hAvrt)
|
||||
FreeLibrary(state->VistaBlob.hAvrt);
|
||||
if (pSetSearchPathMode)
|
||||
pSetDllDirectory(NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -226,7 +226,7 @@ struct demux_packet *demux_copy_packet(struct demux_packet *dp)
|
||||
struct sh_stream *new_sh_stream(demuxer_t *demuxer, enum stream_type type)
|
||||
{
|
||||
if (demuxer->num_streams > MAX_SH_STREAMS) {
|
||||
MP_WARN(demuxer, "Too many streams.");
|
||||
MP_WARN(demuxer, "Too many streams.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -373,7 +373,7 @@ static bool demux_check_queue_full(demuxer_t *demux)
|
||||
overflow:
|
||||
|
||||
if (!demux->warned_queue_overflow) {
|
||||
MP_ERR(demux, "\nToo many packets in the demuxer "
|
||||
MP_ERR(demux, "Too many packets in the demuxer "
|
||||
"packet queue (video: %d packets in %d bytes, audio: %d "
|
||||
"packets in %d bytes, sub: %d packets in %d bytes).\n",
|
||||
count_packs(demux, STREAM_VIDEO), count_bytes(demux, STREAM_VIDEO),
|
||||
|
||||
+27
-27
@@ -90,12 +90,16 @@ struct format_hack {
|
||||
const char *mime_type;
|
||||
int probescore;
|
||||
float analyzeduration;
|
||||
bool max_probe; // use probescore only if max. probe size reached
|
||||
};
|
||||
|
||||
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", NULL, 24, .max_probe = true},
|
||||
{0}
|
||||
};
|
||||
|
||||
@@ -104,15 +108,6 @@ static const char *format_blacklist[] = {
|
||||
0
|
||||
};
|
||||
|
||||
static const struct format_hack *find_format_from_mime_type(char *mime_type)
|
||||
{
|
||||
for (int n = 0; format_hacks[n].ff_name; n++) {
|
||||
if (strcasecmp(format_hacks[n].mime_type, mime_type) == 0)
|
||||
return &format_hacks[n];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mp_read(void *opaque, uint8_t *buf, int size)
|
||||
{
|
||||
struct demuxer *demuxer = opaque;
|
||||
@@ -223,17 +218,9 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
|
||||
priv->filename = sep + 1;
|
||||
}
|
||||
|
||||
const char *expected_format = NULL;
|
||||
int expected_format_probescore = AVPROBE_SCORE_MAX;
|
||||
char *mime_type = demuxer->stream->mime_type;
|
||||
|
||||
if (lavfdopts->allow_mimetype && mime_type) {
|
||||
priv->format_hack = find_format_from_mime_type(mime_type);
|
||||
if (priv->format_hack) {
|
||||
expected_format = priv->format_hack->ff_name;
|
||||
expected_format_probescore = priv->format_hack->probescore;
|
||||
}
|
||||
}
|
||||
if (!lavfdopts->allow_mimetype || !mime_type)
|
||||
mime_type = "";
|
||||
|
||||
const char *format = lavfdopts->format;
|
||||
if (!format)
|
||||
@@ -264,17 +251,18 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
|
||||
|
||||
AVProbeData avpd = {
|
||||
// Disable file-extension matching with normal checks
|
||||
.filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : NULL,
|
||||
.filename = check <= DEMUX_CHECK_REQUEST ? priv->filename : "",
|
||||
.buf_size = 0,
|
||||
.buf = av_mallocz(PROBE_BUF_SIZE + FF_INPUT_BUFFER_PADDING_SIZE),
|
||||
};
|
||||
|
||||
while (avpd.buf_size < PROBE_BUF_SIZE) {
|
||||
bool final_probe = false;
|
||||
do {
|
||||
int nsize = av_clip(avpd.buf_size * 2, INITIAL_PROBE_SIZE,
|
||||
PROBE_BUF_SIZE);
|
||||
bstr buf = stream_peek(s, nsize);
|
||||
if (buf.len <= avpd.buf_size)
|
||||
break;
|
||||
final_probe = true;
|
||||
memcpy(avpd.buf, buf.start, buf.len);
|
||||
avpd.buf_size = buf.len;
|
||||
|
||||
@@ -283,20 +271,32 @@ static int lavf_check_file(demuxer_t *demuxer, enum demux_check check)
|
||||
|
||||
if (priv->avif) {
|
||||
MP_VERBOSE(demuxer, "Found '%s' at score=%d size=%d.\n",
|
||||
priv->avif->name, score, avpd.buf_size);
|
||||
priv->avif->name, score, avpd.buf_size);
|
||||
|
||||
priv->format_hack = NULL;
|
||||
for (int n = 0; format_hacks[n].ff_name; n++) {
|
||||
const struct format_hack *entry = &format_hacks[n];
|
||||
if (strcmp(entry->ff_name, priv->avif->name) != 0)
|
||||
continue;
|
||||
if (entry->mime_type && strcasecmp(entry->mime_type, mime_type) != 0)
|
||||
continue;
|
||||
priv->format_hack = entry;
|
||||
break;
|
||||
}
|
||||
|
||||
if (score >= min_probe)
|
||||
break;
|
||||
|
||||
if (expected_format) {
|
||||
if (strcmp(priv->avif->name, expected_format) == 0 &&
|
||||
score >= expected_format_probescore)
|
||||
if (priv->format_hack) {
|
||||
if (score >= priv->format_hack->probescore &&
|
||||
(!priv->format_hack->max_probe || final_probe))
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
priv->avif = NULL;
|
||||
}
|
||||
priv->format_hack = NULL;
|
||||
} while (!final_probe);
|
||||
|
||||
av_free(avpd.buf);
|
||||
|
||||
|
||||
+3
-3
@@ -64,11 +64,11 @@ mf_t *open_mf_pattern(void *talloc_ctx, struct mp_log *log, char *filename)
|
||||
if (filename[0] == '@') {
|
||||
FILE *lst_f = fopen(filename + 1, "r");
|
||||
if (lst_f) {
|
||||
char *fname = talloc_size(mf, MP_PATH_MAX);
|
||||
while (fgets(fname, MP_PATH_MAX, lst_f)) {
|
||||
char *fname = talloc_size(mf, 512);
|
||||
while (fgets(fname, 512, lst_f)) {
|
||||
/* remove spaces from end of fname */
|
||||
char *t = fname + strlen(fname) - 1;
|
||||
while (t > fname && isspace(*t))
|
||||
while (t > fname && isspace((unsigned char)*t))
|
||||
*(t--) = 0;
|
||||
if (!mp_path_exists(fname)) {
|
||||
mp_verbose(log, "file not found: '%s'\n", fname);
|
||||
|
||||
+1
-1
@@ -23,5 +23,5 @@ Exec=mpv --really-quiet --force-window -- %F
|
||||
Terminal=false
|
||||
NoDisplay=true
|
||||
Categories=AudioVideo;Audio;Video;Player;TV;
|
||||
MimeType=application/ogg;application/x-ogg;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/m4a;audio/x-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/x-mpeg;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg;video/x-mpeg2;video/mp4;video/msvideo;video/x-msvideo;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/x-fli;video/x-flv;video/x-theora;video/x-matroska;video/webm;audio/x-flac;
|
||||
MimeType=application/ogg;application/x-ogg;application/sdp;application/smil;application/x-smil;application/streamingmedia;application/x-streamingmedia;application/vnd.rn-realmedia;application/vnd.rn-realmedia-vbr;audio/aac;audio/x-aac;audio/m4a;audio/x-m4a;audio/mp1;audio/x-mp1;audio/mp2;audio/x-mp2;audio/mp3;audio/x-mp3;audio/mpeg;audio/x-mpeg;audio/mpegurl;audio/x-mpegurl;audio/mpg;audio/x-mpg;audio/rn-mpeg;audio/scpls;audio/x-scpls;audio/vnd.rn-realaudio;audio/wav;audio/x-pn-windows-pcm;audio/x-realaudio;audio/x-pn-realaudio;audio/x-ms-wma;audio/x-pls;audio/x-wav;video/mpeg;video/x-mpeg;video/x-mpeg2;video/mp4;video/msvideo;video/x-msvideo;video/quicktime;video/vnd.rn-realvideo;video/x-ms-afs;video/x-ms-asf;video/x-ms-wmv;video/x-ms-wmx;video/x-ms-wvxvideo;video/x-avi;video/x-fli;video/x-flv;video/x-theora;video/x-matroska;video/webm;audio/x-flac;audio/x-vorbis+ogg;video/x-ogm+ogg;
|
||||
X-KDE-Protocols=ftp,http,https,mms,rtmp,rtsp,sftp,smb
|
||||
+2
-2
@@ -1169,10 +1169,10 @@ fi
|
||||
|
||||
if test "$cc_vendor" = "gnu" ; then
|
||||
cflag_check -Wundef && WARNFLAGS="-Wundef $WARNFLAGS"
|
||||
# -std=gnu99 is not a warning flag but is placed in WARN_CFLAGS because
|
||||
# -std=c99 is not a warning flag but is placed in WARN_CFLAGS because
|
||||
# that's the only variable specific to C now, and this option is not valid
|
||||
# for C++.
|
||||
cflag_check -std=gnu99 && WARN_CFLAGS="-std=gnu99 $WARN_CFLAGS"
|
||||
cflag_check -std=c99 && WARN_CFLAGS="-std=c99 $WARN_CFLAGS"
|
||||
cflag_check -Wno-pointer-sign && WARN_CFLAGS="-Wno-pointer-sign $WARN_CFLAGS"
|
||||
cflag_check -Wdisabled-optimization && WARN_CFLAGS="-Wdisabled-optimization $WARN_CFLAGS"
|
||||
cflag_check -Wmissing-prototypes && WARN_CFLAGS="-Wmissing-prototypes $WARN_CFLAGS"
|
||||
|
||||
@@ -316,6 +316,7 @@ const m_option_t mp_opts[] = {
|
||||
({"no", 0}, {"attachment", 1})),
|
||||
|
||||
OPT_STRING("quvi-format", quvi_format, 0),
|
||||
OPT_FLAG("quvi-fetch-subtitles", quvi_fetch_subtitles, 0),
|
||||
|
||||
#if HAVE_CDDA
|
||||
{ "cdda", (void *)&cdda_opts, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
|
||||
@@ -718,6 +719,7 @@ const struct MPOpts mp_default_opts = {
|
||||
.sub_visibility = 1,
|
||||
.sub_pos = 100,
|
||||
.sub_speed = 1.0,
|
||||
.quvi_fetch_subtitles = 0,
|
||||
.audio_output_channels = MP_CHMAP_INIT_STEREO,
|
||||
.audio_output_format = 0, // AF_FORMAT_UNKNOWN
|
||||
.playback_speed = 1.,
|
||||
|
||||
@@ -158,6 +158,7 @@ typedef struct MPOpts {
|
||||
int forced_subs_only;
|
||||
int stretch_dvd_subs;
|
||||
char *quvi_format;
|
||||
int quvi_fetch_subtitles;
|
||||
|
||||
// subreader.c
|
||||
int suboverlap_enabled;
|
||||
|
||||
@@ -334,11 +334,13 @@ static int audio_start_sync(struct MPContext *mpctx, int playsize)
|
||||
res = audio_decode(d_audio, ao->buffer, a);
|
||||
if (skip_samples <= mp_audio_buffer_samples(ao->buffer)) {
|
||||
mp_audio_buffer_skip(ao->buffer, skip_samples);
|
||||
ao->buffer_playable_samples = 0;
|
||||
if (res < 0)
|
||||
return res;
|
||||
return audio_decode(d_audio, ao->buffer, playsize);
|
||||
}
|
||||
mp_audio_buffer_clear(ao->buffer);
|
||||
ao->buffer_playable_samples = 0;
|
||||
if (res < 0)
|
||||
return res;
|
||||
}
|
||||
@@ -442,6 +444,7 @@ int fill_audio_out_buffers(struct MPContext *mpctx, double endpts)
|
||||
mp_audio_buffer_peek(ao->buffer, &data);
|
||||
data.samples = MPMIN(data.samples, playsize);
|
||||
int played = write_to_ao(mpctx, &data, playflags, written_audio_pts(mpctx));
|
||||
assert(played >= 0 && played <= data.samples);
|
||||
ao->buffer_playable_samples = playsize - played;
|
||||
|
||||
if (played > 0) {
|
||||
|
||||
+2
-2
@@ -700,8 +700,8 @@ static int tag_property(m_option_t *prop, int action, void *arg,
|
||||
char **slist = NULL;
|
||||
int num = 0;
|
||||
for (int n = 0; n < tags->num_keys; n++) {
|
||||
MP_TARRAY_APPEND(NULL, slist, num, tags->keys[n]);
|
||||
MP_TARRAY_APPEND(NULL, slist, num, tags->values[n]);
|
||||
MP_TARRAY_APPEND(NULL, slist, num, talloc_strdup(NULL, tags->keys[n]));
|
||||
MP_TARRAY_APPEND(NULL, slist, num, talloc_strdup(NULL, tags->values[n]));
|
||||
}
|
||||
MP_TARRAY_APPEND(NULL, slist, num, NULL);
|
||||
*(char ***)arg = slist;
|
||||
|
||||
@@ -672,6 +672,8 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type
|
||||
}
|
||||
}
|
||||
|
||||
osd_changed_all(mpctx->osd);
|
||||
|
||||
talloc_free(mpctx->track_layout_hash);
|
||||
mpctx->track_layout_hash = talloc_steal(mpctx, track_layout_hash(mpctx));
|
||||
}
|
||||
|
||||
+25
-1
@@ -78,6 +78,14 @@
|
||||
|
||||
#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[] =
|
||||
@@ -260,7 +268,23 @@ static void osdep_preinit(int *p_argc, char ***p_argv)
|
||||
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
// stop Windows from showing all kinds of annoying error dialogs
|
||||
SetErrorMode(0x8003);
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
|
||||
|
||||
// Enable heap corruption detection
|
||||
HeapSetInformation(NULL, HeapEnableTerminationOnCorruption, NULL, 0);
|
||||
|
||||
HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
|
||||
WINBOOL (WINAPI *pSetDllDirectory)(LPCWSTR lpPathName) =
|
||||
(WINBOOL (WINAPI *)(LPCWSTR))GetProcAddress(kernel32, "SetDllDirectoryW");
|
||||
WINBOOL (WINAPI *pSetSearchPathMode)(DWORD Flags) =
|
||||
(WINBOOL (WINAPI *)(DWORD))GetProcAddress(kernel32, "SetSearchPathMode");
|
||||
|
||||
// Always use safe search paths for DLLs and other files, ie. never use the
|
||||
// current directory
|
||||
if (pSetSearchPathMode)
|
||||
pSetDllDirectory(L"");
|
||||
if (pSetSearchPathMode)
|
||||
pSetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
|
||||
#endif
|
||||
|
||||
terminal_init();
|
||||
|
||||
+33
-11
@@ -33,6 +33,9 @@
|
||||
// the cache is active.
|
||||
#define CACHE_UPDATE_CONTROLS_TIME 2.0
|
||||
|
||||
// Time in seconds the cache prints a new message at all.
|
||||
#define CACHE_NO_SPAM 5.0
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -72,11 +75,13 @@ struct priv {
|
||||
int64_t fill_limit; // we should fill buffer only if space>=fill_limit
|
||||
int64_t seek_limit; // keep filling cache if distance is less that seek limit
|
||||
struct byte_meta *bm; // additional per-byte metadata
|
||||
bool seekable; // underlying stream is seekable
|
||||
|
||||
struct mp_log *log;
|
||||
|
||||
// Owned by the main thread
|
||||
stream_t *cache; // wrapper stream, used by demuxer etc.
|
||||
double last_warn_time;
|
||||
|
||||
// Owned by the cache thread
|
||||
stream_t *stream; // "real" stream, used to read from the source media
|
||||
@@ -142,15 +147,19 @@ static int cache_wakeup_and_wait(struct priv *s, double *retry_time)
|
||||
if (stream_check_interrupt(0))
|
||||
return CACHE_INTERRUPTED;
|
||||
|
||||
// Print a "more severe" warning after waiting 1 second and no new data
|
||||
if ((*retry_time) >= 1.0) {
|
||||
MP_ERR(s, "Cache keeps not responding.\n");
|
||||
} else if (*retry_time > 0.1) {
|
||||
MP_WARN(s, "Cache is not responding - slow/stuck network connection?\n");
|
||||
}
|
||||
|
||||
double start = mp_time_sec();
|
||||
|
||||
if (!s->last_warn_time || start - s->last_warn_time >= CACHE_NO_SPAM) {
|
||||
// Print a "more severe" warning after waiting 1 second and no new data
|
||||
if ((*retry_time) >= 1.0) {
|
||||
MP_ERR(s, "Cache keeps not responding.\n");
|
||||
s->last_warn_time = start;
|
||||
} else if (*retry_time > 0.1) {
|
||||
MP_WARN(s, "Cache is not responding - slow/stuck network connection?\n");
|
||||
s->last_warn_time = start;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_cond_signal(&s->wakeup);
|
||||
mpthread_cond_timed_wait(&s->wakeup, &s->mutex, CACHE_WAIT_TIME);
|
||||
|
||||
@@ -467,6 +476,7 @@ static int cache_seek(stream_t *cache, int64_t pos)
|
||||
{
|
||||
struct priv *s = cache->priv;
|
||||
assert(s->cache_thread_running);
|
||||
int r = 1;
|
||||
|
||||
pthread_mutex_lock(&s->mutex);
|
||||
|
||||
@@ -474,12 +484,21 @@ static int cache_seek(stream_t *cache, int64_t pos)
|
||||
" (cur=%" PRId64 ") <= %" PRId64 " \n",
|
||||
s->min_filepos, pos, s->read_filepos, s->max_filepos);
|
||||
|
||||
cache->pos = s->read_filepos = pos;
|
||||
s->eof = false; // so that cache_read() will actually wait for new data
|
||||
pthread_cond_signal(&s->wakeup);
|
||||
if (!s->seekable && pos > s->max_filepos) {
|
||||
MP_ERR(s, "Attempting to seek past cached data in unseekable stream.\n");
|
||||
r = 0;
|
||||
} else if (!s->seekable && pos < s->min_filepos) {
|
||||
MP_ERR(s, "Attempting to seek before cached data in unseekable stream.\n");
|
||||
r = 0;
|
||||
} else {
|
||||
cache->pos = s->read_filepos = pos;
|
||||
s->eof = false; // so that cache_read() will actually wait for new data
|
||||
pthread_cond_signal(&s->wakeup);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s->mutex);
|
||||
|
||||
return 1;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int cache_control(stream_t *cache, int cmd, void *arg)
|
||||
@@ -592,6 +611,9 @@ int stream_cache_init(stream_t *cache, stream_t *stream, int64_t size,
|
||||
if (min > s->buffer_size - s->fill_limit)
|
||||
min = s->buffer_size - s->fill_limit;
|
||||
|
||||
s->seekable = (stream->flags & MP_STREAM_SEEK) == MP_STREAM_SEEK &&
|
||||
stream->end_pos > 0;
|
||||
|
||||
if (pthread_create(&s->cache_thread, NULL, cache_thread, s) != 0) {
|
||||
MP_ERR(s, "Starting cache process/thread failed: %s.\n",
|
||||
strerror(errno));
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ static char *col_dup(void *talloc_ctx, const char *src)
|
||||
}
|
||||
|
||||
/* Finds the start of all the columns */
|
||||
static int parse_line(char **ptr, char *cols[6])
|
||||
static int parse_line(char **ptr, char *cols[7])
|
||||
{
|
||||
int col;
|
||||
cols[0] = *ptr;
|
||||
|
||||
@@ -111,7 +111,7 @@ struct mp_resolve_result *mp_resolve_quvi(const char *url,
|
||||
quvi_media_free(media);
|
||||
}
|
||||
|
||||
if (quvi_supports(q, url, mode, QUVI_SUPPORTS_TYPE_SUBTITLE)) {
|
||||
if (opts->quvi_fetch_subtitles && quvi_supports(q, url, mode, QUVI_SUPPORTS_TYPE_SUBTITLE)) {
|
||||
mp_info(log, "Getting subtitles...\n");
|
||||
quvi_subtitle_t qsub = quvi_subtitle_new(q, url);
|
||||
if (mp_quvi_ok(q, log)) {
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ pvr_uninit (struct pvr_t *pvr)
|
||||
return;
|
||||
|
||||
/* close device */
|
||||
if (pvr->dev_fd)
|
||||
if (pvr->dev_fd != -1)
|
||||
close (pvr->dev_fd);
|
||||
|
||||
free (pvr->video_dev);
|
||||
|
||||
+1
-1
@@ -126,7 +126,7 @@ static mp_vcd_priv_t* vcd_read_toc(stream_t *stream, int fd){
|
||||
|
||||
static int vcd_read(mp_vcd_priv_t* vcd,char *mem){
|
||||
#ifndef sun
|
||||
memcpy(vcd->buf,&vcd->entry.cdte_addr.msf,sizeof(struct cdrom_msf));
|
||||
memcpy(vcd->buf,&vcd->entry.cdte_addr.msf,sizeof(vcd->entry.cdte_addr.msf));
|
||||
if(ioctl(vcd->fd,CDROMREADRAW,vcd->buf)==-1) return 0; // EOF?
|
||||
memcpy(mem,&vcd->buf[VCD_SECTOR_OFFS],VCD_SECTOR_DATA);
|
||||
#else
|
||||
|
||||
+4
-1
@@ -19,6 +19,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libavutil/common.h>
|
||||
#include <ass/ass.h>
|
||||
@@ -142,9 +143,11 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, double pts,
|
||||
opts->ass_vsfilter_aspect_compat))
|
||||
{
|
||||
// Let's use the original video PAR for vsfilter compatibility:
|
||||
scale = scale
|
||||
double par = scale
|
||||
* (ctx->video_params.d_w / (double)ctx->video_params.d_h)
|
||||
/ (ctx->video_params.w / (double)ctx->video_params.h);
|
||||
if (isnormal(par))
|
||||
scale = par;
|
||||
}
|
||||
mp_ass_configure(renderer, opts, &dim);
|
||||
ass_set_aspect_ratio(renderer, scale, 1);
|
||||
|
||||
+8
-3
@@ -17,6 +17,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavutil/common.h>
|
||||
@@ -182,11 +183,13 @@ static void decode(struct sd *sd, struct demux_packet *packet)
|
||||
sub.num_rects);
|
||||
for (int i = 0; i < sub.num_rects; i++) {
|
||||
struct AVSubtitleRect *r = sub.rects[i];
|
||||
struct sub_bitmap *b = &priv->inbitmaps[i];
|
||||
struct osd_bmp_indexed *img = &priv->imgs[i];
|
||||
struct sub_bitmap *b = &priv->inbitmaps[priv->count];
|
||||
struct osd_bmp_indexed *img = &priv->imgs[priv->count];
|
||||
if (!(r->flags & AV_SUBTITLE_FLAG_FORCED) &&
|
||||
opts->forced_subs_only)
|
||||
continue;
|
||||
if (r->w == 0 || r->h == 0)
|
||||
continue;
|
||||
img->bitmap = r->pict.data[0];
|
||||
assert(r->nb_colors > 0);
|
||||
assert(r->nb_colors * 4 <= sizeof(img->palette));
|
||||
@@ -234,9 +237,11 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
|
||||
if (priv->avctx->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
|
||||
opts->stretch_dvd_subs) {
|
||||
// For DVD subs, try to keep the subtitle PAR at display PAR.
|
||||
video_par =
|
||||
double par =
|
||||
(priv->video_params.d_w / (double)priv->video_params.d_h)
|
||||
/ (priv->video_params.w / (double)priv->video_params.h);
|
||||
if (isnormal(par))
|
||||
video_par = par;
|
||||
}
|
||||
int insize[2];
|
||||
get_resolution(sd, insize);
|
||||
|
||||
+2
-30
@@ -26,7 +26,6 @@
|
||||
|
||||
struct sd_spu_priv {
|
||||
void *spudec;
|
||||
struct mp_image_params video_params;
|
||||
};
|
||||
|
||||
static bool is_dvd_sub(const char *t)
|
||||
@@ -72,22 +71,8 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
|
||||
spudec_set_forced_subs_only(priv->spudec, opts->forced_subs_only);
|
||||
spudec_heartbeat(priv->spudec, pts * 90000);
|
||||
|
||||
if (spudec_visible(priv->spudec)) {
|
||||
double xscale = 1;
|
||||
double yscale = 1;
|
||||
if (opts->stretch_dvd_subs) {
|
||||
// For DVD subs, try to keep the subtitle PAR at display PAR.
|
||||
double video_par =
|
||||
(priv->video_params.d_w / (double)priv->video_params.d_h)
|
||||
/ (priv->video_params.w / (double)priv->video_params.h);
|
||||
if (video_par > 1.0) {
|
||||
xscale /= video_par;
|
||||
} else {
|
||||
yscale *= video_par;
|
||||
}
|
||||
}
|
||||
spudec_get_indexed(priv->spudec, &d, xscale, yscale, res);
|
||||
}
|
||||
if (spudec_visible(priv->spudec))
|
||||
spudec_get_indexed(priv->spudec, &d, 1, 1, res);
|
||||
}
|
||||
|
||||
static void reset(struct sd *sd)
|
||||
@@ -105,25 +90,12 @@ static void uninit(struct sd *sd)
|
||||
talloc_free(priv);
|
||||
}
|
||||
|
||||
static int control(struct sd *sd, enum sd_ctrl cmd, void *arg)
|
||||
{
|
||||
struct sd_spu_priv *priv = sd->priv;
|
||||
switch (cmd) {
|
||||
case SD_CTRL_SET_VIDEO_PARAMS:
|
||||
priv->video_params = *(struct mp_image_params *)arg;
|
||||
return CONTROL_OK;
|
||||
default:
|
||||
return CONTROL_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
const struct sd_functions sd_spu = {
|
||||
.name = "spu",
|
||||
.supports_format = supports_format,
|
||||
.init = init,
|
||||
.decode = decode,
|
||||
.get_bitmaps = get_bitmaps,
|
||||
.control = control,
|
||||
.reset = reset,
|
||||
.uninit = uninit,
|
||||
};
|
||||
@@ -399,10 +399,10 @@ int video_reconfig_filters(struct dec_video *d_video,
|
||||
}
|
||||
|
||||
float force_aspect = opts->movie_aspect;
|
||||
if (force_aspect > -1.0 && d_video->stream_aspect != 0.0)
|
||||
if (force_aspect > 0.0 && d_video->stream_aspect != 0.0)
|
||||
force_aspect = d_video->stream_aspect;
|
||||
|
||||
if (force_aspect > 0)
|
||||
if (force_aspect >= 0.0)
|
||||
vf_set_dar(&p.d_w, &p.d_h, p.w, p.h, force_aspect);
|
||||
|
||||
if (abs(p.d_w - p.w) >= 4 || abs(p.d_h - p.h) >= 4) {
|
||||
|
||||
@@ -175,6 +175,10 @@ static int mp_chroma_div_up(int size, int shift)
|
||||
// Caller has to make sure this doesn't exceed the allocated plane data/strides.
|
||||
void mp_image_set_size(struct mp_image *mpi, int w, int h)
|
||||
{
|
||||
// av_image_check_size has similar checks and triggers around 16000*16000
|
||||
if (w >= (1 << 14) || h >= (1 << 14) || w < 0 || h < 0)
|
||||
abort();
|
||||
|
||||
mpi->w = mpi->display_w = w;
|
||||
mpi->h = mpi->display_h = h;
|
||||
for (int n = 0; n < mpi->num_planes; n++) {
|
||||
|
||||
+9
-3
@@ -157,14 +157,20 @@ struct lut3d *mp_load_icc(struct mp_icc_opts *opts, struct mp_log *log,
|
||||
if (!profile)
|
||||
goto error_exit;
|
||||
|
||||
cmsCIExyY d65;
|
||||
cmsWhitePointFromTemp(&d65, 6504);
|
||||
cmsCIExyY d65 = {0.3127, 0.3290, 1.0};
|
||||
static const cmsCIExyYTRIPLE bt709prim = {
|
||||
.Red = {0.64, 0.33, 1.0},
|
||||
.Green = {0.30, 0.60, 1.0},
|
||||
.Blue = {0.15, 0.06, 1.0},
|
||||
};
|
||||
cmsToneCurve *tonecurve = cmsBuildGamma(NULL, 1.0/0.45);
|
||||
|
||||
/* Rec BT.709 defines the tone curve as:
|
||||
V = 1.099 * L^0.45 - 0.099 for L >= 0.018
|
||||
V = 4.500 * L for L < 0.018
|
||||
|
||||
The 0.081 parameter comes from inserting 0.018 into the function */
|
||||
cmsToneCurve *tonecurve = cmsBuildParametricToneCurve(NULL, 4,
|
||||
(cmsFloat64Number[5]){1/0.45, 1/1.099, 0.099/1.099, 1/4.5, 0.081});
|
||||
cmsHPROFILE vid_profile = cmsCreateRGBProfile(&d65, &bt709prim,
|
||||
(cmsToneCurve*[3]){tonecurve, tonecurve, tonecurve});
|
||||
cmsFreeToneCurve(tonecurve);
|
||||
|
||||
@@ -45,8 +45,14 @@
|
||||
#if __VERSION__ >= 130
|
||||
vec3 srgb_compand(vec3 v)
|
||||
{
|
||||
return mix(1.055 * pow(v, vec3(1.0/2.4)) - vec3(0.055), v * 12.92,
|
||||
lessThanEqual(v, vec3(0.0031308)));
|
||||
return mix(v * 12.92, 1.055 * pow(v, vec3(1.0/2.4)) - vec3(0.055),
|
||||
lessThanEqual(vec3(0.0031308), v));
|
||||
}
|
||||
|
||||
vec3 bt709_expand(vec3 v)
|
||||
{
|
||||
return mix(v / 4.5, pow((v + vec3(0.099))/1.099, vec3(1/0.45)),
|
||||
lessThanEqual(vec3(0.0812), v));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -384,6 +390,13 @@ void main() {
|
||||
color = texture3D(lut_3d, color).rgb;
|
||||
#endif
|
||||
#ifdef USE_SRGB
|
||||
// Go from "linear" (0.45) to BT.709 to true linear to sRGB
|
||||
#ifndef USE_3DLUT
|
||||
// Unless we are using a 3DLUT, in which case USE_LINEAR_CONV_INV
|
||||
// already triggered earlier.
|
||||
color = pow(color, vec3(0.45));
|
||||
#endif
|
||||
color = bt709_expand(color.rgb);
|
||||
color.rgb = srgb_compand(color.rgb);
|
||||
#endif
|
||||
#ifdef USE_DITHER
|
||||
|
||||
+11
-4
@@ -44,6 +44,11 @@ static bool create_context_x11_old(struct MPGLContext *ctx)
|
||||
if (glx_ctx->context)
|
||||
return true;
|
||||
|
||||
if (!glx_ctx->vinfo) {
|
||||
MP_FATAL(vo, "Can't create a legacy GLX context without X visual\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
GLXContext new_context = glXCreateContext(display, glx_ctx->vinfo, NULL,
|
||||
True);
|
||||
if (!new_context) {
|
||||
@@ -219,6 +224,7 @@ static bool config_window_x11(struct MPGLContext *ctx, uint32_t d_width,
|
||||
int glx_attribs[] = {
|
||||
GLX_STEREO, False,
|
||||
GLX_X_RENDERABLE, True,
|
||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE, 1,
|
||||
GLX_GREEN_SIZE, 1,
|
||||
GLX_BLUE_SIZE, 1,
|
||||
@@ -254,12 +260,13 @@ static bool config_window_x11(struct MPGLContext *ctx, uint32_t d_width,
|
||||
|
||||
glx_ctx->fbc = fbc;
|
||||
glx_ctx->vinfo = glXGetVisualFromFBConfig(vo->x11->display, fbc);
|
||||
if (!glx_ctx->vinfo) {
|
||||
MP_ERR(vo, "Selected GLX FB config has no associated X visual\n");
|
||||
return false;
|
||||
if (glx_ctx->vinfo) {
|
||||
MP_VERBOSE(vo, "GLX chose visual with ID 0x%x\n",
|
||||
(int)glx_ctx->vinfo->visualid);
|
||||
} else {
|
||||
MP_WARN(vo, "Selected GLX FB config has no associated X visual\n");
|
||||
}
|
||||
|
||||
MP_VERBOSE(vo, "GLX chose visual with ID 0x%x\n", (int)glx_ctx->vinfo->visualid);
|
||||
|
||||
glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_RED_SIZE, &ctx->depth_r);
|
||||
glXGetFBConfigAttrib(vo->x11->display, fbc, GLX_GREEN_SIZE, &ctx->depth_g);
|
||||
|
||||
@@ -176,6 +176,9 @@ static int change_vdptime_sync(struct vo *vo, int64_t *t)
|
||||
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.);
|
||||
@@ -1064,6 +1067,10 @@ 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;
|
||||
|
||||
uint64_t now = sync_vdptime(vo);
|
||||
uint64_t pts = pts_us ? convert_to_vdptime(vo, pts_us) : now;
|
||||
uint64_t ideal_pts = pts;
|
||||
|
||||
+38
-47
@@ -41,13 +41,6 @@
|
||||
|
||||
#define MAX_BUFFERS 2
|
||||
|
||||
// minium target version for the new formats (1.2.90)
|
||||
#define MINIMUM_VERSION (1 << 16 | 2 << 8 | 90)
|
||||
|
||||
#define CURRENT_VERSION (WAYLAND_VERSION_MAJOR << 16 | \
|
||||
WAYLAND_VERSION_MINOR << 8 | \
|
||||
WAYLAND_VERSION_MICRO)
|
||||
|
||||
static void draw_image(struct vo *vo, mp_image_t *mpi);
|
||||
|
||||
static const struct wl_callback_listener frame_listener;
|
||||
@@ -65,7 +58,6 @@ struct fmtentry {
|
||||
static const struct fmtentry fmttable[] = {
|
||||
{WL_SHM_FORMAT_ARGB8888, IMGFMT_BGRA}, // 8b 8g 8r 8a
|
||||
{WL_SHM_FORMAT_XRGB8888, IMGFMT_BGR0},
|
||||
#if CURRENT_VERSION >= MINIMUM_VERSION
|
||||
{WL_SHM_FORMAT_RGB332, IMGFMT_BGR8}, // 3b 3g 2r
|
||||
{WL_SHM_FORMAT_BGR233, IMGFMT_RGB8}, // 3r 3g 3b,
|
||||
{WL_SHM_FORMAT_XRGB4444, IMGFMT_BGR12_LE}, // 4b 4g 4r 4a
|
||||
@@ -94,7 +86,6 @@ static const struct fmtentry fmttable[] = {
|
||||
{WL_SHM_FORMAT_ABGR8888, IMGFMT_RGBA},
|
||||
{WL_SHM_FORMAT_RGBA8888, IMGFMT_ABGR},
|
||||
{WL_SHM_FORMAT_BGRA8888, IMGFMT_ARGB},
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MAX_FORMAT_ENTRIES (sizeof(fmttable) / sizeof(fmttable[0]))
|
||||
@@ -149,7 +140,7 @@ struct priv {
|
||||
|
||||
// options
|
||||
int enable_alpha;
|
||||
int use_default;
|
||||
int use_rgb565;
|
||||
};
|
||||
|
||||
/* copied from weston clients */
|
||||
@@ -232,6 +223,21 @@ static bool is_alpha_format(const struct fmtentry *fmt)
|
||||
return !!(mp_imgfmt_get_desc(fmt->mp_fmt).flags & MP_IMGFLAG_ALPHA);
|
||||
}
|
||||
|
||||
static const struct fmtentry * is_wayland_format_supported(struct priv *p,
|
||||
enum wl_shm_format fmt)
|
||||
{
|
||||
struct supported_format *sf;
|
||||
|
||||
// find the matching format first
|
||||
wl_list_for_each(sf, &p->format_list, link) {
|
||||
if (sf->fmt->wl_fmt == fmt) {
|
||||
return sf->fmt;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void buffer_swap(struct priv *p)
|
||||
{
|
||||
if (!p->back_buffer->is_new)
|
||||
@@ -466,27 +472,7 @@ static void frame_handle_redraw(void *data,
|
||||
struct buffer *buf = buffer_get_front(p);
|
||||
|
||||
if (buf) {
|
||||
if (p->resize_attach) {
|
||||
wl_surface_attach(wl->window.surface, buf->wlbuf, p->x, p->y);
|
||||
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
||||
wl_surface_commit(wl->window.surface);
|
||||
|
||||
if (callback)
|
||||
wl_callback_destroy(callback);
|
||||
|
||||
p->redraw_callback = NULL;
|
||||
buffer_finalise_front(buf);
|
||||
p->resize_attach = false;
|
||||
|
||||
destroy_shm_buffer(&p->tmp_buffer);
|
||||
|
||||
// I have to destroy the callback and return early to avoid black flickers
|
||||
// I don't exactly know why this, but I guess the back buffer is still
|
||||
// empty. The callback loop will be restored on the next flip_page call
|
||||
return;
|
||||
}
|
||||
|
||||
wl_surface_attach(wl->window.surface, buf->wlbuf, 0, 0);
|
||||
wl_surface_attach(wl->window.surface, buf->wlbuf, p->x, p->y);
|
||||
wl_surface_damage(wl->window.surface, 0, 0, p->dst_w, p->dst_h);
|
||||
|
||||
if (callback)
|
||||
@@ -496,6 +482,14 @@ static void frame_handle_redraw(void *data,
|
||||
wl_callback_add_listener(p->redraw_callback, &frame_listener, p);
|
||||
wl_surface_commit(wl->window.surface);
|
||||
buffer_finalise_front(buf);
|
||||
|
||||
// to avoid multiple resizes of non-shown frames
|
||||
if (p->resize_attach) {
|
||||
destroy_shm_buffer(&p->tmp_buffer);
|
||||
p->resize_attach = false;
|
||||
p->x = 0;
|
||||
p->y = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (callback)
|
||||
@@ -595,13 +589,13 @@ static int reconfig(struct vo *vo, struct mp_image_params *fmt, int flags)
|
||||
struct priv *p = vo->priv;
|
||||
mp_image_unrefp(&p->original_image);
|
||||
|
||||
p->width = vo->dwidth;
|
||||
p->height = vo->dheight;
|
||||
p->width = fmt->w;
|
||||
p->height = fmt->h;
|
||||
p->in_format = *fmt;
|
||||
|
||||
struct supported_format *sf;
|
||||
|
||||
// find the same format first
|
||||
// find the matching format first
|
||||
wl_list_for_each(sf, &p->format_list, link) {
|
||||
if (sf->fmt->mp_fmt == fmt->imgfmt && (p->enable_alpha == sf->is_alpha)) {
|
||||
p->pref_format = sf->fmt;
|
||||
@@ -609,25 +603,22 @@ static int reconfig(struct vo *vo, struct mp_image_params *fmt, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
// if the format is not supported choose one of the fancy formats next
|
||||
// the default formats are always last
|
||||
if (!p->pref_format) {
|
||||
wl_list_for_each(sf, &p->format_list, link) {
|
||||
if (p->enable_alpha == sf->is_alpha) {
|
||||
p->pref_format = sf->fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if use default is enable overwrite the auto selected one
|
||||
if (p->use_default) {
|
||||
// if use default is enable overwrite the auto selected one
|
||||
if (p->enable_alpha)
|
||||
p->pref_format = &fmttable[DEFAULT_ALPHA_FORMAT_ENTRY];
|
||||
else
|
||||
p->pref_format = &fmttable[DEFAULT_FORMAT_ENTRY];
|
||||
}
|
||||
|
||||
// overides alpha
|
||||
// use rgb565 if performance is your main concern
|
||||
if (p->use_rgb565) {
|
||||
const struct fmtentry *mp_fmt =
|
||||
is_wayland_format_supported(p, WL_SHM_FORMAT_RGB565);
|
||||
if (mp_fmt)
|
||||
p->pref_format = mp_fmt;
|
||||
}
|
||||
|
||||
p->bytes_per_pixel = mp_imgfmt_get_desc(p->pref_format->mp_fmt).bytes[0];
|
||||
MP_VERBOSE(p->wl, "bytes per pixel: %d\n", p->bytes_per_pixel);
|
||||
@@ -732,7 +723,7 @@ const struct vo_driver video_out_wayland = {
|
||||
.uninit = uninit,
|
||||
.options = (const struct m_option[]) {
|
||||
OPT_FLAG("alpha", enable_alpha, 0),
|
||||
OPT_FLAG("default-format", use_default, 0),
|
||||
OPT_FLAG("rgb565", use_rgb565, 0),
|
||||
{0}
|
||||
},
|
||||
};
|
||||
|
||||
+11
-9
@@ -757,7 +757,6 @@ int vo_x11_check_events(struct vo *vo)
|
||||
vo_x11_update_geometry(vo);
|
||||
while (XPending(display)) {
|
||||
XNextEvent(display, &Event);
|
||||
// printf("\rEvent.type=%X \n",Event.type);
|
||||
switch (Event.type) {
|
||||
case Expose:
|
||||
x11->pending_vo_events |= VO_EVENT_EXPOSE;
|
||||
@@ -818,14 +817,9 @@ int vo_x11_check_events(struct vo *vo)
|
||||
(MP_MOUSE_BTN0 + Event.xbutton.button - 1) |
|
||||
get_mods(Event.xbutton.state) | MP_KEY_STATE_UP);
|
||||
break;
|
||||
case PropertyNotify: {
|
||||
char *name = XGetAtomName(display, Event.xproperty.atom);
|
||||
if (!name)
|
||||
break;
|
||||
XFree(name);
|
||||
break;
|
||||
}
|
||||
case MapNotify:
|
||||
x11->window_hidden = false;
|
||||
vo_x11_update_geometry(vo);
|
||||
x11->vo_hint.win_gravity = x11->old_gravity;
|
||||
XSetWMNormalHints(display, x11->window, &x11->vo_hint);
|
||||
x11->fs_flip = 0;
|
||||
@@ -1135,7 +1129,6 @@ static void vo_x11_map_window(struct vo *vo, int x, int y, int w, int h)
|
||||
{
|
||||
struct vo_x11_state *x11 = vo->x11;
|
||||
|
||||
x11->window_hidden = false;
|
||||
vo_x11_move_resize(vo, true, true, x, y, w, h);
|
||||
if (!vo->opts->border)
|
||||
vo_x11_decoration(vo, 0);
|
||||
@@ -1230,6 +1223,13 @@ void vo_x11_config_vo_window(struct vo *vo, XVisualInfo *vis, int x, int y,
|
||||
XSync(x11->display, False);
|
||||
|
||||
vo_x11_update_geometry(vo);
|
||||
if (x11->window_hidden) {
|
||||
// The real size is only known when the window is mapped, which
|
||||
// unfortunately happens asynchronous to VO initialization. At least
|
||||
// vdpau needs a _some_ window size, though.
|
||||
x11->win_width = width;
|
||||
x11->win_height = height;
|
||||
}
|
||||
update_vo_size(vo);
|
||||
x11->pending_vo_events &= ~VO_EVENT_RESIZE; // implicitly done by the VO
|
||||
}
|
||||
@@ -1342,6 +1342,8 @@ static void vo_x11_update_geometry(struct vo *vo)
|
||||
int dummy_int;
|
||||
Window dummy_win;
|
||||
Window win = vo->opts->WinID > 0 ? vo->opts->WinID : x11->window;
|
||||
if (x11->window_hidden)
|
||||
return;
|
||||
XGetGeometry(x11->display, win, &dummy_win, &dummy_int, &dummy_int,
|
||||
&w, &h, &dummy_int, &dummy_uint);
|
||||
if (w <= INT_MAX && h <= INT_MAX) {
|
||||
|
||||
@@ -15,7 +15,7 @@ def __add_generic_flags__(ctx):
|
||||
ctx.env.CFLAGS += ["-D_ISOC99_SOURCE", "-D_GNU_SOURCE",
|
||||
"-D_LARGEFILE_SOURCE", "-D_FILE_OFFSET_BITS=64",
|
||||
"-D_LARGEFILE64_SOURCE",
|
||||
"-std=gnu99", "-Wall"]
|
||||
"-std=c99", "-Wall"]
|
||||
|
||||
if ctx.is_debug_build():
|
||||
ctx.env.CFLAGS += ['-g']
|
||||
|
||||
@@ -6,7 +6,7 @@ def __get_version__(ctx):
|
||||
cwd=ctx.srcnode.abspath())
|
||||
process.wait()
|
||||
(version, err) = process.communicate()
|
||||
return version.strip()
|
||||
return version.strip().decode("utf-8")
|
||||
|
||||
def __get_build_date__():
|
||||
import time
|
||||
|
||||
@@ -507,8 +507,8 @@ video_output_features = [
|
||||
} , {
|
||||
'name': '--wayland',
|
||||
'desc': 'Wayland',
|
||||
'func': check_pkg_config('wayland-client', '>= 1.2.0',
|
||||
'wayland-cursor', '>= 1.2.0',
|
||||
'func': check_pkg_config('wayland-client', '>= 1.3.0',
|
||||
'wayland-cursor', '>= 1.3.0',
|
||||
'xkbcommon', '>= 0.3.0'),
|
||||
} , {
|
||||
'name': '--x11',
|
||||
|
||||
Reference in new issue
Block a user