Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

SRT Streaming – ZLMediaKit TS Demuxer Crash

Open
#2,024 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 3 days

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
18/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Stale
Tech stack
android, c, docker, kotlin

Research direction

The crash is an assertion in ts_demuxer_input in libmpeg/source/mpeg-ts-dec.c (line 261) on the ZLMediaKit side, preceded by packet-loss logs from SrtTransport.cpp (handleDataPacket) and TSDecoder.cpp (line 69). On the client, the muxing setup is in SrtSender.kt (setTrackConfig, sendAudioFrame). Start by reproducing with the ZLMediaKit Docker image and capturing the TS packets around the lost-packet range. Done means identifying which TS invariant the demuxer rejects, and the issue has no assignee and no maintainer answer.

Written by the indexing model from the issue text.

Description

Environment

  • Client Library: RootEncoder (Pedro's library)
  • Server: ZLMediaKit (latest master branch, Docker)
  • Docker Image: zlmediakit/zlmediakit:master
  • Protocol: SRT with MPEG-TS muxing
  • Codec: H.264 (also tested with H.265)
  • Platform: Android (tested Android 11+)

Issue Description

SRT streaming using MPEG-TS causes ZLMediaKit to crash after approximately 4–5 minutes of streaming.
The server terminates due to an assertion failure inside the TS demuxer.

Assertion failed: (0), function ts_demuxer_input,
file /opt/media/ZLMediaKit/3rdpart/media-server/libmpeg/source/mpeg-ts-dec.c,
line 261

Error Details

ZLMediaKit Log
2026-01-20 17:28:52.692 T [MediaServer] [1-event poller 5] SrtTransport.cpp:776 handleDataPacket | pkt lost 1770381322->1770382164
2026-01-20 17:28:52.692 W [MediaServer] [1-event poller 5] TSDecoder.cpp:69 operator() | ts packet lost, dts:25771715 pts:25771715 bytes:14465
2026-01-20 17:28:55.275 T [MediaServer] [1-event poller 5] UdpServer.cpp:342 operator() | 60-57(192.168.1.36:59624) SRT::SrtSession on err: 6(Assertion failed: (0), function ts_demuxer_input, file /opt/media/ZLMediaKit/3rdpart/media-server/libmpeg/source/mpeg-ts-dec.c, line 261.)
  • Stream duration before crash: ~291 seconds

Configuration

Video Encoder (Android)
  • Resolution: 720p (1280×720)
  • FPS: 30
  • Bitrate: 2.5 Mbps
  • GOP: 2 seconds (60 frames)
  • Codec: H.264 (also tested H.265)
  • Audio: Disabled (video-only stream)
SRT Client
  • Latency: 300ms
  • Cache: 1200 frames
  • CheckServerAlive: true

Code Implementation

SrtSender.kt (video-only TS)
private fun setTrackConfig(videoEnabled: Boolean, audioEnabled: Boolean) {
  Pid.reset()
  service.clearTracks()
  if (videoEnabled) service.addTrack(commandsManager.videoCodec.toCodec())
  service.generatePmt()
  psiManager.updateService(service)
  Log.i(TAG, "Track config: video=$videoEnabled, audio=false (forced video-only for SRT)")
}

override suspend fun sendAudioFrame(mediaFrame: MediaFrame) {
  Log.d(TAG, "Skipping audio packet for video-only SRT stream")
  return
}

Reproduction Steps

  1. Configure GenericStream with H.264 encoder (720p @ 30fps, 2.5Mbps)
  2. Set SRT URL:
    srt://server:9000?streamid=publish:app/stream
    
  3. Start streaming
  4. Stream runs normally for 4–5 minutes
  5. ZLMediaKit crashes with TS demuxer assertion failure

Observations

  • RTMP streaming with identical encoder settings is stable for 1–5 hours
  • SRT streaming crashes consistently after 4–5 minutes
  • Issue reproduces with:
    • H.264 and H.265
    • Bitrates from 1.5 Mbps to 5 Mbps
    • Resolutions from 360p to 720p

Analysis / Suspected Causes

PCR Timing Issues
val pcr = if (isAudio && !mpegTsPayload.isKeyFrame)
  null
else
  TimeUtils.getCurrentTimeMicro()

For video-only streams, PCR may not be continuous or frequent enough for strict TS demuxers.

Adaptation Field Flags
  • randomAccessIndicator is only set for keyframes
Continuity Counter
  • Potential overflow or reset issues during long streams
PTS / DTS Drift
  • Timestamp drift may accumulate over time

Potential Fixes

Fix 1: Always Include PCR for Video-Only Streams
val pcr = TimeUtils.getCurrentTimeMicro()
Fix 2: Enforce PCR Interval (e.g. every 100ms)
private var lastPcrTime = 0L
private val pcrInterval = 100_000L

val currentTime = TimeUtils.getCurrentTimeMicro()
val pcr = if (currentTime - lastPcrTime >= pcrInterval) {
  lastPcrTime = currentTime
  currentTime
} else null
Fix 3: Validate Continuity Counter Wrap
pesContinuity = (pesContinuity + 1) and 0xF
if (pesContinuity == 0) {
  Log.w(TAG, "PES continuity counter wrapped")
}

Workarounds

  • Use RTMP instead of SRT (stable for hours)
  • Patch ZLMediaKit TS demuxer to skip invalid packets instead of asserting

Expected Behavior

SRT streaming should remain stable for hours without TS demuxer crashes.


Questions

  • Is this a known compatibility issue with ZLMediaKit’s TS demuxer?
  • Does ZLMediaKit expect stricter PCR / continuity rules for MPEG-TS over SRT?
  • Should TS packet generation be adjusted to be more conservative?
Dominant language
Kotlin
Stars
3k
Forks
946
Avg merge
5d 1h
Merged PRs (30d)
6

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from pedroSG94/RootEncoder

All issues in pedroSG94/RootEncoder

Similar issues

More Kotlin issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.