-
Notifications
You must be signed in to change notification settings - Fork 731
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Voice Broadcast] Use internal playback timer to compute the playback position #8012
Conversation
|
||
package im.vector.lib.core.utils.timer | ||
|
||
interface Clock { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not find a better way instead of duplicating this file. I have issues with DI after moving the existing clock interface from the vector module into this one. Also, I cannot move the CountUpTimer to the vector module because another lib is using it.
…he media player position
library/core-utils/src/main/java/im/vector/lib/core/utils/timer/CountUpTimer.kt
Outdated
Show resolved
Hide resolved
@@ -270,6 +282,8 @@ class VoiceBroadcastPlayerImpl @Inject constructor( | |||
playbackTracker.updatePausedAtPlaybackTime(voiceBroadcast.voiceBroadcastId, positionMillis, positionMillis.toFloat() / duration) | |||
} | |||
playingState == State.Playing || playingState == State.Buffering -> { | |||
stopPlayer() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it right that when the playing state is State.Playing
that we call stopPlayer()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, as the user requested to listen from another position (potentially in another chunk file), we stop the current player and will start a new one just two lines later. If we don't stop it, the playback position which is saved in the next line could be erased by the current player
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... but you're right, this is not necessary, it is already done in startPlayback
method. I'll remove it from this place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one question, not blocking.
init { | ||
startCounter() | ||
} | ||
|
||
private fun startCounter() { | ||
tickerFlow(coroutineScope, intervalInMs / 10) | ||
tickerFlow(coroutineScope, intervalInMs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/ 10
was used for this reason: c69bc12
Are you sure you want to revert this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bmarty The elapsed time and the current time are updated when the timer is paused & resumed (see https://github.com/vector-im/element-android/blob/941d0e5cf4c509fbc1ef6d3f29fa4242266dc74e/library/core-utils/src/main/java/im/vector/lib/core/utils/timer/CountUpTimer.kt#L58-L66), it should be more precise now and the previous trick should not be necessary anymore. Moreover, the timer does not work anymore if the interval is too low (eg. under 10 ms), the ticks are too close and it does not notify in the expected delay (it can take more than 2 seconds to notify 1 second...), so it is better to keep the real interval value and do not divide the value by ten to prevent this bad behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading the code again, I think user can observe an extra delay if we keep a tick per second.
The pb is that the tickerFlow
ticks every second, and not when the UI has to be udpated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed together IRL, @Florian14 will make a dedicated PR to improve CountUpTimer
implementation, and make it respect its expected contract. Ideally with some tests around it.
941d0e5
to
3ce757e
Compare
Some minor improvements since the last review: https://github.com/vector-im/element-android/pull/8012/files/3d87b796b46441e1c08fd8bd772565ecce587715..3ce757ee4bd52b6ab945c1bc532a34a67cca7b63 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM. I did some tests.
SonarCloud Quality Gate failed. |
Type of change
Content
Rely on an internal playback timer to display the current playback position instead of relying on the position given by the android media player.
Note:In my opinion, this is not an ideal solution, I reused and improved the existing CountUpTimer which is not based on real elapsed time. Under the hood, it's a
tickerFlow
which notifies at a fixed interval (50 ms in our case) except if we pause it. It can shift a bit for about +/- theintervalMs
on each pause/resume depending on the timing.Btw, I noticed that a too-low interval (eg. 10 ms) will break the timer. I also noticed perfs issues after enabling the debugger on android studio, the Flow takes too much time to notify. I don't know if a busy device can have the same kind of issue.
Motivation and context
Voice broadcasts sent by Element-Web were causing trouble in the playback position computation.
The chunks sent from the web are encoded in ogg format with aggregated metadata which is not the case for the other VB sent from iOS or Android.
Also, when the recorder is paused on the web, the aggregation is reset, so we cannot rely on the ogg file metadata to calculate the current playback position. The android media player also gives the aggregated position and duration of these files causing glitches in the playback rendering.
I did not find a way to get the relative position in the android MediaPlayer API. Moreover, there are some glitches when we switch to the next file,
MediaPlayer.currentPosition
starts returning the relative position (eg. 0ms/250ms/375ms) and then jumps to the aggregatedPosition (eg. 15_000ms...) but always returns the aggregated duration (eg. 45_000ms for a chunk of 15_000ms, supposing we are listening to the third chunk).Screenshots / GIFs
Tests
/devtools
options) recording from the web and iOS or AndroidTested devices
Checklist
developmain branch