shogo4405 / SRTHaishinKit.swift

Camera and Microphone streaming library via SRT for iOS, macOS.
BSD 3-Clause "New" or "Revised" License
70 stars 25 forks source link

Use correct Transport Stream standard for SRT #10

Closed themaxsmith closed 2 years ago

themaxsmith commented 4 years ago

Unable to stream to SRS 4.0

https://github.com/ossrs/srs/ https://github.com/ossrs/srs/blob/4.0release/trunk/src/srt/ts_demux.cpp

Crashes SRS with error srs: ./src/srt/ts_demux.cpp:415: int ts_demux::pes_parse(unsigned char*, size_t, unsigned char**, size_t&, uint64_t&, uint64_t&): Assertion0x80 == p[pos]' failed. ` I believe this is due to TSWriter. OBS and FFMPEG work fine so I believe it is the config in Hashinkit. Here is the defaults for FFMPEG https://ffmpeg.org/ffmpeg-formats.html#mpegts

I am looking into this but I would love it if someone else can also attempt to take a look at solving this.

themaxsmith commented 4 years ago

https://en.wikipedia.org/wiki/Packetized_elementary_stream

themaxsmith commented 4 years ago

https://github.com/shogo4405/HaishinKit.swift/blob/master/Sources/ISO/TSWriter.swift

themaxsmith commented 4 years ago

ffprobe shows this error Invalid timestamps stream=1, pts=8999, dts=11999, size=3497 throughout stream - stream 1 = video stream. also missing ts metadata service_name and serivce_provider.

RobbieElias commented 3 years ago

@themaxsmith Did you ever figure this out?

themaxsmith commented 3 years ago

@themaxsmith Did you ever figure this out?

I ended up using srt-live-server instead of srs on the server-side. It will accept the SRT output then you can use an HTTP callback to create an FFmpeg instance that generates the correct timestamps then you can send it to SRS or any type of media server.

RobbieElias commented 3 years ago

@themaxsmith I actually got it working by simply changing the profile level to baseline.

Example: srtStream.videoSettings = [.profileLevel: kVTProfileLevel_H264_Baseline_3_1]

themaxsmith commented 3 years ago

@themaxsmith I actually got it working by simply changing the profile level to baseline.

Example: srtStream.videoSettings = [.profileLevel: kVTProfileLevel_H264_Baseline_3_1]

Good to know there is a workaround. The only problem is that the baseline profile is significantly worse on picture quality compared to high and uses 50% more bandwidth to create a similar quality picture. Can't use it on commercial products were paying customers may be limited on bandwidth and expect a high-quality stream. It is okay where you may not have to worry about bandwidth. It is also possible that since srt standard is not well defined when it comes to the TS format that SRS follows ffmpeg default values (so does OBS) and TSWriter may be following the HLS default values. It may be fixed in the future but for now, I think the best idea is to switch it to RTMP with generated timestamps on the server-side to prevent corruption. This is what we are doing at SeasonCast for a few hundred srt streams every night using this library and we have gotten a good result from it (extremely better than RTMP). From what I learned, you want to also build in some type of adaptive bitrate handling.

RobbieElias commented 3 years ago

@themaxsmith I was able to find another workaround, while still using the Main or High profiles. I modified the H264Encoder.swift file to disable frame reordering in the encoder:

Change: kVTCompressionPropertyKey_AllowFrameReordering: !isBaseline as NSObject,

To: kVTCompressionPropertyKey_AllowFrameReordering: kCFBooleanFalse,

I'm not sure if there are any drawbacks to this, but I haven't experienced any so far.

shogo4405 commented 2 years ago

stream.videoSettings[.allowFrameReordering] = false option is now available. https://github.com/shogo4405/HaishinKit.swift/pull/1050