diff options
author | Marton Balint <cus@passwd.hu> | 2021-02-09 22:24:50 +0100 |
---|---|---|
committer | Marton Balint <cus@passwd.hu> | 2021-03-12 23:55:30 +0100 |
commit | 1a90cf4410a3464c8d749242e23629776f310ee0 (patch) | |
tree | 29e9f37ea37029c880933fa0508e26d6fbfd283d | |
parent | 6e7e3a3820f0888ff92d6be44f40ff733bcce874 (diff) | |
download | ffmpeg-1a90cf4410a3464c8d749242e23629776f310ee0.tar.gz |
avdevice/alsa_dec: make sure we have enough data in non-blocking mode
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>
-rw-r--r-- | libavdevice/alsa.c | 5 | ||||
-rw-r--r-- | libavdevice/alsa.h | 1 | ||||
-rw-r--r-- | libavdevice/alsa_dec.c | 22 |
3 files changed, 18 insertions, 10 deletions
diff --git a/libavdevice/alsa.c b/libavdevice/alsa.c index 117b2ea144..ee282fac16 100644 --- a/libavdevice/alsa.c +++ b/libavdevice/alsa.c @@ -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; } diff --git a/libavdevice/alsa.h b/libavdevice/alsa.h index 1ed8c82199..07783c983a 100644 --- a/libavdevice/alsa.h +++ b/libavdevice/alsa.h @@ -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; /** diff --git a/libavdevice/alsa_dec.c b/libavdevice/alsa_dec.c index 36494e921c..d8d4f3293b 100644 --- a/libavdevice/alsa_dec.c +++ b/libavdevice/alsa_dec.c @@ -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; } |