static int reinit_vs(struct vf_instance *vf) { struct vf_priv_s *p = vf->priv; VSMap *vars = NULL, *in = NULL, *out = NULL; int res = -1; destroy_vs(vf); MP_DBG(vf, "initializing...\n"); p->initializing = true; if (p->drv->load_core(vf) < 0 || !p->vsapi || !p->vscore) { MP_FATAL(vf, "Could not get vapoursynth API handle.\n"); goto error; } in = p->vsapi->createMap(); out = p->vsapi->createMap(); vars = p->vsapi->createMap(); if (!in || !out || !vars) goto error; p->vsapi->createFilter(in, out, "Input", infiltInit, infiltGetFrame, infiltFree, fmSerial, 0, vf, p->vscore); int vserr; p->in_node = p->vsapi->propGetNode(out, "clip", 0, &vserr); if (!p->in_node) { MP_FATAL(vf, "Could not get our own input node.\n"); goto error; } if (p->vsapi->propSetNode(vars, "video_in", p->in_node, 0)) goto error; int d_w, d_h; mp_image_params_get_dsize(&p->fmt_in, &d_w, &d_h); p->vsapi->propSetInt(vars, "video_in_dw", d_w, 0); p->vsapi->propSetInt(vars, "video_in_dh", d_h, 0); p->vsapi->propSetFloat(vars, "container_fps", vf->chain->container_fps, 0); p->vsapi->propSetFloat(vars, "display_fps", vf->chain->display_fps, 0); if (p->drv->load(vf, vars) < 0) goto error; if (!p->out_node) { MP_FATAL(vf, "Could not get script output node.\n"); goto error; } const VSVideoInfo *vi = p->vsapi->getVideoInfo(p->out_node); if (!isConstantFormat(vi)) { MP_FATAL(vf, "Video format is required to be constant.\n"); goto error; } pthread_mutex_lock(&p->lock); p->initializing = false; pthread_mutex_unlock(&p->lock); MP_DBG(vf, "initialized.\n"); res = 0; error: if (p->vsapi) { p->vsapi->freeMap(in); p->vsapi->freeMap(out); p->vsapi->freeMap(vars); } if (res < 0) destroy_vs(vf); return res; }
static void hotplug_uninit(struct ao *ao) { MP_DBG(ao, "Hotplug uninit\n"); wasapi_change_uninit(ao); CoUninitialize(); }
static int dvd_read_sector(stream_t *stream, dvd_priv_t *d, unsigned char *data) { int len; if(d->packs_left==0) { /** * If we're not at the end of this cell, we can determine the next * VOBU to display using the VOBU_SRI information section of the * DSI. Using this value correctly follows the current angle, * avoiding the doubled scenes in The Matrix, and makes our life * really happy. * * Otherwise, we set our next address past the end of this cell to * force the code above to go to the next cell in the program. */ if(d->dsi_pack.vobu_sri.next_vobu != SRI_END_OF_CELL) { d->cur_pack= d->dsi_pack.dsi_gi.nv_pck_lbn + ( d->dsi_pack.vobu_sri.next_vobu & 0x7fffffff ); MP_DBG(stream, "Navi new pos=0x%X \n",d->cur_pack); } else { // end of cell! find next cell! MP_VERBOSE(stream, "--- END OF CELL !!! ---\n"); d->cur_pack=d->cell_last_pack+1; } } read_next: if(d->cur_pack>d->cell_last_pack) { // end of cell! int next=dvd_next_cell(stream, d); if(next>=0) { d->cur_cell=next; // if( d->cur_pgc->cell_playback[d->cur_cell].block_type // == BLOCK_TYPE_ANGLE_BLOCK ) d->cur_cell+=dvd_angle-1; d->cur_pack = d->cur_pgc->cell_playback[ d->cur_cell ].first_sector; d->cell_last_pack=d->cur_pgc->cell_playback[ d->cur_cell ].last_sector; MP_VERBOSE(stream, "DVD next cell: %d pack: 0x%X-0x%X \n",d->cur_cell,d->cur_pack,d->cell_last_pack); } else return -1; // EOF } len = DVDReadBlocks(d->title, d->cur_pack, 1, data); // only == 0 should indicate an error, but some dvdread version are buggy when used with dvdcss if(len <= 0) return -1; //error if(data[38]==0 && data[39]==0 && data[40]==1 && data[41]==0xBF && data[1024]==0 && data[1025]==0 && data[1026]==1 && data[1027]==0xBF) { // found a Navi packet!!! #if DVDREAD_VERSION >= LIBDVDREAD_VERSION(0,9,0) navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ])); #else navRead_DSI(&d->dsi_pack, &(data[ DSI_START_BYTE ]), sizeof(dsi_t)); #endif if(d->cur_pack != d->dsi_pack.dsi_gi.nv_pck_lbn ) { MP_VERBOSE(stream, "Invalid NAVI packet! lba=0x%X navi=0x%X \n", d->cur_pack,d->dsi_pack.dsi_gi.nv_pck_lbn); } else { // process! d->packs_left = d->dsi_pack.dsi_gi.vobu_ea; MP_DBG(stream, "Found NAVI packet! lba=0x%X len=%d \n",d->cur_pack,d->packs_left); //navPrint_DSI(&d->dsi_pack); MP_TRACE(stream, "\r### CELL %d: Navi: %d/%d IFO: %d/%d \n",d->cur_cell, d->dsi_pack.dsi_gi.vobu_c_idn,d->dsi_pack.dsi_gi.vobu_vob_idn, d->cur_pgc->cell_position[d->cur_cell].cell_nr, d->cur_pgc->cell_position[d->cur_cell].vob_id_nr); if(d->angle_seek) { int i,skip=0; for(i=0;i<9;i++) // check if all values zero: if((skip=d->dsi_pack.sml_agli.data[i].address)!=0) break; if(skip && skip!=0x7fffffff) { // sml_agli table has valid data (at least one non-zero): d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+ d->dsi_pack.sml_agli.data[d->dvd_angle-1].address; d->angle_seek=0; d->cur_pack--; MP_VERBOSE(stream, "Angle-seek synced using sml_agli map! new_lba=0x%X \n",d->cur_pack); } else { // check if we're in the right cell, jump otherwise: if( (d->dsi_pack.dsi_gi.vobu_c_idn==d->cur_pgc->cell_position[d->cur_cell].cell_nr) && (d->dsi_pack.dsi_gi.vobu_vob_idn==d->cur_pgc->cell_position[d->cur_cell].vob_id_nr) ){ d->angle_seek=0; MP_VERBOSE(stream, "Angle-seek synced by cell/vob IDN search! \n"); } else { // wrong angle, skip this vobu: d->cur_pack=d->dsi_pack.dsi_gi.nv_pck_lbn+ d->dsi_pack.dsi_gi.vobu_ea; d->angle_seek=2; // DEBUG } } } } ++d->cur_pack; goto read_next; } ++d->cur_pack; if(d->packs_left>=0) --d->packs_left; if(d->angle_seek) { if(d->angle_seek==2) MP_VERBOSE(stream, "!!! warning! reading packet while angle_seek !!!\n"); goto read_next; // searching for Navi packet } return d->cur_pack-1; }
static void VS_CC infiltInit(VSMap *in, VSMap *out, void **instanceData, VSNode *node, VSCore *core, const VSAPI *vsapi) { struct vf_instance *vf = *instanceData; struct vf_priv_s *p = vf->priv; // The number of frames of our input node is obviously unknown. The user // could for example seek any time, randomly "ending" the clip. // This specific value was suggested by the VapourSynth developer. int enough_for_everyone = INT_MAX / 16; // Note: this is called from createFilter, so no need for locking. VSVideoInfo fmt = { .format = p->vsapi->getFormatPreset(mp_to_vs(p->fmt_in.imgfmt), p->vscore), .width = p->fmt_in.w, .height = p->fmt_in.h, .numFrames = enough_for_everyone, }; if (!fmt.format) { p->vsapi->setError(out, "Unsupported input format.\n"); return; } p->vsapi->setVideoInfo(&fmt, 1, node); p->in_node_active = true; } static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason, void **instanceData, void **frameData, VSFrameContext *frameCtx, VSCore *core, const VSAPI *vsapi) { struct vf_instance *vf = *instanceData; struct vf_priv_s *p = vf->priv; VSFrameRef *ret = NULL; pthread_mutex_lock(&p->lock); MP_DBG(vf, "VS asking for frame %d (at %d)\n", frameno, p->in_frameno); while (1) { if (p->shutdown) { p->vsapi->setFilterError("EOF or filter reinit/uninit", frameCtx); MP_DBG(vf, "returning error on EOF/reset\n"); break; } if (p->initializing) { MP_WARN(vf, "Frame requested during init! This is unsupported.\n" "Returning black dummy frame with 0 duration.\n"); ret = alloc_vs_frame(p, &vf->fmt_in); if (!ret) { p->vsapi->setFilterError("Could not allocate VS frame", frameCtx); break; } struct mp_image vsframe = map_vs_frame(p, ret, true); mp_image_clear(&vsframe, 0, 0, vf->fmt_in.w, vf->fmt_in.h); struct mp_image dummy = {0}; mp_image_set_params(&dummy, &vf->fmt_in); set_vs_frame_props(p, ret, &dummy, 0, 1); break; } if (frameno < p->in_frameno) { char msg[180]; snprintf(msg, sizeof(msg), "Frame %d requested, but only have frames starting from %d. " "Try increasing the buffered-frames suboption.", frameno, p->in_frameno); MP_FATAL(vf, "%s\n", msg); p->vsapi->setFilterError(msg, frameCtx); break; } if (frameno >= p->in_frameno + MP_TALLOC_AVAIL(p->buffered)) { // Too far in the future. Remove frames, so that the main thread can // queue new frames. if (p->num_buffered) { drain_oldest_buffered_frame(p); pthread_cond_broadcast(&p->wakeup); if (vf->chain->wakeup_callback) vf->chain->wakeup_callback(vf->chain->wakeup_callback_ctx); continue; } } if (frameno >= p->in_frameno + p->num_buffered) { // If we think EOF was reached, don't wait for new input, and assume // the VS filter has reached EOF. if (p->eof) { p->shutdown = true; continue; } } if (frameno < p->in_frameno + p->num_buffered) { struct mp_image *img = p->buffered[frameno - p->in_frameno]; ret = alloc_vs_frame(p, &img->params); if (!ret) { p->vsapi->setFilterError("Could not allocate VS frame", frameCtx); break; } struct mp_image vsframe = map_vs_frame(p, ret, true); mp_image_copy(&vsframe, img); int res = 1e6; int dur = img->pts * res + 0.5; set_vs_frame_props(p, ret, img, dur, res); break; } pthread_cond_wait(&p->wakeup, &p->lock); } pthread_cond_broadcast(&p->wakeup); pthread_mutex_unlock(&p->lock); return ret; } static void VS_CC infiltFree(void *instanceData, VSCore *core, const VSAPI *vsapi) { struct vf_instance *vf = instanceData; struct vf_priv_s *p = vf->priv; pthread_mutex_lock(&p->lock); p->in_node_active = false; pthread_cond_broadcast(&p->wakeup); pthread_mutex_unlock(&p->lock); } // number of getAsyncFrame calls in progress // must be called with p->lock held static int num_requested(struct vf_priv_s *p) { int r = 0; for (int n = 0; n < p->max_requests; n++) r += p->requested[n] == &dummy_img; return r; }
// Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { af_scaletempo_t *s = af->priv; switch (cmd) { case AF_CONTROL_REINIT: { struct mp_audio *data = (struct mp_audio *)arg; float srate = data->rate / 1000; int nch = data->nch; int use_int = 0; MP_VERBOSE(af, "[scaletempo] %.3f speed * %.3f scale_nominal = %.3f\n", s->speed, s->scale_nominal, s->scale); mp_audio_force_interleaved_format(data); mp_audio_copy_config(af->data, data); if (s->scale == 1.0) { if (s->speed_tempo && s->speed_pitch) return AF_DETACH; af->delay = 0; af->mul = 1; return af_test_output(af, data); } if (data->format == AF_FORMAT_S16) { use_int = 1; } else { mp_audio_set_format(af->data, AF_FORMAT_FLOAT); } int bps = af->data->bps; s->frames_stride = srate * s->ms_stride; s->bytes_stride = s->frames_stride * bps * nch; s->frames_stride_scaled = s->scale * s->frames_stride; s->frames_stride_error = 0; af->mul = 1.0 / s->scale; af->delay = 0; int frames_overlap = s->frames_stride * s->percent_overlap; if (frames_overlap <= 0) { s->bytes_standing = s->bytes_stride; s->samples_standing = s->bytes_standing / bps; s->output_overlap = NULL; s->bytes_overlap = 0; } else { s->samples_overlap = frames_overlap * nch; s->bytes_overlap = frames_overlap * nch * bps; s->bytes_standing = s->bytes_stride - s->bytes_overlap; s->samples_standing = s->bytes_standing / bps; s->buf_overlap = realloc(s->buf_overlap, s->bytes_overlap); s->table_blend = realloc(s->table_blend, s->bytes_overlap * 4); if (!s->buf_overlap || !s->table_blend) { MP_FATAL(af, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset(s->buf_overlap, 0, s->bytes_overlap); if (use_int) { int32_t *pb = s->table_blend; int64_t blend = 0; for (int i = 0; i < frames_overlap; i++) { int32_t v = blend / frames_overlap; for (int j = 0; j < nch; j++) *pb++ = v; blend += 65536; // 2^16 } s->output_overlap = output_overlap_s16; } else { float *pb = s->table_blend; for (int i = 0; i < frames_overlap; i++) { float v = i / (float)frames_overlap; for (int j = 0; j < nch; j++) *pb++ = v; } s->output_overlap = output_overlap_float; } } s->frames_search = (frames_overlap > 1) ? srate * s->ms_search : 0; if (s->frames_search <= 0) s->best_overlap_offset = NULL; else { if (use_int) { int64_t t = frames_overlap; int32_t n = 8589934588LL / (t * t); // 4 * (2^31 - 1) / t^2 s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap * 2 + UNROLL_PADDING); s->table_window = realloc(s->table_window, s->bytes_overlap * 2 - nch * bps * 2); if (!s->buf_pre_corr || !s->table_window) { MP_FATAL(af, "[scaletempo] Out of memory\n"); return AF_ERROR; } memset((char *)s->buf_pre_corr + s->bytes_overlap * 2, 0, UNROLL_PADDING); int32_t *pw = s->table_window; for (int i = 1; i < frames_overlap; i++) { int32_t v = (i * (t - i) * n) >> 15; for (int j = 0; j < nch; j++) *pw++ = v; } s->best_overlap_offset = best_overlap_offset_s16; } else { s->buf_pre_corr = realloc(s->buf_pre_corr, s->bytes_overlap); s->table_window = realloc(s->table_window, s->bytes_overlap - nch * bps); if (!s->buf_pre_corr || !s->table_window) { MP_FATAL(af, "[scaletempo] Out of memory\n"); return AF_ERROR; } float *pw = s->table_window; for (int i = 1; i < frames_overlap; i++) { float v = i * (frames_overlap - i); for (int j = 0; j < nch; j++) *pw++ = v; } s->best_overlap_offset = best_overlap_offset_float; } } s->bytes_per_frame = bps * nch; s->num_channels = nch; s->bytes_queue = (s->frames_search + s->frames_stride + frames_overlap) * bps * nch; s->buf_queue = realloc(s->buf_queue, s->bytes_queue + UNROLL_PADDING); if (!s->buf_queue) { MP_FATAL(af, "[scaletempo] Out of memory\n"); return AF_ERROR; } s->bytes_queued = 0; s->bytes_to_slide = 0; MP_DBG(af, "[scaletempo] " "%.2f stride_in, %i stride_out, %i standing, " "%i overlap, %i search, %i queue, %s mode\n", s->frames_stride_scaled, (int)(s->bytes_stride / nch / bps), (int)(s->bytes_standing / nch / bps), (int)(s->bytes_overlap / nch / bps), s->frames_search, (int)(s->bytes_queue / nch / bps), (use_int ? "s16" : "float")); return af_test_output(af, (struct mp_audio *)arg); } case AF_CONTROL_SET_PLAYBACK_SPEED: { if (s->speed_tempo) { if (s->speed_pitch) break; s->speed = *(double *)arg; s->scale = s->speed * s->scale_nominal; } else { if (s->speed_pitch) { s->speed = 1 / *(double *)arg; s->scale = s->speed * s->scale_nominal; break; } } return AF_OK; } case AF_CONTROL_RESET: s->bytes_queued = 0; s->bytes_to_slide = 0; s->frames_stride_error = 0; memset(s->buf_overlap, 0, s->bytes_overlap); }
static int filter_out(struct af_instance *af) { af_ac3enc_t *s = af->priv; if (!s->pending) return 0; AVFrame *frame = av_frame_alloc(); if (!frame) { MP_FATAL(af, "Could not allocate memory \n"); return -1; } int err = -1; AVPacket pkt = {0}; av_init_packet(&pkt); // Send input as long as it wants. while (1) { err = read_input_frame(af, frame); if (err < 0) goto done; if (err == 0) break; err = -1; int lavc_ret = avcodec_send_frame(s->lavc_actx, frame); // On EAGAIN, we're supposed to read remaining output. if (lavc_ret == AVERROR(EAGAIN)) break; if (lavc_ret < 0) { MP_FATAL(af, "Encode failed.\n"); goto done; } s->encoder_buffered += s->input->samples; s->input->samples = 0; } int lavc_ret = avcodec_receive_packet(s->lavc_actx, &pkt); if (lavc_ret == AVERROR(EAGAIN)) { // Need to buffer more input. err = 0; goto done; } if (lavc_ret < 0) { MP_FATAL(af, "Encode failed.\n"); goto done; } MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", pkt.size, s->pending->samples + s->input->samples); s->encoder_buffered -= AC3_FRAME_SIZE; struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); if (!out) goto done; mp_audio_copy_attributes(out, s->pending); int frame_size = pkt.size; int header_len = 0; char hdr[8]; if (s->cfg_add_iec61937_header && pkt.size > 5) { int bsmod = pkt.data[5] & 0x7; int len = frame_size; frame_size = AC3_FRAME_SIZE * 2 * 2; header_len = 8; AV_WL16(hdr, 0xF872); // iec 61937 syncword 1 AV_WL16(hdr + 2, 0x4E1F); // iec 61937 syncword 2 hdr[5] = bsmod; // bsmod hdr[4] = 0x01; // data-type ac3 AV_WL16(hdr + 6, len << 3); // number of bits in payload } if (frame_size > out->samples * out->sstride) abort(); char *buf = (char *)out->planes[0]; memcpy(buf, hdr, header_len); memcpy(buf + header_len, pkt.data, pkt.size); memset(buf + header_len + pkt.size, 0, frame_size - (header_len + pkt.size)); swap_16((uint16_t *)(buf + header_len), pkt.size / 2); out->samples = frame_size / out->sstride; af_add_output_frame(af, out); err = 0; done: av_packet_unref(&pkt); av_frame_free(&frame); update_delay(af); return err; }
// Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { af_ac3enc_t *s = af->priv; static const int default_bit_rate[AC3_MAX_CHANNELS+1] = \ {0, 96000, 192000, 256000, 384000, 448000, 448000}; switch (cmd){ case AF_CONTROL_REINIT: { struct mp_audio *in = arg; struct mp_audio orig_in = *in; if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num) return AF_DETACH; // At least currently, the AC3 encoder doesn't export sample rates. in->rate = 48000; select_encode_format(s->lavc_actx, in); af->data->rate = in->rate; mp_audio_set_format(af->data, AF_FORMAT_S_AC3); mp_audio_set_num_channels(af->data, 2); if (!mp_audio_config_equals(in, &orig_in)) return AF_FALSE; if (s->cfg_add_iec61937_header) { s->out_samples = AC3_FRAME_SIZE; } else { s->out_samples = AC3_MAX_CODED_FRAME_SIZE / af->data->sstride; } mp_audio_copy_config(s->input, in); talloc_free(s->pending); s->pending = NULL; MP_DBG(af, "reinit: %d, %d, %d.\n", in->nch, in->rate, s->in_samples); int bit_rate = s->bit_rate ? s->bit_rate : default_bit_rate[in->nch]; if (s->lavc_actx->channels != in->nch || s->lavc_actx->sample_rate != in->rate || s->lavc_actx->bit_rate != bit_rate) { avcodec_close(s->lavc_actx); // Put sample parameters s->lavc_actx->sample_fmt = af_to_avformat(in->format); s->lavc_actx->channels = in->nch; s->lavc_actx->channel_layout = mp_chmap_to_lavc(&in->channels); s->lavc_actx->sample_rate = in->rate; s->lavc_actx->bit_rate = bit_rate; if (avcodec_open2(s->lavc_actx, s->lavc_acodec, NULL) < 0) { MP_ERR(af, "Couldn't open codec %s, br=%d.\n", "ac3", bit_rate); return AF_ERROR; } if (s->lavc_actx->frame_size < 1) { MP_ERR(af, "encoder didn't specify input frame size\n"); return AF_ERROR; } } s->in_samples = s->lavc_actx->frame_size; mp_audio_realloc(s->input, s->in_samples); s->input->samples = 0; s->encoder_buffered = 0; return AF_OK; } case AF_CONTROL_RESET: if (avcodec_is_open(s->lavc_actx)) avcodec_flush_buffers(s->lavc_actx); talloc_free(s->pending); s->pending = NULL; s->input->samples = 0; s->encoder_buffered = 0; return AF_OK; } return AF_UNKNOWN; }
static int control(struct ao *ao, enum aocontrol cmd, void *arg) { struct priv *p = ao->priv; snd_mixer_t *handle = NULL; switch (cmd) { case AOCONTROL_GET_MUTE: case AOCONTROL_SET_MUTE: case AOCONTROL_GET_VOLUME: case AOCONTROL_SET_VOLUME: { int err; snd_mixer_elem_t *elem; snd_mixer_selem_id_t *sid; long pmin, pmax; long get_vol, set_vol; float f_multi; if (!af_fmt_is_pcm(ao->format)) return CONTROL_FALSE; snd_mixer_selem_id_alloca(&sid); snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index); snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name); err = snd_mixer_open(&handle, 0); CHECK_ALSA_ERROR("Mixer open error"); err = snd_mixer_attach(handle, p->cfg_mixer_device); CHECK_ALSA_ERROR("Mixer attach error"); err = snd_mixer_selem_register(handle, NULL, NULL); CHECK_ALSA_ERROR("Mixer register error"); err = snd_mixer_load(handle); CHECK_ALSA_ERROR("Mixer load error"); elem = snd_mixer_find_selem(handle, sid); if (!elem) { MP_VERBOSE(ao, "Unable to find simple control '%s',%i.\n", snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid)); goto alsa_error; } snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); f_multi = (100 / (float)(pmax - pmin)); switch (cmd) { case AOCONTROL_SET_VOLUME: { ao_control_vol_t *vol = arg; set_vol = vol->left / f_multi + pmin + 0.5; err = snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol); CHECK_ALSA_ERROR("Error setting left channel"); MP_DBG(ao, "left=%li, ", set_vol); set_vol = vol->right / f_multi + pmin + 0.5; err = snd_mixer_selem_set_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol); CHECK_ALSA_ERROR("Error setting right channel"); MP_DBG(ao, "right=%li, pmin=%li, pmax=%li, mult=%f\n", set_vol, pmin, pmax, f_multi); break; } case AOCONTROL_GET_VOLUME: { ao_control_vol_t *vol = arg; snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol); vol->left = (get_vol - pmin) * f_multi; snd_mixer_selem_get_playback_volume (elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol); vol->right = (get_vol - pmin) * f_multi; MP_DBG(ao, "left=%f, right=%f\n", vol->left, vol->right); break; } case AOCONTROL_SET_MUTE: { bool *mute = arg; if (!snd_mixer_selem_has_playback_switch(elem)) goto alsa_error; if (!snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_set_playback_switch (elem, SND_MIXER_SCHN_FRONT_RIGHT, !*mute); } snd_mixer_selem_set_playback_switch (elem, SND_MIXER_SCHN_FRONT_LEFT, !*mute); break; } case AOCONTROL_GET_MUTE: { bool *mute = arg; if (!snd_mixer_selem_has_playback_switch(elem)) goto alsa_error; int tmp = 1; snd_mixer_selem_get_playback_switch (elem, SND_MIXER_SCHN_FRONT_LEFT, &tmp); *mute = !tmp; if (!snd_mixer_selem_has_playback_switch_joined(elem)) { snd_mixer_selem_get_playback_switch (elem, SND_MIXER_SCHN_FRONT_RIGHT, &tmp); *mute &= !tmp; } break; } } snd_mixer_close(handle); return CONTROL_OK; } } //end switch return CONTROL_UNKNOWN; alsa_error: if (handle) snd_mixer_close(handle); return CONTROL_ERROR; }
static int reconfig(struct vf_instance *vf, struct mp_image_params *in, struct mp_image_params *out) { int width = in->w, height = in->h, d_width = in->d_w, d_height = in->d_h; unsigned int outfmt = in->imgfmt; unsigned int best = find_best_out(vf, outfmt); int round_w = 0, round_h = 0; if (!best) { MP_WARN(vf, "SwScale: no supported outfmt found :(\n"); return -1; } vf->next->query_format(vf->next, best); vf->priv->w = vf->priv->cfg_w; vf->priv->h = vf->priv->cfg_h; if (vf->priv->w <= -8) { vf->priv->w += 8; round_w = 1; } if (vf->priv->h <= -8) { vf->priv->h += 8; round_h = 1; } if (vf->priv->w < -3 || vf->priv->h < -3 || (vf->priv->w < -1 && vf->priv->h < -1)) { // TODO: establish a direct connection to the user's brain // and find out what the heck he thinks MPlayer should do // with this nonsense. MP_ERR(vf, "SwScale: EUSERBROKEN Check your parameters, they make no sense!\n"); return -1; } if (vf->priv->w == -1) vf->priv->w = width; if (vf->priv->w == 0) vf->priv->w = d_width; if (vf->priv->h == -1) vf->priv->h = height; if (vf->priv->h == 0) vf->priv->h = d_height; if (vf->priv->w == -3) vf->priv->w = vf->priv->h * width / height; if (vf->priv->w == -2) vf->priv->w = vf->priv->h * d_width / d_height; if (vf->priv->h == -3) vf->priv->h = vf->priv->w * height / width; if (vf->priv->h == -2) vf->priv->h = vf->priv->w * d_height / d_width; if (round_w) vf->priv->w = ((vf->priv->w + 8) / 16) * 16; if (round_h) vf->priv->h = ((vf->priv->h + 8) / 16) * 16; // check for upscaling, now that all parameters had been applied if (vf->priv->noup) { if ((vf->priv->w > width) + (vf->priv->h > height) >= vf->priv->noup) { vf->priv->w = width; vf->priv->h = height; } } MP_DBG(vf, "SwScale: scaling %dx%d %s to %dx%d %s \n", width, height, vo_format_name(outfmt), vf->priv->w, vf->priv->h, vo_format_name(best)); // Compute new d_width and d_height, preserving aspect // while ensuring that both are >= output size in pixels. if (vf->priv->h * d_width > vf->priv->w * d_height) { d_width = vf->priv->h * d_width / d_height; d_height = vf->priv->h; } else { d_height = vf->priv->w * d_height / d_width; d_width = vf->priv->w; } *out = *in; out->w = vf->priv->w; out->h = vf->priv->h; out->d_w = d_width; out->d_h = d_height; out->imgfmt = best; // Second-guess what libswscale is going to output and what not. // It depends what libswscale supports for in/output, and what makes sense. struct mp_imgfmt_desc s_fmt = mp_imgfmt_get_desc(in->imgfmt); struct mp_imgfmt_desc d_fmt = mp_imgfmt_get_desc(out->imgfmt); // keep colorspace settings if the data stays in yuv if (!(s_fmt.flags & MP_IMGFLAG_YUV) || !(d_fmt.flags & MP_IMGFLAG_YUV)) { out->colorspace = MP_CSP_AUTO; out->colorlevels = MP_CSP_LEVELS_AUTO; } mp_image_params_guess_csp(out); mp_sws_set_from_cmdline(vf->priv->sws, vf->chain->opts->vo.sws_opts); vf->priv->sws->flags |= vf->priv->v_chr_drop << SWS_SRC_V_CHR_DROP_SHIFT; vf->priv->sws->flags |= vf->priv->accurate_rnd * SWS_ACCURATE_RND; vf->priv->sws->src = *in; vf->priv->sws->dst = *out; if (mp_sws_reinit(vf->priv->sws) < 0) { // error... MP_WARN(vf, "Couldn't init libswscale for this setup\n"); return -1; } return 0; }