Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect timestamp processing #44

Open
PyvesB opened this issue Sep 13, 2018 · 4 comments
Open

Incorrect timestamp processing #44

PyvesB opened this issue Sep 13, 2018 · 4 comments

Comments

@PyvesB
Copy link

PyvesB commented Sep 13, 2018

Hello,

We are currently using the Red5 Client module to consume an RTMP input stream and proxy it to a different output destination. Nevertheless, Red5 seems to be ignoring most RTMP messages and streaming is not working as expected. See the following debug logs:

2018-09-12 13:55:34.206 DEBUG org.red5.client.net.rtmp.RTMPMinaIoHandler - messageReceived
2018-09-12 13:55:34.206 DEBUG org.red5.client.net.rtmp.RTMPConnManager - Getting connection by session id: AZZRP5I8SU291
2018-09-12 13:55:34.206 DEBUG org.red5.server.api.Red5 - Set connection: AZZRP5I8SU291 with thread: NioProcessor-75
2018-09-12 13:55:34.206 DEBUG org.red5.server.api.Red5 - Caller: org.red5.client.net.rtmp.RTMPMinaIoHandler.messageReceived #136
2018-09-12 13:55:34.206 DEBUG org.red5.server.net.rtmp.RTMPConnection - Executor is null on AZZRP5I8SU291 state: connected
2018-09-12 13:55:34.206 DEBUG org.red5.client.net.rtmp.BaseRTMPClientHandler - NetStream dispatchEvent: Video - ts: -837759002 length: 140
2018-09-12 13:55:34.206 DEBUG org.red5.client.net.rtmp.BaseRTMPClientHandler - publishStreamData - stream data map: {1.0=org.red5.client.net.rtmp.BaseRTMPClientHandler$NetStreamPrivateData@1497d1d9}
2018-09-12 13:55:34.206 DEBUG org.red5.server.stream.consumer.ConnectionConsumer - Message timestamp: -837759002
2018-09-12 13:55:34.206 DEBUG org.red5.server.stream.consumer.ConnectionConsumer - Message has negative timestamp: -837759002

The code responsible for this behaviour is coming from red5-server-common, in the pushMessage method. If an incoming RTMP message has a negative timestamp, it is simply ignored.

Monitoring the source RTMP input with the rtmpdump tool shows that none of the timestamps that are sent to Red5 are negative. However, they have large values, more specifically between 231 and 232. The IRTMPEvent defines the timestamp as int, which is a signed data type ranging from -231 and 231 - 1. Any value between 231 and 232 -1 will overflow and be interpreted as a negative timestamp by Red5.

Adobe's official RTMP specification states the following:

Timestamps in RTMP are given as an integer number of milliseconds relative to an unspecified epoch. Typically, each stream will start with a timestamp of 0, but this is not required, as long as the two endpoints agree on the epoch. Note that this means that any synchronization across multiple streams (especially from separate hosts) requires some additional mechanism outside of RTMP.

Because timestamps are 32 bits long, they roll over every 49 days, 17 hours, 2 minutes and 47.296 seconds. Because streams are allowed to run continuously, potentially for years on end, an RTMP application SHOULD use serial number arithmetic [RFC1982] when processing timestamps, and SHOULD be capable of handling wraparound. For example, an application assumes that all adjacent timestamps are within 2^31 - 1 milliseconds of each other, so 10000 comes after 4000000000, and 3000000000 comes before 000000000.

Timestamp deltas are also specified as an unsigned integer number of milliseconds, relative to the previous timestamp. Timestamp deltas may be either 24 or 32 bits long.

If my understanding is correct, according to the specification RTMP applications should be using unsigned integer arithmetic and not assume that timestamps start at 0 at the beginning of each stream.

Two of our current encoder vendors currently can't be used in conjunction with Red5 as they don't start the timestamp at 0 and may use a value between 231 and 232. Even for encoder vendors who reset their timestamps to 0, we believe that if the stream has been running for more than 24 days, 20 hours, 31 minutes and 23.648 seconds (231 milliseconds), it will suddenly break down as the timestamps will be interpreted as negative by Red5 past that point.

Thanks in advance for your help!

Regards,

Pyves

@solomax
Copy link
Contributor

solomax commented Sep 17, 2018

@mondain I tried to address this one, but this seems to require lots of changes :((
I can't just change all timestmps to be long
Integer.toUnsignedLong should also be used with care :(

@mondain
Copy link
Member

mondain commented Sep 17, 2018

@Andy--S I know you've done a lot of work with timestamps; would you like to weigh-in on this?

@Andy--S
Copy link

Andy--S commented Sep 18, 2018

It is correct that dropping negatives on a signed integer will limit live streams to 50% or their potential duration if the timestamps start at zero. more if they have an arbitrary start.

Ideally red5 wants a zero timestamp for the 'creationTime' of the ClientBroadcastStream.
As a workaround, subtract the first timestamp from all timestamps so your first video packet has a zero timestamp. Watch out for your source's timestamps roll over as well. might be 90,000 or whatever, and use the difference between the frame times to increment. (time+=delta)/scale convert to red5 milliseconds as needed.

@PyvesB
Copy link
Author

PyvesB commented Sep 21, 2018

Thank you for your responses.

Just to clarify, are there any plans on the Red5 team implementing a fix for this? I appreciate @solomax's observation that it would require a lot of changes, but such an issue is unlikely to be properly fixed by first time contributors unfamiliar with the Red5 code basis.

Is there any specific reason why Red5 discards RTMP messages if the int value is negative (see this code line)? More straightforward workarounds could consist in either removing the return statement or replacing it by a roll over of big unsigned timestamps 231 and 232 - 1 to timestamps between 0 and 231 - 1. I have tested such fixes on a modified version of Red5, video streaming is working as expected on downstream platforms.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants