Closed
Bug 840311
Opened 13 years ago
Closed 12 years ago
Gonk backend for sydneyaudio uses wrong buffer/latency size
Categories
(Core :: Audio/Video, defect)
Tracking
()
People
(Reporter: kinetik, Assigned: mchen)
References
Details
Attachments
(1 file, 4 obsolete files)
1.69 KB,
patch
|
mchen
:
review+
|
Details | Diff | Splinter Review |
The Android backend that the Gonk backend was based on queries the minimum buffer size and ensures the calculated buffer size is never less than that. The Gonk backend queries the minimum buffer size, then uses that and ignores the calculated buffer size.
See http://mxr.mozilla.org/mozilla-central/source/media/libsydneyaudio/src/sydney_audio_gonk.cpp#163
frameCount is passed to the AudioTrack constructor, but the original intent is to pass s->bufferSize (converted back to frames).
The result of this is that we always construct an AudioTrack with a ~55ms buffer, rather than the intended ~1000ms buffer. This is likely to result in more frequent wakeups to refill buffers, and more underruns during media playback. It also means the calculations in get_write_size and drain are incorrect as they use s->bufferSize.
Reporter | ||
Comment 1•13 years ago
|
||
Assignee: nobody → kinetik
Status: NEW → ASSIGNED
Reporter | ||
Comment 2•12 years ago
|
||
The problem with fixing this is that the Gaia dialer wants to play short (~150ms) sounds, but the mozWriteAudio API provides no way to detect how much the caller must write before playback begins.
If we increase the AudioTrack buffer size, either the mozWriteAudio needs to be extended to expose buffer sizing, or (as a hack) the dialer needs to write "enough" silence after the dialtone to force playback to begin.
Status: ASSIGNED → NEW
Assignee | ||
Comment 3•12 years ago
|
||
Hi Matthew,
Could we set different lentency based on stream types?
For example, if stream type is SYSTEM then we set it as minFrames. If MUSIC then we set it to more bigger size. Since audio data api will be deprecated and only dialer used it, maybe we could do this hack to cover this issue.
Reporter | ||
Comment 4•12 years ago
|
||
Yeah, that could work.
Assignee | ||
Comment 5•12 years ago
|
||
Hi Matthew,
As we discussed, I set minFrames to 4 times for music stream only.
(the code only show 2 times because the calculation of AudioTrack::getMinFrameCount already do twice of minFrames.)
Thanks.
Attachment #723823 -
Flags: feedback?(kinetik)
Reporter | ||
Comment 6•12 years ago
|
||
s->bufferSize needs to reflect the buffer size passed to AudioTrack, otherwise calculations using s->bufferSize (e.g. get_write_size) will produce incorrect results.
So I'd make this something like:
s->bufferSize = frameCount * s->channels * sizeof(int16_t);
if (s->streamType == AudioSystem::MUSIC) {
s->bufferSize *= 2;
}
But rather than special casing MUSIC (which doesn't help general media elements that default to SYSTEM), can we special case RINGER to use the minimum buffer size and use a larger (2x or whatever's appropriate) one for every other type instead?
Reporter | ||
Updated•12 years ago
|
Attachment #723823 -
Flags: feedback?(kinetik) → feedback-
Reporter | ||
Updated•12 years ago
|
Attachment #712658 -
Attachment is obsolete: true
Assignee | ||
Comment 7•12 years ago
|
||
Hi Matthew,
Thanks for your comment here.
1. I checked that dialer app use normal channel for keypad tone so it is SYSTEM stream type after mapping to Android Audio Stream Type.
2. Following your suggestion, set minframes to 4 times but keep twice when stream type is SYSTEM.
Attachment #723823 -
Attachment is obsolete: true
Attachment #724301 -
Flags: review?(kinetik)
Reporter | ||
Comment 8•12 years ago
|
||
Ah, I was confused, I thought the dialer was using "ringer", but it looks like that changed since I last looked.
The problem then is that the default for media elements is also "system", and we really want to apply this hack to the dialer and nothing else.
Reporter | ||
Comment 9•12 years ago
|
||
Comment on attachment 724301 [details] [diff] [review]
Patch v2
Based on my previous comment, I don't think we should do it this way.
Having thought about it some more, the goal here is to increase the buffer size for general audio playback without breaking the dialer (which uses mozWriteAudio), so another approach is to add a B2G specific change to nsHTMLAudioElement that enables the small buffer hack/workaround for streams created via mozSetup, and then increase the default buffer size.
Attachment #724301 -
Flags: review?(kinetik) → review-
Assignee | ||
Comment 10•12 years ago
|
||
Hi Matthew,
Thanks for the review and suggestion.
So the goal here is
1. enlarge the buffer size.
2. Hack the mozWriteAudio path for padding the slience data to fill buffer full "on each call".
My opinion:
1. Based on different stream type to give difference min buffer size for reason of lantency.
On the other way, may I take this bug to fix it?
Thanks.
Reporter | ||
Comment 11•12 years ago
|
||
Just to clarify, is a fix for this bug targeted for B2G 1.x? If not, we can just switch to cubeb and close this out. Otherwise, please do take the bug, thank you!
Reporter | ||
Updated•12 years ago
|
Assignee: kinetik → mchen
Assignee | ||
Comment 12•12 years ago
|
||
The only reason now is Bug 842195 which is posted by leo.
And leo is on V1.1.
But currently it is not with leo+, I will ask there first.
Assignee | ||
Comment 13•12 years ago
|
||
Hi Matthew,
1. I hack mozWriteAudio API to fill the buffer full with silence data if writing size is small then avaliable size. (with MOZ_B2G)
2. In sydney_audio_gonk, I set frameCount to 1s in AudioTrack with music stream type and 4 times of minframes with others stream type (for short latency).
Thanks for your feedback.
Attachment #724301 -
Attachment is obsolete: true
Attachment #726571 -
Flags: feedback?(kinetik)
Reporter | ||
Comment 14•12 years ago
|
||
Comment on attachment 726571 [details] [diff] [review]
Patch v3
Thanks, if this works well enough, let's go with it. I'm a bit uneasy about adding these hacks, but we have a plan to get away from them after 1.x.
+#ifdef MOZ_B2G
+ uint32_t availableLen = mAudioStream->Available();
+ // Don't write more than can be written without blocking.
+ uint32_t writeLen = std::min(availableLen, dataLength / mChannels);
+#else
// Don't write more than can be written without blocking.
uint32_t writeLen = std::min(mAudioStream->Available(), dataLength / mChannels);
+#endif
For this part, just use the B2G bit on all platforms, i.e.:
uint32_t availableLen = mAudioStream->Available();
// Don't write more than can be written without blocking.
uint32_t writeLen = std::min(availableLen, dataLength / mChannels);
...with no ifdef.
Attachment #726571 -
Flags: feedback?(kinetik) → review+
Assignee | ||
Comment 15•12 years ago
|
||
Issue: sydney_audio_gonk set FrameCount as twice of min frames when creating AudioTrack. But there is a bug as below in AudioFlinger. (Please refer to Bug 842195)
mixing thread will hold 1 more frame then twice of min frames, when source is needed to re-sample.
Solution:
1. Like what Android do, we set FrameCount to 4 times of min frames. And specially set frameCount to 1 seconds for matching the buffer from decoding thread.
2. In mozAudioWrite(), we append slience data to fill the backend buffer full or once backend buffer size is more then size wrote by mozWriteAudio(). That will not be played. This is a lack on this seriels of APIs (Note that this API will be removed from master and instead by WebAudio and now only dialer - keypad.js uses it.)
Test:
Tested it with music/FM/video and ring tone.
Risk:
It needs Bug 833724 & Bug 832842 too.
blocking-b2g: --- → leo?
Comment 16•12 years ago
|
||
(In reply to Marco Chen [:mchen] from comment #15)
> Risk:
> It needs Bug 833724 & Bug 832842 too.
Does it need those bug or does it block them? Seems like 832842 at least is blocked by this bug.
Flags: needinfo?(mchen)
Assignee | ||
Comment 17•12 years ago
|
||
Flags: needinfo?(mchen)
Updated•12 years ago
|
blocking-b2g: leo? → leo+
Assignee | ||
Comment 18•12 years ago
|
||
After discussing with Matthew, the check-in patch doesn't contain the part of hacking mozWriteAudio() because the frameCounts set by sydney backend is not larger then key tone frames.
Attachment #726571 -
Attachment is obsolete: true
Attachment #729421 -
Flags: review+
Assignee | ||
Comment 19•12 years ago
|
||
Hi Sheriff,
Thanks for your help to checkin first.
And according to sydney backend already be removed from m-c tree, I can't give the patch into try server or in inbound tree. So I tested by patch on b2g18 and b2g18-v1.0.1. Please help to check-in into b2g18 series branch only.
I don't meet this situation before, if I miss any rule please let me know.
Thanks.
Keywords: checkin-needed
Updated•12 years ago
|
Whiteboard: [checkin to b2g18 branch only]
Comment 20•12 years ago
|
||
Status: NEW → RESOLVED
Closed: 12 years ago
status-b2g18:
--- → fixed
status-b2g18-v1.0.0:
--- → wontfix
status-b2g18-v1.0.1:
--- → wontfix
status-firefox20:
--- → wontfix
status-firefox21:
--- → wontfix
status-firefox22:
--- → wontfix
Keywords: checkin-needed
Resolution: --- → FIXED
Whiteboard: [checkin to b2g18 branch only]
Target Milestone: --- → B2G C4 (2jan on)
Updated•12 years ago
|
Flags: in-moztrap-
You need to log in
before you can comment on or make changes to this bug.
Description
•