From 7d116a979b9ab8401bc8d12f520cee03102879ab Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 6 Apr 2015 20:34:46 +0200 Subject: screenshots: select best image format the encoder supports This matters for png screenshots. We used to hardcode rgb24, but libavformat's png encoder can do much more. Use the image format list provided by the encoder, and select the best format from it (according to the source format). As a consequence, rgb48 (i.e. 16 bit per component) will be selected if the source format is e.g. 10 bit yuv. This happens in accordance to FFmpeg's avcodec_find_best_pix_fmt_of_list() function, which assumes that 16 bit rgb should be preferred for 10 bit yuv. This also causes it to print this message in this case: [ffmpeg] swscaler: full chroma interpolation for destination format 'rgb48be' not yet implemented I'm not 100% sure whether this is a problem. --- video/image_writer.c | 58 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/video/image_writer.c b/video/image_writer.c index ab00b5bb01..939b435787 100644 --- a/video/image_writer.c +++ b/video/image_writer.c @@ -221,22 +221,42 @@ static int write_jpeg(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp) #endif +static int get_target_format(struct image_writer_ctx *ctx, int srcfmt) +{ + if (!ctx->writer->lavc_codec) + goto unknown; + + struct AVCodec *codec = avcodec_find_encoder(ctx->writer->lavc_codec); + if (!codec) + goto unknown; + + const enum AVPixelFormat *pix_fmts = codec->pix_fmts; + if (!pix_fmts) + goto unknown; + + int current = 0; + for (int n = 0; pix_fmts[n] != AV_PIX_FMT_NONE; n++) { + int fmt = pixfmt2imgfmt(pix_fmts[n]); + if (!fmt) + continue; + current = current ? mp_imgfmt_select_best(current, fmt, srcfmt) : fmt; + } + + if (!current) + goto unknown; + + return current; + +unknown: + return IMGFMT_RGB24; +} + static const struct img_writer img_writers[] = { { "png", write_lavc, .lavc_codec = AV_CODEC_ID_PNG }, { "ppm", write_lavc, .lavc_codec = AV_CODEC_ID_PPM }, - { "pgm", write_lavc, - .lavc_codec = AV_CODEC_ID_PGM, - .pixfmts = (const int[]) { IMGFMT_Y8, 0 }, - }, - { "pgmyuv", write_lavc, - .lavc_codec = AV_CODEC_ID_PGMYUV, - .pixfmts = (const int[]) { IMGFMT_420P, 0 }, - }, - { "tga", write_lavc, - .lavc_codec = AV_CODEC_ID_TARGA, - .pixfmts = (const int[]) { IMGFMT_BGR24, IMGFMT_BGRA, IMGFMT_RGB555, - IMGFMT_Y8, 0}, - }, + { "pgm", write_lavc, .lavc_codec = AV_CODEC_ID_PGM }, + { "pgmyuv", write_lavc, .lavc_codec = AV_CODEC_ID_PGMYUV }, + { "tga", write_lavc, .lavc_codec = AV_CODEC_ID_TARGA }, #if HAVE_JPEG { "jpg", write_jpeg }, { "jpeg", write_jpeg }, @@ -280,17 +300,7 @@ int write_image(struct mp_image *image, const struct image_writer_opts *opts, const struct img_writer *writer = get_writer(opts); struct image_writer_ctx ctx = { log, opts, writer }; - int destfmt = IMGFMT_RGB24; - - if (writer->pixfmts) { - destfmt = writer->pixfmts[0]; // default to first pixel format - for (const int *fmt = writer->pixfmts; *fmt; fmt++) { - if (*fmt == image->imgfmt) { - destfmt = *fmt; - break; - } - } - } + int destfmt = get_target_format(&ctx, image->imgfmt); // Caveat: no colorspace/levels conversion done if pixel formats equal // it's unclear what colorspace/levels the target wants -- cgit v1.2.3 From edef17fcb7c454ca4cf7a1d8d2a6c0973fa291dd Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 10:16:31 +0200 Subject: manpage: remove confusing statement There still might be FFmpeg demuxers which mess up if audio is disabled (like it happened to the FLV demuxer), but these are bugs and shouldn't happen. --- DOCS/man/options.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index e86bb812d1..b380db9ffb 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -887,8 +887,7 @@ Audio delay the audio, and negative values delay the video. ``--no-audio`` - Do not play sound. With some demuxers this may not work. In those cases - you can try ``--ao=null`` instead. + Do not play sound. ``--mute=`` Set startup audio mute status. ``auto`` (default) will not change the mute -- cgit v1.2.3 From f316f1ec16fa32c055d8d96613d466d01436fe87 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 10:17:54 +0200 Subject: screenshot: use GPU readback only for hardware decoded images Avoids a confusing message printed by the vdpau code when taking a screenshot while using software decoding (because obviously GPU readback won't work on normal in-memory video frames). --- player/screenshot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player/screenshot.c b/player/screenshot.c index 27ef468544..4e80934494 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -349,7 +349,7 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode) if (image && mpctx->d_video && mpctx->d_video->hwdec_info) { struct mp_hwdec_ctx *ctx = mpctx->d_video->hwdec_info->hwctx; struct mp_image *nimage = NULL; - if (ctx && ctx->download_image) + if (ctx && ctx->download_image && (image->fmt.flags & MP_IMGFLAG_HWACCEL)) nimage = ctx->download_image(ctx, image, NULL); if (nimage) { talloc_free(image); -- cgit v1.2.3 From efae88e5212372513bdad6c335050fe50d28c22d Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 10:18:48 +0200 Subject: vdpau: don't use a transparent image format for screenshots Fixes #1779. --- video/vdpau.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/vdpau.c b/video/vdpau.c index 4ff3d6905a..2fd75a2970 100644 --- a/video/vdpau.c +++ b/video/vdpau.c @@ -70,7 +70,7 @@ static struct mp_image *download_image(struct mp_hwdec_ctx *hwctx, mpi, &in) < 0) goto error; - res = mp_image_pool_get(swpool, IMGFMT_BGR32, ctx->getimg_w, ctx->getimg_h); + res = mp_image_pool_get(swpool, IMGFMT_BGR0, ctx->getimg_w, ctx->getimg_h); if (!res) goto error; -- cgit v1.2.3 From f6b2325c2a4c3ede7fc9cfe9bf32e5c09f5a115e Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 11:43:03 +0200 Subject: video/out: fix screenshot image formats Use variants without alpha. I skipped vo_sdl, because format selection seems a bit more complicated here, and nobody cares about vo_sdl anymore. --- video/out/vo_direct3d.c | 2 +- video/out/vo_rpi.c | 2 +- video/out/vo_vdpau.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/video/out/vo_direct3d.c b/video/out/vo_direct3d.c index ac72efe2f8..b9e1b92326 100644 --- a/video/out/vo_direct3d.c +++ b/video/out/vo_direct3d.c @@ -1517,7 +1517,7 @@ static mp_image_t *get_window_screenshot(d3d_priv *priv) if (width < 1 || height < 1) goto error_exit; - image = mp_image_alloc(IMGFMT_BGR32, width, height); + image = mp_image_alloc(IMGFMT_BGR0, width, height); if (!image) goto error_exit; diff --git a/video/out/vo_rpi.c b/video/out/vo_rpi.c index e197477987..48827b8a67 100644 --- a/video/out/vo_rpi.c +++ b/video/out/vo_rpi.c @@ -421,7 +421,7 @@ static struct mp_image *take_screenshot(struct vo *vo) { struct priv *p = vo->priv; - struct mp_image *img = mp_image_alloc(IMGFMT_BGRA, p->w, p->h); + struct mp_image *img = mp_image_alloc(IMGFMT_BGR0, p->w, p->h); if (!img) return NULL; diff --git a/video/out/vo_vdpau.c b/video/out/vo_vdpau.c index c0deea8178..f482b83236 100644 --- a/video/out/vo_vdpau.c +++ b/video/out/vo_vdpau.c @@ -831,7 +831,7 @@ static struct mp_image *read_output_surface(struct vo *vo, if (!vo->params) return NULL; - struct mp_image *image = mp_image_alloc(IMGFMT_BGR32, width, height); + struct mp_image *image = mp_image_alloc(IMGFMT_BGR0, width, height); if (!image) return NULL; -- cgit v1.2.3 From c7a6b94d63aa4877906d29021ed29aeb2b07fb42 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 11:46:02 +0200 Subject: travis: re-enable OSX Let's see if it works better now. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 31a5492e17..dab4b6d631 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: c os: - linux -# - osx + - osx env: matrix: - LIBAV=libav-stable -- cgit v1.2.3 From 5574820f13e6402b2377281886b23800c7eb9655 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 12:02:33 +0200 Subject: ao_coreaudio: do not error if retrieving info for verbose mode fails The message log level shouldn't get to decide whether something fails or not. So replace the fatal error check on the verbose output code path with a warning. --- audio/out/ao_coreaudio_utils.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index 64d98e5ece..8485011722 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -117,12 +117,12 @@ OSStatus ca_select_device(struct ao *ao, char* name, AudioDeviceID *device) if (mp_msg_test(ao->log, MSGL_V)) { char *desc; err = CA_GET_STR(*device, kAudioObjectPropertyName, &desc); - CHECK_CA_ERROR("could not get selected audio device name"); - - MP_VERBOSE(ao, "selected audio output device: %s (%" PRIu32 ")\n", - desc, *device); - - talloc_free(desc); + CHECK_CA_WARN("could not get selected audio device name"); + if (err == noErr) { + MP_VERBOSE(ao, "selected audio output device: %s (%" PRIu32 ")\n", + desc, *device); + talloc_free(desc); + } } coreaudio_error: -- cgit v1.2.3 From d857b5f5ab24bd9261148d6c00a4add3d0970063 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 13:38:03 +0200 Subject: audio: avoid one more redundant audio filter reinit Only reinit filters if it's actually needed. This is also slightly easier to understand: if you look at the code, it should now be more obvious why a reinit is needed (hopefully). --- player/audio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/player/audio.c b/player/audio.c index ba692e3955..f4c69803a4 100644 --- a/player/audio.c +++ b/player/audio.c @@ -260,8 +260,6 @@ void reinit_audio_chain(struct MPContext *mpctx) } if (!mpctx->ao) { - afs->initialized = 0; // do it again - mp_chmap_remove_useless_channels(&afs->output.channels, &opts->audio_output_channels); mp_audio_set_channels(&afs->output, &afs->output.channels); @@ -281,6 +279,8 @@ void reinit_audio_chain(struct MPContext *mpctx) mp_audio_buffer_reinit(mpctx->ao_buffer, &fmt); afs->output = fmt; + if (!mp_audio_config_equals(&afs->output, &afs->filter_output)) + afs->initialized = 0; mpctx->ao_decoder_fmt = talloc(NULL, struct mp_audio); *mpctx->ao_decoder_fmt = in_format; -- cgit v1.2.3 From e98ab5e596b003b68e44e8c94b5e393e52ed6b6b Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 18:05:09 +0200 Subject: ao_alsa: change log output Silence the usually user-visible warning about unsupported channel maps. This might be an ALSA bug, but ALSA will never fix this behavior anyway. (Or maybe it's a feature.) Log some other information that might be useful. --- audio/out/ao_alsa.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index f84a781e8a..b60c8363f1 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -376,6 +376,7 @@ static int try_open_device(struct ao *ao, const char *device) IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, map_iec958_srate(ao->samplerate)); const char *ac3_device = append_params(tmp, device, params); + MP_VERBOSE(ao, "opening device '%s' => '%s'\n", device, ac3_device); int err = snd_pcm_open (&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, 0); talloc_free(tmp); @@ -383,6 +384,7 @@ static int try_open_device(struct ao *ao, const char *device) return 0; } + MP_VERBOSE(ao, "opening device '%s'\n", device); return snd_pcm_open(&p->alsa, device, SND_PCM_STREAM_PLAYBACK, 0); } @@ -408,23 +410,14 @@ static int init_device(struct ao *ao) struct priv *p = ao->priv; int err; - if (!p->cfg_ni) - ao->format = af_fmt_from_planar(ao->format); - const char *device = "default"; - if (AF_FORMAT_IS_IEC61937(ao->format)) { + if (AF_FORMAT_IS_IEC61937(ao->format)) device = "iec958"; - MP_VERBOSE(ao, "playing AC3/iec61937/iec958, %i channels\n", - ao->channels.num); - } if (ao->device) device = ao->device; if (p->cfg_device && p->cfg_device[0]) device = p->cfg_device; - MP_VERBOSE(ao, "using device: %s\n", device); - MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version()); - err = try_open_device(ao, device); CHECK_ALSA_ERROR("Playback open error"); @@ -551,8 +544,11 @@ static int init_device(struct ao *ao) err = snd_pcm_set_chmap(p->alsa, alsa_chmap); if (err == -ENXIO) { - MP_WARN(ao, "Device does not support requested channel map (%s)\n", - mp_chmap_to_str(&dev_chmap)); + // I consider this an ALSA bug: the channel map was reported as + // supported, but we still can't set it. It happens virtually + // always with dmix, though. + MP_VERBOSE(ao, "Device does not support requested channel map (%s)\n", + mp_chmap_to_str(&dev_chmap)); } else { CHECK_ALSA_WARN("Channel map setup failed"); } @@ -607,6 +603,7 @@ static int init_device(struct ao *ao) // the number of channels to 2 either, because the hw params // are already set! So just fuck it and reopen the device with // the chmap "cleaned out" of NA entries. + MP_VERBOSE(ao, "Working around braindead ALSA behavior.\n"); err = snd_pcm_close(p->alsa); p->alsa = NULL; CHECK_ALSA_ERROR("pcm close error"); @@ -678,6 +675,12 @@ alsa_error: static int init(struct ao *ao) { + struct priv *p = ao->priv; + if (!p->cfg_ni) + ao->format = af_fmt_from_planar(ao->format); + + MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version()); + int r = init_device(ao); if (r == INIT_BRAINDEATH) r = init_device(ao); // retry with normalized channel layout -- cgit v1.2.3 From 579c4dac34546357a5fd1dfd67712df6a5930bf6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 21:23:23 +0200 Subject: audio: change a detail about filter insertion The af_add() function has a problem: if the inserted filter returns AF_DETACH during init, the function will have a dangling pointer. Until now this was avoided by making sure none of the used filters actually return AF_DETACH, but it's getting infeasible. Solve this by requiring passing an unique label to af_add(), which is then used instead of the pointer. --- audio/filter/af.c | 17 ++++++++++------- audio/filter/af.h | 3 ++- audio/mixer.c | 4 ++-- player/audio.c | 19 +------------------ 4 files changed, 15 insertions(+), 28 deletions(-) diff --git a/audio/filter/af.c b/audio/filter/af.c index 2889e87bb7..48f6d58868 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -689,8 +689,14 @@ int af_init(struct af_stream *s) to the stream s. The filter will be inserted somewhere nice in the list of filters. The return value is a pointer to the new filter, If the filter couldn't be added the return value is NULL. */ -struct af_instance *af_add(struct af_stream *s, char *name, char **args) +struct af_instance *af_add(struct af_stream *s, char *name, char *label, + char **args) { + assert(label); + + if (af_find_by_label(s, label)) + return NULL; + struct af_instance *new; // Insert the filter somewhere nice if (af_is_conversion_filter(s->first->next)) @@ -699,17 +705,14 @@ struct af_instance *af_add(struct af_stream *s, char *name, char **args) new = af_prepend(s, s->first->next, name, args); if (!new) return NULL; + new->label = talloc_strdup(new, label); // Reinitalize the filter list if (af_reinit(s) != AF_OK) { - af_remove(s, new); - if (af_reinit(s) != AF_OK) { - af_uninit(s); - af_init(s); - } + af_remove_by_label(s, label); return NULL; } - return new; + return af_find_by_label(s, label); } struct af_instance *af_find_by_label(struct af_stream *s, char *label) diff --git a/audio/filter/af.h b/audio/filter/af.h index 4c67208123..65a30f7dd1 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -141,7 +141,8 @@ struct af_stream *af_new(struct mpv_global *global); void af_destroy(struct af_stream *s); int af_init(struct af_stream *s); void af_uninit(struct af_stream *s); -struct af_instance *af_add(struct af_stream *s, char *name, char **args); +struct af_instance *af_add(struct af_stream *s, char *name, char *label, + char **args); int af_remove_by_label(struct af_stream *s, char *label); struct af_instance *af_find_by_label(struct af_stream *s, char *label); struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg); diff --git a/audio/mixer.c b/audio/mixer.c index 0eb9c86453..7ae7ed458d 100644 --- a/audio/mixer.c +++ b/audio/mixer.c @@ -135,7 +135,7 @@ static void setvolume_internal(struct mixer *mixer, float l, float r) if (gain == 1.0) return; MP_VERBOSE(mixer, "Inserting volume filter.\n"); - if (!(af_add(mixer->af, "volume", NULL) + if (!(af_add(mixer->af, "volume", "softvol", NULL) && af_control_any_rev(mixer->af, AF_CONTROL_SET_VOLUME, &gain))) MP_ERR(mixer, "No volume control available.\n"); } @@ -222,7 +222,7 @@ void mixer_setbalance(struct mixer *mixer, float val) if (val == 0) return; - if (!(af_pan_balance = af_add(mixer->af, "pan", NULL))) { + if (!(af_pan_balance = af_add(mixer->af, "pan", "autopan", NULL))) { MP_ERR(mixer, "No balance control available.\n"); return; } diff --git a/player/audio.c b/player/audio.c index f4c69803a4..6f91f8ee32 100644 --- a/player/audio.c +++ b/player/audio.c @@ -43,23 +43,6 @@ #include "core.h" #include "command.h" -static int try_filter(struct MPContext *mpctx, - char *name, char *label, char **args) -{ - struct dec_audio *d_audio = mpctx->d_audio; - - if (af_find_by_label(d_audio->afilter, label)) - return 0; - - struct af_instance *af = af_add(d_audio->afilter, name, args); - if (!af) - return -1; - - af->label = talloc_strdup(af, label); - - return 1; -} - static int update_playback_speed_filters(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; @@ -90,7 +73,7 @@ static int update_playback_speed_filters(struct MPContext *mpctx) char *filter = method == AF_CONTROL_SET_PLAYBACK_SPEED ? "scaletempo" : "lavrresample"; - if (try_filter(mpctx, filter, "playback-speed", NULL) < 0) + if (af_add(afs, filter, "playback-speed", NULL) < 0) return -1; // Try again. if (!af_control_any_rev(afs, method, &speed)) -- cgit v1.2.3 From 36ae8a6cab69f849b3e78ddf6840e5f95c86c659 Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 7 Apr 2015 21:38:39 +0200 Subject: audio: automatically deatch filters if spdif prevents their use Fixes #1743 and partially #1780. --- audio/filter/af.c | 17 +++++++++++++++++ audio/filter/af_scaletempo.c | 5 ----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/audio/filter/af.c b/audio/filter/af.c index 48f6d58868..8d29e332a8 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -561,6 +561,23 @@ static int af_reinit(struct af_stream *s) retry++; continue; } + // If the format conversion is (probably) caused by spdif, then + // (as a feature) drop the filter, instead of failing hard. + int fmt_in1 = af->prev->data->format; + int fmt_in2 = in.format; + if (af_fmt_is_valid(fmt_in1) && af_fmt_is_valid(fmt_in2)) { + bool spd1 = AF_FORMAT_IS_IEC61937(fmt_in1); + bool spd2 = AF_FORMAT_IS_IEC61937(fmt_in2); + if (spd1 != spd2) { + MP_WARN(af, "Filter %s apparently cannot be used due to " + "spdif passthrough - removing it.\n", + af->info->name); + struct af_instance *aft = af->prev; + af_remove(s, af); + af = aft->next; + break; + } + } goto negotiate_error; } case AF_DETACH: { // Filter is redundant and wants to be unloaded diff --git a/audio/filter/af_scaletempo.c b/audio/filter/af_scaletempo.c index 1f187a98bc..ad8e520601 100644 --- a/audio/filter/af_scaletempo.c +++ b/audio/filter/af_scaletempo.c @@ -303,11 +303,6 @@ static int control(struct af_instance *af, int cmd, void *arg) int nch = data->nch; int use_int = 0; - if (AF_FORMAT_IS_SPECIAL(data->format)) { - MP_ERR(af, "Changing speed is not supported with spdif formats.\n"); - return AF_ERROR; - } - mp_audio_force_interleaved_format(data); mp_audio_copy_config(af->data, data); -- cgit v1.2.3 From 26909c1113ab86801ca3e1f8097f7ed0e06d35d4 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 8 Apr 2015 21:21:44 +0200 Subject: manpage: lua: clarify timer usage This seems to come up often. I guess '.' vs. ':' for Lua calls is confusing, and this part of the scripting API is the only one which requires using it. --- DOCS/man/lua.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst index d8912dac2b..4700b90cb2 100644 --- a/DOCS/man/lua.rst +++ b/DOCS/man/lua.rst @@ -356,6 +356,23 @@ The ``mp`` module is preloaded, although it can be loaded manually with (``true``). This value is used when the timer expires (but before the timer callback function fn is run). + Note that these are method, and you have to call them using ``:`` instead + of ``.`` (Refer to http://www.lua.org/manual/5.2/manual.html#3.4.9 .) + + Example: + + :: + + seconds = 0 + timer = mp.add_periodic_timer(1, function() + print("called every second") + # stop it after 10 seconds + seconds = seconds + 1 + if seconds >= 10 then + timer:kill() + end + end) + ``mp.get_opt(key)`` Return a setting from the ``--script-opts`` option. It's up to the user and -- cgit v1.2.3 From 78fe1d3a2c9cb1c5562cefc1c22a305754c21871 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 8 Apr 2015 22:18:20 +0200 Subject: sub: unprefer libavcodec's MicroDVD converter Prefer the builtin one again. libavcodec still uses the ASS packet format that uses inline timestamps, so the packet timestamps are ignored. This again leads to additional rounding of timestamps, because the ASS storage format only has 10ms resolution (instead of 1ms resolution like libass). This again can lead to unintentional overlaps when converting subtitles. The internal MicroDVD converter avoids this, because it always uses packet timestamps. --- sub/dec_sub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sub/dec_sub.c b/sub/dec_sub.c index 0a26e6f6a5..c08e5a0fa2 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -49,8 +49,8 @@ static const struct sd_functions *const sd_list[] = { &sd_movtext, &sd_srt, &sd_lavf_srt, - &sd_lavc_conv, &sd_microdvd, + &sd_lavc_conv, NULL }; -- cgit v1.2.3 From 7a65c44922d5be4a67be4e4c3f4fd47cb06c5e00 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 8 Apr 2015 22:19:51 +0200 Subject: sub: don't truncate timestamps to int Realistically probably no problem at all since they're in ms and usually start from 0, but whatever. --- sub/dec_sub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sub/dec_sub.c b/sub/dec_sub.c index c08e5a0fa2..eb96131be7 100644 --- a/sub/dec_sub.c +++ b/sub/dec_sub.c @@ -344,7 +344,7 @@ static void multiply_timings(struct packet_list *subs, double factor) } } -#define MS_TS(f_ts) ((int)((f_ts) * 1000 + 0.5)) +#define MS_TS(f_ts) ((long long)((f_ts) * 1000 + 0.5)) // Remove overlaps and fill gaps between adjacent subtitle packets. This is done // by adjusting the duration of the earlier packet. If the gaps or overlap are -- cgit v1.2.3