summaryrefslogtreecommitdiffstats
path: root/audio
diff options
context:
space:
mode:
authorKevin Mitchell <kevmitch@gmail.com>2015-12-21 00:02:21 -0800
committerKevin Mitchell <kevmitch@gmail.com>2015-12-21 05:23:22 -0800
commit35296c1f3357cf4ee17f2a6ad58c1ff3e550070d (patch)
tree862240355f28cf3244155facbdb0c68a5a141cb7 /audio
parent3ae726e8dd15638b84fcd5a168134f186119f240 (diff)
downloadmpv-35296c1f3357cf4ee17f2a6ad58c1ff3e550070d.tar.bz2
mpv-35296c1f3357cf4ee17f2a6ad58c1ff3e550070d.tar.xz
ao_wasapi: non-fatal error handling for COM marshalling
Also make sure that CoReleaseMarshalData is called if errors occur before unmarshalling.
Diffstat (limited to 'audio')
-rw-r--r--audio/out/ao_wasapi.c2
-rwxr-xr-xaudio/out/ao_wasapi_utils.c116
-rwxr-xr-xaudio/out/ao_wasapi_utils.h2
3 files changed, 65 insertions, 55 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index 2fcb2e9bba..bafeae1d63 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -290,7 +290,7 @@ static int init(struct ao *ao)
return -1;
}
- wasapi_setup_proxies(state);
+ wasapi_receive_proxies(state);
MP_DBG(ao, "Init wasapi done\n");
return 0;
}
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c
index 235d0db8c7..9f672b24f5 100755
--- a/audio/out/ao_wasapi_utils.c
+++ b/audio/out/ao_wasapi_utils.c
@@ -1006,28 +1006,27 @@ exit_label:
return hr;
}
-HRESULT wasapi_setup_proxies(struct wasapi_state *state) {
- HRESULT hr;
-
-#define UNMARSHAL(type, to, from) do { \
- hr = CoGetInterfaceAndReleaseStream((from), &(type), (void **)&(to)); \
- (from) = NULL; \
- EXIT_ON_ERROR(hr); \
-} while (0)
-
- UNMARSHAL(IID_ISimpleAudioVolume, state->pAudioVolumeProxy,
- state->sAudioVolume);
- UNMARSHAL(IID_IAudioEndpointVolume, state->pEndpointVolumeProxy,
- state->sEndpointVolume);
- UNMARSHAL(IID_IAudioSessionControl, state->pSessionControlProxy,
- state->sSessionControl);
-
-#undef UNMARSHAL
-
- return S_OK;
+static void *unmarshal(struct wasapi_state *state, REFIID type, IStream **from)
+{
+ if (!*from)
+ return NULL;
+ void *to_proxy = NULL;
+ HRESULT hr = CoGetInterfaceAndReleaseStream(*from, type, &to_proxy);
+ *from = NULL; // the stream is released even on failure
+ EXIT_ON_ERROR(hr);
+ return to_proxy;
exit_label:
- MP_ERR(state, "Error reading COM proxy: %s\n", mp_HRESULT_to_str(hr));
- return hr;
+ MP_WARN(state, "Error reading COM proxy: %s\n", mp_HRESULT_to_str(hr));
+ return to_proxy;
+}
+
+void wasapi_receive_proxies(struct wasapi_state *state) {
+ state->pAudioVolumeProxy = unmarshal(state, &IID_ISimpleAudioVolume,
+ &state->sAudioVolume);
+ state->pEndpointVolumeProxy = unmarshal(state, &IID_IAudioEndpointVolume,
+ &state->sEndpointVolume);
+ state->pSessionControlProxy = unmarshal(state, &IID_IAudioSessionControl,
+ &state->sSessionControl);
}
void wasapi_release_proxies(wasapi_state *state) {
@@ -1039,38 +1038,50 @@ void wasapi_release_proxies(wasapi_state *state) {
IAudioSessionControl_Release(state->pSessionControlProxy));
}
-static HRESULT create_proxies(struct wasapi_state *state) {
- HRESULT hr;
-
-#define MARSHAL(type, to, from) do { \
- hr = CreateStreamOnHGlobal(NULL, TRUE, &(to)); \
- EXIT_ON_ERROR(hr); \
- hr = CoMarshalInterThreadInterfaceInStream(&(type), \
- (IUnknown *)(from), \
- &(to)); \
- EXIT_ON_ERROR(hr); \
-} while (0)
-
- MARSHAL(IID_ISimpleAudioVolume, state->sAudioVolume,
- state->pAudioVolume);
- MARSHAL(IID_IAudioEndpointVolume, state->sEndpointVolume,
- state->pEndpointVolume);
- MARSHAL(IID_IAudioSessionControl, state->sSessionControl,
- state->pSessionControl);
-
- return S_OK;
+// Must call CoReleaseMarshalData to decrement marshalled object's reference
+// count.
+#define SAFE_RELEASE_INTERFACE_STREAM(stream) do { \
+ if ((stream) != NULL) { \
+ CoReleaseMarshalData((stream)); \
+ IStream_Release((stream)); \
+ (stream) = NULL; \
+ } \
+ } while(0)
+
+static IStream *marshal(struct wasapi_state *state,
+ REFIID type, void *from_obj)
+{
+ if (!from_obj)
+ return NULL;
+ IStream *to;
+ HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &to);
+ EXIT_ON_ERROR(hr);
+ hr = CoMarshalInterThreadInterfaceInStream(type, (IUnknown *)from_obj, &to);
+ EXIT_ON_ERROR(hr);
+ return to;
exit_label:
- MP_ERR(state, "Error creating COM proxy: %s\n", mp_HRESULT_to_str(hr));
- return hr;
+ SAFE_RELEASE_INTERFACE_STREAM(to);
+ MP_WARN(state, "Error creating COM proxy stream: %s\n",
+ mp_HRESULT_to_str(hr));
+ return to;
}
-static void destroy_proxies(struct wasapi_state *state) {
- SAFE_RELEASE(state->sAudioVolume,
- IStream_Release(state->sAudioVolume));
- SAFE_RELEASE(state->sEndpointVolume,
- IStream_Release(state->sEndpointVolume));
- SAFE_RELEASE(state->sSessionControl,
- IStream_Release(state->sSessionControl));
+static void create_proxy_streams(struct wasapi_state *state) {
+ state->sAudioVolume = marshal(state, &IID_ISimpleAudioVolume,
+ state->pAudioVolume);
+ state->sEndpointVolume = marshal(state, &IID_IAudioEndpointVolume,
+ state->pEndpointVolume);
+ state->sSessionControl = marshal(state, &IID_IAudioSessionControl,
+ state->pSessionControl);
+}
+
+static void destroy_proxy_streams(struct wasapi_state *state) {
+ // This is only to handle error conditions.
+ // During normal operation, these will already have been released by
+ // unmarshaling.
+ SAFE_RELEASE_INTERFACE_STREAM(state->sAudioVolume);
+ SAFE_RELEASE_INTERFACE_STREAM(state->sEndpointVolume);
+ SAFE_RELEASE_INTERFACE_STREAM(state->sSessionControl);
}
void wasapi_dispatch(struct ao *ao)
@@ -1152,8 +1163,7 @@ retry: ;
EXIT_ON_ERROR(hr);
MP_DBG(ao, "Creating proxies\n");
- hr = create_proxies(state);
- EXIT_ON_ERROR(hr);
+ create_proxy_streams(state);
wasapi_change_init(ao, false);
@@ -1174,7 +1184,7 @@ void wasapi_thread_uninit(struct ao *ao)
IAudioClient_Stop(state->pAudioClient);
wasapi_change_uninit(ao);
- destroy_proxies(state);
+ destroy_proxy_streams(state);
SAFE_RELEASE(state->pRenderClient, IAudioRenderClient_Release(state->pRenderClient));
SAFE_RELEASE(state->pAudioClock, IAudioClock_Release(state->pAudioClock));
diff --git a/audio/out/ao_wasapi_utils.h b/audio/out/ao_wasapi_utils.h
index deaffd77e4..8e6b4318d3 100755
--- a/audio/out/ao_wasapi_utils.h
+++ b/audio/out/ao_wasapi_utils.h
@@ -43,7 +43,7 @@ void wasapi_dispatch(struct ao *ao);
HRESULT wasapi_thread_init(struct ao *ao);
void wasapi_thread_uninit(struct ao *ao);
-HRESULT wasapi_setup_proxies(wasapi_state *state);
+void wasapi_receive_proxies(wasapi_state *state);
void wasapi_release_proxies(wasapi_state *state);
#endif