Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6bb684d55 | ||
|
|
4c97c3a1b3 | ||
|
|
4b36023273 | ||
|
|
864a2da9ea | ||
|
|
e6ac54e333 | ||
|
|
54c2a95792 | ||
|
|
661633b689 | ||
|
|
a0eea7aba8 | ||
|
|
9de0db208d | ||
|
|
d52c491fec | ||
|
|
ff2e39a3d2 | ||
|
|
844656d135 | ||
|
|
c0f85c18f8 | ||
|
|
60111d3f0f | ||
|
|
2f86a06528 | ||
|
|
7e61bf134a | ||
|
|
61a2f3d2bf | ||
|
|
213ea94ee3 | ||
|
|
f1409ceacf | ||
|
|
44f62ff6f3 | ||
|
|
55c3055784 | ||
|
|
58fbe50d68 | ||
|
|
6a0036ea03 | ||
|
|
2e4fdf01f5 | ||
|
|
a2259b3fd3 | ||
|
|
aeeb7a92f2 | ||
|
|
1e2f3191a7 | ||
|
|
51d030308e | ||
|
|
4cd8aab84f | ||
|
|
3795154155 | ||
|
|
461198e149 | ||
|
|
7b1f12adba | ||
|
|
cf1645aebb | ||
|
|
1b20ec4864 | ||
|
|
ee529da760 | ||
|
|
c9e6e7cc04 | ||
|
|
cb1d1e7a62 | ||
|
|
e6d4ec62ae | ||
|
|
e7e2a6c8f7 | ||
|
|
6643ebaa28 | ||
|
|
98d33db5da |
No files matched your search
@@ -134,6 +134,8 @@ Sending patches
|
||||
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
|
||||
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.
|
||||
- If you add a new command line option, document it in options.rst. If you
|
||||
add a new input property, document it in input.rst.
|
||||
+3
-3
@@ -36,14 +36,14 @@ Available audio output drivers are:
|
||||
``alsa`` (Linux only)
|
||||
ALSA audio output driver
|
||||
|
||||
``device=<device>``
|
||||
Sets the device name. For ac3 output via S/PDIF, use an "iec958" or
|
||||
"spdif" device, unless you really know how to set it correctly.
|
||||
``no-block``
|
||||
Sets noblock-mode.
|
||||
``resample=yes``
|
||||
Enable ALSA resampling plugin. (This is disabled by default, because
|
||||
some drivers report incorrect audio delay in some cases.)
|
||||
``device=<device>``
|
||||
Sets the device name. For ac3 output via S/PDIF, use an "iec958" or
|
||||
"spdif" device, unless you really know how to set it correctly.
|
||||
``mixer-device=<device>``
|
||||
Set the mixer device used with ``--no-softvol`` (default: ``default``).
|
||||
``mixer-name=<name>``
|
||||
|
||||
+10
-5
@@ -1648,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.)
|
||||
|
||||
+11
-9
@@ -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[:param[:param2[: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,14 +116,6 @@ 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.
|
||||
|
||||
``<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.
|
||||
|
||||
|
||||
@@ -82,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
|
||||
-----------
|
||||
|
||||
@@ -95,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.
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -724,8 +724,8 @@ const struct ao_driver audio_out_alsa = {
|
||||
.cfg_mixer_index = 0,
|
||||
},
|
||||
.options = (const struct m_option[]) {
|
||||
OPT_FLAG("resample", cfg_resample, 0),
|
||||
OPT_STRING("device", cfg_device, 0),
|
||||
OPT_FLAG("resample", cfg_resample, 0),
|
||||
OPT_FLAG("block", cfg_block, 0),
|
||||
OPT_STRING("mixer-device", cfg_mixer_device, 0),
|
||||
OPT_STRING("mixer-name", cfg_mixer_name, 0),
|
||||
|
||||
+4
-1
@@ -114,10 +114,13 @@ void playlist_clear(struct playlist *pl)
|
||||
pl->current_was_replaced = false;
|
||||
}
|
||||
|
||||
// Moves entry such that entry->prev = at (even if at is NULL)
|
||||
// Moves the entry so that it takes "at"'s place (or move to end, if at==NULL).
|
||||
void playlist_move(struct playlist *pl, struct playlist_entry *entry,
|
||||
struct playlist_entry *at)
|
||||
{
|
||||
if (entry == at)
|
||||
return;
|
||||
|
||||
struct playlist_entry *save_current = pl->current;
|
||||
bool save_replaced = pl->current_was_replaced;
|
||||
|
||||
|
||||
+6
-20
@@ -44,10 +44,6 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#if MP_INPUT_BUFFER_PADDING_SIZE < FF_INPUT_BUFFER_PADDING_SIZE
|
||||
#error MP_INPUT_BUFFER_PADDING_SIZE is too small!
|
||||
#endif
|
||||
|
||||
// Demuxer list
|
||||
extern const struct demuxer_desc demuxer_desc_edl;
|
||||
extern const struct demuxer_desc demuxer_desc_cue;
|
||||
@@ -117,7 +113,7 @@ static void packet_destroy(void *ptr)
|
||||
{
|
||||
struct demux_packet *dp = ptr;
|
||||
talloc_free(dp->avpacket);
|
||||
free(dp->allocation);
|
||||
av_free(dp->allocation);
|
||||
}
|
||||
|
||||
static struct demux_packet *create_packet(size_t len)
|
||||
@@ -143,12 +139,12 @@ static struct demux_packet *create_packet(size_t len)
|
||||
struct demux_packet *new_demux_packet(size_t len)
|
||||
{
|
||||
struct demux_packet *dp = create_packet(len);
|
||||
dp->buffer = malloc(len + MP_INPUT_BUFFER_PADDING_SIZE);
|
||||
dp->buffer = av_malloc(len + FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!dp->buffer) {
|
||||
fprintf(stderr, "Memory allocation failure!\n");
|
||||
abort();
|
||||
}
|
||||
memset(dp->buffer + len, 0, MP_INPUT_BUFFER_PADDING_SIZE);
|
||||
memset(dp->buffer + len, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
dp->allocation = dp->buffer;
|
||||
return dp;
|
||||
}
|
||||
@@ -168,21 +164,11 @@ struct demux_packet *new_demux_packet_from(void *data, size_t len)
|
||||
return dp;
|
||||
}
|
||||
|
||||
void resize_demux_packet(struct demux_packet *dp, size_t len)
|
||||
void demux_packet_shorten(struct demux_packet *dp, size_t len)
|
||||
{
|
||||
if (len > 1000000000) {
|
||||
fprintf(stderr, "Attempt to realloc demux packet over 1 GB!\n");
|
||||
abort();
|
||||
}
|
||||
assert(dp->allocation);
|
||||
dp->buffer = realloc(dp->buffer, len + MP_INPUT_BUFFER_PADDING_SIZE);
|
||||
if (!dp->buffer) {
|
||||
fprintf(stderr, "Memory allocation failure!\n");
|
||||
abort();
|
||||
}
|
||||
memset(dp->buffer + len, 0, MP_INPUT_BUFFER_PADDING_SIZE);
|
||||
assert(len <= dp->len);
|
||||
dp->len = len;
|
||||
dp->allocation = dp->buffer;
|
||||
memset(dp->buffer + dp->len, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||
}
|
||||
|
||||
void free_demux_packet(struct demux_packet *dp)
|
||||
|
||||
+1
-4
@@ -80,9 +80,6 @@ enum demux_check {
|
||||
DEMUX_CHECK_NORMAL, // normal, safe detection
|
||||
};
|
||||
|
||||
// demux_lavf can pass lavf buffers using FF_INPUT_BUFFER_PADDING_SIZE instead
|
||||
#define MP_INPUT_BUFFER_PADDING_SIZE 16
|
||||
|
||||
#define MAX_SH_STREAMS 256
|
||||
|
||||
struct demuxer;
|
||||
@@ -210,7 +207,7 @@ struct demux_packet *new_demux_packet(size_t len);
|
||||
// data must already have suitable padding
|
||||
struct demux_packet *new_demux_packet_fromdata(void *data, size_t len);
|
||||
struct demux_packet *new_demux_packet_from(void *data, size_t len);
|
||||
void resize_demux_packet(struct demux_packet *dp, size_t len);
|
||||
void demux_packet_shorten(struct demux_packet *dp, size_t len);
|
||||
void free_demux_packet(struct demux_packet *dp);
|
||||
struct demux_packet *demux_copy_packet(struct demux_packet *dp);
|
||||
|
||||
|
||||
+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}
|
||||
};
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ static int raw_fill_buffer(demuxer_t *demuxer)
|
||||
dp->pts = (dp->pos / p->frame_size) / p->frame_rate;
|
||||
|
||||
int len = stream_read(demuxer->stream, dp->buffer, dp->len);
|
||||
resize_demux_packet(dp, len);
|
||||
demux_packet_shorten(dp, len);
|
||||
demuxer_add_packet(demuxer, demuxer->streams[0], dp);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
#Q quit_watch_later
|
||||
#q {encode} quit
|
||||
#ESC quit
|
||||
#ESC {encode} quit
|
||||
#p cycle pause # toggle pause/playback mode
|
||||
#. frame_step # advance one frame and pause
|
||||
#, frame_back_step # go back by one frame and pause
|
||||
|
||||
+7
-1
@@ -271,13 +271,19 @@ 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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd)
|
||||
{
|
||||
return (cmd->def && cmd->def->allow_auto_repeat) ||
|
||||
cmd->id == MP_CMD_COMMAND_LIST;
|
||||
}
|
||||
|
||||
void mp_print_cmd_list(struct mp_log *out)
|
||||
{
|
||||
for (int i = 0; mp_cmds[i].name; i++) {
|
||||
|
||||
@@ -110,6 +110,8 @@ enum mp_command_type {
|
||||
struct mp_cmd;
|
||||
bool mp_input_is_abort_cmd(struct mp_cmd *cmd);
|
||||
|
||||
bool mp_input_is_repeatable_cmd(struct mp_cmd *cmd);
|
||||
|
||||
struct bstr;
|
||||
bool mp_replace_legacy_cmd(void *talloc_ctx, struct bstr *s);
|
||||
|
||||
|
||||
+2
-2
@@ -517,7 +517,7 @@ static void update_mouse_section(struct input_ctx *ictx)
|
||||
}
|
||||
|
||||
// Called when the currently held-down key is released. This (usually) sends
|
||||
// the a key-up versiob of the command associated with the keys that were held
|
||||
// the a key-up version of the command associated with the keys that were held
|
||||
// down.
|
||||
// If the drop_current parameter is set to true, then don't send the key-up
|
||||
// command. Unless we've already sent a key-down event, in which case the
|
||||
@@ -1155,7 +1155,7 @@ mp_cmd_t *mp_input_get_cmd(struct input_ctx *ictx, int time, int peek_only)
|
||||
struct mp_cmd *repeated = check_autorepeat(ictx);
|
||||
if (repeated) {
|
||||
repeated->repeated = true;
|
||||
if (repeated->def && repeated->def->allow_auto_repeat) {
|
||||
if (mp_input_is_repeatable_cmd(repeated)) {
|
||||
queue_add_tail(queue, repeated);
|
||||
} else {
|
||||
talloc_free(repeated);
|
||||
|
||||
@@ -343,6 +343,7 @@ DIRS = . \
|
||||
player/timeline \
|
||||
demux \
|
||||
misc \
|
||||
options \
|
||||
osdep \
|
||||
osdep/ar \
|
||||
player \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -138,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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
+49
-22
@@ -40,15 +40,13 @@ known issues:
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#if HAVE_SYS_SYSINFO_H
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
#if HAVE_SYS_VIDEOIO_H
|
||||
#include <sys/videoio.h>
|
||||
#else
|
||||
@@ -71,6 +69,13 @@ known issues:
|
||||
#define v4l2_munmap munmap
|
||||
#endif
|
||||
|
||||
// flag introduced in kernel 3.10
|
||||
#ifndef V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC
|
||||
#define V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC 0x2000
|
||||
#endif
|
||||
|
||||
#define HAVE_CLOCK_GETTIME (defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
|
||||
|
||||
#define info tvi_info_v4l2
|
||||
static tvi_handle_t *tvi_init_v4l2(struct mp_log *log, tv_param_t* tv_param);
|
||||
/* information about this file */
|
||||
@@ -112,8 +117,10 @@ typedef struct priv {
|
||||
struct map *map;
|
||||
int mapcount;
|
||||
int frames;
|
||||
volatile long long first_frame;
|
||||
long long curr_frame;
|
||||
volatile long long first_frame; ///< number of useconds
|
||||
long long curr_frame; ///< usec, using kernel timestamps
|
||||
int clk_id; /**< clk_id from clock_gettime
|
||||
used in frame timestamps */
|
||||
/* audio video interleaving ;-) */
|
||||
volatile int streamon;
|
||||
pthread_t audio_grabber_thread;
|
||||
@@ -500,6 +507,30 @@ static int getstd(priv_t *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAVE_CLOCK_GETTIME
|
||||
/*
|
||||
** Gets current timestamp, using specified clock id.
|
||||
** @return number of microseconds.
|
||||
*/
|
||||
static long long get_curr_timestamp(int clk_id)
|
||||
{
|
||||
struct timespec ts;
|
||||
clock_gettime(clk_id, &ts);
|
||||
return (long long)ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
|
||||
}
|
||||
#else
|
||||
/*
|
||||
** Gets current timestamp, using system time.
|
||||
** @return number of microseconds.
|
||||
*/
|
||||
static long long get_curr_timestamp(int clk_id)
|
||||
{
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
return (long long)tv.tv_sec * 1000000 + tv.tv_usec;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************************\
|
||||
* *
|
||||
* *
|
||||
@@ -1230,13 +1261,6 @@ static int get_capture_buffer_size(priv_t *priv)
|
||||
if (priv->tv_param->buffer_size >= 0) {
|
||||
bufsize = priv->tv_param->buffer_size*1024*1024;
|
||||
} else {
|
||||
#if HAVE_SYS_SYSINFO_H
|
||||
struct sysinfo si;
|
||||
|
||||
sysinfo(&si);
|
||||
bufsize = (si.freeram/2)*si.mem_unit;
|
||||
if ( bufsize < 16*1024*1024)
|
||||
#endif
|
||||
bufsize = 16*1024*1024;
|
||||
}
|
||||
|
||||
@@ -1378,6 +1402,13 @@ static int start(priv_t *priv)
|
||||
return 0;
|
||||
}
|
||||
priv->map[i].len = priv->map[i].buf.length;
|
||||
#ifdef HAVE_CLOCK_GETTIME
|
||||
priv->clk_id = (priv->map[i].buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
|
||||
? CLOCK_MONOTONIC : CLOCK_REALTIME;
|
||||
#else
|
||||
if (priv->map[i].buf.flags & V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC)
|
||||
mp_msg(MSGT_TV, MSGL_WARN, "MPlayer compiled without clock_gettime() that is needed to handle monotone video timestamps from the kernel. Expect desync.\n");
|
||||
#endif
|
||||
/* count up to make sure this is correct everytime */
|
||||
priv->mapcount++;
|
||||
|
||||
@@ -1653,13 +1684,11 @@ static int get_video_framesize(priv_t *priv)
|
||||
static void *audio_grabber(void *data)
|
||||
{
|
||||
priv_t *priv = (priv_t*)data;
|
||||
struct timeval tv;
|
||||
int i, audio_skew_ptr = 0;
|
||||
long long current_time, prev_skew = 0, prev_skew_uncorr = 0;
|
||||
long long start_time_avg;
|
||||
long long start_time_avg, curr_timestamp;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
|
||||
start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id);
|
||||
audio_in_start_capture(&priv->audio_in);
|
||||
for (i = 0; i < priv->aud_skew_cnt; i++)
|
||||
priv->audio_skew_buffer[i] = 0;
|
||||
@@ -1673,21 +1702,19 @@ static void *audio_grabber(void *data)
|
||||
pthread_mutex_lock(&priv->skew_mutex);
|
||||
if (priv->first_frame == 0) {
|
||||
// there is no first frame yet (unlikely to happen)
|
||||
gettimeofday(&tv, NULL);
|
||||
start_time_avg = priv->audio_start_time = (long long)1e6*tv.tv_sec + tv.tv_usec;
|
||||
start_time_avg = priv->audio_start_time = get_curr_timestamp(priv->clk_id);
|
||||
// fprintf(stderr, "warning - first frame not yet available!\n");
|
||||
pthread_mutex_unlock(&priv->skew_mutex);
|
||||
continue;
|
||||
}
|
||||
pthread_mutex_unlock(&priv->skew_mutex);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
priv->audio_recv_blocks_total++;
|
||||
current_time = (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_start_time;
|
||||
curr_timestamp = get_curr_timestamp(priv->clk_id);
|
||||
current_time = curr_timestamp - priv->audio_start_time;
|
||||
|
||||
if (priv->audio_recv_blocks_total < priv->aud_skew_cnt*2) {
|
||||
start_time_avg += (long long)1e6*tv.tv_sec + tv.tv_usec - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
|
||||
start_time_avg += curr_timestamp - priv->audio_usecs_per_block*priv->audio_recv_blocks_total;
|
||||
priv->audio_start_time = start_time_avg/(priv->audio_recv_blocks_total+1);
|
||||
}
|
||||
|
||||
|
||||
+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)
|
||||
|
||||
+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);
|
||||
}
|
||||
}
|
||||
@@ -290,6 +290,14 @@ struct mp_image *video_decode(struct dec_video *d_video,
|
||||
bool sort_pts =
|
||||
(opts->user_pts_assoc_mode != 1 || d_video->header->video->avi_dts)
|
||||
&& opts->correct_pts;
|
||||
|
||||
struct demux_packet packet_copy;
|
||||
if (packet && packet->dts == MP_NOPTS_VALUE) {
|
||||
packet_copy = *packet;
|
||||
packet = &packet_copy;
|
||||
packet->dts = packet->pts;
|
||||
}
|
||||
|
||||
double pkt_pts = packet ? packet->pts : MP_NOPTS_VALUE;
|
||||
double pkt_dts = packet ? packet->dts : MP_NOPTS_VALUE;
|
||||
|
||||
@@ -323,7 +331,7 @@ struct mp_image *video_decode(struct dec_video *d_video,
|
||||
|
||||
if (pts == MP_NOPTS_VALUE) {
|
||||
d_video->codec_pts = prev_codec_pts;
|
||||
} else if (pts <= prev_codec_pts) {
|
||||
} else if (pts < prev_codec_pts) {
|
||||
d_video->num_codec_pts_problems++;
|
||||
}
|
||||
|
||||
|
||||
@@ -334,11 +334,12 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int format,
|
||||
|
||||
static void destroy_va_dummy_ctx(struct priv *p)
|
||||
{
|
||||
va_destroy(p->ctx);
|
||||
p->ctx = NULL;
|
||||
p->display = NULL;
|
||||
if (p->x11_display)
|
||||
XCloseDisplay(p->x11_display);
|
||||
p->x11_display = NULL;
|
||||
va_destroy(p->ctx);
|
||||
p->ctx = NULL;
|
||||
}
|
||||
|
||||
// Creates a "private" VADisplay, disconnected from the VO. We just create a
|
||||
@@ -372,6 +373,7 @@ static void uninit(struct lavc_ctx *ctx)
|
||||
|
||||
destroy_decoder(ctx);
|
||||
va_surface_pool_release(p->pool);
|
||||
p->pool = NULL;
|
||||
|
||||
if (p->x11_display)
|
||||
destroy_va_dummy_ctx(p);
|
||||
|
||||
@@ -502,7 +502,7 @@ void mpgl_load_functions(GL *gl, void *(*getProcAddress)(const GLubyte *),
|
||||
if (!gl->GetString)
|
||||
gl->GetString = glGetString;
|
||||
|
||||
GLint major = 0, minor = 0;
|
||||
int major = 0, minor = 0;
|
||||
const char *version = gl->GetString(GL_VERSION);
|
||||
sscanf(version, "%d.%d", &major, &minor);
|
||||
gl->version = MPGL_VER(major, minor);
|
||||
|
||||
@@ -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
|
||||
|
||||
+9
-10
@@ -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;
|
||||
@@ -577,16 +571,17 @@ static int preinit(struct vo *vo)
|
||||
VAStatus status;
|
||||
|
||||
if (!vo_x11_init(vo))
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
p->display = vaGetDisplay(vo->x11->display);
|
||||
if (!p->display)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
p->mpvaapi = va_initialize(p->display, p->log);
|
||||
if (!p->mpvaapi) {
|
||||
vaTerminate(p->display);
|
||||
return -1;
|
||||
p->display = NULL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
p->pool = va_surface_pool_alloc(p->mpvaapi, VA_RT_FORMAT_YUV420);
|
||||
@@ -636,6 +631,10 @@ static int preinit(struct vo *vo)
|
||||
p->va_num_display_attrs = 0;
|
||||
}
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
uninit(vo);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define OPT_BASE_STRUCT struct priv
|
||||
|
||||
@@ -655,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");
|
||||
@@ -663,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);
|
||||
|
||||
+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]);
|
||||
|
||||
+14
-14
@@ -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);
|
||||
|
||||
@@ -126,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,
|
||||
@@ -529,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;
|
||||
@@ -778,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)
|
||||
@@ -814,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -941,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:
|
||||
@@ -979,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);
|
||||
}
|
||||
|
||||
@@ -668,7 +668,7 @@ static void vo_x11_classhint(struct vo *vo, Window window, const char *name)
|
||||
struct mp_vo_opts *opts = vo->opts;
|
||||
struct vo_x11_state *x11 = vo->x11;
|
||||
XClassHint wmClass;
|
||||
pid_t pid = getpid();
|
||||
long pid = getpid();
|
||||
|
||||
wmClass.res_name = opts->winname ? opts->winname : (char *)name;
|
||||
wmClass.res_class = "mpv";
|
||||
@@ -680,7 +680,8 @@ static void vo_x11_classhint(struct vo *vo, Window window, const char *name)
|
||||
void vo_x11_uninit(struct vo *vo)
|
||||
{
|
||||
struct vo_x11_state *x11 = vo->x11;
|
||||
assert(x11);
|
||||
if (!x11)
|
||||
return;
|
||||
|
||||
mp_input_put_key(vo->input_ctx, MP_INPUT_RELEASE_ALL);
|
||||
|
||||
@@ -1054,9 +1055,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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -4,9 +4,11 @@ def __get_version__(ctx):
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
cwd=ctx.srcnode.abspath())
|
||||
process.wait()
|
||||
(version, err) = process.communicate()
|
||||
return version.strip().decode('utf-8').encode('ascii', 'ignore')
|
||||
version = version.strip()
|
||||
if not isinstance(version, str):
|
||||
version = version.decode('utf-8')
|
||||
return version
|
||||
|
||||
def __get_build_date__():
|
||||
import time
|
||||
|
||||
@@ -187,11 +187,6 @@ iconv support use --disable-iconv.",
|
||||
'name': 'setmode',
|
||||
'desc': 'setmode()',
|
||||
'func': check_statement('io.h', 'setmode(0, 0)')
|
||||
}, {
|
||||
'name': 'sys-sysinfo-h',
|
||||
'desc': 'sys/sysinfo.h',
|
||||
'func': check_statement('sys/sysinfo.h',
|
||||
'struct sysinfo s_info; s_info.mem_unit=0; sysinfo(&s_info)')
|
||||
}, {
|
||||
'name': '--libguess',
|
||||
'desc': 'libguess support',
|
||||
@@ -716,6 +711,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 +814,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':
|
||||
|
||||
Reference in new issue
Block a user