summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
Diffstat (limited to 'audio')
-rw-r--r--audio/decode/ad.h7
-rw-r--r--audio/decode/ad_lavc.c87
-rw-r--r--audio/decode/ad_spdif.c95
-rw-r--r--audio/decode/dec_audio.c21
-rw-r--r--audio/decode/dec_audio.h2
-rw-r--r--audio/filter/af_lavfi.c8
-rw-r--r--audio/filter/af_lavrresample.c3
-rw-r--r--audio/out/ao_oss.c18
-rw-r--r--audio/out/ao_wasapi.c12
-rw-r--r--audio/out/ao_wasapi.h2
-rw-r--r--audio/out/ao_wasapi_changenotify.c2
-rw-r--r--audio/out/ao_wasapi_utils.c41
-rw-r--r--audio/out/push.c7
13 files changed, 184 insertions, 121 deletions
diff --git a/audio/decode/ad.h b/audio/decode/ad.h
index 771ceb7e88..bbb050eb4c 100644
--- a/audio/decode/ad.h
+++ b/audio/decode/ad.h
@@ -35,8 +35,11 @@ struct ad_functions {
int (*init)(struct dec_audio *da, const char *decoder);
void (*uninit)(struct dec_audio *da);
int (*control)(struct dec_audio *da, int cmd, void *arg);
- int (*decode_packet)(struct dec_audio *da, struct demux_packet *pkt,
- struct mp_audio **out);
+ // Return whether or not the packet has been consumed.
+ bool (*send_packet)(struct dec_audio *da, struct demux_packet *pkt);
+ // Return whether decoding is still going on (false if EOF was reached).
+ // Never returns false & *out set, but can return true with !*out.
+ bool (*receive_frame)(struct dec_audio *da, struct mp_audio **out);
};
enum ad_ctrl {
diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c
index c4d3a2ae7b..7f3abfd612 100644
--- a/audio/decode/ad_lavc.c
+++ b/audio/decode/ad_lavc.c
@@ -45,7 +45,6 @@ struct priv {
uint32_t skip_samples, trim_samples;
bool preroll_done;
double next_pts;
- bool needs_reset;
AVRational codec_timebase;
};
@@ -116,26 +115,18 @@ static int init(struct dec_audio *da, const char *decoder)
av_opt_set_double(lavc_context, "drc_scale", opts->ac3drc,
AV_OPT_SEARCH_CHILDREN);
-#if HAVE_AVFRAME_SKIP_SAMPLES
+#if LIBAVCODEC_VERSION_MICRO >= 100
// Let decoder add AV_FRAME_DATA_SKIP_SAMPLES.
av_opt_set(lavc_context, "flags2", "+skip_manual", AV_OPT_SEARCH_CHILDREN);
#endif
mp_set_avopts(da->log, lavc_context, opts->avopts);
- lavc_context->codec_tag = c->codec_tag;
- lavc_context->sample_rate = c->samplerate;
- lavc_context->bit_rate = c->bitrate;
- lavc_context->block_align = c->block_align;
- lavc_context->bits_per_coded_sample = c->bits_per_coded_sample;
- lavc_context->channels = c->channels.num;
- if (!mp_chmap_is_unknown(&c->channels))
- lavc_context->channel_layout = mp_chmap_to_lavc(&c->channels);
-
- // demux_mkv
- mp_lavc_set_extradata(lavc_context, c->extradata, c->extradata_size);
-
- mp_set_lav_codec_headers(lavc_context, c);
+ if (mp_set_avctx_codec_headers(lavc_context, c) < 0) {
+ MP_ERR(da, "Could not set decoder parameters.\n");
+ uninit(da);
+ return 0;
+ }
mp_set_avcodec_threads(da->log, lavc_context, opts->threads);
@@ -177,14 +168,12 @@ 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;
}
-static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
- struct mp_audio **out)
+static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt)
{
struct priv *priv = da->priv;
AVCodecContext *avctx = priv->avctx;
@@ -195,41 +184,48 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
if (mpkt && priv->next_pts == MP_NOPTS_VALUE)
priv->next_pts = mpkt->pts;
- int in_len = mpkt ? mpkt->len : 0;
-
AVPacket pkt;
mp_set_av_packet(&pkt, mpkt, &priv->codec_timebase);
- int got_frame = 0;
- av_frame_unref(priv->avframe);
+ int ret = avcodec_send_packet(avctx, mpkt ? &pkt : NULL);
- if (priv->needs_reset)
- control(da, ADCTRL_RESET, NULL);
+ if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
+ return false;
- int ret = avcodec_send_packet(avctx, &pkt);
- if (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
- if (ret >= 0 && mpkt)
- mpkt->len = 0;
- 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;
- }
- if (ret < 0) {
+ if (ret < 0)
+ MP_ERR(da, "Error decoding audio.\n");
+ return true;
+}
+
+static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
+{
+ struct priv *priv = da->priv;
+ AVCodecContext *avctx = priv->avctx;
+
+ int ret = avcodec_receive_frame(avctx, priv->avframe);
+
+ if (ret == AVERROR_EOF) {
+ // If flushing was initialized earlier and has ended now, make it start
+ // over in case we get new packets at some point in the future.
+ control(da, ADCTRL_RESET, NULL);
+ return false;
+ } else if (ret < 0 && ret != AVERROR(EAGAIN)) {
MP_ERR(da, "Error decoding audio.\n");
- return -1;
}
- if (!got_frame)
- return 0;
+
+#if LIBAVCODEC_VERSION_MICRO >= 100
+ if (priv->avframe->flags & AV_FRAME_FLAG_DISCARD)
+ av_frame_unref(priv->avframe);
+#endif
+
+ if (!priv->avframe->buf[0])
+ return true;
double out_pts = mp_pts_from_av(priv->avframe->pts, &priv->codec_timebase);
struct mp_audio *mpframe = mp_audio_from_avframe(priv->avframe);
if (!mpframe)
- return -1;
+ return true;
struct mp_chmap lavc_chmap = mpframe->channels;
if (lavc_chmap.num != avctx->channels)
@@ -247,7 +243,7 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
if (mpframe->pts != MP_NOPTS_VALUE)
priv->next_pts = mpframe->pts + mpframe->samples / (double)mpframe->rate;
-#if HAVE_AVFRAME_SKIP_SAMPLES
+#if LIBAVCODEC_VERSION_MICRO >= 100
AVFrameSideData *sd =
av_frame_get_side_data(priv->avframe, AV_FRAME_DATA_SKIP_SAMPLES);
if (sd && sd->size >= 10) {
@@ -279,8 +275,8 @@ static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
av_frame_unref(priv->avframe);
- MP_DBG(da, "Decoded %d -> %d samples\n", in_len, mpframe->samples);
- return 0;
+ MP_DBG(da, "Decoded %d samples\n", mpframe->samples);
+ return true;
}
static void add_decoders(struct mp_decoder_list *list)
@@ -294,5 +290,6 @@ const struct ad_functions ad_lavc = {
.init = init,
.uninit = uninit,
.control = control,
- .decode_packet = decode_packet,
+ .send_packet = send_packet,
+ .receive_frame = receive_frame,
};
diff --git a/audio/decode/ad_spdif.c b/audio/decode/ad_spdif.c
index 30c7883bf4..e38c9e5077 100644
--- a/audio/decode/ad_spdif.c
+++ b/audio/decode/ad_spdif.c
@@ -42,6 +42,8 @@ struct spdifContext {
bool use_dts_hd;
struct mp_audio fmt;
struct mp_audio_pool *pool;
+ bool got_eof;
+ struct demux_packet *queued_packet;
};
static int write_packet(void *p, uint8_t *buf, int buf_size)
@@ -71,6 +73,7 @@ static void uninit(struct dec_audio *da)
av_freep(&lavf_ctx->pb->buffer);
av_freep(&lavf_ctx->pb);
avformat_free_context(lavf_ctx);
+ talloc_free(spdif_ctx->queued_packet);
spdif_ctx->lavf_ctx = NULL;
}
}
@@ -90,13 +93,34 @@ static int init(struct dec_audio *da, const char *decoder)
return spdif_ctx->codec_id != AV_CODEC_ID_NONE;
}
-static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt)
+static void determine_codec_params(struct dec_audio *da, AVPacket *pkt,
+ int *out_profile, int *out_rate)
{
struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN;
AVCodecContext *ctx = NULL;
AVFrame *frame = NULL;
+ AVCodecParserContext *parser = av_parser_init(spdif_ctx->codec_id);
+ if (parser) {
+ // Don't make it wait for the next frame.
+ parser->flags |= PARSER_FLAG_COMPLETE_FRAMES;
+
+ ctx = avcodec_alloc_context3(NULL);
+
+ uint8_t *d = NULL;
+ int s = 0;
+ av_parser_parse2(parser, ctx, &d, &s, pkt->data, pkt->size, 0, 0, 0);
+ *out_profile = profile = ctx->profile;
+ *out_rate = ctx->sample_rate;
+
+ av_free(ctx);
+ av_parser_close(parser);
+ }
+
+ if (profile != FF_PROFILE_UNKNOWN || spdif_ctx->codec_id != AV_CODEC_ID_DTS)
+ return;
+
AVCodec *codec = avcodec_find_decoder(spdif_ctx->codec_id);
if (!codec)
goto done;
@@ -120,7 +144,8 @@ static int determine_codec_profile(struct dec_audio *da, AVPacket *pkt)
if (avcodec_receive_frame(ctx, frame) < 0)
goto done;
- profile = ctx->profile;
+ *out_profile = profile = ctx->profile;
+ *out_rate = ctx->sample_rate;
done:
av_frame_free(&frame);
@@ -130,8 +155,6 @@ done:
if (profile == FF_PROFILE_UNKNOWN)
MP_WARN(da, "Failed to parse codec profile.\n");
-
- return profile;
}
static int init_filter(struct dec_audio *da, AVPacket *pkt)
@@ -139,8 +162,9 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
struct spdifContext *spdif_ctx = da->priv;
int profile = FF_PROFILE_UNKNOWN;
- if (spdif_ctx->codec_id == AV_CODEC_ID_DTS)
- profile = determine_codec_profile(da, pkt);
+ int c_rate = 0;
+ determine_codec_params(da, pkt, &profile, &c_rate);
+ MP_VERBOSE(da, "In: profile=%d samplerate=%d\n", profile, c_rate);
AVFormatContext *lavf_ctx = avformat_alloc_context();
if (!lavf_ctx)
@@ -186,7 +210,7 @@ static int init_filter(struct dec_audio *da, AVPacket *pkt)
break;
case AV_CODEC_ID_AC3:
sample_format = AF_FORMAT_S_AC3;
- samplerate = 48000;
+ samplerate = c_rate > 0 ? c_rate : 48000;
num_channels = 2;
break;
case AV_CODEC_ID_DTS: {
@@ -243,44 +267,72 @@ fail:
return -1;
}
-static int decode_packet(struct dec_audio *da, struct demux_packet *mpkt,
- struct mp_audio **out)
+
+static bool send_packet(struct dec_audio *da, struct demux_packet *mpkt)
{
struct spdifContext *spdif_ctx = da->priv;
- spdif_ctx->out_buffer_len = 0;
+ if (spdif_ctx->queued_packet || spdif_ctx->got_eof)
+ return false;
- if (!mpkt)
- return 0;
+ spdif_ctx->queued_packet = mpkt ? demux_copy_packet(mpkt) : NULL;
+ spdif_ctx->got_eof = !mpkt;
+ return true;
+}
- double pts = mpkt->pts;
+static bool receive_frame(struct dec_audio *da, struct mp_audio **out)
+{
+ struct spdifContext *spdif_ctx = da->priv;
+
+ if (spdif_ctx->got_eof) {
+ spdif_ctx->got_eof = false;
+ return false;
+ }
+
+ if (!spdif_ctx->queued_packet)
+ return true;
+
+ double pts = spdif_ctx->queued_packet->pts;
AVPacket pkt;
- mp_set_av_packet(&pkt, mpkt, NULL);
- mpkt->len = 0; // will be fully consumed
+ mp_set_av_packet(&pkt, spdif_ctx->queued_packet, NULL);
pkt.pts = pkt.dts = 0;
if (!spdif_ctx->lavf_ctx) {
if (init_filter(da, &pkt) < 0)
- return -1;
+ goto done;
}
+ spdif_ctx->out_buffer_len = 0;
int ret = av_write_frame(spdif_ctx->lavf_ctx, &pkt);
avio_flush(spdif_ctx->lavf_ctx->pb);
- if (ret < 0)
- return -1;
+ if (ret < 0) {
+ MP_ERR(da, "spdif mux error: '%s'\n", mp_strerror(AVUNERROR(ret)));
+ goto done;
+ }
int samples = spdif_ctx->out_buffer_len / spdif_ctx->fmt.sstride;
*out = mp_audio_pool_get(spdif_ctx->pool, &spdif_ctx->fmt, samples);
if (!*out)
- return -1;
+ goto done;
memcpy((*out)->planes[0], spdif_ctx->out_buffer, spdif_ctx->out_buffer_len);
(*out)->pts = pts;
- return 0;
+done:
+ talloc_free(spdif_ctx->queued_packet);
+ spdif_ctx->queued_packet = NULL;
+ return true;
}
static int control(struct dec_audio *da, int cmd, void *arg)
{
+ struct spdifContext *spdif_ctx = da->priv;
+ switch (cmd) {
+ case ADCTRL_RESET:
+ talloc_free(spdif_ctx->queued_packet);
+ spdif_ctx->queued_packet = NULL;
+ spdif_ctx->got_eof = false;
+ return CONTROL_TRUE;
+ }
return CONTROL_UNKNOWN;
}
@@ -344,5 +396,6 @@ const struct ad_functions ad_spdif = {
.init = init,
.uninit = uninit,
.control = control,
- .decode_packet = decode_packet,
+ .send_packet = send_packet,
+ .receive_frame = receive_frame,
};
diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c
index 9f28302bd5..5a2735ef20 100644
--- a/audio/decode/dec_audio.c
+++ b/audio/decode/dec_audio.c
@@ -27,6 +27,7 @@
#include "common/codecs.h"
#include "common/msg.h"
+#include "common/recorder.h"
#include "misc/bstr.h"
#include "stream/stream.h"
@@ -201,7 +202,7 @@ static void fix_audio_pts(struct dec_audio *da)
void audio_work(struct dec_audio *da)
{
- if (da->current_frame)
+ if (da->current_frame || !da->ad_driver)
return;
if (!da->packet && !da->new_segment &&
@@ -217,30 +218,28 @@ void audio_work(struct dec_audio *da)
da->packet = NULL;
}
- bool had_input_packet = !!da->packet;
- bool had_packet = da->packet || da->new_segment;
+ if (da->ad_driver->send_packet(da, da->packet)) {
+ if (da->recorder_sink)
+ mp_recorder_feed_packet(da->recorder_sink, da->packet);
- int ret = da->ad_driver->decode_packet(da, da->packet, &da->current_frame);
- if (ret < 0 || (da->packet && da->packet->len == 0)) {
talloc_free(da->packet);
da->packet = NULL;
}
+ bool progress = da->ad_driver->receive_frame(da, &da->current_frame);
+
if (da->current_frame && !mp_audio_config_valid(da->current_frame)) {
talloc_free(da->current_frame);
da->current_frame = NULL;
}
- da->current_state = DATA_OK;
- if (!da->current_frame) {
+ da->current_state = da->current_frame ? DATA_OK : DATA_AGAIN;
+ if (!progress)
da->current_state = DATA_EOF;
- if (had_packet)
- da->current_state = DATA_AGAIN;
- }
fix_audio_pts(da);
- bool segment_end = !da->current_frame && !had_input_packet;
+ bool segment_end = da->current_state == DATA_EOF;
if (da->current_frame) {
mp_audio_clip_timestamps(da->current_frame, da->start, da->end);
diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h
index ebe7c8ae5b..02447d6742 100644
--- a/audio/decode/dec_audio.h
+++ b/audio/decode/dec_audio.h
@@ -37,6 +37,8 @@ struct dec_audio {
bool try_spdif;
+ struct mp_recorder_sink *recorder_sink;
+
// For free use by the ad_driver
void *priv;
diff --git a/audio/filter/af_lavfi.c b/audio/filter/af_lavfi.c
index bc4a687487..55fb7cb0dc 100644
--- a/audio/filter/af_lavfi.c
+++ b/audio/filter/af_lavfi.c
@@ -246,7 +246,7 @@ static int control(struct af_instance *af, int cmd, void *arg)
static void get_metadata_from_av_frame(struct af_instance *af, AVFrame *frame)
{
-#if HAVE_AVFRAME_METADATA
+#if LIBAVUTIL_VERSION_MICRO >= 100
struct priv *p = af->priv;
if (!p->metadata)
p->metadata = talloc_zero(p, struct mp_tags);
@@ -266,6 +266,12 @@ static int filter_frame(struct af_instance *af, struct mp_audio *data)
if (!p->graph)
goto error;
+ if (!data) {
+ if (p->eof)
+ return 0;
+ p->eof = true;
+ }
+
if (data) {
frame = mp_audio_to_avframe_and_unref(data);
data = NULL;
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index 828be66247..47c374b227 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -36,6 +36,9 @@
#include "common/common.h"
#include "config.h"
+#define HAVE_LIBSWRESAMPLE HAVE_IS_FFMPEG
+#define HAVE_LIBAVRESAMPLE HAVE_IS_LIBAV
+
#if HAVE_LIBAVRESAMPLE
#include <libavresample/avresample.h>
#elif HAVE_LIBSWRESAMPLE
diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c
index c0446eb2aa..7e73644b8f 100644
--- a/audio/out/ao_oss.c
+++ b/audio/out/ao_oss.c
@@ -279,14 +279,21 @@ static int reopen_device(struct ao *ao, bool allow_format_changes)
int format = ao->format;
struct mp_chmap channels = ao->channels;
+ const char *device = PATH_DEV_DSP;
+ if (ao->device)
+ device = ao->device;
+ if (p->dsp && p->dsp[0])
+ device = p->dsp;
+
+ MP_VERBOSE(ao, "using '%s' dsp device\n", device);
#ifdef __linux__
- p->audio_fd = open(p->dsp, O_WRONLY | O_NONBLOCK);
+ p->audio_fd = open(device, O_WRONLY | O_NONBLOCK);
#else
- p->audio_fd = open(p->dsp, O_WRONLY);
+ p->audio_fd = open(device, O_WRONLY);
#endif
if (p->audio_fd < 0) {
MP_ERR(ao, "Can't open audio device %s: %s\n",
- p->dsp, mp_strerror(errno));
+ device, mp_strerror(errno));
goto fail;
}
@@ -443,9 +450,8 @@ static int init(struct ao *ao)
p->oss_mixer_channel = SOUND_MIXER_PCM;
}
- MP_VERBOSE(ao, "using '%s' dsp device\n", p->dsp);
MP_VERBOSE(ao, "using '%s' mixer device\n", p->oss_mixer_device);
- MP_VERBOSE(ao, "using '%s' mixer device\n", mixer_channels[p->oss_mixer_channel]);
+ MP_VERBOSE(ao, "using '%s' mixer channel\n", mixer_channels[p->oss_mixer_channel]);
ao->format = af_fmt_from_planar(ao->format);
@@ -643,8 +649,6 @@ const struct ao_driver audio_out_oss = {
.buffersize = -1,
.outburst = 512,
.oss_mixer_channel = SOUND_MIXER_PCM,
-
- .dsp = PATH_DEV_DSP,
.oss_mixer_device = PATH_DEV_MIXER,
},
.options = (const struct m_option[]) {
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index b2e035d3dc..3a4c341387 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -255,9 +255,9 @@ static void uninit(struct ao *ao)
"while waiting for audio thread to terminate\n");
}
- SAFE_RELEASE(state->hInitDone, CloseHandle(state->hInitDone));
- SAFE_RELEASE(state->hWake, CloseHandle(state->hWake));
- SAFE_RELEASE(state->hAudioThread,CloseHandle(state->hAudioThread));
+ SAFE_DESTROY(state->hInitDone, CloseHandle(state->hInitDone));
+ SAFE_DESTROY(state->hWake, CloseHandle(state->hWake));
+ SAFE_DESTROY(state->hAudioThread,CloseHandle(state->hAudioThread));
wasapi_change_uninit(ao);
@@ -305,7 +305,7 @@ static int init(struct ao *ao)
}
WaitForSingleObject(state->hInitDone, INFINITE); // wait on init complete
- SAFE_RELEASE(state->hInitDone,CloseHandle(state->hInitDone));
+ SAFE_DESTROY(state->hInitDone,CloseHandle(state->hInitDone));
if (FAILED(state->init_ret)) {
if (!ao->probing)
MP_FATAL(ao, "Received failure from audio thread\n");
@@ -418,10 +418,10 @@ static int thread_control(struct ao *ao, enum aocontrol cmd, void *arg)
do {
IAudioSessionControl_SetDisplayName(state->pSessionControl, title, NULL);
- SAFE_RELEASE(tmp, CoTaskMemFree(tmp));
+ SAFE_DESTROY(tmp, CoTaskMemFree(tmp));
IAudioSessionControl_GetDisplayName(state->pSessionControl, &tmp);
} while (lstrcmpW(title, tmp));
- SAFE_RELEASE(tmp, CoTaskMemFree(tmp));
+ SAFE_DESTROY(tmp, CoTaskMemFree(tmp));
talloc_free(title);
return CONTROL_OK;
}
diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h
index 65f16d11c1..8f6e38867c 100644
--- a/audio/out/ao_wasapi.h
+++ b/audio/out/ao_wasapi.h
@@ -47,7 +47,7 @@ void wasapi_change_uninit(struct ao* ao);
#define EXIT_ON_ERROR(hres) \
do { if (FAILED(hres)) { goto exit_label; } } while(0)
-#define SAFE_RELEASE(unk, release) \
+#define SAFE_DESTROY(unk, release) \
do { if ((unk) != NULL) { release; (unk) = NULL; } } while(0)
#define mp_format_res_str(hres) \
diff --git a/audio/out/ao_wasapi_changenotify.c b/audio/out/ao_wasapi_changenotify.c
index e1b3a9d604..b9806e0adb 100644
--- a/audio/out/ao_wasapi_changenotify.c
+++ b/audio/out/ao_wasapi_changenotify.c
@@ -242,5 +242,5 @@ void wasapi_change_uninit(struct ao *ao)
change->pEnumerator, (IMMNotificationClient *)change);
}
- SAFE_RELEASE(change->pEnumerator, IMMDeviceEnumerator_Release(change->pEnumerator));
+ SAFE_RELEASE(change->pEnumerator);
}
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index 4667b57ae8..a449dbec10 100644
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -539,8 +539,7 @@ static void init_session_display(struct wasapi_state *state) {
return;
exit_label:
// if we got here then the session control is useless - release it
- SAFE_RELEASE(state->pSessionControl,
- IAudioSessionControl_Release(state->pSessionControl));
+ SAFE_RELEASE(state->pSessionControl);
MP_WARN(state, "Error setting audio session display name: %s\n",
mp_HRESULT_to_str(hr));
return;
@@ -571,10 +570,8 @@ static void init_volume_control(struct wasapi_state *state)
return;
exit_label:
state->vol_hw_support = 0;
- SAFE_RELEASE(state->pEndpointVolume,
- IAudioEndpointVolume_Release(state->pEndpointVolume));
- SAFE_RELEASE(state->pAudioVolume,
- ISimpleAudioVolume_Release(state->pAudioVolume));
+ SAFE_RELEASE(state->pEndpointVolume);
+ SAFE_RELEASE(state->pAudioVolume);
MP_WARN(state, "Error setting up volume control: %s\n",
mp_HRESULT_to_str(hr));
}
@@ -707,7 +704,7 @@ exit_label:
if (FAILED(hr))
mp_warn(l, "Failed getting device name: %s\n", mp_HRESULT_to_str(hr));
PropVariantClear(&devname);
- SAFE_RELEASE(pProps, IPropertyStore_Release(pProps));
+ SAFE_RELEASE(pProps);
return namestr ? namestr : talloc_strdup(talloc_ctx, "");
}
@@ -722,7 +719,7 @@ static struct device_desc *get_device_desc(struct mp_log *l, IMMDevice *pDevice)
struct device_desc *d = talloc_zero(NULL, struct device_desc);
d->deviceID = talloc_memdup(d, deviceID,
(wcslen(deviceID) + 1) * sizeof(wchar_t));
- SAFE_RELEASE(deviceID, CoTaskMemFree(deviceID));
+ SAFE_DESTROY(deviceID, CoTaskMemFree(deviceID));
char *full_id = mp_to_utf8(NULL, d->deviceID);
bstr id = bstr0(full_id);
@@ -745,8 +742,8 @@ static void destroy_enumerator(struct enumerator *e)
{
if (!e)
return;
- SAFE_RELEASE(e->pDevices, IMMDeviceCollection_Release(e->pDevices));
- SAFE_RELEASE(e->pEnumerator, IMMDeviceEnumerator_Release(e->pEnumerator));
+ SAFE_RELEASE(e->pDevices);
+ SAFE_RELEASE(e->pEnumerator);
talloc_free(e);
}
@@ -782,7 +779,7 @@ static struct device_desc *device_desc_for_num(struct enumerator *e, UINT i)
return NULL;
}
struct device_desc *d = get_device_desc(e->log, pDevice);
- SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice));
+ SAFE_RELEASE(pDevice);
return d;
}
@@ -797,7 +794,7 @@ static struct device_desc *default_device_desc(struct enumerator *e)
return NULL;
}
struct device_desc *d = get_device_desc(e->log, pDevice);
- SAFE_RELEASE(pDevice, IMMDevice_Release(pDevice));
+ SAFE_RELEASE(pDevice);
return d;
}
@@ -834,7 +831,7 @@ static HRESULT load_device(struct mp_log *l,
exit_label:
if (FAILED(hr))
mp_err(l, "Error loading selected device: %s\n", mp_HRESULT_to_str(hr));
- SAFE_RELEASE(pEnumerator, IMMDeviceEnumerator_Release(pEnumerator));
+ SAFE_RELEASE(pEnumerator);
return hr;
}
@@ -908,7 +905,7 @@ LPWSTR wasapi_find_deviceID(struct ao *ao)
BSTR_P(device), d->id, d->name);
}
}
- SAFE_RELEASE(d, talloc_free(d));
+ SAFE_DESTROY(d, talloc_free(d));
}
if (!deviceID)
@@ -969,13 +966,13 @@ void wasapi_thread_uninit(struct ao *ao)
if (state->pAudioClient)
IAudioClient_Stop(state->pAudioClient);
- SAFE_RELEASE(state->pRenderClient, IAudioRenderClient_Release(state->pRenderClient));
- SAFE_RELEASE(state->pAudioClock, IAudioClock_Release(state->pAudioClock));
- SAFE_RELEASE(state->pAudioVolume, ISimpleAudioVolume_Release(state->pAudioVolume));
- SAFE_RELEASE(state->pEndpointVolume, IAudioEndpointVolume_Release(state->pEndpointVolume));
- SAFE_RELEASE(state->pSessionControl, IAudioSessionControl_Release(state->pSessionControl));
- SAFE_RELEASE(state->pAudioClient, IAudioClient_Release(state->pAudioClient));
- SAFE_RELEASE(state->pDevice, IMMDevice_Release(state->pDevice));
- SAFE_RELEASE(state->hTask, AvRevertMmThreadCharacteristics(state->hTask));
+ SAFE_RELEASE(state->pRenderClient);
+ SAFE_RELEASE(state->pAudioClock);
+ SAFE_RELEASE(state->pAudioVolume);
+ SAFE_RELEASE(state->pEndpointVolume);
+ SAFE_RELEASE(state->pSessionControl);
+ SAFE_RELEASE(state->pAudioClient);
+ SAFE_RELEASE(state->pDevice);
+ SAFE_DESTROY(state->hTask, AvRevertMmThreadCharacteristics(state->hTask));
MP_DBG(ao, "Thread uninit done\n");
}
diff --git a/audio/out/push.c b/audio/out/push.c
index a4a6808d7f..a722d19ea2 100644
--- a/audio/out/push.c
+++ b/audio/out/push.c
@@ -251,12 +251,11 @@ static int play(struct ao *ao, void **data, int samples, int flags)
if (got_data) {
p->still_playing = true;
p->expected_end_time = 0;
- }
- // If we don't have new data, the decoder thread basically promises it
- // will send new data as soon as it's available.
- if (got_data)
+ // If we don't have new data, the decoder thread basically promises it
+ // will send new data as soon as it's available.
wakeup_playthread(ao);
+ }
pthread_mutex_unlock(&p->lock);
return write_samples;
}