diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/decode/ad_lavc.c | 7 | ||||
-rw-r--r-- | audio/decode/ad_spdif.c | 7 | ||||
-rw-r--r-- | audio/filter/af_lavcac3enc.c | 180 | ||||
-rw-r--r-- | audio/out/ao_alsa.c | 78 | ||||
-rw-r--r-- | audio/out/ao_coreaudio.c | 5 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_utils.c | 27 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_utils.h | 1 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 82 | ||||
-rw-r--r-- | audio/out/ao_opensles.c | 1 | ||||
-rw-r--r-- | audio/out/ao_oss.c | 2 | ||||
-rw-r--r-- | audio/out/ao_wasapi.c | 4 | ||||
-rw-r--r-- | audio/out/ao_wasapi_changenotify.c | 1 | ||||
-rw-r--r-- | audio/out/push.c | 27 |
13 files changed, 282 insertions, 140 deletions
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 8a6bb4061b..f48993f81f 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -45,6 +45,7 @@ struct priv { uint32_t skip_samples, trim_samples; bool preroll_done; double next_pts; + bool needs_reset; AVRational codec_timebase; }; @@ -173,6 +174,7 @@ static int control(struct dec_audio *da, int cmd, void *arg) ctx->trim_samples = 0; ctx->preroll_done = false; ctx->next_pts = MP_NOPTS_VALUE; + ctx->needs_reset = false; return CONTROL_TRUE; } return CONTROL_UNKNOWN; @@ -192,6 +194,9 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, int got_frame = 0; av_frame_unref(priv->avframe); + if (priv->needs_reset) + control(da, ADCTRL_RESET, NULL); + #if HAVE_AVCODEC_NEW_CODEC_API int ret = avcodec_send_packet(avctx, &pkt); if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { @@ -200,6 +205,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt, ret = avcodec_receive_frame(avctx, priv->avframe); if (ret >= 0) got_frame = 1; + if (ret == AVERROR_EOF) + priv->needs_reset = true; if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) ret = 0; } diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c index eb2e2bb0a9..56e4a8102d 100644 --- a/audio/decode/ad_spdif.c +++ b/audio/decode/ad_spdif.c @@ -116,9 +116,16 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt) goto done; } +#if HAVE_AVCODEC_NEW_CODEC_API + if (avcodec_send_packet(ctx, pkt) < 0) + goto done; + if (avcodec_receive_frame(ctx, frame) < 0) + goto done; +#else int got_frame = 0; if (avcodec_decode_audio4(ctx, frame, &got_frame, pkt) < 1 || !got_frame) goto done; +#endif profile = ctx->profile; diff --git a/audio/filter/af_lavcac3enc.c b/audio/filter/af_lavcac3enc.c index 973e688aaa..26c9cbff58 100644 --- a/audio/filter/af_lavcac3enc.c +++ b/audio/filter/af_lavcac3enc.c @@ -31,9 +31,12 @@ #include <libavutil/bswap.h> #include <libavutil/mem.h> +#include "config.h" + #include "common/common.h" #include "af.h" #include "audio/audio_buffer.h" +#include "audio/chmap_sel.h" #include "audio/fmt-conversion.h" @@ -54,13 +57,50 @@ typedef struct af_ac3enc_s { struct mp_audio *pending; // unconsumed input data int in_samples; // samples of input per AC3 frame int out_samples; // upper bound on encoded output per AC3 frame - int in_sampleformat; int cfg_add_iec61937_header; int cfg_bit_rate; int cfg_min_channel_num; + char *cfg_encoder; } af_ac3enc_t; +// 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); +} + // Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { @@ -76,23 +116,17 @@ static int control(struct af_instance *af, int cmd, void *arg) if (!af_fmt_is_pcm(in->format) || in->nch < s->cfg_min_channel_num) return AF_DETACH; - mp_audio_set_format(in, s->in_sampleformat); + // At least currently, the AC3 encoder doesn't export sample rates. + in->rate = 48000; + select_encode_format(s->lavc_actx, in); - if (in->rate != 48000 && in->rate != 44100 && in->rate != 32000) - in->rate = 48000; af->data->rate = in->rate; - - mp_chmap_reorder_to_lavc(&in->channels); - if (in->nch > AC3_MAX_CHANNELS) - mp_audio_set_num_channels(in, AC3_MAX_CHANNELS); - 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; - s->in_samples = AC3_FRAME_SIZE; if (s->cfg_add_iec61937_header) { s->out_samples = AC3_FRAME_SIZE; } else { @@ -100,14 +134,11 @@ static int control(struct af_instance *af, int cmd, void *arg) } mp_audio_copy_config(s->input, in); - mp_audio_realloc(s->input, s->in_samples); - s->input->samples = 0; talloc_free(s->pending); s->pending = NULL; - MP_DBG(af, "af_lavcac3enc reinit: %d, %d, %d.\n", - in->nch, in->rate, s->in_samples); + 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]; @@ -118,6 +149,7 @@ static int control(struct af_instance *af, int cmd, void *arg) 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; @@ -127,14 +159,24 @@ static int control(struct af_instance *af, int cmd, void *arg) 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; + } } - if (s->lavc_actx->frame_size != AC3_FRAME_SIZE) { - MP_ERR(af, "lavcac3enc: unexpected ac3 " - "encoder frame size %d\n", s->lavc_actx->frame_size); - return AF_ERROR; - } + s->in_samples = s->lavc_actx->frame_size; + mp_audio_realloc(s->input, s->in_samples); + s->input->samples = 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; + return AF_OK; } return AF_UNKNOWN; } @@ -199,31 +241,75 @@ static bool fill_buffer(struct af_instance *af) return s->input->samples >= s->in_samples; } -static int filter_out(struct af_instance *af) +// Return <0 on error, 0 on need more input, 1 on success (and *frame set). +// To actually advance the read pointer, set s->input->samples=0 afterwards. +static int read_input_frame(struct af_instance *af, AVFrame *frame) { af_ac3enc_t *s = af->priv; if (!fill_buffer(af)) return 0; // need more input - AVFrame *frame = av_frame_alloc(); - if (!frame) { - MP_FATAL(af, "Could not allocate memory \n"); - return -1; - } - int err = -1; - frame->nb_samples = s->in_samples; frame->format = s->lavc_actx->sample_fmt; frame->channel_layout = s->lavc_actx->channel_layout; +#if LIBAVUTIL_VERSION_MICRO >= 100 + frame->channels = s->lavc_actx->channels; +#endif assert(s->input->num_planes <= AV_NUM_DATA_POINTERS); frame->extended_data = frame->data; for (int n = 0; n < s->input->num_planes; n++) frame->data[n] = s->input->planes[n]; frame->linesize[0] = s->input->samples * s->input->sstride; + return 1; +} + +static int filter_out(struct af_instance *af) +{ + af_ac3enc_t *s = af->priv; + + 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); +#if HAVE_AVCODEC_NEW_CODEC_API + // 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->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; + } +#else + err = read_input_frame(af, frame); + if (err < 0) + goto done; + if (err == 0) + goto done; + err = -1; int ok; int lavc_ret = avcodec_encode_audio2(s->lavc_actx, &pkt, frame, &ok); av_frame_free(&frame); @@ -232,9 +318,10 @@ static int filter_out(struct af_instance *af) MP_FATAL(af, "Encode failed.\n"); goto done; } +#endif MP_DBG(af, "avcodec_encode_audio got %d, pending %d.\n", - pkt.size, s->pending->samples); + pkt.size, s->pending->samples); struct mp_audio *out = mp_audio_pool_get(af->out_pool, af->data, s->out_samples); @@ -287,9 +374,9 @@ static int af_open(struct af_instance* af){ af->filter_frame = filter_frame; af->filter_out = filter_out; - s->lavc_acodec = avcodec_find_encoder_by_name("ac3"); + s->lavc_acodec = avcodec_find_encoder_by_name(s->cfg_encoder); if (!s->lavc_acodec) { - MP_ERR(af, "Audio LAVC, couldn't find encoder for codec %s.\n", "ac3"); + MP_ERR(af, "Couldn't find encoder %s.\n", s->cfg_encoder); return AF_ERROR; } @@ -298,35 +385,30 @@ static int af_open(struct af_instance* af){ 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"); + // 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; } - MP_VERBOSE(af, "[af_lavcac3enc]: in sample format: %s\n", - af_fmt_to_str(s->in_sampleformat)); 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) + if (ac3_bitrate_tab[i] == s->cfg_bit_rate) { + s->bit_rate = ac3_bitrate_tab[i] * 1000; 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; + MP_WARN(af, "unable set unsupported bitrate %d, use default " + "bitrate (check manpage to see supported bitrates).\n", + s->cfg_bit_rate); } } @@ -344,12 +426,14 @@ const struct af_info af_info_lavcac3enc = { .cfg_add_iec61937_header = 1, .cfg_bit_rate = 640, .cfg_min_channel_num = 3, + .cfg_encoder = "ac3", }, .options = (const struct m_option[]) { OPT_FLAG("tospdif", cfg_add_iec61937_header, 0), OPT_CHOICE_OR_INT("bitrate", cfg_bit_rate, 0, 32, 640, ({"auto", 0}, {"default", 0})), OPT_INTRANGE("minch", cfg_min_channel_num, 0, 2, 6), + OPT_STRING("encoder", cfg_encoder, 0), {0} }, }; diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index 9ffd4792ee..d09f5fc499 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -58,6 +58,8 @@ struct priv { snd_pcm_uframes_t buffersize; snd_pcm_uframes_t outburst; + snd_output_t *output; + char *cfg_device; char *cfg_mixer_device; char *cfg_mixer_name; @@ -477,6 +479,22 @@ static int set_chmap(struct ao *ao, struct mp_chmap *dev_chmap, int num_channels #endif /* else HAVE_CHMAP_API */ +static void dump_hw_params(struct ao *ao, int msglevel, const char *msg, + snd_pcm_hw_params_t *hw_params) +{ + struct priv *p = ao->priv; + int err; + + err = snd_pcm_hw_params_dump(hw_params, p->output); + CHECK_ALSA_WARN("Dump hwparams error"); + + char *tmp = NULL; + size_t tmp_s = snd_output_buffer_string(p->output, &tmp); + if (tmp) + mp_msg(ao->log, msglevel, "%s---\n%.*s---\n", msg, (int)tmp_s, tmp); + snd_output_flush(p->output); +} + static int map_iec958_srate(int srate) { switch (srate) { @@ -520,7 +538,7 @@ static char *append_params(void *ta_parent, const char *device, const char *p) abort(); } -static int try_open_device(struct ao *ao, const char *device) +static int try_open_device(struct ao *ao, const char *device, int mode) { struct priv *p = ao->priv; int err; @@ -534,7 +552,7 @@ static int try_open_device(struct ao *ao, const char *device) 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); - err = snd_pcm_open(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, 0); + err = snd_pcm_open(&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, mode); if (err < 0) { // Some spdif-capable devices do not accept the AES0 parameter, // and instead require the iec958 pseudo-device (they will play @@ -547,13 +565,13 @@ static int try_open_device(struct ao *ao, const char *device) MP_VERBOSE(ao, "got error %d; opening iec fallback device '%s'\n", err, ac3_device); err = snd_pcm_open - (&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, 0); + (&p->alsa, ac3_device, SND_PCM_STREAM_PLAYBACK, mode); } } talloc_free(tmp); } else { MP_VERBOSE(ao, "opening device '%s'\n", device); - err = snd_pcm_open(&p->alsa, device, SND_PCM_STREAM_PLAYBACK, 0); + err = snd_pcm_open(&p->alsa, device, SND_PCM_STREAM_PLAYBACK, mode); } return err; @@ -563,6 +581,10 @@ static void uninit(struct ao *ao) { struct priv *p = ao->priv; + if (p->output) + snd_output_close(p->output); + p->output = NULL; + if (p->alsa) { int err; @@ -574,20 +596,35 @@ static void uninit(struct ao *ao) alsa_error: ; } -static int init_device(struct ao *ao) +#define INIT_DEVICE_ERR_GENERIC -1 +#define INIT_DEVICE_ERR_HWPARAMS -2 +static int init_device(struct ao *ao, int mode) { struct priv *p = ao->priv; + int ret = INIT_DEVICE_ERR_GENERIC; + char *tmp; + size_t tmp_s; int err; + err = snd_output_buffer_open(&p->output); + CHECK_ALSA_ERROR("Unable to create output buffer"); + const char *device = "default"; if (ao->device) device = ao->device; if (p->cfg_device && p->cfg_device[0]) device = p->cfg_device; - err = try_open_device(ao, device); + err = try_open_device(ao, device, mode); CHECK_ALSA_ERROR("Playback open error"); + err = snd_pcm_dump(p->alsa, p->output); + CHECK_ALSA_WARN("Dump PCM error"); + tmp_s = snd_output_buffer_string(p->output, &tmp); + if (tmp) + MP_DBG(ao, "PCM setup:\n---\n%.*s---\n", (int)tmp_s, tmp); + snd_output_flush(p->output); + err = snd_pcm_nonblock(p->alsa, 0); CHECK_ALSA_WARN("Unable to set blocking mode"); @@ -597,12 +634,15 @@ static int init_device(struct ao *ao) err = snd_pcm_hw_params_any(p->alsa, alsa_hwparams); CHECK_ALSA_ERROR("Unable to get initial parameters"); + dump_hw_params(ao, MSGL_DEBUG, "Start HW params:\n", alsa_hwparams); + // Some ALSA drivers have broken delay reporting, so disable the ALSA // resampling plugin by default. if (!p->cfg_resample) { err = snd_pcm_hw_params_set_rate_resample(p->alsa, alsa_hwparams, 0); CHECK_ALSA_ERROR("Unable to disable resampling"); } + dump_hw_params(ao, MSGL_DEBUG, "HW params after rate:\n", alsa_hwparams); snd_pcm_access_t access = af_fmt_is_planar(ao->format) ? SND_PCM_ACCESS_RW_NONINTERLEAVED @@ -614,6 +654,7 @@ static int init_device(struct ao *ao) err = snd_pcm_hw_params_set_access(p->alsa, alsa_hwparams, access); } CHECK_ALSA_ERROR("Unable to set access type"); + dump_hw_params(ao, MSGL_DEBUG, "HW params after access:\n", alsa_hwparams); bool found_format = false; int try_formats[AF_FORMAT_COUNT]; @@ -637,6 +678,7 @@ static int init_device(struct ao *ao) err = snd_pcm_hw_params_set_format(p->alsa, alsa_hwparams, p->alsa_fmt); CHECK_ALSA_ERROR("Unable to set format"); + dump_hw_params(ao, MSGL_DEBUG, "HW params after format:\n", alsa_hwparams); struct mp_chmap dev_chmap = ao->channels; if (af_fmt_is_spdif(ao->format) || p->cfg_ignore_chmap) { @@ -656,6 +698,7 @@ static int init_device(struct ao *ao) err = snd_pcm_hw_params_set_channels_near (p->alsa, alsa_hwparams, &num_channels); CHECK_ALSA_ERROR("Unable to set channels"); + dump_hw_params(ao, MSGL_DEBUG, "HW params after channels:\n", alsa_hwparams); if (num_channels > MP_NUM_CHANNELS) { MP_FATAL(ao, "Too many audio channels (%d).\n", num_channels); @@ -665,6 +708,7 @@ static int init_device(struct ao *ao) err = snd_pcm_hw_params_set_rate_near (p->alsa, alsa_hwparams, &ao->samplerate, NULL); CHECK_ALSA_ERROR("Unable to set samplerate-2"); + dump_hw_params(ao, MSGL_DEBUG, "HW params after rate-2:\n", alsa_hwparams); snd_pcm_hw_params_t *hwparams_backup; snd_pcm_hw_params_alloca(&hwparams_backup); @@ -682,9 +726,14 @@ static int init_device(struct ao *ao) if (err < 0) snd_pcm_hw_params_copy(alsa_hwparams, hwparams_backup); + dump_hw_params(ao, MSGL_V, "Going to set final HW params:\n", alsa_hwparams); + /* finally install hardware parameters */ err = snd_pcm_hw_params(p->alsa, alsa_hwparams); + ret = INIT_DEVICE_ERR_HWPARAMS; CHECK_ALSA_ERROR("Unable to set hw-parameters"); + ret = INIT_DEVICE_ERR_GENERIC; + dump_hw_params(ao, MSGL_DEBUG, "Final HW params:\n", alsa_hwparams); if (set_chmap(ao, &dev_chmap, num_channels) < 0) goto alsa_error; @@ -740,7 +789,7 @@ static int init_device(struct ao *ao) alsa_error: uninit(ao); - return -1; + return ret; } static int init(struct ao *ao) @@ -751,7 +800,18 @@ static int init(struct ao *ao) MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version()); - int r = init_device(ao); + int mode = 0; + int r = init_device(ao, mode); + if (r == INIT_DEVICE_ERR_HWPARAMS) { + // With some drivers, ALSA appears to be unable to set valid hwparams, + // but they work if at least SND_PCM_NO_AUTO_FORMAT is set. Also, it + // appears you can set this flag only on opening a device, thus there + // is the need to retry opening the device. + MP_WARN(ao, "Attempting to work around even more ALSA bugs...\n"); + mode |= SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT | + SND_PCM_NO_AUTO_RESAMPLE; + r = init_device(ao, mode); + } // Sometimes, ALSA will advertise certain chmaps, but it's not possible to // set them. This can happen with dmix: as of alsa 1.0.29, dmix can do @@ -773,7 +833,7 @@ static int init(struct ao *ao) MP_VERBOSE(ao, "Working around braindead dmix multichannel behavior.\n"); uninit(ao); ao->channels = without_na; - r = init_device(ao); + r = init_device(ao, mode); } } diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 471ab6d928..b0a5dc0da1 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -133,11 +133,6 @@ static bool reinit_device(struct ao *ao) { OSStatus err = ca_select_device(ao, ao->device, &p->device); CHECK_CA_ERROR("failed to select device"); - char *uid; - err = CA_GET_STR(p->device, kAudioDevicePropertyDeviceUID, &uid); - CHECK_CA_ERROR("failed to get device UID"); - ao->detected_device = talloc_steal(ao, uid); - return true; coreaudio_error: diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index 6b5d8a7195..8f9690fc22 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -323,6 +323,9 @@ bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream) for (int i = 0; i < n_formats; i++) { AudioStreamBasicDescription asbd = formats[i].mFormat; + + ca_print_asbd(ao, "- ", &asbd); + if (ca_formatid_is_compressed(asbd.mFormatID)) { talloc_free(formats); return true; @@ -334,30 +337,6 @@ coreaudio_error: return false; } -bool ca_device_supports_compressed(struct ao *ao, AudioDeviceID device) -{ - AudioStreamID *streams = NULL; - size_t n_streams; - - /* Retrieve all the output streams. */ - OSStatus err = - CA_GET_ARY_O(device, kAudioDevicePropertyStreams, &streams, &n_streams); - - CHECK_CA_ERROR("could not get number of streams."); - - for (int i = 0; i < n_streams; i++) { - if (ca_stream_supports_compressed(ao, streams[i])) { - talloc_free(streams); - return true; - } - } - - talloc_free(streams); - -coreaudio_error: - return false; -} - OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid) { *pid = getpid(); diff --git a/audio/out/ao_coreaudio_utils.h b/audio/out/ao_coreaudio_utils.h index 780c56864b..5cc7db53be 100644 --- a/audio/out/ao_coreaudio_utils.h +++ b/audio/out/ao_coreaudio_utils.h @@ -65,7 +65,6 @@ bool ca_asbd_is_better(AudioStreamBasicDescription *req, int64_t ca_frames_to_us(struct ao *ao, uint32_t frames); int64_t ca_get_latency(const AudioTimeStamp *ts); -bool ca_device_supports_compressed(struct ao *ao, AudioDeviceID device); bool ca_stream_supports_compressed(struct ao *ao, AudioStreamID stream); OSStatus ca_lock_device(AudioDeviceID device, pid_t *pid); OSStatus ca_unlock_device(AudioDeviceID device, pid_t *pid); diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index bf1728682a..572874d27c 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -42,6 +42,7 @@ struct priv { uint8_t *buffer; size_t buffer_size; AVStream *stream; + AVCodecContext *codec; int pcmhack; int aframesize; int aframecount; @@ -98,15 +99,14 @@ static int init(struct ao *ao) pthread_mutex_lock(&ao->encode_lavc_ctx->lock); - ac->stream = encode_lavc_alloc_stream(ao->encode_lavc_ctx, - AVMEDIA_TYPE_AUDIO); - - if (!ac->stream) { - MP_ERR(ao, "could not get a new audio stream\n"); - goto fail; + if (encode_lavc_alloc_stream(ao->encode_lavc_ctx, + AVMEDIA_TYPE_AUDIO, + &ac->stream, &ac->codec) < 0) { + MP_ERR(ao, "could not get a new audio stream\n"); + goto fail; } - codec = encode_lavc_get_codec(ao->encode_lavc_ctx, ac->stream); + codec = ao->encode_lavc_ctx->ac; int samplerate = af_select_best_samplerate(ao->samplerate, codec->supported_samplerates); @@ -118,40 +118,40 @@ static int init(struct ao *ao) // Using codec->time_bvase is deprecated, but needed for older lavf. ac->stream->time_base.num = 1; ac->stream->time_base.den = ao->samplerate; - ac->stream->codec->time_base.num = 1; - ac->stream->codec->time_base.den = ao->samplerate; + ac->codec->time_base.num = 1; + ac->codec->time_base.den = ao->samplerate; - ac->stream->codec->sample_rate = ao->samplerate; + ac->codec->sample_rate = ao->samplerate; struct mp_chmap_sel sel = {0}; mp_chmap_sel_add_any(&sel); if (!ao_chmap_sel_adjust(ao, &sel, &ao->channels)) goto fail; mp_chmap_reorder_to_lavc(&ao->channels); - ac->stream->codec->channels = ao->channels.num; - ac->stream->codec->channel_layout = mp_chmap_to_lavc(&ao->channels); + ac->codec->channels = ao->channels.num; + ac->codec->channel_layout = mp_chmap_to_lavc(&ao->channels); - ac->stream->codec->sample_fmt = AV_SAMPLE_FMT_NONE; + ac->codec->sample_fmt = AV_SAMPLE_FMT_NONE; select_format(ao, codec); ac->sample_size = af_fmt_to_bytes(ao->format); - ac->stream->codec->sample_fmt = af_to_avformat(ao->format); - ac->stream->codec->bits_per_raw_sample = ac->sample_size * 8; + ac->codec->sample_fmt = af_to_avformat(ao->format); + ac->codec->bits_per_raw_sample = ac->sample_size * 8; - if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->stream) < 0) + if (encode_lavc_open_codec(ao->encode_lavc_ctx, ac->codec) < 0) goto fail; ac->pcmhack = 0; - if (ac->stream->codec->frame_size <= 1) - ac->pcmhack = av_get_bits_per_sample(ac->stream->codec->codec_id) / 8; + if (ac->codec->frame_size <= 1) + ac->pcmhack = av_get_bits_per_sample(ac->codec->codec_id) / 8; if (ac->pcmhack) { ac->aframesize = 16384; // "enough" ac->buffer_size = ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200; } else { - ac->aframesize = ac->stream->codec->frame_size; + ac->aframesize = ac->codec->frame_size; ac->buffer_size = ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200; } @@ -203,7 +203,7 @@ static void uninit(struct ao *ao) double outpts = ac->expected_next_pts; if (!ectx->options->rawts && ectx->options->copyts) outpts += ectx->discontinuity_pts_offset; - outpts += encode_lavc_getoffset(ectx, ac->stream); + outpts += encode_lavc_getoffset(ectx, ac->codec); while (encode(ao, outpts, NULL) > 0) ; } @@ -252,25 +252,25 @@ static int encode(struct ao *ao, double apts, void **data) if (ectx->options->rawts || ectx->options->copyts) { // real audio pts - frame->pts = floor(apts * ac->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); + 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->stream->codec->time_base.den / ac->stream->codec->time_base.num + 0.5); + 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->stream->codec->time_base, ac->worst_time_base); + 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->stream->codec->time_base); + frame->pts = av_rescale_q(frame_pts, ac->worst_time_base, ac->codec->time_base); } ac->lastpts = frame_pts; - frame->quality = ac->stream->codec->global_quality; - status = avcodec_encode_audio2(ac->stream->codec, &packet, frame, &gotpacket); + frame->quality = ac->codec->global_quality; + status = avcodec_encode_audio2(ac->codec, &packet, frame, &gotpacket); if (!status) { if (ac->savepts == AV_NOPTS_VALUE) @@ -281,7 +281,7 @@ static int encode(struct ao *ao, double apts, void **data) } else { - status = avcodec_encode_audio2(ac->stream->codec, &packet, NULL, &gotpacket); + status = avcodec_encode_audio2(ac->codec, &packet, NULL, &gotpacket); } if(status) { @@ -295,7 +295,7 @@ static int encode(struct ao *ao, double apts, void **data) MP_DBG(ao, "got pts %f (playback time: %f); out size: %d\n", apts, realapts, packet.size); - encode_lavc_write_stats(ao->encode_lavc_ctx, ac->stream); + encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); packet.stream_index = ac->stream->index; @@ -307,20 +307,20 @@ static int encode(struct ao *ao, double apts, void **data) } if (packet.pts != AV_NOPTS_VALUE) - packet.pts = av_rescale_q(packet.pts, ac->stream->codec->time_base, + packet.pts = av_rescale_q(packet.pts, ac->codec->time_base, ac->stream->time_base); if (packet.dts != AV_NOPTS_VALUE) - packet.dts = av_rescale_q(packet.dts, ac->stream->codec->time_base, + packet.dts = av_rescale_q(packet.dts, ac->codec->time_base, ac->stream->time_base); if(packet.duration > 0) - packet.duration = av_rescale_q(packet.duration, ac->stream->codec->time_base, + packet.duration = av_rescale_q(packet.duration, ac->codec->time_base, ac->stream->time_base); ac->savepts = AV_NOPTS_VALUE; - if (encode_lavc_write_frame(ao->encode_lavc_ctx, &packet) < 0) { + if (encode_lavc_write_frame(ao->encode_lavc_ctx, ac->stream, &packet) < 0) { MP_ERR(ao, "error writing at %f %f/%f\n", realapts, (double) ac->stream->time_base.num, (double) ac->stream->time_base.den); @@ -377,22 +377,22 @@ static int play(struct ao *ao, void **data, int samples, int flags) } if (ac->worst_time_base.den == 0) { - //if (ac->stream->codec->time_base.num / ac->stream->codec->time_base.den >= ac->stream->time_base.num / ac->stream->time_base.den) - if (ac->stream->codec->time_base.num * (double) ac->stream->time_base.den >= - ac->stream->time_base.num * (double) ac->stream->codec->time_base.den |