-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Which version are you using?
Which operating system are you using?
macOS Arm64 standard
Describe how to replicate the issue
Steps to Reproduce
This is easily reproducible on macOS Arm64, and the exact circumstances may rely on the hardware encoder present on an M3 Max processor, but the root cause is general, and the issue should reproduce in many other circumstances as well.
- start the server
- publish using RTMP with OBS on a Mac, using
Apple VT HEVC Hardware Encoder
, withUse B-Frames
checked - read with any HLS client
The viewing stream will abort with an error stating the DTS is not monotonic.
Root Cause
For this specific encoder
In this specific case, the issue is that the HLS library infers DTS
from the received PTS
and the contents of the H.265 NALs:
dts, err := track.h265DTSExtractor.Extract(au, pts)
This Extract()
code in turn relies on the presence of the H.265 parameters vui_num_units_in_tick
and vui_num_units_in_tick
, which are optional:
if d.spsp.VUI == nil || d.spsp.VUI.TimingInfo == nil {
return pts, nil
}
For this particular encoder, the TimingInfo
field for the VUI is nil (or, in spec language: vui_timing_info_present_flag
is 0):
&{
AspectRatioInfoPresentFlag:false
AspectRatioIdc:0
SarWidth:0
SarHeight:0
OverscanInfoPresentFlag:false
OverscanAppropriateFlag:false
VideoSignalTypePresentFlag:true
VideoFormat:5
VideoFullRangeFlag:false
ColourDescriptionPresentFlag:true
ColourPrimaries:1
TransferCharacteristics:1
MatrixCoefficients:1
ChromaLocInfoPresentFlag:false
ChromaSampleLocTypeTopField:0
ChromaSampleLocTypeBottomField:0
NeutralChromaIndicationFlag:false
FieldSeqFlag:false
FrameFieldInfoPresentFlag:false
DefaultDisplayWindow:<nil>
TimingInfo:<nil>
}
timeDiff := int64(samplesDiff) * 90000 *
int64(d.spsp.VUI.TimingInfo.NumUnitsInTick) / int64(d.spsp.VUI.TimingInfo.TimeScale)
dts := pts - timeDiff
In the general case
In the more general case, the problem is that mediamtx only conveys PTS
through the system, discarding the DTS
information received via (e.g.) RTMP:
mediamtx/internal/protocols/rtmp/reader.go
Line 554 in da1a00f
cb(msg.DTS+msg.PTSDelta, tu) |
mediamtx/internal/unit/base.go
Lines 9 to 14 in da1a00f
// Base contains fields shared across all units. | |
type Base struct { | |
RTPPackets []*rtp.Packet | |
NTP time.Time | |
PTS int64 | |
} |
The handling of H.264 and H.265 in the HLS library does some clever calculation to try to recover DTS
in the presence of B-frames, but they rely on assumptions that don't always hold (VUI missing timing information is one, but there are others in the DTS extraction code).
Solution
Fundamentally, the issue arises from the system not tracking DTS
from input to output. Fixing this in a way that doesn't fail when the DTS extraction code's assumptions don't hold requires small changes to many parts of the code -- not just in mediamtx, but in mediacommon and gohlslib as well. Here is a complete solution:
0001-mediacommon.patch
0002-gohlslib.patch
0003-mediamtx.patch
These API changes will require a /v3
release for incorporation into the library projects, as they require breaking changes to several signatures.
I'm not submitting these as PRs yet because the solution spans multiple repositories and has project-level implications (due to the version change).
Related Issues
Although I haven't diagnosed it, there is a very high probability that #4768 is related to this DTS discarding and recalculation behavior.
Server logs
No response
Network dump
No response