Skip to content

SRT Streaming – ZLMediaKit TS Demuxer Crash #2024

@Piyoxz

Description

@Piyoxz

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions