Skip to content

Develop#111

Merged
Davidona merged 51 commits into
masterfrom
develop
Jun 9, 2026
Merged

Develop#111
Davidona merged 51 commits into
masterfrom
develop

Conversation

@Davidona

@Davidona Davidona commented Jun 9, 2026

Copy link
Copy Markdown
Owner

No description provided.

metanet and others added 30 commits May 16, 2026 21:35
Release builds loaded the Media3 FFmpeg extension after the ProGuard keep rule, but the bundled local FFmpeg artifact still lacked the mp3 decoder. Some IPTV live streams report MPEG layer audio as audio/mpeg-L2, and Media3 maps that MIME type to the FFmpeg mp3 decoder. Without it, the player could not keep playing those streams through the FFmpeg fallback path.

Rebuild the local Media3 1.9.2 FFmpeg decoder artifact from the matching AndroidX commit with the existing LGPL-compatible decoder set plus mp3, keep the FFmpeg extension classes from being stripped in release builds, and update the local artifact metadata/docs to match the checked-in binary. This keeps the existing local-AAR approach instead of adding a new runtime dependency, because the app already verifies and packages this artifact explicitly and the fix is decoder coverage inside that artifact.

Test plan and results:

- Ran AndroidX :lib-decoder-ffmpeg:assembleRelease for the rebuilt AAR; build succeeded.

- Ran ./gradlew :player:verifyLocalFfmpegArtifact :app:lintRelease :app:assembleRelease test; artifact verification ran, but :app:lintRelease failed on existing lint debt unrelated to this change. First failure: ExternalNavigationRequest.kt uses URLDecoder.decode requiring API 33/desugaring.

- Ran ./gradlew :app:assembleRelease test; build and unit tests passed.

- Installed app/build/outputs/apk/release/app-release.apk on the emulator and verified landscape display cur=2340x1080 app=2340x1080.

- Replayed the previously failed live stream. Logs showed ffmpeg-extension available=true, audio-decoder name=ffmpegLavc60.3.100-mp3, and first-frame-success. The stream later hit a separate Source error because a fetched HLS input did not start with #EXTM3U, so the mp3/FFmpeg failure is resolved but the provider/source error remains separate.
Add live playback retry and stall recovery helpers, including HLS malformed refresh retries, live retry state preservation, TS fallback URL support, and data-source read progress tracking.

Improve player diagnostics by logging retry reasons, fatal retry reasons, sanitized source details, external player probe support, and alternate stream/content resolution fallback behavior.

Document the emulator orientation lock and 2-second live TV validation workflow, and add regression coverage for retry policy, stall recovery, log sanitization, fallback URL handling, data-source stats, media source selection, and player fallback support.

Test Plan:\n- ./gradlew :player:testDebugUnitTest :app:testDebugUnitTest\n- ./gradlew :app:assembleRelease\n- graphify update .\n- ./gradlew :app:lintDebug :player:lintDebug --continue (fails on existing lint backlog: app first failure ExternalNavigationRequest.kt:88 NewApi; player first failure PlayerTrackController.kt:200 MissingPermission)
Add a persisted playback setting for Fast retry on transient failures so exponential backoff remains the default and 500 ms retry delay is opt-in.

Also tighten live-stall fallback timing, increase live transient retry ceilings, avoid showing 0s for sub-second retry delays, and cover the retry notice formatting and retry-policy behavior with tests.

Test plan:

- ./gradlew :player:testDebugUnitTest :app:testDebugUnitTest :data:testDebugUnitTest :app:assembleRelease
Problem: progressive movie and series streams can hit SocketTimeoutException or ConnectException after playback has already started, especially around repeated seeks. Retry reprepares preserved retry counters but reset playbackStarted, so progressive VOD was treated like startup playback and stopped after the conservative two-attempt budget, leaving a fatal network error or frozen frame.

Solution: give progressive post-start timeout/connect failures the transient retry ceiling, carry effective playback-started state across same-media retry reprepares, and use that effective state consistently for retry, stall, and compatibility decisions.

Tests: ./gradlew :player:testDebugUnitTest :app:testDebugUnitTest :data:testDebugUnitTest; ./gradlew :app:assembleRelease; emulator validation covered Dopesick repeated seeks and The Assessment 20 alternating seeks with no fatal/stuck/retry/timeout log matches. Known pre-existing failure: ./gradlew :player:lintDebug still reports 37 errors/4 warnings, first PlayerTrackController.kt:200 MissingPermission.
Keeps the Fire TV screen awake while a live preview is active in the Home
sidebar so the device screensaver doesn't kick in mid-stream.
Hardens the handoff system so returning from fullscreen always restores
preview to the correct screen (Home or Guide). Introduces HOME vs GUIDE
source tagging so each screen only consumes its own reverse handoff.
Adds a live video preview pane to the Guide screen that replaces the old
static channel-info block. Single-clicking a channel starts a preview in
the pane; clicking the same channel again goes fullscreen. Long-pressing
a channel opens the options menu.
Extends screen-awake suppression to the Guide preview pane so Fire TV
won't blank the screen while a live stream is playing there.
Removes the redundant "Timeline / 7h window" header row and "Now HH:MM"
label from the Guide grid for a cleaner, less cluttered look.
Fixes the timeline markers so they always land on clean :00 / :30
boundaries instead of offset times like 7:48, 8:18, etc.
Adds a per-provider EPG time shift control in Settings (up to ±12 hours)
with quick-tap buttons for common adjustments. Fixes EPG data that shows
the wrong times due to timezone mismatches in the provider's feed.
Adds reverse handoff test coverage (source filtering, timeout, flow
visibility) and fixes EpgViewModelTest and EpgRepositoryImplTest to
compile against the new constructor params.
Previously, when channelRepository.getStreamInfo(channel) returned a
Result.error (e.g. 'No stream URL available for channel: XYZ'), the
error was silently discarded by getOrNull() and playback would try
fallback URL resolution without showing any message to the user.

Now check isSuccess/isError explicitly for LIVE, MOVIE, and SERIES
content types and propagate the error message as resolutionFailureMessage
so the user sees a meaningful error instead of silent failure.
… XMLTV date parsing

Decoder error recovery:
- After software decoder retry fails on a live channel, automatically try
  an alternate stream (e.g. HLS→MPEG-TS or MPEG-TS→HLS) before showing
  a permanent error. This resolves the 'stream couldn't play in current
  decoder mode' error for Xtream servers that serve MPEG-TS by default.

Stream format selector UI:
- Add StreamFormatSelectionDialog for choosing between HLS and MPEG-TS
  when a channel has multiple qualityOptions with distinct stream URLs.
- Add 'Format' quick-action button in the channel info overlay (shown
  when qualityOptionCount > 1).
- Add selectStreamFormat() to PlayerViewModel for switching stream format.
- Add qualityOptionCount parameter to PlayerChannelInfoOverlay.
- Add player_stream_format, player_action_format, player_format_short strings.

XMLTV date parsing:
- Add 'yyyy-MM-dd'T'HH:mm:ssX' formatter to localDateTimeFormats to handle
  ISO-8601 dates with an explicit but offset-only timezone suffix.
- Improve last-resort comment to document T-handling.
@Davidona Davidona merged commit 3814c6b into master Jun 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants