obs-outputs: Add eRTMP Reconnect
Description
This PR includes Reconnect Request enhancement to the eRTMP protocol according the spec. It makes OBS Studio react to the eRTMP server's "reconnect" message and change the target eRTMP receiver on the fly while streaming (on the first key-frame).
The rtmp sending process has been a very slightly updated to avoid packet loss in case of internal obs sending issues (get_next_packet -> pair of peek_next_packet and free_next_packet). Important for sending video key frames, for example to keep reconnected video stream continuous as possible.
Motivation and Context
Enable reaction on the eRTMP "reconnect" feature and perform a real reconnect.
How Has This Been Tested?
It has been tested using:
- OBS Studio as RTMP sender (Linux, Windows, macOS),
- two modified FFmpeg instances as eRTMP servers (Linux only),
- two unmodified FFplay instances as RTMP clients (Linux only).
The provided FFMpeg patch makes the servers to generate a "reconnect" event on demand. OBS Studio reacts to the generated events and changes the streaming destination. We monitor the workflow using FFplay. The full setup and instructions are provided at the end of this pull request.
Types of changes
- Tweak (non-breaking change to improve existing functionality)
Checklist:
- [x] My code has been run through clang-format.
- [x] I have read the contributing document.
- [x] My code is not on the master branch.
- [x] The code has been tested.
- [x] All commit messages are properly formatted and commits squashed where appropriate.
- [x] I have included updates to all appropriate documentation.
Testing
The Reconnect Request can be tested using a modified FFmpeg library. Modified FFmpeg tracks the reconnect.dat file presence in its working directory and generates the reconnect command with reconnect.dat file content as the "url reconnection" message parameter. The 0001-demo-reconnect.patch is provided.
The following steps are a working example of the testing pipeline. It provides steps for two backends, but the number of backends can easily be increased to any number needed.
Preparation
- Clone the https://github.com/FFmpeg/FFmpeg repository,
- Apply provided patch,
- Build the FFmpeg library including FFmpeg and FFplay.
Configure and Run Backends (Linux)
- Note two empty rtmp ports for a backend instances. Let it be
8889and9998. - Prepare an it's own folder for every backend instance.
- Add next shell script to every folder (change the
${port-number}for every script, change the${the_folder_with_ffmpeg}to the real FFmpeg path), we will use this script as a backend with controlling the received eRTMP stream using FFplay#!/bin/sh export LD_LIBRARY_PATH=${the_folder_with_ffmpeg} export PATH=${the_folder_with_ffmpeg}:$PATH while true; do echo =============================== `date` ============================ ffmpeg -f flv -listen 1 \ -v trace -hide_banner \ -i rtmp://localhost:${port-number}/live/app \ -c:v copy -c:a copy \ -f flv - \ | ffplay - -autoexit sleep 1 done - Run all backends by running
rtmp-server.shin their own shell session. We should now have two working backend sessions waiting for the data.
Configure and Run OBS Studio (any OS)
- Run OBS Studio and change the next "Stream" settings:
- Service:
Custom... - Server:
rtmp://localhost:8889/live(the port value must be a port of a first backend) - Stream Key: "app"
- Service:
- Start OBS-Studio Streaming.
We must see the running logs in the first backend console, and a proper status notifications in the OBS-Studio.
We must see the proper video with automatically run FFplay.
Reconnect test cases
-
Create an empty file named
reconnect.datin the first backend folder (empty means file with no content, size 0).
After a few seconds (when OBS finds a key-frame) we must see OBS-Studio notifications about disconnect and reconnecting to the same backend. FFplay must stop playing and start playing same media content again.
-
Create a file named
reconnect.datin the first backend folder with next content:rtmp://localhost:9998/live(no newline at the end, the port number must be a second backend port).
After a few seconds (when OBS finds a key-frame) we must see OBS-Studio notifications about disconnect and reconnecting, the first FFplay must stop playing, the second backend console must start receive the data, the second FFplay must start showing the media stream. -
Create a file named
reconnect.datin the second backend folder with next content:rtmp://localhost:8889/live(no newline at the end, the port number must be a second backend port).
After a few seconds (when OBS finds a key-frame) we must see OBS-Studio notifications about disconnect and reconnecting, the second FFplay must stop playing, the first backend console must start receive the data, the first FFplay must start showing the media stream. -
If we have more than two backends, then we do the same steps with different backend ports.
Please updated references to clarify that this is eRTMP, not RTMP.
When adding an API to deque, it's description should be added to the document docs/sphinx/reference-libobs-util-deque.rst.
However, I don't know why deque_pop_front is not sufficient for the usage and you want to add deque_free_front. You can pass NULL to the data parameter so that deque_peek_front will do nothing except checking size.
You can pass
NULLto thedataparameter so thatdeque_peek_frontwill do nothing except checkingsize.
Do not use merge commits, rebase is preferred.
Do not use merge commits, rebase is preferred.
Yeah, I know. Unfortunately github button made merge instead of rebase. Next time I'll do it by hands.