From: Werner Van Belle <werner@yellowcouch.org>
To: "alsa-devel@alsa-project.org" <alsa-devel@alsa-project.org>
Cc: Takashi Iwai <tiwai@suse.de>
Subject: Re: Third time: Unlink PCM resource ?
Date: Mon, 25 May 2009 21:36:38 +0200 [thread overview]
Message-ID: <4A1AF346.9040602@yellowcouch.org> (raw)
In-Reply-To: <alpine.LNX.2.00.0905252036550.4067@eeebox2.perex-int.cz>
[-- Attachment #1.1.1: Type: text/plain, Size: 1398 bytes --]
Jaroslav Kysela wrote:
> The question is if it's not better to free also allocated memory
> associated to the pcm handle in child process - so snd_pcm_close()
> call in child is not a bad idea.
>
Okay, while you both have been discussing some internals, which I didn't
try yet, I created a demonstration program to illustrate the mixed
semantics of the 'sharing' versus 'not sharing' behavior of the dsp
devices. In the example the parent thread will play a sound, then the
child closes the dsp, which affects the playback in the parent (it
either hangs or skips all remaining samples). From this one would
conclude that the pcm device is fully shared between the two processes
(semantics I can live with). However, when the parent then tries to
reopen the device it cannot do so because the device is still 'busy'.
As a solution, a call to an unlink function would maybe solve it but it
is indicative of a deeper unclarity of how the semantics of shared DSP
devices should be. I would propose to let alsa act as a true filehandle.
In such a scenario a close in the child should not affect the playback
in the parent since the parent still has the descriptor open. Please
have a look at the attached code. It is 256 lines :-) The problem is
documented in the main routine.
With kind regards,
Werner,-
--
Dr. Werner Van Belle
http://werner.yellowcouch.org/
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1.1.2: close-affects-play.cpp --]
[-- Type: text/x-c++src; name="close-affects-play.cpp", Size: 6736 bytes --]
using namespace std;
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define ALSA_PCM_NEW_HW_PARAMS_API
#define ALSA_PCM_NEW_SW_PARAMS_API
#include <stdarg.h>
#include <alsa/asoundlib.h>
#include "memory.h"
#include <iostream>
typedef unsigned int unsigned4;
typedef signed long long signed8;
typedef signed short signed2;
snd_pcm_t *dsp;
snd_pcm_uframes_t buffer_size;
snd_pcm_uframes_t period_size;
unsigned4 * buffer;
unsigned4 filled;
int arg_latency;
char * arg_dev;
const int err_dsp=1;
const int err_none=0;
void Info(const char* script, ...)
{
char toexecute[1024];
va_list ap;
va_start(ap,script);
vsnprintf(toexecute,1024,script,ap);
va_end(ap);
cout << toexecute << '\n';
fflush(stdout);
};
void dsp_write(unsigned4 *value)
{
int err = 0;
while(!err)
{
err = snd_pcm_writei(dsp,value,1);
}
assert(err!=-EAGAIN);
assert(err!=-ESTRPIPE);
if (err==-EPIPE)
{
Info("underrun occured...");
err = snd_pcm_prepare(dsp);
if (err < 0)
Info("cant recover from underrun: %s",snd_strerror(err));
return;
}
}
int dsp_open()
{
int err;
unsigned int buffer_time, period_time;
snd_pcm_hw_params_t *hparams;
snd_pcm_sw_params_t *sparams;
snd_output_t * output = NULL;
err = snd_output_stdio_attach(&output,stdout,0);
if (err < 0 )
{
Info("attaching to stdio didn't succeed: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_open(&dsp, arg_dev, SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0)
{
Info("opening alsa device failed : %s",snd_strerror(err));
return err_dsp;
}
snd_pcm_sw_params_alloca(&sparams);
snd_pcm_hw_params_alloca(&hparams);
err = snd_pcm_hw_params_any(dsp, hparams);
if (err<0)
{
Info("Broken configuration file for pcm : %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_hw_params_set_access(dsp, hparams, SND_PCM_ACCESS_RW_INTERLEAVED);
if (err<0)
{
Info("Unable to set interleaved access to pcm device: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_hw_params_set_format(dsp, hparams, SND_PCM_FORMAT_S16);
if (err<0)
{
Info("Unable to set sample format to standard 16 bit: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_hw_params_set_channels(dsp, hparams, 2);
if (err < 0)
{
Info("setting dsp to 2 channels failed : %s",snd_strerror(err));
return err_dsp;
}
unsigned int q = 44100;
err = snd_pcm_hw_params_set_rate_near(dsp, hparams, &q, 0);
if (err < 0)
{
Info("setting dsp speed (%d) failed",q);
return err_dsp;
}
if (q != 44100)
Info("setting dsp speed (%d) failed, resulting rate = %d ",44100, q);
period_time = arg_latency * 1000;
buffer_time = period_time *2;
{
unsigned int t = buffer_time;
int dir = 1;
err = snd_pcm_hw_params_set_buffer_time_near(dsp,hparams,&t,&dir);
if (err<0)
{
Info("dsp-alsa: Impossible to set pcm buffer time to %i (%i): %s", buffer_time,t,snd_strerror(err));
return err_dsp;
}
err = snd_pcm_hw_params_get_buffer_size(hparams,&buffer_size);
if (err<0)
{
Info(" impossible to obtain buffer size: %s",snd_strerror(err));
return err_dsp;
}
t = period_time;
err = snd_pcm_hw_params_set_period_time_near(dsp, hparams,&t,&dir);
if (err<0)
{
Info(" impossible to set pcm period time to %i (%i): %s", period_time,t,snd_strerror(err));
return err_dsp;
}
err = snd_pcm_hw_params_get_period_size(hparams,&period_size,&dir);
if (err<0)
{
Info(" ompossible to obtain period data size: %s",snd_strerror(err));
return err_dsp;
}
if (period_size*2 - 1>buffer_size)
{
Info("The alsa driver cannot allocate sufficiently large buffers due to the "
"large requested latency. (playbuffer size = %li, "
"total buffer size = %li). Try decreasing the latency.",period_size,buffer_size);
return err_dsp;
}
dir = 0;
}
err = snd_pcm_hw_params(dsp,hparams);
if (err < 0)
{
Info("unable to set hw parameters for pcm: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_sw_params_current(dsp,sparams);
if (err < 0)
{
Info("unable to determine sw parameters for pcm: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_sw_params_set_start_threshold(dsp,sparams,buffer_size);
if (err < 0)
{
Info("unable to set start to treshold mode: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_sw_params_set_avail_min(dsp,sparams,period_size);
if (err < 0 )
{
Info("unable to set minimum start size: %s",snd_strerror(err));
return err_dsp;
}
err = snd_pcm_sw_params(dsp,sparams);
if (err < 0)
{
Info("unable to set software parameters: %s",snd_strerror(err));
return err_dsp;
}
snd_pcm_dump(dsp,output);
buffer = (unsigned4*)malloc(period_size*sizeof(unsigned4));
return err_none;
}
void dsp_close()
{
int err = snd_pcm_close(dsp);
if (err < 0)
Info("cant close pcm device: %s",snd_strerror(err));
dsp=0;
}
void stream_wave()
{
for(int t=10; t>=0; t--)
{
cerr << "Parent plays (" << t << "s left)\n";
for(int i = 0 ; i < 44100; i++)
{
float x=i;
float y=16384.*sin(x*2*M_PI*220./44100.)/4;
struct {signed2 l; signed2 r;} lr;
lr.l=y;
lr.r=y;
dsp_write((unsigned4*)&lr);
}
}
}
/**
* This example first shows that a close in the child will
* affect the playback in the parent. Sometimes the parents
* just hangs in the write call, sometimes it just skips
* all samples.
*
* However, the device in the parent is actually not
* closed at all since we cannot reopen it.
*/
int main (int argc, char* argv[])
{
arg_dev = "hw:0";
dsp = NULL;
filled = 0;
buffer_size = 0;
period_size = 0;
arg_latency = 150;
// first open the DSP device.
Info("Opening DSP Device in parent thread");
dsp_open();
int childpid=fork(); assert(childpid>-1);
if (childpid)
{
// the parent thread now waits two seconds and the closes the device
Info("Parent thread playing");
stream_wave();
Info("Parent tries to reopen the device");
dsp_open();
stream_wave();
}
else
{
sleep(5);
Info("Child closes the dsp device");
dsp_close();
}
}
[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]
[-- Attachment #2: Type: text/plain, Size: 160 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
next prev parent reply other threads:[~2009-05-25 19:34 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-05-25 15:30 Third time: Unlink PCM resource ? Werner Van Belle
2009-05-25 15:43 ` Takashi Iwai
2009-05-25 17:52 ` Werner Van Belle
2009-05-25 18:09 ` Jaroslav Kysela
2009-05-25 18:15 ` Werner Van Belle
2009-05-25 18:18 ` Takashi Iwai
2009-05-25 18:27 ` Werner Van Belle
2009-05-25 18:31 ` Jaroslav Kysela
2009-05-25 18:38 ` Takashi Iwai
2009-05-25 18:34 ` Takashi Iwai
2009-05-25 18:39 ` Jaroslav Kysela
2009-05-25 19:36 ` Werner Van Belle [this message]
2009-05-25 21:54 ` Jaroslav Kysela
2009-05-25 22:29 ` Werner Van Belle
2009-05-26 5:53 ` Takashi Iwai
2009-05-26 8:14 ` Werner Van Belle
2009-05-26 8:17 ` Takashi Iwai
2009-07-07 15:06 ` Takashi Iwai
2009-05-25 21:25 ` Werner Van Belle
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A1AF346.9040602@yellowcouch.org \
--to=werner@yellowcouch.org \
--cc=alsa-devel@alsa-project.org \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.