I try to refine the code like below(only show the code i modify meaningful), I
calculate the each 1ms timer wanted_wpos which I named it wanted_wpos_delta
first instead of caculate the hole duration wanted_wpos in one time
and summer all of them to calcute the wanted_wpos
/* calcute each 1ms delta wanted pos */
int64_t wanted_wpos_delta = hda_bytes_per_second(st) * (now -
st->last_start)
/ NANOSECONDS_PER_SECOND;
/* summer it all to wanted_wpos */
st->wanted_wpos += wanted_wpos_delta;
error_report("delta = %ld, wanted = %ld wpos = %ld,
now=%ld,buft=%ld,last=%ld\n",
wanted_wpos_delta, st->wanted_wpos, wpos, now, buft_start,
st->last_start);
/* mark the last timer timestamp */
st->last_start = now;
in the function hda_timer_sync_adjust, i add the corr to the last_start value
st->last_start += corr;
the output log like below:
2023-08-17T05:29:17.730066Z qemu-fix: delta = 196, wanted = 22027480 wpos =
22027284, now=213350279414,buft=97328733406,last=213349253800
2023-08-17T05:29:17.731090Z qemu-fix: delta = 196, wanted = 22027676 wpos =
22027480, now=213351303295,buft=97328733406,last=213350279414
2023-08-17T05:29:17.732179Z qemu-fix: delta = 209, wanted = 22027884 wpos =
22027676, now=213352392204,buft=97328733406,last=213351303295
2023-08-17T05:29:17.733201Z qemu-fix: delta = 196, wanted = 22028080 wpos =
22027884, now=213353414012,buft=97328733406,last=213352392204
2023-08-17T05:29:17.734234Z qemu-fix: delta = 198, wanted = 22028276 wpos =
22028080, now=213354447484,buft=97328733406,last=213353414012
I currently test with playback, it works and seems to work as expected.
What about this solution for this bug? any suggestion for me?
在 2023-08-16 15:04:14,"Volker Rümelin" 写道:
>Cc: qemu-devel@nongnu.org
>
>> cc Volker Rümelin
>>
>> ==
>>
>> so I was curious about:
>> 1. why using wpos, rpos which will increasing along the time, which
>> may overflow in the feature time?
>
>wpos and rpos are 64 bit integers. At a sample rate of 96kHz and with 32
>bit stereo audio frames they overflow after 2^63 bytes / (8 bytes/frame
>* 96000 frames/s) = 1.2E13 s = 380561.23 years. I don't think you will
>notice an overflow.
>
>But you're right anyway. The wanted_rpos and wanted_wpos calculation
>overflows quite early. At a sample rate of 44100kHz and with 16 bit
>stereo samples the multiplication hda_bytes_per_second(st) * (now -
>buft_start) overflows after 2^63 bytes / 176400 bytes/ns = 5,23E13 ns =
>14.58 hours.
>
>I don't think your fix below is correct. There are certainly ways to
>prevent the overflow without resetting the buffer.
>
>> 2. how to fix the wanted_wpos or wanted_rpos, I current don't
>> understand the wanted_pos mean and how it work to optimize the codec
>
>This is a jitter-buffer implementation to decouple the audio backend
>updates from the hda device updates. The code splits large >10ms sized
>audio packets into 1ms sized audio packets.
>
>With best regards,
>Volker
>
>> ===
>>
>> Currently I got Playback and Capture issue
>>
>> I test Playing and recoding for a very long time, Playback issue is
>> hard to reproduce, Capture issue is easy to reproduce for recording
>> about 14 hours
>>
>> Playback issue current can only be found on qemu 2.11, which I found
>> the code below (remove some unnecessary)
>>
>> wanted_wpos overflow, and is always little then the wpos,(current wpos
>> - rpos = 0) so qemu will no long get data from vm, as a result
>>
>> static void hda_audio_output_timer(void *opaque)
>> {
>> .
>>
>> int64_t wanted_wpos = hda_bytes_per_second(st) * (now -
>> buft_start) > overflow here
>> / NANOSECONDS_PER_SECOND;
>> wanted_wpos &= -4; /* IMPORTANT! clip to frames */
>>
>> if (wanted_wpos <= wpos) {
>> /* we already received the data */
>> goto out_timer;
>> }
>> }
>>
>>
>> Capture issue: Just record all the time
>> (i using qemu 6.0 to test) I add code below to the input callback
>> function like below, the issue dispear
>> hda_audio_input_cb
>> if (wpos - rpos == B_SIZE) {
>> /* drop buffer, reset timer adjust */
>> st->rpos = 0;
>> st->wpos = 0;
>> st->buft_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
>> error_report("input drop buffer, reset timer adjust\n");
>> return;
>> }
>>
>>
>>
>>
>>
>>