]> git.sesse.net Git - ffmpeg/commitdiff
avdevice/alsa_dec: make sure we have enough data in non-blocking mode
authorMarton Balint <cus@passwd.hu>
Tue, 9 Feb 2021 21:24:50 +0000 (22:24 +0100)
committerMarton Balint <cus@passwd.hu>
Fri, 12 Mar 2021 22:55:30 +0000 (23:55 +0100)
Otherwise we might return 1-2 samples per packet if av_read_frame() call rate is
only sligthly less than the stream sample rate.

Signed-off-by: Marton Balint <cus@passwd.hu>
libavdevice/alsa.c
libavdevice/alsa.h
libavdevice/alsa_dec.c

index 117b2ea144eac4e52d07985cc0074ec4f9f36307..ee282fac1681c8856dc1bfa53ef3e659fd98be8a 100644 (file)
@@ -286,6 +286,10 @@ av_cold int ff_alsa_open(AVFormatContext *ctx, snd_pcm_stream_t mode,
         }
     }
 
+    s->pkt = av_packet_alloc();
+    if (!s->pkt)
+        goto fail1;
+
     s->h = h;
     return 0;
 
@@ -308,6 +312,7 @@ av_cold int ff_alsa_close(AVFormatContext *s1)
     if (CONFIG_ALSA_INDEV)
         ff_timefilter_destroy(s->timefilter);
     snd_pcm_close(s->h);
+    av_packet_free(&s->pkt);
     return 0;
 }
 
index 1ed8c82199267d38168da8a852229b06c491056b..07783c983a7eb8c6584f8906dbcb64f035d97b1b 100644 (file)
@@ -58,6 +58,7 @@ typedef struct AlsaData {
     void *reorder_buf;
     int reorder_buf_size; ///< in frames
     int64_t timestamp; ///< current timestamp, without latency applied.
+    AVPacket *pkt;
 } AlsaData;
 
 /**
index 36494e921cc0c22659c3a25fbd3452344e0d27c3..d8d4f3293bc5cd65f4cdd610555017fb0fe50286 100644 (file)
@@ -105,34 +105,36 @@ static int audio_read_packet(AVFormatContext *s1, AVPacket *pkt)
     int64_t dts;
     snd_pcm_sframes_t delay = 0;
 
-    if (av_new_packet(pkt, s->period_size * s->frame_size) < 0) {
-        return AVERROR(EIO);
+    if (!s->pkt->data) {
+        int ret = av_new_packet(s->pkt, s->period_size * s->frame_size);
+        if (ret < 0)
+            return ret;
+        s->pkt->size = 0;
     }
 
-    while ((res = snd_pcm_readi(s->h, pkt->data, s->period_size)) < 0) {
+    do {
+        while ((res = snd_pcm_readi(s->h, s->pkt->data + s->pkt->size, s->period_size - s->pkt->size / s->frame_size)) < 0) {
         if (res == -EAGAIN) {
-            av_packet_unref(pkt);
-
             return AVERROR(EAGAIN);
         }
+        s->pkt->size = 0;
         if (ff_alsa_xrun_recover(s1, res) < 0) {
             av_log(s1, AV_LOG_ERROR, "ALSA read error: %s\n",
                    snd_strerror(res));
-            av_packet_unref(pkt);
-
             return AVERROR(EIO);
         }
         ff_timefilter_reset(s->timefilter);
-    }
+        }
+        s->pkt->size += res * s->frame_size;
+    } while (s->pkt->size < s->period_size * s->frame_size);
 
+    av_packet_move_ref(pkt, s->pkt);
     dts = av_gettime();
     snd_pcm_delay(s->h, &delay);
     dts -= av_rescale(delay + res, 1000000, s->sample_rate);
     pkt->pts = ff_timefilter_update(s->timefilter, dts, s->last_period);
     s->last_period = res;
 
-    pkt->size = res * s->frame_size;
-
     return 0;
 }