doc: add very basic libcdio documentation
[ffmpeg.git] / libavdevice / pulse_audio_enc.c
index 92e0697..bc4d1f0 100644 (file)
@@ -38,6 +38,8 @@ typedef struct PulseData {
     int64_t timestamp;
     int buffer_size;               /**< Buffer size in bytes */
     int buffer_duration;           /**< Buffer size in ms, recalculated to buffer_size */
+    int prebuf;
+    int minreq;
     int last_result;
     pa_threaded_mainloop *mainloop;
     pa_context *ctx;
@@ -475,6 +477,10 @@ static av_cold int pulse_write_header(AVFormatContext *h)
         av_log(s, AV_LOG_DEBUG, "Real buffer length is %u bytes\n", buffer_attributes.tlength);
     } else if (s->buffer_size)
         buffer_attributes.tlength = s->buffer_size;
+    if (s->prebuf)
+        buffer_attributes.prebuf = s->prebuf;
+    if (s->minreq)
+        buffer_attributes.minreq = s->minreq;
 
     sample_spec.format = ff_codec_id_to_pulse_format(st->codec->codec_id);
     sample_spec.rate = st->codec->sample_rate;
@@ -578,6 +584,14 @@ static av_cold int pulse_write_header(AVFormatContext *h)
         goto fail;
     }
 
+    /* read back buffer attributes for future use */
+    buffer_attributes = *pa_stream_get_buffer_attr(s->stream);
+    s->buffer_size = buffer_attributes.tlength;
+    s->prebuf = buffer_attributes.prebuf;
+    s->minreq = buffer_attributes.minreq;
+    av_log(s, AV_LOG_DEBUG, "Real buffer attributes: size: %d, prebuf: %d, minreq: %d\n",
+           s->buffer_size, s->prebuf, s->minreq);
+
     pa_threaded_mainloop_unlock(s->mainloop);
 
     if ((ret = pulse_subscribe_events(s)) < 0) {
@@ -610,6 +624,7 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
 {
     PulseData *s = h->priv_data;
     int ret;
+    int64_t writable_size;
 
     if (!pkt)
         return pulse_flash_stream(s);
@@ -632,7 +647,7 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
         av_log(s, AV_LOG_ERROR, "PulseAudio stream is in invalid state.\n");
         goto fail;
     }
-    while (!pa_stream_writable_size(s->stream)) {
+    while (pa_stream_writable_size(s->stream) < s->minreq) {
         if (s->nonblocking) {
             pa_threaded_mainloop_unlock(s->mainloop);
             return AVERROR(EAGAIN);
@@ -644,6 +659,9 @@ static int pulse_write_packet(AVFormatContext *h, AVPacket *pkt)
         av_log(s, AV_LOG_ERROR, "pa_stream_write failed: %s\n", pa_strerror(ret));
         goto fail;
     }
+    if ((writable_size = pa_stream_writable_size(s->stream)) >= s->minreq)
+        avdevice_dev_to_app_control_message(h, AV_DEV_TO_APP_BUFFER_WRITABLE, &writable_size, sizeof(writable_size));
+
     pa_threaded_mainloop_unlock(s->mainloop);
 
     return 0;
@@ -663,7 +681,7 @@ static int pulse_write_frame(AVFormatContext *h, int stream_index,
                AVERROR(EINVAL) : 0;
 
     pkt.data     = (*frame)->data[0];
-    pkt.size     = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * (*frame)->channels;
+    pkt.size     = (*frame)->nb_samples * av_get_bytes_per_sample((*frame)->format) * av_frame_get_channels(*frame);
     pkt.dts      = (*frame)->pkt_dts;
     pkt.duration = av_frame_get_pkt_duration(*frame);
     return pulse_write_packet(h, &pkt);
@@ -678,8 +696,10 @@ static void pulse_get_output_timestamp(AVFormatContext *h, int stream, int64_t *
     pa_threaded_mainloop_lock(s->mainloop);
     pa_stream_get_latency(s->stream, &latency, &neg);
     pa_threaded_mainloop_unlock(s->mainloop);
-    *wall = av_gettime();
-    *dts = s->timestamp - (neg ? -latency : latency);
+    if (wall)
+        *wall = av_gettime();
+    if (dts)
+        *dts = s->timestamp - (neg ? -latency : latency);
 }
 
 static int pulse_get_device_list(AVFormatContext *h, AVDeviceInfoList *device_list)
@@ -724,7 +744,7 @@ static int pulse_control_message(AVFormatContext *h, int type,
         ret = pulse_update_sink_input_info(h);
         pa_threaded_mainloop_unlock(s->mainloop);
         return ret;
-    case AV_APP_TO_DEV_GET_MUTE:        
+    case AV_APP_TO_DEV_GET_MUTE:
         s->mute = -1;
         pa_threaded_mainloop_lock(s->mainloop);
         ret = pulse_update_sink_input_info(h);
@@ -745,6 +765,8 @@ static const AVOption options[] = {
     { "device",          "set device name",                  OFFSET(device),          AV_OPT_TYPE_STRING, {.str = NULL}, 0, 0, E },
     { "buffer_size",     "set buffer size in bytes",         OFFSET(buffer_size),     AV_OPT_TYPE_INT,    {.i64 = 0}, 0, INT_MAX, E },
     { "buffer_duration", "set buffer duration in millisecs", OFFSET(buffer_duration), AV_OPT_TYPE_INT,    {.i64 = 0}, 0, INT_MAX, E },
+    { "prebuf",          "set pre-buffering size",           OFFSET(prebuf),          AV_OPT_TYPE_INT,    {.i64 = 0}, 0, INT_MAX, E },
+    { "minreq",          "set minimum request size",         OFFSET(minreq),          AV_OPT_TYPE_INT,    {.i64 = 0}, 0, INT_MAX, E },
     { NULL }
 };