diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-07-10 01:06:17 +0200 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-07-10 01:06:17 +0200 |
commit | 76354385929b76b02b8c32a7b1cd4d669a8f2e0a (patch) | |
tree | 738a432ac5648098cf93101bf64a010cff47486a /audio/out | |
parent | 69e7b0d3ea4b75a8040ede5b9b7e6fa93ec68056 (diff) | |
parent | e518bf2c72fc862fbe1de1c98313a03fa0db2e98 (diff) | |
download | mpv-76354385929b76b02b8c32a7b1cd4d669a8f2e0a.tar.bz2 mpv-76354385929b76b02b8c32a7b1cd4d669a8f2e0a.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'audio/out')
-rw-r--r-- | audio/out/ao.c | 5 | ||||
-rw-r--r-- | audio/out/ao_coreaudio_utils.c | 7 | ||||
-rw-r--r-- | audio/out/ao_lavc.c | 197 | ||||
-rw-r--r-- | audio/out/ao_oss.c | 7 | ||||
-rw-r--r-- | audio/out/ao_wasapi.c | 2 | ||||
-rw-r--r-- | audio/out/ao_wasapi_changenotify.c | 2 |
6 files changed, 139 insertions, 81 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c index 9c0f644c75..c9d8f42b4a 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -490,10 +490,9 @@ struct ao_hotplug *ao_hotplug_create(struct mpv_global *global, static void get_devices(struct ao *ao, struct ao_device_list *list) { int num = list->num_devices; - if (ao->driver->list_devs) + if (ao->driver->list_devs) { ao->driver->list_devs(ao, list); - // Add at least a default entry - if (list->num_devices == num) { + } else { char name[80] = "Default"; if (num > 1) mp_snprintf_cat(name, sizeof(name), " (%s)", ao->driver->name); diff --git a/audio/out/ao_coreaudio_utils.c b/audio/out/ao_coreaudio_utils.c index 8f9690fc22..0bcc0d62a1 100644 --- a/audio/out/ao_coreaudio_utils.c +++ b/audio/out/ao_coreaudio_utils.c @@ -114,6 +114,13 @@ OSStatus ca_select_device(struct ao *ao, char* name, AudioDeviceID *device) kAudioObjectSystemObject, &p_addr, 0, 0, &size, &v); CFRelease(uid); CHECK_CA_ERROR("unable to query for device UID"); + + uint32_t is_alive = 1; + err = CA_GET(*device, kAudioDevicePropertyDeviceIsAlive, &is_alive); + CHECK_CA_ERROR("could not check whether device is alive (invalid device?)"); + + if (!is_alive) + MP_WARN(ao, "device is not alive!\n"); } else { // device not set by user, get the default one err = CA_GET(kAudioObjectSystemObject, diff --git a/audio/out/ao_lavc.c b/audio/out/ao_lavc.c index 572874d27c..6b4279ca87 100644 --- a/audio/out/ao_lavc.c +++ b/audio/out/ao_lavc.c @@ -39,8 +39,6 @@ #include "common/encode_lavc.h" struct priv { - uint8_t *buffer; - size_t buffer_size; AVStream *stream; AVCodecContext *codec; int pcmhack; @@ -146,18 +144,10 @@ static int init(struct ao *ao) if (ac->codec->frame_size <= 1) ac->pcmhack = av_get_bits_per_sample(ac->codec->codec_id) / 8; - if (ac->pcmhack) { + if (ac->pcmhack) ac->aframesize = 16384; // "enough" - ac->buffer_size = - ac->aframesize * ac->pcmhack * ao->channels.num * 2 + 200; - } else { + else ac->aframesize = ac->codec->frame_size; - ac->buffer_size = - ac->aframesize * ac->sample_size * ao->channels.num * 2 + 200; - } - if (ac->buffer_size < FF_MIN_BUFFER_SIZE) - ac->buffer_size = FF_MIN_BUFFER_SIZE; - ac->buffer = talloc_size(ac, ac->buffer_size); // enough frames for at least 0.25 seconds ac->framecount = ceil(ao->samplerate * 0.25 / ac->aframesize); @@ -182,7 +172,7 @@ fail: } // close audio device -static int encode(struct ao *ao, double apts, void **data); +static void encode(struct ao *ao, double apts, void **data); static void uninit(struct ao *ao) { struct priv *ac = ao->priv; @@ -199,12 +189,12 @@ static void uninit(struct ao *ao) return; } - if (ac->buffer) { + 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); - while (encode(ao, outpts, NULL) > 0) ; + encode(ao, outpts, NULL); } pthread_mutex_unlock(&ectx->lock); @@ -220,24 +210,130 @@ static int get_space(struct ao *ao) return ac->aframesize * ac->framecount; } +static void write_packet(struct ao *ao, AVPacket *packet) +{ + // TODO: Can we unify this with the equivalent video code path? + struct priv *ac = ao->priv; + + packet->stream_index = ac->stream->index; + if (packet->pts != AV_NOPTS_VALUE) { + packet->pts = av_rescale_q(packet->pts, + ac->codec->time_base, + ac->stream->time_base); + } else { + // Do we need this at all? Better be safe than sorry... + MP_WARN(ao, "encoder lost pts, why?\n"); + if (ac->savepts != MP_NOPTS_VALUE) { + packet->pts = av_rescale_q(ac->savepts, + ac->codec->time_base, + ac->stream->time_base); + } + } + if (packet->dts != AV_NOPTS_VALUE) { + 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->codec->time_base, + ac->stream->time_base); + } + + ac->savepts = AV_NOPTS_VALUE; + + if (encode_lavc_write_frame(ao->encode_lavc_ctx, + ac->stream, packet) < 0) { + MP_ERR(ao, "error writing at %d %d/%d\n", + (int) packet->pts, + ac->stream->time_base.num, + ac->stream->time_base.den); + return; + } +} + +static void encode_audio_and_write(struct ao *ao, AVFrame *frame) +{ + // TODO: Can we unify this with the equivalent video code path? + struct priv *ac = ao->priv; + AVPacket packet = {0}; + +#if HAVE_AVCODEC_NEW_CODEC_API + int status = avcodec_send_frame(ac->codec, frame); + if (status < 0) { + MP_ERR(ao, "error encoding at %d %d/%d\n", + frame ? (int) frame->pts : -1, + ac->codec->time_base.num, + ac->codec->time_base.den); + return; + } + for (;;) { + av_init_packet(&packet); + status = avcodec_receive_packet(ac->codec, &packet); + if (status == AVERROR(EAGAIN)) { // No more packets for now. + if (frame == NULL) { + MP_ERR(ao, "sent flush frame, got EAGAIN"); + } + break; + } + if (status == AVERROR_EOF) { // No more packets, ever. + if (frame != NULL) { + MP_ERR(ao, "sent audio frame, got EOF"); + } + break; + } + if (status < 0) { + MP_ERR(ao, "error encoding at %d %d/%d\n", + frame ? (int) frame->pts : -1, + ac->codec->time_base.num, + ac->codec->time_base.den); + break; + } + if (frame) { + if (ac->savepts == AV_NOPTS_VALUE) + ac->savepts = frame->pts; + } + encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); + write_packet(ao, &packet); + av_packet_unref(&packet); + } +#else + av_init_packet(&packet); + int got_packet = 0; + int status = avcodec_encode_audio2(ac->codec, &packet, frame, &got_packet); + if (status < 0) { + MP_ERR(ao, "error encoding at %d %d/%d\n", + frame ? (int) frame->pts : -1, + ac->codec->time_base.num, + ac->codec->time_base.den); + return; + } + if (!got_packet) { + return; + } + if (frame) { + if (ac->savepts == AV_NOPTS_VALUE) + ac->savepts = frame->pts; + } + encode_lavc_write_stats(ao->encode_lavc_ctx, ac->codec); + write_packet(ao, &packet); + av_packet_unref(&packet); +#endif +} + // must get exactly ac->aframesize amount of data -static int encode(struct ao *ao, double apts, void **data) +static void encode(struct ao *ao, double apts, void **data) { - AVPacket packet; struct priv *ac = ao->priv; struct encode_lavc_context *ectx = ao->encode_lavc_ctx; double realapts = ac->aframecount * (double) ac->aframesize / ao->samplerate; - int status, gotpacket; ac->aframecount++; if (data) ectx->audio_pts_offset = realapts - apts; - av_init_packet(&packet); - packet.data = ac->buffer; - packet.size = ac->buffer_size; if(data) { AVFrame *frame = av_frame_alloc(); frame->format = af_to_avformat(ao->format); @@ -270,64 +366,11 @@ static int encode(struct ao *ao, double apts, void **data) ac->lastpts = frame_pts; frame->quality = ac->codec->global_quality; - status = avcodec_encode_audio2(ac->codec, &packet, frame, &gotpacket); - - if (!status) { - if (ac->savepts == AV_NOPTS_VALUE) - ac->savepts = frame->pts; - } - + encode_audio_and_write(ao, frame); av_frame_free(&frame); } else - { - status = avcodec_encode_audio2(ac->codec, &packet, NULL, &gotpacket); - } - - if(status) { - MP_ERR(ao, "error encoding\n"); - return -1; - } - - if(!gotpacket) - return 0; - - 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->codec); - - packet.stream_index = ac->stream->index; - - // Do we need this at all? Better be safe than sorry... - if (packet.pts == AV_NOPTS_VALUE) { - MP_WARN(ao, "encoder lost pts, why?\n"); - if (ac->savepts != MP_NOPTS_VALUE) - packet.pts = ac->savepts; - } - - if (packet.pts != AV_NOPTS_VALUE) - 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->codec->time_base, - ac->stream->time_base); - - if(packet.duration > 0) - 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, 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); - return -1; - } - - return packet.size; + encode_audio_and_write(ao, NULL); } // this should round samples down to frame sizes @@ -492,3 +535,5 @@ const struct ao_driver audio_out_lavc = { .play = play, .drain = drain, }; + +// vim: sw=4 ts=4 et tw=80 diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 3216d673e1..90d3b3e5c5 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -612,6 +612,12 @@ static int audio_wait(struct ao *ao, pthread_mutex_t *lock) return r; } +static void list_devs(struct ao *ao, struct ao_device_list *list) +{ + if (stat(PATH_DEV_DSP, &(struct stat){0}) == 0) + ao_device_list_add(list, ao, &(struct ao_device_desc){"", "Default"}); +} + #define OPT_BASE_STRUCT struct priv const struct ao_driver audio_out_oss = { @@ -629,6 +635,7 @@ const struct ao_driver audio_out_oss = { .drain = drain, .wait = audio_wait, .wakeup = ao_wakeup_poll, + .list_devs = list_devs, .priv_size = sizeof(struct priv), .priv_defaults = &(const struct priv) { .audio_fd = -1, diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index ae6bd3d9dc..325a7cf72b 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -132,7 +132,7 @@ static bool thread_feed(struct ao *ao) mp_time_us() + (int64_t)llrint(delay_us)); // note, we can't use ao_read_data return value here since we already - // commited to frame_count above in the GetBuffer call + // committed to frame_count above in the GetBuffer call hr = IAudioRenderClient_ReleaseBuffer(state->pRenderClient, frame_count, 0); EXIT_ON_ERROR(hr); diff --git a/audio/out/ao_wasapi_changenotify.c b/audio/out/ao_wasapi_changenotify.c index e3ca4e4936..46843ec5e3 100644 --- a/audio/out/ao_wasapi_changenotify.c +++ b/audio/out/ao_wasapi_changenotify.c @@ -95,7 +95,7 @@ static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceAdded( return S_OK; } -// maybe MPV can go over to the prefered device once it is plugged in? +// maybe MPV can go over to the preferred device once it is plugged in? static HRESULT STDMETHODCALLTYPE sIMMNotificationClient_OnDeviceRemoved( IMMNotificationClient *This, LPCWSTR pwstrDeviceId) |