GstWasapiSink *self = GST_WASAPI_SINK (asink);
HRESULT hr;
gint16 *dst = NULL;
- guint pending = length;
+ DWORD dwWaitResult;
+ guint can_frames, have_frames, n_frames, write_len, written_len = 0;
GST_OBJECT_LOCK (self);
if (self->client_needs_restart) {
hr = IAudioClient_Start (self->client);
- HR_FAILED_AND (hr, IAudioClient::Start,
- GST_OBJECT_UNLOCK (self); length = 0; goto beach);
+ HR_FAILED_AND (hr, IAudioClient::Start, GST_OBJECT_UNLOCK (self); goto beach);
self->client_needs_restart = FALSE;
}
GST_OBJECT_UNLOCK (self);
- while (pending > 0) {
- DWORD dwWaitResult;
- guint can_frames, have_frames, n_frames, write_len;
+ /* We have N frames to be written out */
+ have_frames = length / (self->mix_format->nBlockAlign);
+ if (self->sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) {
+ /* In exlusive mode we have to wait always */
dwWaitResult = WaitForSingleObject (self->event_handle, INFINITE);
if (dwWaitResult != WAIT_OBJECT_0) {
GST_ERROR_OBJECT (self, "Error waiting for event handle: %x",
(guint) dwWaitResult);
- length -= pending;
goto beach;
}
- /* We have N frames to be written out */
- have_frames = pending / (self->mix_format->nBlockAlign);
- /* We have can_frames space in the output buffer */
can_frames = gst_wasapi_sink_get_can_frames (self);
- /* We will write out these many frames, and this much length */
- n_frames = MIN (can_frames, have_frames);
- write_len = n_frames * self->mix_format->nBlockAlign;
+ /* In exclusive mode we need to fill the whole buffer in one go or
+ * GetBuffer will error out */
+ if (can_frames != have_frames) {
+ GST_ERROR_OBJECT (self,
+ "Need at %i frames to write for exclusive mode, but got %i",
+ can_frames, have_frames);
+ written_len = -1;
+ goto beach;
+ }
+ } else {
+ /* In shared mode we can write parts of the buffer, so only wait
+ * in case we can't write anything */
+ can_frames = gst_wasapi_sink_get_can_frames (self);
- GST_DEBUG_OBJECT (self, "total: %i, have_frames: %i (%i bytes), "
- "can_frames: %i, will write: %i (%i bytes)", self->buffer_frame_count,
- have_frames, pending, can_frames, n_frames, write_len);
+ if (can_frames == 0) {
+ dwWaitResult = WaitForSingleObject (self->event_handle, INFINITE);
+ if (dwWaitResult != WAIT_OBJECT_0) {
+ GST_ERROR_OBJECT (self, "Error waiting for event handle: %x",
+ (guint) dwWaitResult);
+ goto beach;
+ }
+ can_frames = gst_wasapi_sink_get_can_frames (self);
+ }
+ }
- hr = IAudioRenderClient_GetBuffer (self->render_client, n_frames,
- (BYTE **) & dst);
- HR_FAILED_AND (hr, IAudioRenderClient::GetBuffer, length = 0; goto beach);
+ /* We will write out these many frames, and this much length */
+ n_frames = MIN (can_frames, have_frames);
+ write_len = n_frames * self->mix_format->nBlockAlign;
- memcpy (dst, data, write_len);
+ GST_DEBUG_OBJECT (self, "total: %i, have_frames: %i (%i bytes), "
+ "can_frames: %i, will write: %i (%i bytes)", self->buffer_frame_count,
+ have_frames, length, can_frames, n_frames, write_len);
- hr = IAudioRenderClient_ReleaseBuffer (self->render_client, n_frames,
- self->mute ? AUDCLNT_BUFFERFLAGS_SILENT : 0);
- HR_FAILED_AND (hr, IAudioRenderClient::ReleaseBuffer, length = 0;
- goto beach);
+ hr = IAudioRenderClient_GetBuffer (self->render_client, n_frames,
+ (BYTE **) & dst);
+ HR_FAILED_AND (hr, IAudioRenderClient::GetBuffer, goto beach);
- pending -= write_len;
- }
+ memcpy (dst, data, write_len);
+
+ hr = IAudioRenderClient_ReleaseBuffer (self->render_client, n_frames,
+ self->mute ? AUDCLNT_BUFFERFLAGS_SILENT : 0);
+ HR_FAILED_AND (hr, IAudioRenderClient::ReleaseBuffer, goto beach);
+
+ written_len = write_len;
beach:
- return length;
+ return written_len;
}
static guint