bool ca_init_chmap(struct ao *ao, AudioDeviceID device) { void *ta_ctx = talloc_new(NULL); struct mp_chmap_sel chmap_sel = {.tmp = ta_ctx}; struct mp_chmap chmap = {0}; AudioChannelLayout *ml = ca_query_layout(ao, device, ta_ctx); if (ml && ca_layout_to_mp_chmap(ao, ml, &chmap)) mp_chmap_sel_add_map(&chmap_sel, &chmap); AudioChannelLayout *sl = ca_query_stereo_layout(ao, device, ta_ctx); if (sl && ca_layout_to_mp_chmap(ao, sl, &chmap)) mp_chmap_sel_add_map(&chmap_sel, &chmap); if (!ao_chmap_sel_adjust(ao, &chmap_sel, &ao->channels)) { MP_ERR(ao, "could not select a suitable channel map among the " "hardware supported ones. Make sure to configure your " "output device correctly in 'Audio MIDI Setup.app'\n"); goto coreaudio_error; } talloc_free(ta_ctx); return true; coreaudio_error: talloc_free(ta_ctx); return false; }
static void ca_retrieve_layouts(struct ao *ao, struct mp_chmap_sel *s, AudioDeviceID device) { void *ta_ctx = talloc_new(NULL); struct mp_chmap chmap; AudioChannelLayout *ml = ca_query_layout(ao, device, ta_ctx); if (ml && ca_layout_to_mp_chmap(ao, ml, &chmap)) mp_chmap_sel_add_map(s, &chmap); AudioChannelLayout *sl = ca_query_stereo_layout(ao, device, ta_ctx); if (sl && ca_layout_to_mp_chmap(ao, sl, &chmap)) mp_chmap_sel_add_map(s, &chmap); talloc_free(ta_ctx); }
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; }
// fmt carries the input format. Change it to the best next-possible format // the encoder likely accepts. static void select_encode_format(AVCodecContext *c, struct mp_audio *fmt) { int formats[AF_FORMAT_COUNT]; af_get_best_sample_formats(fmt->format, formats); for (int n = 0; formats[n]; n++) { const enum AVSampleFormat *lf = c->codec->sample_fmts; for (int i = 0; lf && lf[i] != AV_SAMPLE_FMT_NONE; i++) { int mpfmt = af_from_avformat(lf[i]); if (mpfmt && mpfmt == formats[n]) { mp_audio_set_format(fmt, mpfmt); goto done_fmt; } } } done_fmt: ; int rate = af_select_best_samplerate(fmt->rate, c->codec->supported_samplerates); if (rate > 0) fmt->rate = rate; struct mp_chmap_sel sel = {0}; const uint64_t *lch = c->codec->channel_layouts; for (int n = 0; lch && lch[n]; n++) { struct mp_chmap chmap = {0}; mp_chmap_from_lavc(&chmap, lch[n]); mp_chmap_sel_add_map(&sel, &chmap); } struct mp_chmap res = fmt->channels; mp_chmap_sel_adjust(&sel, &res); if (!mp_chmap_is_empty(&res)) mp_audio_set_channels(fmt, &res); }
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; }
bool ca_init_chmap(struct ao *ao, AudioDeviceID device) { struct mp_chmap_sel chmap_sel = {0}; ca_retrieve_layouts(ao, &chmap_sel, device); if (!chmap_sel.num_chmaps) mp_chmap_sel_add_map(&chmap_sel, &(struct mp_chmap)MP_CHMAP_INIT_STEREO); mp_chmap_sel_add_map(&chmap_sel, &(struct mp_chmap)MP_CHMAP_INIT_MONO); if (!ao_chmap_sel_adjust(ao, &chmap_sel, &ao->channels)) { MP_ERR(ao, "could not select a suitable channel map among the " "hardware supported ones. Make sure to configure your " "output device correctly in 'Audio MIDI Setup.app'\n"); return false; } return true; }
/* * open device and setup parameters * return: 0=success -1=fail */ static int init(struct ao *ao) { struct priv *p = ao->priv; struct af_to_par { int format, bits, sig, le; } static const af_to_par[] = { {AF_FORMAT_U8, 8, 0, 0}, {AF_FORMAT_S8, 8, 1, 0}, {AF_FORMAT_U16_LE, 16, 0, 1}, {AF_FORMAT_U16_BE, 16, 0, 0}, {AF_FORMAT_S16_LE, 16, 1, 1}, {AF_FORMAT_S16_BE, 16, 1, 0}, {AF_FORMAT_U24_LE, 16, 0, 1}, {AF_FORMAT_U24_BE, 24, 0, 0}, {AF_FORMAT_S24_LE, 24, 1, 1}, {AF_FORMAT_S24_BE, 24, 1, 0}, {AF_FORMAT_U32_LE, 32, 0, 1}, {AF_FORMAT_U32_BE, 32, 0, 0}, {AF_FORMAT_S32_LE, 32, 1, 1}, {AF_FORMAT_S32_BE, 32, 1, 0} }, *ap; int i; p->hdl = sio_open(p->dev, SIO_PLAY, 0); if (p->hdl == NULL) { MP_ERR(ao, "can't open sndio %s\n", p->dev); goto error; } ao->format = af_fmt_from_planar(ao->format); sio_initpar(&p->par); for (i = 0, ap = af_to_par;; i++, ap++) { if (i == sizeof(af_to_par) / sizeof(struct af_to_par)) { MP_VERBOSE(ao, "unsupported format\n"); p->par.bits = 16; p->par.sig = 1; p->par.le = SIO_LE_NATIVE; break; } if (ap->format == ao->format) { p->par.bits = ap->bits; p->par.sig = ap->sig; if (ap->bits > 8) p->par.le = ap->le; if (ap->bits != SIO_BPS(ap->bits)) p->par.bps = ap->bits / 8; break; } } p->par.rate = ao->samplerate; struct mp_chmap_sel sel = {0}; for (int n = 0; n < MP_NUM_CHANNELS+1; n++) mp_chmap_sel_add_map(&sel, &sndio_layouts[n]); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto error; p->par.pchan = ao->channels.num; p->par.appbufsz = p->par.rate * 250 / 1000; /* 250ms buffer */ p->par.round = p->par.rate * 10 / 1000; /* 10ms block size */ if (!sio_setpar(p->hdl, &p->par)) { MP_ERR(ao, "couldn't set params\n"); goto error; } if (!sio_getpar(p->hdl, &p->par)) { MP_ERR(ao, "couldn't get params\n"); goto error; } if (p->par.bits == 8 && p->par.bps == 1) { ao->format = p->par.sig ? AF_FORMAT_S8 : AF_FORMAT_U8; } else if (p->par.bits == 16 && p->par.bps == 2) { ao->format = p->par.sig ? (p->par.le ? AF_FORMAT_S16_LE : AF_FORMAT_S16_BE) : (p->par.le ? AF_FORMAT_U16_LE : AF_FORMAT_U16_BE); } else if ((p->par.bits == 24 || p->par.msb) && p->par.bps == 3) { ao->format = p->par.sig ? (p->par.le ? AF_FORMAT_S24_LE : AF_FORMAT_S24_BE) : (p->par.le ? AF_FORMAT_U24_LE : AF_FORMAT_U24_BE); } else if ((p->par.bits == 32 || p->par.msb) && p->par.bps == 4) { ao->format = p->par.sig ? (p->par.le ? AF_FORMAT_S32_LE : AF_FORMAT_S32_BE) : (p->par.le ? AF_FORMAT_U32_LE : AF_FORMAT_U32_BE); } else { MP_ERR(ao, "couldn't set format\n"); goto error; } ao->bps = p->par.bps * p->par.pchan * p->par.rate; p->havevol = sio_onvol(p->hdl, volcb, p); sio_onmove(p->hdl, movecb, p); p->delay = 0; if (!sio_start(p->hdl)) MP_ERR(ao, "init: couldn't start\n"); p->pfd = calloc (sio_nfds(p->hdl), sizeof (struct pollfd)); if (!p->pfd) goto error; return 0; error: if (p->hdl) sio_close(p->hdl); return -1; }