summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarton Balint <cus@passwd.hu>2021-02-09 22:24:50 +0100
committerMarton Balint <cus@passwd.hu>2021-03-12 23:55:30 +0100
commit1a90cf4410a3464c8d749242e23629776f310ee0 (patch)
tree29e9f37ea37029c880933fa0508e26d6fbfd283d
parent6e7e3a3820f0888ff92d6be44f40ff733bcce874 (diff)
downloadffmpeg-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.c5
-rw-r--r--libavdevice/alsa.h1
-rw-r--r--libavdevice/alsa_dec.c22
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;
}