media icon indicating copy to clipboard operation
media copied to clipboard

Native crash when switching back to main TS content after HLS ad with custom DataSource

Open amit12kumardish opened this issue 2 months ago • 2 comments

Hi Media3 team,

I’m experiencing a native crash when switching back to a main TS content after playing an HLS ad. My setup is as follows:

Setup

  • I use a custom TunerDataSource that implements a circular buffer and continuously streams TS from a multicast/QAM source.
  • Main content is played using this TunerDataSource.
  • HLS ads are preloaded and played via a MediaSource switch.

The player flow:

  • Main TS content is playing via TunerDataSource ( custom implementation of DataSource).
  • Pause main TS, switch to HLS ad (preloaded via preloadManager or even without preloading, direct mediasource switch).
  • After ad ends, I switch back to the main TS content.
  • If I reuse the previous TunerDataSource for step 3:
  • After 3–4 iterations of this ad switch, the app crashes with native SIGSEGV in MediaCodec / codeclooper / faultaddr.
  • If I create a fresh TunerDataSource instance for every main content switch: No crash occurs.

My observations:

Crash seems related to ExoPlayer / MediaCodec holding stale native buffer references when the same DataSource is reused after a full media source reset.

Scenario – TS → HLS ad → TS (Direct Switch) Description: Main content uses a custom TS datasource, switch to an HLS ad, then back to the main TS datasource (letting buffer overwrite happen).

Result: Crash occurs (native crash in MediaCodec_loop / SIGSEGV / fault addr).


Scenario – TS Pause & Resume (Safe Resume) Description: Main content uses custom TS datasource, pause the player, let the circular buffer fill, then resume playback.

Result: No crash observed. Conclusion: Buffer overwritten is not causing this crash.


Scenario – TS → PreloadManager Ad → TS Description: Main content uses custom TS datasource, switch to an ad via PreloadManager, then switch back to main TS datasource.

Result: Crash occurs.


Possibly, Switching between different types of media sources (custom TS ↔ HLS/PreloadManager) is causing native-level crashes.



Questions

  1. Is this expected behavior in Media3 when switching between different types of media sources (custom TS ↔ HLS)?
  2. What is the recommended approach to safely reuse a custom TS DataSource across MediaSource switches (TS → HLS → TS) without creating a new instance every time?
  3. Would you recommend implementing a “reset” mechanism in the custom DataSource, or avoiding prepare() when switching back to the main TS content?
  4. I want to achieve smooth transitions between main → ad → main content without triggering native crashes. How can this best be handled using Media3?

Any guidance or best practices for handling this scenario would be highly appreciated.

amit12kumardish avatar Oct 13 '25 08:10 amit12kumardish

@amit12kumardish,

Thanks for the information! I don't think this is an expected behaviour when switching between different media sources. Upon switching, media sources should play without any issues. But for your case specifically, problems can potentially happen when you try to reuse the your TunerDataSource after switching back to the content source. From the description, I assume you did the switching by setting ad media source to the player via player.setMediaSource and setting the content media source back in the same way, where internally player can release the period switched from and call the close() method on your data source, could you please check how your TunerDataSource is implemented and see if close() can cause problem when reusing it? I also recommend to send a bug report to us so that we can get more details.

And as you're trying to insert ads during the content playback, I was wondering if you've considered our ad support (https://developer.android.com/media/media3/exoplayer/ad-insertion#client-side-ad), instead of manually switching between separate sources?

tianyif avatar Oct 14 '25 12:10 tianyif

@tianyif Thanks for your response and suggestions. Here’s an update and a few follow-up questions based on our recent observations:

  1. About Ad Insertion Approach We explored the client-side ad insertion support in Media3 (https://developer.android.com/media/media3/exoplayer/ad-insertion#client-side-ad), but in our case, ads are signalled dynamically via SCTE-35 markers on a live transport stream. Since ad opportunities are only known a few seconds before insertion (ad URLs fetched on-the-fly), it wasn’t feasible to use pre-declared ad groups through the standard ad insertion APIs.

  2. Native Crash (Fixed) The native crash we originally reported (SIGSEGV in MediaCodec) was resolved after we changed our flow to release and recreate the TunerDataSource each time we switch back from an HLS ad to the main TS content.

So instead of reusing the same instance, we now:

  • Release and destroy the live content media source (and associated TunerDataSource) before ad playback.
  • Create a new live content media source with a fresh TunerDataSource a few seconds before ad completion.
  • After the ad ends, we switch to this new content media source using player.setMediaSource() and reposition our circular buffer’s read pointer to the live edge.
  1. Current Challenge – Playback Delay After Ad → Live Switch Now, the main issue we are facing is a delay before rendering the first frame when switching back to live content.

Our setup:

  • The TunerDataSource implements a circular buffer that continuously writes incoming TS packets from multicast/QAM input.
  • The write speed of this buffer is slower than the rate at which ExoPlayer issues read() calls, so read() often blocks until enough data becomes available.
  • We cannot increase the incoming stream bitrate.

Attached logs of read and write speed:

exoplayer_read calls.txt

Here exoplayer_read() tag provides info on read calls made by datasource and CustomBuffer tag provides info on bytes written into our buffer.

We observed that if we manually prefill few TS packets before switching back from the ad, read calls occur much faster. However we cannot prefill much data ahead of time because doing so could cause the read pointer to move beyond the live edge.

Attached logs when buffer is prefilled with some TS packets:

buffer_with_few_ts_packets.txt

We attempted to reduce bufferForPlaybackMs and bufferForPlaybackAfterRebufferMs in the LoadControl configuration to encourage the player to start playback with less data, but this didn’t change the number of read() calls observed before the first frame was rendered:

~41 read() calls with bufferForPlaybackMs and bufferForPlaybackAfterRebufferMs = 1000 ~42 read() calls with bufferForPlaybackMs and bufferForPlaybackAfterRebufferMs = 2000

Attached logs for different load control parameter:

bufferForPlaybackMs_1000.txt

bufferForPlaybackMs_2000.txt

4. Questions

  1. How do the LoadControl parameters interact with the player’s internal buffering logic? Specifically, what determines the number of read() calls made before rendering the first frame?
  2. What determines the amount of read calls made before rendering first frame?
  3. Are there recommended ways to reduce how much data the player expects to read before it starts decoding and rendering — for example, any flags or configurations that can make ExoPlayer start playback faster in low-latency/live TS scenarios?
  4. Given that our read() calls are blocking due to slow incoming data, is there a best practice (e.g., custom LoadControl, custom Extractor, or adjusting Allocator behavior) to minimize startup latency when switching from HLS ad → live TS content?

crprajwalDish avatar Oct 24 '25 10:10 crprajwalDish