[vlc-devel] [PATCH] Erase regularily the already played directsound buffer outside of the play callback

Denis Charmet typx at dinauz.org
Thu Apr 17 14:52:15 CEST 2014


Le jeudi 17 avril 2014 à 01:52:37, Rémi Denis-Courmont a écrit :
> By definition, you cannot underrun if you loop...
> You should not loop, though that has other issues.
> 
Seeing how broken the API is, not looping will end up causing audio
gaps.

> > It may look overkill but this properly fix #11145 once and for all.
> 
> I don't see the point in using DirectSound in VLC. I don't know why it was
> introduced when it was, and I don't see how, for a media player, it would
> be any better than WaveOut.
> 
I prefer waveout too but apparently DirectSound has better integration than
WaveOut.

> > [...]
> >  static HRESULT Stop( aout_stream_sys_t *p_sys )
> >  {
> > +    vlc_mutex_lock( &p_sys->lock );
> > +    if( p_sys->b_running )
> > +    {
> > +        p_sys->b_running = false;
> > +        vlc_mutex_unlock( &p_sys->lock );
> > +        vlc_join( p_sys->eraser_thread, NULL );
> > +        vlc_mutex_lock( &p_sys->lock );
> 
> Why?
> 
> > +    }
> 
> else
>
I wasn't too proud of this solution but now I'm ashamed...

> > +    vlc_mutex_unlock( &p_sys->lock );
> >      if( p_sys->p_notify != NULL )
> >      {
> >          IDirectSoundNotify_Release(p_sys->p_notify );
> > @@ -729,7 +726,20 @@ static HRESULT Start( vlc_object_t *obj,
> > aout_stream_sys_t *sys,
> >          }
> >      }
> >  
> > +    vlc_mutex_lock(&sys->lock);
> 
> Why that?
> 
I'd say stupidity but for ego reasons I'll answer sleep deprivation...
> > +    sys->b_running = true;
> > +    int ret = vlc_clone(&sys->eraser_thread, PlayedDataEraser, (void*)
> > obj,
> > +                        VLC_THREAD_PRIORITY_LOW);
> > +    if( unlikely( ret ) )
> > +    {
> > +        if( ret != ENOMEM )
> > +            msg_Err( obj, "Couldn't start eraser thread" );
> > +        sys->b_running = false;
> > +        goto error;
> 
> Dead lock.
> 
> > +    }
> >      sys->i_write = 0;
> > +    vlc_mutex_unlock( &sys->lock );
> > +
> >      return DS_OK;
> >  
> >  error:
> > @@ -1028,6 +1038,8 @@ static int Open(vlc_object_t *obj)
> >      aout_DeviceReport(aout, dev);
> >      free(dev);
> >  
> > +    vlc_mutex_init(&sys->s.lock);
> > +
> >      return VLC_SUCCESS;
> >  }
> >  
> > @@ -1035,8 +1047,76 @@ static void Close(vlc_object_t *obj)
> >  {
> >      audio_output_t *aout = (audio_output_t *)obj;
> >      aout_sys_t *sys = aout->sys;
> > +    vlc_mutex_destroy(&sys->s.lock);
> >  
> >      var_Destroy(aout, "directx-audio-device");
> >      FreeLibrary(sys->hdsound_dll); /* free DSOUND.DLL */
> >      free(sys);
> >  }
> > +
> > +static void * PlayedDataEraser( void * data )
> > +{
> > +    const audio_output_t *aout = (audio_output_t *) data;
> > +    aout_stream_sys_t *p_sys = &aout->sys->s;
> > +    void *p_write_position, *p_wrap_around;
> > +    unsigned long l_bytes1, l_bytes2;
> > +    DWORD i_read, status;
> > +    mtime_t toerase;
> > +    HRESULT dsresult;
> > +
> > +    vlc_mutex_lock( &p_sys->lock );
> > +    while( p_sys->b_running )
> 
> You can either use VLC thread cancellation in which case the boolean is
> useless, or the Win32 thread API in which case the invalid thread handle
> value renders the boolean is useless.
> 
> Either way, the boolean seems useless.
> 
Bad habit of dealing with broken libc where cancellation fails badly but
fair enough.

> > +    {
> > +        dsresult = IDirectSoundBuffer_GetStatus( p_sys->p_dsbuffer,
> > &status );
> > +        if( dsresult != DS_OK ||
> > +            ( status & DSBSTATUS_PLAYING ) != DSBSTATUS_PLAYING )
> > +            goto wait;
> > +
> > +        toerase = 0;
> > +
> > +        dsresult = IDirectSoundBuffer_GetCurrentPosition(
> > p_sys->p_dsbuffer,
> > +                                                          &i_read, NULL
> );
> > +        if( dsresult == DS_OK )
> > +        {
> > +            int64_t max = (int64_t) i_read - (int64_t) p_sys->i_write;
> > +            if( max <= 0 )
> > +                max += DS_BUF_SIZE;
> > +            toerase = max;
> > +        }
> > +
> > +        dsresult = IDirectSoundBuffer_Lock( p_sys->p_dsbuffer,
> > +                                            p_sys->i_write,
> > +                                            toerase,
> > +                                            &p_write_position,
> > +                                            &l_bytes1,
> > +                                            &p_wrap_around,
> > +                                            &l_bytes2,
> > +                                            0 );
> > +        if( dsresult == DSERR_BUFFERLOST )
> > +        {
> > +            IDirectSoundBuffer_Restore( p_sys->p_dsbuffer );
> > +            dsresult = IDirectSoundBuffer_Lock( p_sys->p_dsbuffer,
> > +                                                p_sys->i_write,
> > +                                                toerase,
> > +                                                &p_write_position,
> > +                                                &l_bytes1,
> > +                                                &p_wrap_around,
> > +                                                &l_bytes2,
> > +                                                0 );
> > +        }
> > +        if( dsresult != DS_OK )
> > +            goto wait;
> > +
> > +        memset( p_write_position, 0, l_bytes1 );
> > +        memset( p_wrap_around, 0, l_bytes2 );
> > +
> > +        IDirectSoundBuffer_Unlock( p_sys->p_dsbuffer, p_write_position,
> > l_bytes1,
> > +                                   p_wrap_around, l_bytes2 );
> > +wait:
> > +        vlc_mutex_unlock(&p_sys->lock);
> > +        msleep(20000);
> 
> This is horrible. I would not allow such thing on a platform I cared for.
> 
While I completely agree, I couldn't come up with a better solution,
unless sleeping the time returned by a TimeGet(). If you have a better
idea I'll be glad to implement it. (And throwing away directsound isn't
an acceptable solution for people who care about windows).

Regards,

-- 
Denis Charmet - TypX
Le mauvais esprit est un art de vivre



More information about the vlc-devel mailing list