jellyfin / jellyfin-android

Android Client for Jellyfin
https://jellyfin.org
GNU General Public License v2.0
1.5k stars 243 forks source link

ExoPlayer fails LiveTV playback #1277

Closed jellouser closed 1 week ago

jellouser commented 9 months ago

Describe the bug

  1. Set up M3U live channels providing MPEG-TS stream
  2. Play live channel in app, using ExoPlayer as player
  3. ExoPlayer makes request GET /LiveTv/LiveStreamFiles/\<guid>/stream.ts HTTP/1.1 seen in server tcpdump
  4. Player shows message "Source error"

Logs

ExoPlayerImplInternal: Playback error
ExoPlayerImplInternal:  com.google.android.exoplayer2.ExoPlaybackException: Source error
ExoPlayerImplInternal:      at o5.o0.k(SourceFile:17)
ExoPlayerImplInternal:      at o5.o0.handleMessage(SourceFile:382)
ExoPlayerImplInternal:      at android.os.Handler.dispatchMessage(Handler.java:102)
ExoPlayerImplInternal:      at android.os.Looper.loopOnce(Looper.java:226)
ExoPlayerImplInternal:      at android.os.Looper.loop(Looper.java:313)
ExoPlayerImplInternal:      at android.os.HandlerThread.run(HandlerThread.java:67)
ExoPlayerImplInternal:  Caused by: com.google.android.exoplayer2.ParserException: Input does not start with the #EXTM3U header.{contentIsMalformed=true, dataType=4}
ExoPlayerImplInternal:      at y6.n.f(SourceFile:259)
ExoPlayerImplInternal:      at l7.i0.a(SourceFile:30)
ExoPlayerImplInternal:      at l7.d0.run(SourceFile:41)
ExoPlayerImplInternal:      at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
ExoPlayerImplInternal:      at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
ExoPlayerImplInternal:      at java.lang.Thread.run(Thread.java:1012)

Application version

2.6.0

Where did you install the app from?

Google Play

Device information

Samsung Galaxy S23

Android version

Android 13

Jellyfin server version

10.8.13

Which video player implementations does this bug apply to?

jellouser commented 9 months ago

I believe this is because of client QueueManager.createVideoMediaSource PlayMethod.DIRECT_PLAY logic:

PlayMethod.DIRECT_PLAY -> {
                when (sourceInfo.protocol) {
                    MediaProtocol.FILE -> {
                        val url = videosApi.getVideoStreamUrl(
                            itemId = source.itemId,
                            static = true,
                            playSessionId = source.playSessionId,
                            mediaSourceId = source.id,
                            deviceId = apiClient.deviceInfo.id,
                        )

                        url to get<ProgressiveMediaSource.Factory>()
                    }
                    MediaProtocol.HTTP -> {
                        val url = requireNotNull(sourceInfo.path)
                        val factory = get<HlsMediaSource.Factory>().setAllowChunklessPreparation(true)

                        url to factory
                    }
                    else -> throw IllegalArgumentException("Unsupported protocol ${sourceInfo.protocol}")
                }
            }

HlsMediaSource.Factory is used and M3U source expected, but it seems incorrect, and I think ProgressiveMediaSource.Factory should be used for this LiveStream instead.

jellouser commented 9 months ago

By compiling my own version of the app I can confirm that the playback issue is fixed by using ProgressiveMediaSource.Factory in MediaProtocol.HTTP case instead of HlsMediaSource.Factory

Maxr1998 commented 9 months ago

Thanks for debugging this. It's somewhat odd that the protocol is HTTP in that case, since that should (to my understanding) imply HTTP Live Streaming aka HLS. It seems like we need to handle another case there.

jellouser commented 9 months ago

I am not sure how these different cases should be handled if direct play source can also produce HLS / M3U, but HTTP is indeed the protocol for both cases, only different content type.

This previously reported issue looks exactly the same, .mkv direct play fails https://github.com/jellyfin/jellyfin-android/issues/1217

jellyfin-bot commented 5 months ago

This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.

If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or master branch, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.

This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on Matrix or Social Media.

Kevinjil commented 5 months ago

The problem still persist with Jellyfin 10.9.1 and Jellyfin Android version 2.6.1.

jellyfin-bot commented 1 month ago

This issue has gone 120 days without comment. To avoid abandoned issues, it will be closed in 21 days if there are no new comments.

If you're the original submitter of this issue, please comment confirming if this issue still affects you in the latest release or master branch, or close the issue if it has been fixed. If you're another user also affected by this bug, please comment confirming so. Either action will remove the stale label.

This bot exists to prevent issues from becoming stale and forgotten. Jellyfin is always moving forward, and bugs are often fixed as side effects of other changes. We therefore ask that bug report authors remain vigilant about their issues to ensure they are closed if fixed, or re-confirmed - perhaps with fresh logs or reproduction examples - regularly. If you have any questions you can reach us on Matrix or Social Media.