Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > media > main-testing > by-pkgid > 187676b5433787923dfa2cdd6900c6cd > files > 154

lib64pulseaudio-devel-0.9.15-2.0.7mdv2009.1.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>PulseAudio: Audio Streams</title>
<link href="tabs.css" rel="stylesheet" type="text/css">
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.5.8 -->
<div class="navigation" id="top">
  <div class="tabs">
    <ul>
      <li><a href="main.html"><span>Main&nbsp;Page</span></a></li>
      <li class="current"><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
      <li><a href="annotated.html"><span>Data&nbsp;Structures</span></a></li>
      <li><a href="files.html"><span>Files</span></a></li>
      <li><a href="examples.html"><span>Examples</span></a></li>
    </ul>
  </div>
  <div class="navpath"><a class="el" href="main.html">main</a>&nbsp;&raquo&nbsp;<a class="el" href="async.html">Asynchronous API</a>
  </div>
</div>
<div class="contents">
<h1><a class="anchor" name="streams">Audio Streams </a></h1><h2><a class="anchor" name="overv_sec">
Overview</a></h2>
Audio streams form the central functionality of the sound server. Data is routed, converted and mixed from several sources before it is passed along to a final output. Currently, there are three forms of audio streams:<p>
<ul>
<li>Playback streams - Data flows from the client to the server. </li>
<li>Record streams - Data flows from the server to the client. </li>
<li>Upload streams - Similar to playback streams, but the data is stored in the sample cache. See <a class="el" href="scache.html">Sample Cache</a> for more information about controlling the sample cache.</li>
</ul>
<h2><a class="anchor" name="create_sec">
Creating</a></h2>
To access a stream, a pa_stream object must be created using <a class="el" href="stream_8h.html#b95a64207d12a1da61d31289d8b3ff3f" title="Create a new, unconnected stream with the specified name and sample type.">pa_stream_new()</a>. At this point the audio sample format and mapping of channels must be specified. See <a class="el" href="sample.html">Sample Format Specifications</a> and <a class="el" href="channelmap.html">Channel Maps</a> for more information about those structures.<p>
This first step will only create a client-side object, representing the stream. To use the stream, a server-side object must be created and associated with the local object. Depending on which type of stream is desired, a different function is needed:<p>
<ul>
<li>Playback stream - <a class="el" href="stream_8h.html#e13072bc6107aa050f2ff4d50dd49640" title="Connect the stream to a sink.">pa_stream_connect_playback()</a> </li>
<li>Record stream - <a class="el" href="stream_8h.html#bfd34293aae8f170f572d1093c1bcdf9" title="Connect the stream to a source.">pa_stream_connect_record()</a> </li>
<li>Upload stream - <a class="el" href="scache_8h.html#4725d83c96ddb3a4c67954bf5ec3a8c1" title="Make this stream a sample upload stream.">pa_stream_connect_upload()</a> (see <a class="el" href="scache.html">Sample Cache</a>)</li>
</ul>
Similar to how connections are done in contexts, connecting a stream will not generate a pa_operation object. Also like contexts, the application should register a state change callback, using <a class="el" href="stream_8h.html#295da6cbb032850600598d59fed2cc18" title="Set the callback function that is called whenever the state of the stream changes...">pa_stream_set_state_callback()</a>, and wait for the stream to enter an active state.<h3><a class="anchor" name="bufattr_subsec">
Buffer Attributes</a></h3>
Playback and record streams always have a server-side buffer as part of the data flow. The size of this buffer needs to be chosen in a compromise between low latency and sensitivity for buffer overflows/underruns.<p>
The buffer metrics may be controlled by the application. They are described with a <a class="el" href="structpa__buffer__attr.html" title="Playback and record buffer metrics.">pa_buffer_attr</a> structure which contains a number of fields:<p>
<ul>
<li>maxlength - The absolute maximum number of bytes that can be stored in the buffer. If this value is exceeded then data will be lost. It is recommended to pass (uint32_t) -1 here which will cause the server to fill in the maximum possible value.</li>
</ul>
<ul>
<li>tlength - The target fill level of the playback buffer. The server will only send requests for more data as long as the buffer has less than this number of bytes of data. If you pass (uint32_t) -1 (which is recommended) here the server will choose the longest target buffer fill level possible to minimize the number of necessary wakeups and maximize drop-out safety. This can exceed 2s of buffering. For low-latency applications or applications where latency matters you should pass a proper value here.</li>
</ul>
<ul>
<li>prebuf - Number of bytes that need to be in the buffer before playback will commence. Start of playback can be forced using <a class="el" href="stream_8h.html#e17a3a9f6ee0403c4665f6f4ce02ca3c" title="Request immediate start of playback on this stream.">pa_stream_trigger()</a> even though the prebuffer size hasn't been reached. If a buffer underrun occurs, this prebuffering will be again enabled. If the playback shall never stop in case of a buffer underrun, this value should be set to 0. In that case the read index of the output buffer overtakes the write index, and hence the fill level of the buffer is negative. If you pass (uint32_t) -1 here (which is recommended) the server will choose the same value as tlength here.</li>
</ul>
<ul>
<li>minreq - Minimum free number of the bytes in the playback buffer before the server will request more data. It is recommended to fill in (uint32_t) -1 here. This value influences how much time the sound server has to move data from the per-stream server-side playback buffer to the hardware playback buffer.</li>
</ul>
<ul>
<li>fragsize - Maximum number of bytes that the server will push in one chunk for record streams. If you pass (uint32_t) -1 (which is recommended) here, the server will choose the longest fragment setting possible to minimize the number of necessary wakeups and maximize drop-out safety. This can exceed 2s of buffering. For low-latency applications or applications where latency matters you should pass a proper value here.</li>
</ul>
If PA_STREAM_ADJUST_LATENCY is set, then the tlength/fragsize parameters will be interpreted slightly differently than described above when passed to <a class="el" href="stream_8h.html#bfd34293aae8f170f572d1093c1bcdf9" title="Connect the stream to a source.">pa_stream_connect_record()</a> and <a class="el" href="stream_8h.html#e13072bc6107aa050f2ff4d50dd49640" title="Connect the stream to a sink.">pa_stream_connect_playback()</a>: the overall latency that is comprised of both the server side playback buffer length, the hardware playback buffer length and additional latencies will be adjusted in a way that it matches tlength resp. fragsize. Set PA_STREAM_ADJUST_LATENCY if you want to control the overall playback latency for your stream. Unset it if you want to control only the latency induced by the server-side, rewritable playback buffer. The server will try to fulfill the clients latency requests as good as possible. However if the underlying hardware cannot change the hardware buffer length or only in a limited range, the actually resulting latency might be different from what the client requested. Thus, for synchronization clients always need to check the actual measured latency via <a class="el" href="stream_8h.html#a521efcc16fe2abf0f8461462432ac16" title="Return the total stream latency.">pa_stream_get_latency()</a> or a similar call, and not make any assumptions. about the latency available. The function <a class="el" href="stream_8h.html#9a3c3e78eafb28cce3a16cef2b68a385" title="Return the per-stream server-side buffer metrics of the stream.">pa_stream_get_buffer_attr()</a> will always return the actual size of the server-side per-stream buffer in tlength/fragsize, regardless whether PA_STREAM_ADJUST_LATENCY is set or not.<p>
The server-side per-stream playback buffers are indexed by a write and a read index. The application writes to the write index and the sound device reads from the read index. The read index is increased monotonically, while the write index may be freely controlled by the application. Substracting the read index from the write index will give you the current fill level of the buffer. The read/write indexes are 64bit values and measured in bytes, they will never wrap. The current read/write index may be queried using <a class="el" href="stream_8h.html#090147751441a97e04a4acef1d6514cb" title="Return the latest raw timing data structure.">pa_stream_get_timing_info()</a> (see below for more information). In case of a buffer underrun the read index is equal or larger than the write index. Unless the prebuf value is 0, PulseAudio will temporarily pause playback in such a case, and wait until the buffer is filled up to prebuf bytes again. If prebuf is 0, the read index may be larger than the write index, in which case silence is played. If the application writes data to indexes lower than the read index, the data is immediately lost.<h2><a class="anchor" name="transfer_sec">
Transferring Data</a></h2>
Once the stream is up, data can start flowing between the client and the server. Two different access models can be used to transfer the data:<p>
<ul>
<li>Asynchronous - The application register a callback using <a class="el" href="stream_8h.html#2dcc985c65964da290a0c2e1bf103175" title="Set the callback function that is called when new data may be written to the stream...">pa_stream_set_write_callback()</a> and <a class="el" href="stream_8h.html#b9949b66e1aca2c1988f864e90f2ae4c" title="Set the callback function that is called when new data is available from the stream...">pa_stream_set_read_callback()</a> to receive notifications that data can either be written or read. </li>
<li>Polled - Query the library for available data/space using <a class="el" href="stream_8h.html#b63ccd1908b6deae1b2ca7be6fa759e7" title="Return the number of bytes that may be written using pa_stream_write().">pa_stream_writable_size()</a> and <a class="el" href="stream_8h.html#a2e5ff19aa36b90471c34badbdfdf345" title="Return the number of bytes that may be read using pa_stream_peek().">pa_stream_readable_size()</a> and transfer data as needed. The sizes are stored locally, in the client end, so there is no delay when reading them.</li>
</ul>
It is also possible to mix the two models freely.<p>
Once there is data/space available, it can be transferred using either <a class="el" href="stream_8h.html#4fc69dec0cc202fcc174125dc88dada7" title="Write some data to the server (for playback sinks), if free_cb is non-NULL this routine...">pa_stream_write()</a> for playback, or <a class="el" href="stream_8h.html#c2838c449cde56e169224d7fe3d00824" title="Read the next fragment from the buffer (for recording).">pa_stream_peek()</a> / <a class="el" href="stream_8h.html#2e8a3e15fb63a5bb9cbba2d01a6538a5" title="Remove the current fragment on record streams.">pa_stream_drop()</a> for record. Make sure you do not overflow the playback buffers as data will be dropped.<h2><a class="anchor" name="bufctl_sec">
Buffer Control</a></h2>
The transfer buffers can be controlled through a number of operations:<p>
<ul>
<li><a class="el" href="stream_8h.html#14e698233ac2d246646651955ab0ec7b" title="Pause (or resume) playback of this stream temporarily.">pa_stream_cork()</a> - Start or stop the playback or recording. </li>
<li><a class="el" href="stream_8h.html#e17a3a9f6ee0403c4665f6f4ce02ca3c" title="Request immediate start of playback on this stream.">pa_stream_trigger()</a> - Start playback immediatly and do not wait for the buffer to fill up to the set trigger level. </li>
<li><a class="el" href="stream_8h.html#628650e49917cc9459a4a601a7f2a6fc" title="Reenable prebuffering as specified in the pa_buffer_attr structure.">pa_stream_prebuf()</a> - Reenable the playback trigger level. </li>
<li><a class="el" href="stream_8h.html#8d263f188073f244b3820f3f50db4ba5" title="Drain a playback stream.">pa_stream_drain()</a> - Wait for the playback buffer to go empty. Will return a pa_operation object that will indicate when the buffer is completely drained. </li>
<li><a class="el" href="stream_8h.html#c9c524eb275d258b00c553409682409c" title="Flush the playback buffer of this stream.">pa_stream_flush()</a> - Drop all data from the playback buffer and do not wait for it to finish playing.</li>
</ul>
<h2><a class="anchor" name="seek_modes">
Seeking in the Playback Buffer</a></h2>
A client application may freely seek in the playback buffer. To accomplish that the <a class="el" href="stream_8h.html#4fc69dec0cc202fcc174125dc88dada7" title="Write some data to the server (for playback sinks), if free_cb is non-NULL this routine...">pa_stream_write()</a> function takes a seek mode and an offset argument. The seek mode is one of:<p>
<ul>
<li>PA_SEEK_RELATIVE - seek relative to the current write index </li>
<li>PA_SEEK_ABSOLUTE - seek relative to the beginning of the playback buffer, (i.e. the first that was ever played in the stream) </li>
<li>PA_SEEK_RELATIVE_ON_READ - seek relative to the current read index. Use this to write data to the output buffer that should be played as soon as possible </li>
<li>PA_SEEK_RELATIVE_END - seek relative to the last byte ever written.</li>
</ul>
If an application just wants to append some data to the output buffer, PA_SEEK_RELATIVE and an offset of 0 should be used.<p>
After a call to <a class="el" href="stream_8h.html#4fc69dec0cc202fcc174125dc88dada7" title="Write some data to the server (for playback sinks), if free_cb is non-NULL this routine...">pa_stream_write()</a> the write index will be left at the position right after the last byte of the written data.<h2><a class="anchor" name="latency_sec">
Latency</a></h2>
A major problem with networked audio is the increased latency caused by the network. To remedy this, PulseAudio supports an advanced system of monitoring the current latency.<p>
To get the raw data needed to calculate latencies, call <a class="el" href="stream_8h.html#090147751441a97e04a4acef1d6514cb" title="Return the latest raw timing data structure.">pa_stream_get_timing_info()</a>. This will give you a <a class="el" href="structpa__timing__info.html" title="A structure for all kinds of timing information of a stream.">pa_timing_info</a> structure that contains everything that is known about the server side buffer transport delays and the backend active in the server. (Besides other things it contains the write and read index values mentioned above.)<p>
This structure is updated every time a <a class="el" href="stream_8h.html#c8300aa5136a223b14a5384f44564284" title="Request a timing info structure update for a stream.">pa_stream_update_timing_info()</a> operation is executed. (i.e. before the first call to this function the timing information structure is not available!) Since it is a lot of work to keep this structure up-to-date manually, PulseAudio can do that automatically for you: if PA_STREAM_AUTO_TIMING_UPDATE is passed when connecting the stream PulseAudio will automatically update the structure every 100ms and every time a function is called that might invalidate the previously known timing data (such as <a class="el" href="stream_8h.html#4fc69dec0cc202fcc174125dc88dada7" title="Write some data to the server (for playback sinks), if free_cb is non-NULL this routine...">pa_stream_write()</a> or <a class="el" href="stream_8h.html#c9c524eb275d258b00c553409682409c" title="Flush the playback buffer of this stream.">pa_stream_flush()</a>). Please note however, that there always is a short time window when the data in the timing information structure is out-of-date. PulseAudio tries to mark these situations by setting the write_index_corrupt and read_index_corrupt fields accordingly.<p>
The raw timing data in the <a class="el" href="structpa__timing__info.html" title="A structure for all kinds of timing information of a stream.">pa_timing_info</a> structure is usually hard to deal with. Therefore a simpler interface is available: you can call <a class="el" href="stream_8h.html#9b1caba84c7a5c90efdbcaed31e9dfca" title="Return the current playback/recording time.">pa_stream_get_time()</a> or <a class="el" href="stream_8h.html#a521efcc16fe2abf0f8461462432ac16" title="Return the total stream latency.">pa_stream_get_latency()</a>. The former will return the current playback time of the hardware since the stream has been started. The latter returns the overall time a sample that you write now takes to be played by the hardware. These two functions base their calculations on the same data that is returned by <a class="el" href="stream_8h.html#090147751441a97e04a4acef1d6514cb" title="Return the latest raw timing data structure.">pa_stream_get_timing_info()</a>. Hence the same rules for keeping the timing data up-to-date apply here. In case the write or read index is corrupted, these two functions will fail with PA_ERR_NODATA set.<p>
Since updating the timing info structure usually requires a full network round trip and some applications monitor the timing very often PulseAudio offers a timing interpolation system. If PA_STREAM_INTERPOLATE_TIMING is passed when connecting the stream, <a class="el" href="stream_8h.html#9b1caba84c7a5c90efdbcaed31e9dfca" title="Return the current playback/recording time.">pa_stream_get_time()</a> and <a class="el" href="stream_8h.html#a521efcc16fe2abf0f8461462432ac16" title="Return the total stream latency.">pa_stream_get_latency()</a> will try to interpolate the current playback time/latency by estimating the number of samples that have been played back by the hardware since the last regular timing update. It is espcially useful to combine this option with PA_STREAM_AUTO_TIMING_UPDATE, which will enable you to monitor the current playback time/latency very precisely and very frequently without requiring a network round trip every time.<h2><a class="anchor" name="flow_sec">
Overflow and underflow</a></h2>
Even with the best precautions, buffers will sometime over - or underflow. To handle this gracefully, the application can be notified when this happens. Callbacks are registered using <a class="el" href="stream_8h.html#f1e07bc89d12aca66d2725a60cfdbdc3" title="Set the callback function that is called when a buffer overflow happens.">pa_stream_set_overflow_callback()</a> and <a class="el" href="stream_8h.html#660b5a7096409f41ef52b8e0b7e96d38" title="Set the callback function that is called when a buffer underflow happens.">pa_stream_set_underflow_callback()</a>.<h2><a class="anchor" name="sync_streams">
Sychronizing Multiple Playback Streams</a></h2>
PulseAudio allows applications to fully synchronize multiple playback streams that are connected to the same output device. That means the streams will always be played back sample-by-sample synchronously. If stream operations like <a class="el" href="stream_8h.html#14e698233ac2d246646651955ab0ec7b" title="Pause (or resume) playback of this stream temporarily.">pa_stream_cork()</a> are issued on one of the synchronized streams, they are simultaneously issued on the others.<p>
To synchronize a stream to another, just pass the "master" stream as last argument to pa_stream_connect_playack(). To make sure that the freshly created stream doesn't start playback right-away, make sure to pass PA_STREAM_START_CORKED and - after all streams have been created - uncork them all with a single call to <a class="el" href="stream_8h.html#14e698233ac2d246646651955ab0ec7b" title="Pause (or resume) playback of this stream temporarily.">pa_stream_cork()</a> for the master stream.<p>
To make sure that a particular stream doesn't stop to play when a server side buffer underrun happens on it while the other synchronized streams continue playing and hence deviate you need to pass a "prebuf" <a class="el" href="structpa__buffer__attr.html" title="Playback and record buffer metrics.">pa_buffer_attr</a> of 0 when connecting it.<h2><a class="anchor" name="disc_sec">
Disconnecting</a></h2>
When a stream has served is purpose it must be disconnected with <a class="el" href="stream_8h.html#a4e0c83264f3935911e6b30e6f8ef2b1" title="Disconnect a stream from a source/sink.">pa_stream_disconnect()</a>. If you only unreference it, then it will live on and eat resources both locally and on the server until you disconnect the context. </div>
<hr size="1"><address style="text-align: right;"><small>Generated on Wed Sep 2 04:18:20 2009 for PulseAudio by&nbsp;
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.8 </small></address>
</body>
</html>