[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] audio output overflow when play movies
From: |
address@hidden |
Subject: |
[Qemu-devel] audio output overflow when play movies |
Date: |
Tue, 8 Mar 2016 16:31:17 +0800 |
Hi,
I run Windows7, which plays HD Movies again and again, on QEMU emulator 2.0.1 for several days. then I found the main thread which invoke audio_pcm_sw_read->st_rate_flow get stuck.
Is anyone ever notice it?
here is the backtrace:
Thread 1 (Thread 0x7f5e569dc920 (LWP 2683)):
#0 st_rate_flow (opaque=0x7f5e5a83efd0, ibuf=0x7f5e5a0b8070, obuf=0x7f5e5acd11c0, address@hidden, address@hidden)
at audio/rate_template.h:71
#1 0x00007f5e56b95a16 in audio_pcm_sw_read (sw=0x7f5e59f9ca10, buf=0x7f5e59fa06d8, size=<optimized out>) at audio/audio.c:954
#2 0x00007f5e56c0d0ee in hda_audio_input_cb (opaque=0x7f5e59fa0690, avail=2640) at hw/audio/hda-codec.c:187
#3 0x00007f5e56b974ed in audio_run_in (s=<optimized out>) at audio/audio.c:1490
#4 audio_run (address@hidden "timer") at audio/audio.c:1549
#5 0x00007f5e56b97524 in audio_timer (opaque=0x7f5e573cfd20) at audio/audio.c:1137
#6 0x00007f5e56d1adb9 in timerlist_run_timers (timer_list=0x7f5e597e83c0) at qemu-timer.c:493
#7 0x00007f5e56d1ae8a in qemu_clock_run_timers (address@hidden) at qemu-timer.c:504
#8 0x00007f5e56d1b2d8 in qemu_clock_run_all_timers () at qemu-timer.c:610
#9 0x00007f5e56cdda4c in main_loop_wait (nonblocking=<optimized out>) at main-loop.c:515
#10 0x00007f5e56b8e203 in main_loop () at vl.c:2360
#11 main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at vl.c:4970
with the follow code:
/*
* Processed signed long samples from ibuf to obuf.
* Return number of samples processed.
*/
void st_rate_flow (void *opaque, struct st_sample *ibuf, struct st_sample *obuf,
int *isamp, int *osamp)
{
struct rate *rate = opaque;
struct st_sample *istart, *iend;
struct st_sample *ostart, *oend;
struct st_sample ilast, icur, out;
#ifdef FLOAT_MIXENG
mixeng_real t;
#else
int64_t t;
#endif
ilast = rate->ilast;
istart = ibuf;
iend = ibuf + *isamp;
ostart = obuf;
oend = obuf + *osamp;
if (rate->opos_inc == (1ULL + UINT_MAX)) {
int i, n = *isamp > *osamp ? *osamp : *isamp;
for (i = 0; i < n; i++) {
OP (obuf[i].l, ibuf[i].l);
OP (obuf[i].r, ibuf[i].r);
}
*isamp = n;
*osamp = n;
return;
}
while (obuf < oend) {
/* Safety catch to make sure we have input samples. */
if (ibuf >= iend) {
break;
}
/* read as many input samples so that ipos > opos */
while (rate->ipos <= (rate->opos >> 32)) { // P1: (rate->opos >> 32) = 0xFFFFFFFF
ilast = *ibuf++;
rate->ipos++;
/* See if we finished the input buffer yet */
if (ibuf >= iend) {
goto the_end; // P2: goto the end
}
}
icur = *ibuf;
/* interpolate */
#ifdef FLOAT_MIXENG
#ifdef RECIPROCAL
t = (rate->opos & UINT_MAX) * (1.f / UINT_MAX);
#else
t = (rate->opos & UINT_MAX) / (mixeng_real) UINT_MAX;
#endif
out.l = (ilast.l * (1.0 - t)) + icur.l * t;
out.r = (ilast.r * (1.0 - t)) + icur.r * t;
#else
t = rate->opos & 0xffffffff;
out.l = (ilast.l * ((int64_t) UINT_MAX - t) + icur.l * t) >> 32;
out.r = (ilast.r * ((int64_t) UINT_MAX - t) + icur.r * t) >> 32;
#endif
/* output sample & increment position */
OP (obuf->l, out.l);
OP (obuf->r, out.r);
obuf += 1;
rate->opos += rate->opos_inc;
}
the_end:
*isamp = ibuf - istart;
*osamp = obuf - ostart; // P3: osamp is 0 for obuf equal ostart
rate->ilast = ilast;
}
int audio_pcm_sw_read (SWVoiceIn *sw, void *buf, int size)
{
HWVoiceIn *hw = sw->hw;
int samples, live, ret = 0, swlim, isamp, osamp, rpos, total = 0;
struct st_sample *src, *dst = sw->buf;
rpos = audio_pcm_sw_get_rpos_in (sw) % hw->samples;
live = hw->total_samples_captured - sw->total_hw_samples_acquired;
if (audio_bug (AUDIO_FUNC, live < 0 || live > hw->samples)) {
dolog ("live_in=%d hw->samples=%d\n", live, hw->samples);
return 0;
}
samples = size >> sw->info.shift;
if (!live) {
return 0;
}
swlim = (live * sw->ratio) >> 32;
swlim = audio_MIN (swlim, samples);
while (swlim) { // P5: come back again
src = hw->conv_buf + rpos;
isamp = hw->wpos - rpos;
/* XXX: <= ? */
if (isamp <= 0) {
isamp = hw->samples - rpos;
}
if (!isamp) {
break;
}
osamp = swlim;
if (audio_bug (AUDIO_FUNC, osamp < 0)) {
dolog ("osamp=%d\n", osamp);
return 0;
}
st_rate_flow (sw->rate, src, dst, &isamp, &osamp);
swlim -= osamp; // P4: nothing change when swlim substract 0
rpos = (rpos + isamp) % hw->samples;
dst += osamp;
ret += osamp;
total += isamp;
}
if (!(hw->ctl_caps & VOICE_VOLUME_CAP)) {
mixeng_volume (sw->buf, ret, &sw->vol);
}
sw->clip (buf, sw->buf, ret);
sw->total_hw_samples_acquired += total;
return ret << sw->info.shift;
}
#ANALYSIS:
at position 1, P1:
/* Private data */
struct rate {
uint64_t opos;
uint64_t opos_inc;
uint32_t ipos; /* position in the input stream (integer) */
struct st_sample ilast; /* last sample in the input stream */
};
while (rate->ipos <= (rate->opos >> 32)) { // P1: (rate->opos >> 32) = 0xFFFFFFFF
ilast = *ibuf++;
rate->ipos++;
/* See if we finished the input buffer yet */
if (ibuf >= iend) {
goto the_end; // P2: goto the end
}
}
I dump the value:
(gdb) p *rate
$45 = {opos = 18446744069687585005, opos_inc = 4674794335, ipos = 3649290292, ilast = {l = 0, r = 0}}
as u can see, rate->opos = 18446744069687585005 = 0xFFFFFFFF1045A8ED, which higher part is 0xFFFFFFFF
rate->ipos with uint32 type, which max value is 0xFFFFFFFF
in the situation, (rate->ipos <= (rate->opos >> 32)) is definitely true forever.
every time when the program break out at P2, go to P3, assign osamp to 0, return to audio_pcm_sw_read and swlim - 0 at P4, excute again at P5. so the main thread repeats the same flow again and again.
the follow datas maybe useful:
(gdb) p sw
$13 = (SWVoiceIn *) 0x7f5e59f9ca10
(gdb) p *sw
$14 = {card = 0x7f5e59fa0520, active = 1, info = {bits = 16, sign = 1, freq = 44100, nchannels = 2, align = 3, shift = 2, bytes_per_second = 176400,
swap_endianness = 0}, ratio = 3946001203, rate = 0x7f5e5a83efd0, total_hw_samples_acquired = 70, buf = 0x7f5e5acd0e90,
clip = 0x7f5e56b98610 <clip_natural_int16_t_from_stereo>, hw = 0x7f5e5a15d1f0, name = 0x7f5e5a0f46c0 "adc", vol = {mute = 0, r = 4294967296, l = 4294967296},
callback = {opaque = 0x7f5e59fa0690, fn = 0x7f5e56c0d080 <hda_audio_input_cb>}, entries = {le_next = 0x0, le_prev = 0x7f5e5a15d240}}
(gdb) p *hw
$32 = {enabled = 1, poll_mode = 0, info = {bits = 16, sign = 1, freq = 48000, nchannels = 2, align = 3, shift = 2, bytes_per_second = 192000, swap_endianness = 0},
conv = 0x7f5e56b98540 <conv_natural_int16_t_to_stereo>, wpos = 736, total_samples_captured = 607, ts_helper = 4294967776, conv_buf = 0x7f5e5a0b68f0,
samples = 1920, sw_head = {lh_first = 0x7f5e59f9ca10}, ctl_caps = 8, pcm_ops = 0x7f5e5736eaa0, entries = {le_next = 0x0, le_prev = 0x7f5e573cfd40}}
#TRIED
1. I am not sure if this error occured just because I snapshotted the VM, but I really did 'snapshot operation' at that moment.
2. If I change the value of rate->opos from 18446744069687585005 to 1, the program run just fine:
(gdb) p rate->opos
$47 = 18446744069687585005
(gdb) p rate->opos = 1
$48 = 1
3. I calculated the value of opos/opos_inc = 18446744069687585005/4674794335 = 0xEB333333
compared with the normal situation, opos/opos_inc = 17544193733109040684/3946001203 = 0x10901A124
(gdb) p *rate
$2 = {opos = 17544193733109040684, opos_inc = 3946001203, ipos = 4084825920, ilast = {l = 57737216, r = 63569920}}
maybe the opos_inc is incorrect.
4. qemu argument with '-soundhw hda'
5. the same phenomenon: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=685353
thanks!!!
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] audio output overflow when play movies,
address@hidden <=