bool video_init_best_codec(struct dec_video *d_video, char* video_decoders) { assert(!d_video->vd_driver); video_reset(d_video); d_video->has_broken_packet_pts = -10; // needs 10 packets to reach decision struct mp_decoder_entry *decoder = NULL; struct mp_decoder_list *list = mp_select_video_decoders(d_video->header->codec->codec, video_decoders); mp_print_decoders(d_video->log, MSGL_V, "Codec list:", list); for (int n = 0; n < list->num_entries; n++) { struct mp_decoder_entry *sel = &list->entries[n]; const struct vd_functions *driver = find_driver(sel->family); if (!driver) continue; MP_VERBOSE(d_video, "Opening video decoder %s:%s\n", sel->family, sel->decoder); d_video->vd_driver = driver; if (init_video_codec(d_video, sel->decoder)) { decoder = sel; break; } d_video->vd_driver = NULL; MP_WARN(d_video, "Video decoder init failed for " "%s:%s\n", sel->family, sel->decoder); } if (d_video->vd_driver) { d_video->decoder_desc = talloc_asprintf(d_video, "%s [%s:%s]", decoder->desc, decoder->family, decoder->decoder); MP_VERBOSE(d_video, "Selected video codec: %s\n", d_video->decoder_desc); } else { MP_ERR(d_video, "Failed to initialize a video decoder for codec '%s'.\n", d_video->header->codec->codec); } if (d_video->header->missing_timestamps) { MP_WARN(d_video, "This stream has no timestamps!\n"); MP_WARN(d_video, "Making up playback time using %f FPS.\n", d_video->fps); MP_WARN(d_video, "Seeking will probably fail badly.\n"); } talloc_free(list); return !!d_video->vd_driver; }
static void encode_2pass_prepare(struct encode_lavc_context *ctx, AVDictionary **dictp, AVStream *stream, AVCodecContext *codec, struct stream **bytebuf, const char *prefix) { if (!*bytebuf) { char buf[sizeof(ctx->avc->filename) + 12]; AVDictionaryEntry *de = av_dict_get(ctx->voptions, "flags", NULL, 0); snprintf(buf, sizeof(buf), "%s-%s-pass1.log", ctx->avc->filename, prefix); buf[sizeof(buf) - 1] = 0; if (value_has_flag(de ? de->value : "", "pass2")) { if (!(*bytebuf = stream_open(buf, ctx->global))) { MP_WARN(ctx, "%s: could not open '%s', " "disabling 2-pass encoding at pass 2\n", prefix, buf); codec->flags &= ~AV_CODEC_FLAG_PASS2; set_to_avdictionary(ctx, dictp, "flags", "-pass2"); } else { struct bstr content = stream_read_complete(*bytebuf, NULL, 1000000000); if (content.start == NULL) { MP_WARN(ctx, "%s: could not read '%s', " "disabling 2-pass encoding at pass 1\n", prefix, ctx->avc->filename); } else { content.start[content.len] = 0; codec->stats_in = content.start; } free_stream(*bytebuf); *bytebuf = NULL; } } if (value_has_flag(de ? de->value : "", "pass1")) { if (!(*bytebuf = open_output_stream(buf, ctx->global))) { MP_WARN(ctx, "%s: could not open '%s', disabling " "2-pass encoding at pass 1\n", prefix, ctx->avc->filename); set_to_avdictionary(ctx, dictp, "flags", "-pass1"); } } } }
// 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; }
OSStatus ca_select_device(struct ao *ao, char* name, AudioDeviceID *device) { OSStatus err = noErr; int selection = name ? strtol(name, (char **)NULL, 10) : -1; if (errno == EINVAL || errno == ERANGE) { selection = -1; MP_WARN(ao, "device identifier '%s' is invalid\n", name); } *device = 0; if (selection < 0) { // device not set by user, get the default one err = CA_GET(kAudioObjectSystemObject, kAudioHardwarePropertyDefaultOutputDevice, device); CHECK_CA_ERROR("could not get default audio device"); } else { *device = selection; } 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); } coreaudio_error: return err; }
static int config(struct vf_instance *vf, int width, int height, int d_width, int d_height, unsigned int flags, unsigned int outfmt) { // calculate the missing parameters: if(vf->priv->crop_w<=0 || vf->priv->crop_w>width) vf->priv->crop_w=width; if(vf->priv->crop_h<=0 || vf->priv->crop_h>height) vf->priv->crop_h=height; if(vf->priv->crop_x<0) vf->priv->crop_x=(width-vf->priv->crop_w)/2; if(vf->priv->crop_y<0) vf->priv->crop_y=(height-vf->priv->crop_h)/2; // rounding: struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(outfmt); vf->priv->crop_x = MP_ALIGN_DOWN(vf->priv->crop_x, fmt.align_x); vf->priv->crop_y = MP_ALIGN_DOWN(vf->priv->crop_y, fmt.align_y); // check: if(vf->priv->crop_w+vf->priv->crop_x>width || vf->priv->crop_h+vf->priv->crop_y>height){ MP_WARN(vf, "Bad position/width/height - cropped area outside of the original!\n"); return 0; } vf_rescale_dsize(&d_width, &d_height, width, height, vf->priv->crop_w, vf->priv->crop_h); return vf_next_config(vf,vf->priv->crop_w,vf->priv->crop_h,d_width,d_height,flags,outfmt); }
static bool try_open(struct timeline *tl, char *filename) { struct bstr bfilename = bstr0(filename); // Avoid trying to open itself or another .cue file. Best would be // to check the result of demuxer auto-detection, but the demuxer // API doesn't allow this without opening a full demuxer. if (bstr_case_endswith(bfilename, bstr0(".cue")) || bstrcasecmp(bstr0(tl->demuxer->filename), bfilename) == 0) return false; struct demuxer *d = demux_open_url(filename, NULL, tl->cancel, tl->global); // Since .bin files are raw PCM data with no headers, we have to explicitly // open them. Also, try to avoid to open files that are most likely not .bin // files, as that would only play noise. Checking the file extension is // fragile, but it's about the only way we have. // TODO: maybe also could check if the .bin file is a multiple of the Audio // CD sector size (2352 bytes) if (!d && bstr_case_endswith(bfilename, bstr0(".bin"))) { MP_WARN(tl, "CUE: Opening as BIN file!\n"); struct demuxer_params p = {.force_format = "rawaudio"}; d = demux_open_url(filename, &p, tl->cancel, tl->global); } if (d) { add_source(tl, d); return true; } MP_ERR(tl, "Could not open source '%s'!\n", filename); return false; }
static int init(struct ao *ao) { struct priv *p = ao->priv; if (AF_FORMAT_IS_IEC61937(ao->format)) { MP_WARN(ao, "detected IEC61937, redirecting to coreaudio_exclusive\n"); ao->redirect = "coreaudio_exclusive"; return CONTROL_ERROR; } if (!reinit_device(ao)) goto coreaudio_error; if (p->change_physical_format) init_physical_format(ao); if (!ca_init_chmap(ao, p->device)) goto coreaudio_error; ao->format = af_fmt_from_planar(ao->format); AudioStreamBasicDescription asbd; ca_fill_asbd(ao, &asbd); if (!init_audiounit(ao, asbd)) goto coreaudio_error; return CONTROL_OK; coreaudio_error: return CONTROL_ERROR; }
void ca_get_active_chmap(struct ao *ao, AudioDeviceID device, int channel_count, struct mp_chmap *out_map) { // Apparently, we have to guess by looking back at the supported layouts, // and I haven't found a property that retrieves the actual currently // active channel layout. struct mp_chmap_sel chmap_sel = {0}; ca_retrieve_layouts(ao, &chmap_sel, device); // Use any exact match. for (int n = 0; n < chmap_sel.num_chmaps; n++) { if (chmap_sel.chmaps[n].num == channel_count) { MP_VERBOSE(ao, "mismatching channels - fallback #%d\n", n); *out_map = chmap_sel.chmaps[n]; return; } } // Fall back to stereo or mono, and fill the rest with silence. (We don't // know what the device expects. We could use a larger default layout here, // but let's not.) mp_chmap_from_channels(out_map, MPMIN(2, channel_count)); out_map->num = channel_count; for (int n = 2; n < out_map->num; n++) out_map->speaker[n] = MP_SPEAKER_ID_NA; MP_WARN(ao, "mismatching channels - falling back to %s\n", mp_chmap_to_str(out_map)); }
static void decode(struct sd *sd, struct demux_packet *packet) { struct sd_ass_priv *ctx = sd->priv; ASS_Track *track = ctx->ass_track; if (ctx->converter) { if (!sd->opts->sub_clear_on_seek && packet->pos >= 0 && check_packet_seen(sd, packet->pos)) return; if (packet->duration < 0) { if (!ctx->duration_unknown) { MP_WARN(sd, "Subtitle with unknown duration.\n"); ctx->duration_unknown = true; } packet->duration = UNKNOWN_DURATION; } char **r = lavc_conv_decode(ctx->converter, packet); for (int n = 0; r && r[n]; n++) ass_process_data(track, r[n], strlen(r[n])); if (ctx->duration_unknown) { for (int n = 0; n < track->n_events - 1; n++) { if (track->events[n].Duration == UNKNOWN_DURATION * 1000) { track->events[n].Duration = track->events[n + 1].Start - track->events[n].Start; } } } } else { // Note that for this packet format, libass has an internal mechanism // for discarding duplicate (already seen) packets. ass_process_chunk(track, packet->buffer, packet->len, llrint(packet->pts * 1000), llrint(packet->duration * 1000)); } }
static void select_format(struct ao *ao, AVCodec *codec) { int best_score = INT_MIN; int best_format = 0; // Check the encoder's list of supported formats. for (const enum AVSampleFormat *sampleformat = codec->sample_fmts; sampleformat && *sampleformat != AV_SAMPLE_FMT_NONE; ++sampleformat) { int fmt = af_from_avformat(*sampleformat); if (!fmt) { MP_WARN(ao, "unsupported lavc format %s", av_get_sample_fmt_name(*sampleformat)); continue; } int score = af_format_conversion_score(fmt, ao->format); if (score > best_score) { best_score = score; best_format = fmt; } } if (best_format) { ao->format = best_format; } else { MP_ERR(ao, "sample format not found\n"); // shouldn't happen } }
static void uninit(struct ao *ao) { struct priv *ac = ao->priv; struct encode_lavc_context *ectx = ao->encode_lavc_ctx; if (!ac || ac->shutdown) return; pthread_mutex_lock(&ectx->lock); if (!encode_lavc_start(ectx)) { MP_WARN(ao, "not even ready to encode audio at end -> dropped\n"); pthread_mutex_unlock(&ectx->lock); return; } if (ac->stream) { double outpts = ac->expected_next_pts; if (!ectx->options->rawts && ectx->options->copyts) outpts += ectx->discontinuity_pts_offset; outpts += encode_lavc_getoffset(ectx, ac->codec); encode(ao, outpts, NULL); } pthread_mutex_unlock(&ectx->lock); ac->shutdown = true; }
static void mp_load_per_file_config(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; char *confpath; char cfg[512]; 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"); return; } char *name = mp_basename(cfg); if (opts->use_filedir_conf) { bstr dir = mp_dirname(cfg); char *dircfg = mp_path_join(NULL, dir, bstr0("mpv.conf")); try_load_config(mpctx, dircfg, FILE_LOCAL_FLAGS); talloc_free(dircfg); if (try_load_config(mpctx, cfg, FILE_LOCAL_FLAGS)) return; } if ((confpath = mp_find_user_config_file(NULL, mpctx->global, name))) { try_load_config(mpctx, confpath, FILE_LOCAL_FLAGS); talloc_free(confpath); } }
static int drm_egl_init_deprecated(struct MPGLContext *ctx, int flags) { if (ctx->vo->probing) return -1; MP_WARN(ctx->vo, "'drm-egl' is deprecated, use 'drm' instead.\n"); return drm_egl_init(ctx, flags); }
static void show_sw_adapter_msg(struct MPGLContext *ctx) { struct priv *p = ctx->priv; if (p->sw_adapter_msg_shown) return; MP_WARN(ctx->vo, "Using a software adapter\n"); p->sw_adapter_msg_shown = true; }
static int archive_entry_seek(stream_t *s, int64_t newpos) { struct priv *p = s->priv; if (p->mpa && !p->broken_seek) { locale_t oldlocale = uselocale(p->mpa->locale); int r = archive_seek_data(p->mpa->arch, newpos, SEEK_SET); uselocale(oldlocale); if (r >= 0) return 1; MP_WARN(s, "possibly unsupported seeking - switching to reopening\n"); p->broken_seek = true; if (reopen_archive(s) < STREAM_OK) return -1; } // libarchive can't seek in most formats. if (newpos < s->pos) { // Hack seeking backwards into working by reopening the archive and // starting over. MP_VERBOSE(s, "trying to reopen archive for performing seek\n"); if (reopen_archive(s) < STREAM_OK) return -1; s->pos = 0; } if (newpos > s->pos) { // For seeking forwards, just keep reading data (there's no libarchive // skip function either). char buffer[4096]; while (newpos > s->pos) { if (mp_cancel_test(s->cancel)) return -1; int size = MPMIN(newpos - s->pos, sizeof(buffer)); locale_t oldlocale = uselocale(p->mpa->locale); int r = archive_read_data(p->mpa->arch, buffer, size); if (r <= 0) { if (r == 0 && newpos > p->entry_size) { MP_ERR(s, "demuxer trying to seek beyond end of archive " "entry\n"); } else if (r == 0) { MP_ERR(s, "end of archive entry reached while seeking\n"); } else { MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch)); } uselocale(oldlocale); if (mp_archive_check_fatal(p->mpa, r)) { mp_archive_free(p->mpa); p->mpa = NULL; } return -1; } uselocale(oldlocale); s->pos += r; } } return 1; }
static int af_open(struct af_instance* af){ af_ac3enc_t *s = af->priv; af->control=control; af->uninit=uninit; af->filter_frame = filter_frame; af->filter_out = filter_out; s->lavc_acodec = avcodec_find_encoder_by_name("ac3"); if (!s->lavc_acodec) { MP_ERR(af, "Audio LAVC, couldn't find encoder for codec %s.\n", "ac3"); return AF_ERROR; } s->lavc_actx = avcodec_alloc_context3(s->lavc_acodec); if (!s->lavc_actx) { MP_ERR(af, "Audio LAVC, couldn't allocate context!\n"); return AF_ERROR; } const enum AVSampleFormat *fmts = s->lavc_acodec->sample_fmts; for (int i = 0; fmts[i] != AV_SAMPLE_FMT_NONE; i++) { s->in_sampleformat = af_from_avformat(fmts[i]); if (s->in_sampleformat) { s->lavc_actx->sample_fmt = fmts[i]; break; } } if (!s->in_sampleformat) { MP_ERR(af, "Audio LAVC, encoder doesn't " "support expected sample formats!\n"); return AF_ERROR; } MP_VERBOSE(af, "[af_lavcac3enc]: in sample format: %s\n", af_fmt_to_str(s->in_sampleformat)); av_init_packet(&s->pkt); s->input = talloc_zero(s, struct mp_audio); if (s->cfg_bit_rate) { int i; for (i = 0; i < 19; i++) { if (ac3_bitrate_tab[i] == s->cfg_bit_rate) break; } if (i >= 19) { MP_WARN(af, "af_lavcac3enc unable set unsupported " "bitrate %d, use default bitrate (check manpage to see " "supported bitrates).\n", s->cfg_bit_rate); s->cfg_bit_rate = 0; } } return AF_OK; }
static int reconfig(struct vf_instance *vf, struct mp_image_params *in, struct mp_image_params *out) { int width = in->w, height = in->h; // calculate the missing parameters: if(vf->priv->crop_w<=0 || vf->priv->crop_w>width) vf->priv->crop_w=width; if(vf->priv->crop_h<=0 || vf->priv->crop_h>height) vf->priv->crop_h=height; if(vf->priv->crop_x<0) vf->priv->crop_x=(width-vf->priv->crop_w)/2; if(vf->priv->crop_y<0) vf->priv->crop_y=(height-vf->priv->crop_h)/2; // rounding: int orig_x = vf->priv->crop_x; int orig_y = vf->priv->crop_y; struct mp_imgfmt_desc fmt = mp_imgfmt_get_desc(in->imgfmt); if (fmt.flags & MP_IMGFLAG_HWACCEL) { vf->priv->crop_x = 0; vf->priv->crop_y = 0; } else { vf->priv->crop_x = MP_ALIGN_DOWN(vf->priv->crop_x, fmt.align_x); vf->priv->crop_y = MP_ALIGN_DOWN(vf->priv->crop_y, fmt.align_y); } if (vf->priv->crop_x != orig_x || vf->priv->crop_y != orig_y) { MP_WARN(vf, "Adjusting crop origin to %d/%d for pixel format alignment.\n", vf->priv->crop_x, vf->priv->crop_y); } // check: if(vf->priv->crop_w+vf->priv->crop_x>width || vf->priv->crop_h+vf->priv->crop_y>height){ MP_WARN(vf, "Bad position/width/height - cropped area outside of the original!\n"); return -1; } *out = *in; out->w = vf->priv->crop_w; out->h = vf->priv->crop_h; return 0; }
static void decode(struct sd *sd, struct demux_packet *packet) { struct sd_ass_priv *ctx = sd->priv; ASS_Track *track = ctx->ass_track; long long ipts = packet->pts * 1000 + 0.5; long long iduration = packet->duration * 1000 + 0.5; if (strcmp(sd->codec, "ass") == 0) { ass_process_chunk(track, packet->buffer, packet->len, ipts, iduration); return; } else if (strcmp(sd->codec, "ssa") == 0) { // broken ffmpeg ASS packet format ctx->flush_on_seek = true; ass_process_data(track, packet->buffer, packet->len); return; } // plaintext subs if (packet->pts == MP_NOPTS_VALUE) { MP_WARN(sd, "Subtitle without pts, ignored\n"); return; } if (packet->duration <= 0) { MP_WARN(sd, "Subtitle without duration or " "duration set to 0 at pts %f, ignored\n", packet->pts); return; } unsigned char *text = packet->buffer; if (!sd->no_remove_duplicates) { for (int i = 0; i < track->n_events; i++) { if (track->events[i].Start == ipts && (track->events[i].Duration == iduration) && strcmp(track->events[i].Text, text) == 0) return; // We've already added this subtitle } } int eid = ass_alloc_event(track); ASS_Event *event = track->events + eid; event->Start = ipts; event->Duration = iduration; event->Style = track->default_style; event->Text = strdup(text); }
// Common code for handling ENODEV, which happens if a device gets "lost", and // can't be used anymore. Returns true if alsa_err is not ENODEV. static bool check_device_present(struct ao *ao, int alsa_err) { struct priv *p = ao->priv; if (alsa_err != -ENODEV) return true; if (!p->device_lost) { MP_WARN(ao, "Device lost, trying to recover...\n"); ao_request_reload(ao); p->device_lost = true; } return false; }
static int norm_from_string(tvi_handle_t *tvh, char* norm) { const tvi_functions_t *funcs = tvh->functions; char str[20]; int ret; strncpy(str, norm, sizeof(str)-1); str[sizeof(str)-1] = '\0'; ret=funcs->control(tvh->priv, TVI_CONTROL_SPC_GET_NORMID, str); if (ret == TVI_CONTROL_TRUE) { int *v = (int *)str; return *v; } if(ret!=TVI_CONTROL_UNKNOWN) { MP_WARN(tvh, "tv.c: norm_from_string(%s): Bogus norm parameter, setting %s.\n", norm,"default"); return 0; } if (!strcasecmp(norm, "pal")) return TV_NORM_PAL; else if (!strcasecmp(norm, "ntsc")) return TV_NORM_NTSC; else if (!strcasecmp(norm, "secam")) return TV_NORM_SECAM; else if (!strcasecmp(norm, "palnc")) return TV_NORM_PALNC; else if (!strcasecmp(norm, "palm")) return TV_NORM_PALM; else if (!strcasecmp(norm, "paln")) return TV_NORM_PALN; else if (!strcasecmp(norm, "ntscjp")) return TV_NORM_NTSCJP; else { MP_WARN(tvh, "tv.c: norm_from_string(%s): Bogus norm parameter, setting %s.\n", norm, "PAL"); return TV_NORM_PAL; } }
static int af_open(struct af_instance* af){ af_ac3enc_t *s = af->priv; af->control=control; af->uninit=uninit; af->filter_frame = filter_frame; af->filter_out = filter_out; s->lavc_acodec = avcodec_find_encoder_by_name(s->cfg_encoder); if (!s->lavc_acodec) { MP_ERR(af, "Couldn't find encoder %s.\n", s->cfg_encoder); return AF_ERROR; } s->lavc_actx = avcodec_alloc_context3(s->lavc_acodec); if (!s->lavc_actx) { MP_ERR(af, "Audio LAVC, couldn't allocate context!\n"); return AF_ERROR; } if (mp_set_avopts(af->log, s->lavc_actx, s->cfg_avopts) < 0) return AF_ERROR; // For this one, we require the decoder to expert lists of all supported // parameters. (Not all decoders do that, but the ones we're interested // in do.) if (!s->lavc_acodec->sample_fmts || !s->lavc_acodec->channel_layouts) { MP_ERR(af, "Audio encoder doesn't list supported parameters.\n"); return AF_ERROR; } s->input = talloc_zero(s, struct mp_audio); if (s->cfg_bit_rate) { int i; for (i = 0; i < 19; i++) { if (ac3_bitrate_tab[i] == s->cfg_bit_rate) { s->bit_rate = ac3_bitrate_tab[i] * 1000; break; } } if (i >= 19) { MP_WARN(af, "unable set unsupported bitrate %d, use default " "bitrate (check manpage to see supported bitrates).\n", s->cfg_bit_rate); } } return AF_OK; }
static void acquire_vt(void *data) { struct MPGLContext *ctx = data; MP_VERBOSE(ctx->vo, "Acquiring VT"); if (USE_MASTER) { struct priv *p = ctx->priv; if (drmSetMaster(p->kms->fd)) { MP_WARN(ctx->vo, "Failed to acquire DRM master: %s\n", mp_strerror(errno)); } } crtc_setup(ctx); }
static bool create_context_x11_old(struct MPGLContext *ctx) { struct glx_context *glx_ctx = ctx->priv; Display *display = ctx->vo->x11->display; struct vo *vo = ctx->vo; GL *gl = ctx->gl; if (glx_ctx->context) return true; GLXContext new_context = glXCreateContext(display, glx_ctx->vinfo, NULL, True); if (!new_context) { MP_FATAL(vo, "Could not create GLX context!\n"); return false; } if (!glXMakeCurrent(display, ctx->vo->x11->window, new_context)) { MP_FATAL(vo, "Could not set GLX context!\n"); glXDestroyContext(display, new_context); return false; } void *(*getProcAddress)(const GLubyte *); getProcAddress = mp_getdladdr("glXGetProcAddress"); if (!getProcAddress) getProcAddress = mp_getdladdr("glXGetProcAddressARB"); const char *glxstr = ""; const char *(*glXExtStr)(Display *, int) = mp_getdladdr("glXQueryExtensionsString"); if (glXExtStr) glxstr = glXExtStr(display, ctx->vo->x11->screen); mpgl_load_functions(gl, getProcAddress, glxstr, vo->log); if (!gl->GenPrograms && gl->GetString && gl->version < MPGL_VER(3, 0) && strstr(gl->GetString(GL_EXTENSIONS), "GL_ARB_vertex_program")) { MP_WARN(vo, "Broken glXGetProcAddress detected, trying workaround\n"); mpgl_load_functions(gl, NULL, glxstr, vo->log); } glx_ctx->context = new_context; if (!glXIsDirect(vo->x11->display, new_context)) ctx->gl->mpgl_caps &= ~MPGL_CAP_NO_SW; return true; }
static int vf_open(vf_instance_t *vf) { struct vf_priv_s *p = vf->priv; if (p->warn) MP_WARN(vf, "%s", VF_LW_REPLACE); if (vf_lw_set_graph(vf, p->lw_opts, NULL, "%s", rot[p->angle]) >= 0) { vf_lw_set_reconfig_cb(vf, lavfi_reconfig); return 1; } return 0; }
// must get exactly ac->aframesize amount of data static void encode(struct ao *ao, double apts, void **data) { struct priv *ac = ao->priv; struct encode_lavc_context *ectx = ao->encode_lavc_ctx; double realapts = ac->aframecount * (double) ac->aframesize / ao->samplerate; ac->aframecount++; if (data) ectx->audio_pts_offset = realapts - apts; if(data) { AVFrame *frame = av_frame_alloc(); frame->format = af_to_avformat(ao->format); frame->nb_samples = ac->aframesize; size_t num_planes = af_fmt_is_planar(ao->format) ? ao->channels.num : 1; assert(num_planes <= AV_NUM_DATA_POINTERS); for (int n = 0; n < num_planes; n++) frame->extended_data[n] = data[n]; frame->linesize[0] = frame->nb_samples * ao->sstride; if (ectx->options->rawts || ectx->options->copyts) { // real audio pts frame->pts = floor(apts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5); } else { // audio playback time frame->pts = floor(realapts * ac->codec->time_base.den / ac->codec->time_base.num + 0.5); } int64_t frame_pts = av_rescale_q(frame->pts, ac->codec->time_base, ac->worst_time_base); if (ac->lastpts != AV_NOPTS_VALUE && frame_pts <= ac->lastpts) { // this indicates broken video // (video pts failing to increase fast enough to match audio) MP_WARN(ao, "audio frame pts went backwards (%d <- %d), autofixed\n", (int)frame->pts, (int)ac->lastpts); frame_pts = ac->lastpts + 1; frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->codec->time_base); } ac->lastpts = frame_pts; frame->quality = ac->codec->global_quality; encode_audio_and_write(ao, frame); av_frame_free(&frame); } else encode_audio_and_write(ao, NULL); }
static void build_timeline(struct timeline *tl) { struct priv *p = tl->demuxer->priv; void *ctx = talloc_new(NULL); add_source(tl, tl->demuxer); struct cue_track *tracks = NULL; size_t track_count = 0; for (size_t n = 0; n < p->f->num_tracks; n++) { struct cue_track *track = &p->f->tracks[n]; if (track->filename) { MP_TARRAY_APPEND(ctx, tracks, track_count, *track); } else { MP_WARN(tl->demuxer, "No file specified for track entry %zd. " "It will be removed\n", n + 1); } } if (track_count == 0) { MP_ERR(tl, "CUE: no tracks found!\n"); goto out; } // Remove duplicate file entries. This might be too sophisticated, since // CUE files usually use either separate files for every single track, or // only one file for all tracks. char **files = 0; size_t file_count = 0; for (size_t n = 0; n < track_count; n++) { struct cue_track *track = &tracks[n]; track->source = -1; for (size_t file = 0; file < file_count; file++) { if (strcmp(files[file], track->filename) == 0) { track->source = file; break; } } if (track->source == -1) { file_count++; files = talloc_realloc(ctx, files, char *, file_count); files[file_count - 1] = track->filename; track->source = file_count - 1; } }
static int parse_txt(struct pl_parser *p) { if (!p->force) return -1; if (p->probing) return 0; MP_WARN(p, "Reading plaintext playlist.\n"); while (!pl_eof(p)) { bstr line = bstr_strip(pl_get_line(p)); if (line.len == 0) continue; pl_add(p, line); } return 0; }
static void release_vt(void *data) { struct MPGLContext *ctx = data; MP_VERBOSE(ctx->vo, "Releasing VT"); crtc_release(ctx); if (USE_MASTER) { //this function enables support for switching to x, weston etc. //however, for whatever reason, it can be called only by root users. //until things change, this is commented. struct priv *p = ctx->priv; if (drmDropMaster(p->kms->fd)) { MP_WARN(ctx->vo, "Failed to drop DRM master: %s\n", mp_strerror(errno)); } } }
int dvd_sid_from_lang(stream_t *stream, char **lang) { dvd_priv_t *d=stream->priv; int code,i; for (int n = 0; lang[n]; n++) { code = lang[n][1] | (lang[n][0] << 8); for(i=0;i<d->nr_of_subtitles;i++) { if(d->subtitles[i].language==code) { MP_INFO(stream, "Selected DVD subtitle channel: %d language: %c%c\n", i, lang[n][0], lang[n][1]); return d->subtitles[i].id; } } } MP_WARN(stream, "No matching DVD subtitle language found!\n"); return -1; }
// 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; }