static int handle_preemption(struct mp_vdpau_ctx *ctx) { if (!ctx->is_preempted) return 0; mark_vdpau_objects_uninitialized(ctx); if (!ctx->preemption_user_notified) { MP_ERR(ctx, "Got display preemption notice! Will attempt to recover.\n"); ctx->preemption_user_notified = true; } /* Trying to initialize seems to be quite slow, so only try once a * second to avoid using 100% CPU. */ if (ctx->last_preemption_retry_fail && mp_time_sec() - ctx->last_preemption_retry_fail < 1.0) return -1; if (win_x11_init_vdpau_procs(ctx) < 0) { ctx->last_preemption_retry_fail = mp_time_sec(); return -1; } ctx->preemption_user_notified = false; ctx->last_preemption_retry_fail = 0; ctx->is_preempted = false; ctx->preemption_counter++; MP_INFO(ctx, "Recovered from display preemption.\n"); return 1; }
static void *cache_thread(void *arg) { struct priv *s = arg; mpthread_set_name("cache"); pthread_mutex_lock(&s->mutex); update_cached_controls(s); double last = mp_time_sec(); while (s->control != CACHE_CTRL_QUIT) { if (mp_time_sec() - last > CACHE_UPDATE_CONTROLS_TIME) { update_cached_controls(s); last = mp_time_sec(); } if (s->control > 0) { cache_execute_control(s); } else { cache_fill(s); } if (s->control == CACHE_CTRL_PING) { pthread_cond_signal(&s->wakeup); s->control = CACHE_CTRL_NONE; } if (s->idle && s->control == CACHE_CTRL_NONE) { struct timespec ts = mp_rel_time_to_timespec(CACHE_IDLE_SLEEP_TIME); pthread_cond_timedwait(&s->wakeup, &s->mutex, &ts); } } pthread_cond_signal(&s->wakeup); pthread_mutex_unlock(&s->mutex); MP_VERBOSE(s, "Cache exiting...\n"); return NULL; }
static void *cache_thread(void *arg) { struct priv *s = arg; pthread_mutex_lock(&s->mutex); update_cached_controls(s); double last = mp_time_sec(); while (s->control != CACHE_CTRL_QUIT) { if (mp_time_sec() - last > CACHE_UPDATE_CONTROLS_TIME) { update_cached_controls(s); last = mp_time_sec(); } if (s->control > 0) { cache_execute_control(s); } else { cache_fill(s); } if (s->control == CACHE_CTRL_PING) { pthread_cond_signal(&s->wakeup); s->control = CACHE_CTRL_NONE; } if (s->idle && s->control == CACHE_CTRL_NONE) mpthread_cond_timed_wait(&s->wakeup, &s->mutex, CACHE_IDLE_SLEEP_TIME); } pthread_cond_signal(&s->wakeup); pthread_mutex_unlock(&s->mutex); mp_msg(MSGT_CACHE, MSGL_V, "Cache exiting...\n"); return NULL; }
// Used by the main thread to wakeup the cache thread, and to wait for the // cache thread. The cache mutex has to be locked when calling this function. // *retry_time should be set to 0 on the first call. // Returns CACHE_INTERRUPTED if the caller is supposed to abort. static int cache_wakeup_and_wait(struct priv *s, double *retry_time) { if (stream_check_interrupt(s->cache)) return CACHE_INTERRUPTED; 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_timedwait_rel(&s->wakeup, &s->mutex, CACHE_WAIT_TIME); *retry_time += mp_time_sec() - start; return 0; }
// Used by the main thread to wakeup the cache thread, and to wait for the // cache thread. The cache mutex has to be locked when calling this function. // *retry_time should be set to 0 on the first call. static void cache_wakeup_and_wait(struct priv *s, double *retry_time) { double start = mp_time_sec(); if (*retry_time >= CACHE_WAIT_TIME) { MP_WARN(s, "Cache is not responding - slow/stuck network connection?\n"); *retry_time = -1; // do not warn again for this call } pthread_cond_signal(&s->wakeup); struct timespec ts = mp_rel_time_to_timespec(CACHE_WAIT_TIME); pthread_cond_timedwait(&s->wakeup, &s->mutex, &ts); if (*retry_time >= 0) *retry_time += mp_time_sec() - start; }
static int init(struct ao *ao) { struct priv *priv = ao->priv; ao->untimed = priv->untimed; struct mp_chmap_sel sel = {.tmp = ao}; if (priv->channel_layouts) { for (int n = 0; priv->channel_layouts[n]; n++) { struct mp_chmap map = {0}; if (!mp_chmap_from_str(&map, bstr0(priv->channel_layouts[n]))) { MP_FATAL(ao, "Invalid channel map in option.\n"); return -1; } mp_chmap_sel_add_map(&sel, &map); } } else { mp_chmap_sel_add_any(&sel); } if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) mp_chmap_from_channels(&ao->channels, 2); priv->latency = priv->latency_sec * ao->samplerate; // A "buffer" for this many seconds of audio int bursts = (int)(ao->samplerate * priv->bufferlen + 1) / priv->outburst; priv->buffersize = priv->outburst * bursts + priv->latency; priv->last_time = mp_time_sec(); return 0; }
static int init(struct ao *ao) { struct priv *priv = ao->priv; ao->untimed = priv->untimed; struct mp_chmap_sel sel = {.tmp = ao}; if (priv->channel_layouts.num_chmaps) { for (int n = 0; n < priv->channel_layouts.num_chmaps; n++) mp_chmap_sel_add_map(&sel, &priv->channel_layouts.chmaps[n]); } else { mp_chmap_sel_add_any(&sel); } if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) mp_chmap_from_channels(&ao->channels, 2); priv->latency = priv->latency_sec * ao->samplerate; // A "buffer" for this many seconds of audio int bursts = (int)(ao->samplerate * priv->bufferlen + 1) / priv->outburst; priv->buffersize = priv->outburst * bursts + priv->latency; priv->last_time = mp_time_sec(); return 0; }
// resume playing, after pause() static void resume(struct ao *ao) { struct priv *priv = ao->priv; drain(ao); priv->paused = false; priv->last_time = mp_time_sec(); }
// Used by the main thread to wakeup the cache thread, and to wait for the // cache thread. The cache mutex has to be locked when calling this function. // *retry_time should be set to 0 on the first call. // Returns CACHE_INTERRUPTED if the caller is supposed to abort. 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_msg(MSGT_CACHE, MSGL_ERR, "Cache keeps not responding.\n"); } else if (*retry_time > 0.1) { mp_msg(MSGT_CACHE, MSGL_WARN, "Cache is not responding - slow/stuck network connection?\n"); } double start = mp_time_sec(); pthread_cond_signal(&s->wakeup); mpthread_cond_timed_wait(&s->wakeup, &s->mutex, CACHE_WAIT_TIME); *retry_time += mp_time_sec() - start; return 0; }
static int init(struct ao *ao) { struct priv *priv = ao->priv; ao->untimed = priv->untimed; struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_any(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) mp_chmap_from_channels(&ao->channels, 2); priv->latency = priv->latency_sec * ao->samplerate; // A "buffer" for this many seconds of audio int bursts = (int)(ao->samplerate * priv->bufferlen + 1) / priv->outburst; priv->buffersize = priv->outburst * bursts + priv->latency; priv->last_time = mp_time_sec(); return 0; }
static void drain(struct ao *ao) { struct priv *priv = ao->priv; if (ao->untimed) { priv->buffered = 0; return; } if (priv->paused) return; double now = mp_time_sec(); if (priv->buffered > 0) { priv->buffered -= (now - priv->last_time) * ao->samplerate * priv->speed; if (priv->buffered < 0) { if (!priv->playing_final) MP_ERR(ao, "buffer underrun\n"); priv->buffered = 0; } } priv->last_time = now; }
static bool is_busy(struct MPContext *mpctx) { return !mpctx->restart_complete && mp_time_sec() - mpctx->start_timestamp > 0.3; }
int encode_lavc_start(struct encode_lavc_context *ctx) { AVDictionaryEntry *de; if (ctx->header_written < 0) return 0; if (ctx->header_written > 0) return 1; CHECK_FAIL(ctx, 0); if (ctx->expect_video && ctx->vcc == NULL) { if (ctx->avc->oformat->video_codec != AV_CODEC_ID_NONE || ctx->options->vcodec) { encode_lavc_fail(ctx, "no video stream succeeded - invalid codec?\n"); return 0; } } if (ctx->expect_audio && ctx->acc == NULL) { if (ctx->avc->oformat->audio_codec != AV_CODEC_ID_NONE || ctx->options->acodec) { encode_lavc_fail(ctx, "no audio stream succeeded - invalid codec?\n"); return 0; } } ctx->header_written = -1; if (!(ctx->avc->oformat->flags & AVFMT_NOFILE)) { MP_INFO(ctx, "Opening output file: %s\n", ctx->avc->filename); if (avio_open(&ctx->avc->pb, ctx->avc->filename, AVIO_FLAG_WRITE) < 0) { encode_lavc_fail(ctx, "could not open '%s'\n", ctx->avc->filename); return 0; } } ctx->t0 = mp_time_sec(); MP_INFO(ctx, "Opening muxer: %s [%s]\n", ctx->avc->oformat->long_name, ctx->avc->oformat->name); if (ctx->metadata) { for (int i = 0; i < ctx->metadata->num_keys; i++) { av_dict_set(&ctx->avc->metadata, ctx->metadata->keys[i], ctx->metadata->values[i], 0); } } if (avformat_write_header(ctx->avc, &ctx->foptions) < 0) { encode_lavc_fail(ctx, "could not write header\n"); return 0; } for (de = NULL; (de = av_dict_get(ctx->foptions, "", de, AV_DICT_IGNORE_SUFFIX));) MP_WARN(ctx, "ofopts: key '%s' not found.\n", de->key); av_dict_free(&ctx->foptions); ctx->header_written = 1; return 1; }