Add options to control the size of the PulseAudio buffer.
Signed-off-by: Lukasz Marek <lukasz.m.luki@gmail.com>
Signed-off-by: Stefano Sabatini <stefasab@gmail.com>
... | ... |
@@ -164,6 +164,19 @@ by default it is set to the specified output name. |
164 | 164 |
Specify the device to use. Default device is used when not provided. |
165 | 165 |
List of output devices can be obtained with command @command{pactl list sinks}. |
166 | 166 |
|
167 |
+@item buffer_size |
|
168 |
+@item buffer_duration |
|
169 |
+Control the size and duration of the PulseAudio buffer. A small buffer |
|
170 |
+gives more control, but requires more frequent updates. |
|
171 |
+ |
|
172 |
+@option{buffer_size} specifies size in bytes while |
|
173 |
+@option{buffer_duration} specifies duration in milliseconds. |
|
174 |
+ |
|
175 |
+When both options are provided then the highest value is used |
|
176 |
+(duration is recalculated to bytes using stream parameters). If they |
|
177 |
+are set to 0 (which is default), the device will use the default |
|
178 |
+PulseAudio duration value. By default PulseAudio set buffer duration |
|
179 |
+to around 2 seconds. |
|
167 | 180 |
@end table |
168 | 181 |
|
169 | 182 |
@subsection Examples |
... | ... |
@@ -35,6 +35,8 @@ typedef struct PulseData { |
35 | 35 |
const char *device; |
36 | 36 |
pa_simple *pa; |
37 | 37 |
int64_t timestamp; |
38 |
+ int buffer_size; |
|
39 |
+ int buffer_duration; |
|
38 | 40 |
} PulseData; |
39 | 41 |
|
40 | 42 |
static av_cold int pulse_write_header(AVFormatContext *h) |
... | ... |
@@ -59,6 +61,19 @@ static av_cold int pulse_write_header(AVFormatContext *h) |
59 | 59 |
stream_name = "Playback"; |
60 | 60 |
} |
61 | 61 |
|
62 |
+ if (s->buffer_duration) { |
|
63 |
+ int64_t bytes = s->buffer_duration; |
|
64 |
+ bytes *= st->codec->channels * st->codec->sample_rate * |
|
65 |
+ av_get_bytes_per_sample(st->codec->sample_fmt); |
|
66 |
+ bytes /= 1000; |
|
67 |
+ attr.tlength = FFMAX(s->buffer_size, av_clip64(bytes, 0, UINT32_MAX - 1)); |
|
68 |
+ av_log(s, AV_LOG_DEBUG, |
|
69 |
+ "Buffer duration: %ums recalculated into %"PRId64" bytes buffer.\n", |
|
70 |
+ s->buffer_duration, bytes); |
|
71 |
+ av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", attr.tlength); |
|
72 |
+ } else if (s->buffer_size) |
|
73 |
+ attr.tlength = s->buffer_size; |
|
74 |
+ |
|
62 | 75 |
ss.format = ff_codec_id_to_pulse_format(st->codec->codec_id); |
63 | 76 |
ss.rate = st->codec->sample_rate; |
64 | 77 |
ss.channels = st->codec->channels; |
... | ... |
@@ -142,6 +157,8 @@ static const AVOption options[] = { |
142 | 142 |
{ "name", "set application name", OFFSET(name), AV_OPT_TYPE_STRING, {.str = LIBAVFORMAT_IDENT}, 0, 0, E }, |
143 | 143 |
{ "stream_name", "set stream description", OFFSET(stream_name), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, |
144 | 144 |
{ "device", "set device name", OFFSET(device), AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E }, |
145 |
+ { "buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, |
|
146 |
+ { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, E }, |
|
145 | 147 |
{ NULL } |
146 | 148 |
}; |
147 | 149 |
|
... | ... |
@@ -29,7 +29,7 @@ |
29 | 29 |
|
30 | 30 |
#define LIBAVDEVICE_VERSION_MAJOR 55 |
31 | 31 |
#define LIBAVDEVICE_VERSION_MINOR 5 |
32 |
-#define LIBAVDEVICE_VERSION_MICRO 101 |
|
32 |
+#define LIBAVDEVICE_VERSION_MICRO 102 |
|
33 | 33 |
|
34 | 34 |
#define LIBAVDEVICE_VERSION_INT AV_VERSION_INT(LIBAVDEVICE_VERSION_MAJOR, \ |
35 | 35 |
LIBAVDEVICE_VERSION_MINOR, \ |