media icon indicating copy to clipboard operation
media copied to clipboard

Audio stops playing, the player doesn't stop nor reports an error

Open msimonides opened this issue 1 year ago • 2 comments

Version

Media3 1.2.1

More version details

Also reproducible on main c6bf380d50d4601ce6ec567ebd56ccf5e36fa8cf

Devices that reproduce the issue

Android emulator API28 (probably others as well) Samsung Galaxy S22

Devices that do not reproduce the issue

No response

Reproducible in the demo app?

Yes

Reproduction steps

Use the attached file. Play it for 2:18.

Expected result

Audio keeps playing till the end. Alternatively an error is reported to the app and state is no longer "playing"

Actual result

Audio stops at 2:18. The UI is still in the playing state, the progress bar keeps advancing.

Media

audiotrack-stop.zip

Bug Report

  • [X] You will email the zip file produced by adb bugreport to [email protected] after filing this issue.

msimonides avatar Feb 03 '24 19:02 msimonides

When audio stops I can see a logcat message from AudioTrack.stop(). Indeed, I can verify with a debugger that DefaultAudioSink.playPendingData() calls audioTrack.stop(). This is being called indirectly from MediaCodecRenderer.drainOutputBuffer where

boolean isEndOfStream = (outputBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0;

is being set to true.

msimonides avatar Feb 03 '24 19:02 msimonides

I can reproduce the observed behaviour in the demo app on a Pixel 7a.

I also see that after entering the problematic/silent state, if you seek back to just before 2:18 then playback progresses correctly (I didn't test all the way to the end of the file, but at least beyond 3:00).

Seeking forward to just before 2:18 still allows the problem to reproduce.

Immediately seeking to near the end of the file after the start of playback (about 7:33) causes playback to quickly go silent (before the end of the file).

mediainfo and ExoPlayer both think this file is about 7:57 long. VLC on MacOS can't decide how long it thinks the file is. When I started playing it said 10:54, then at about 1:00 it updated this to 7:57 and then to 8:02. It is able to play past the 2:18 mark without interruption though.

This file looks a bit broken - you can see this by trying to parse it with ffprobe:

$ ffprobe -show_frames demo.mp3
....
[mp3float @ 0x55f7f5d5e180] big_values too big
[mp3float @ 0x55f7f5d5e180] Error while decoding MPEG audio frame.
[mp3float @ 0x55f7f5d5e180] Header missing

I also counted the number of frames emitted by ffprobe -show_frames: 18290. Given 1152 samples per frame, and sample rate of 44.1kHz, that gives a duration (derived from frame count) of 18290 * 1152 / 44100 = 477.8 seconds (or 7mins 57s).


Logcat gives a clue as to where things are going wrong in ExoPlayer:

VbriSeeker              androidx.media3.demo.main            W  VBRI data size mismatch: 13097088, 3769067

That log line comes from here:

https://github.com/androidx/media/blob/b930b40a16c06318e43c81771fa2b1024bdb3f29/libraries/extractor/src/main/java/androidx/media3/extractor/mp3/VbriSeeker.java#L94-L97

Hacking the code to pass inputLength into the VbriSeeker constructor instead allows playback to continue past the 2:18 mark.

So this file is broken, since it has a VBRI frame that reports a file size of 3769067 bytes when the real file is actually 13097088 bytes.

If we compare that to the ffprobe -show_frames output above, we can find the frame that ends at the 3769067 byte position (next one starts at pkt_pos=3769319):

[FRAME]
media_type=audio
stream_index=0
key_frame=1
pts=1951580160
pts_time=138.292245
pkt_dts=1951580160
pkt_dts_time=138.292245
best_effort_timestamp=1951580160
best_effort_timestamp_time=138.292245
pkt_duration=368640
pkt_duration_time=0.026122
duration=368640
duration_time=0.026122
pkt_pos=3768693
pkt_size=626
sample_fmt=fltp
nb_samples=1152
channels=2
channel_layout=stereo
[/FRAME]

And from here you can see where 2:18 comes from, since pts_time=138.292245 (in seconds) is 2:18.


In general, when ExoPlayer is provided an invalid/broken file, the result is undefined behaviour. So we don't guarantee to always emit an error in cases like this. It may be that we don't make any changes here. I will have a think.

icbaker avatar Feb 08 '24 10:02 icbaker