Ullaakut / RTSPAllTheThings

Deprecated RTSP media server -- Use github.com/aler9/rtsp-simple-server instead.
Apache License 2.0
275 stars 72 forks source link

Stream from file input without re-encoding #52

Closed frallain closed 5 years ago

frallain commented 6 years ago

If not, is it possible to use gstreamer directly to do it? Thanks and Cheers

frallain commented 6 years ago

I mean, is it feasible codewise in pipeline.cpp?

Ullaakut commented 6 years ago

Hi @frallain,

Yes it is possible. It's written in the readme which options force a transcoding:

RTSP_FRAMERATE | -f: The desired output framerate for your stream [default: 25] - RTSPATT will have to do encoding to change the framerate (Increased CPU usage)

The options that force transcoding are:

If you see that RTSPAtt is transcoding despite none of those options being used, then it's a bug. In which case, let me know and I'll fix it as soon as possible :-)

Thanks for using RTSPATT!

frallain commented 6 years ago

@Ullaakut Ok, I am trying to stream a 1920x1080 10FPS H264 mp4 file:

$ mediainfo legacy_openRTSP.mp4
General
Complete name                            : legacy_openRTSP.mp4
Format                                   : QuickTime
Format/Info                              : Original Apple specifications
File size                                : 27.9 MiB
Duration                                 : 1mn 2s
Overall bit rate mode                    : Variable
Overall bit rate                         : 3 763 Kbps
Encoded date                             : UTC 2017-11-14 11:05:13
Tagged date                              : UTC 2017-11-14 11:05:13
Writing library                          : Apple QuickTime

Video
ID                                       : 1
Format                                   : AVC
Format/Info                              : Advanced Video Codec
Format profile                           : Main@L4.0
Format settings, CABAC                   : Yes
Format settings, ReFrames                : 1 frame
Format settings, GOP                     : M=1, N=50
Codec ID                                 : avc1
Codec ID/Info                            : Advanced Video Coding
Duration                                 : 1mn 2s
Bit rate mode                            : Variable
Bit rate                                 : 3 761 Kbps
Maximum bit rate                         : 8 027 Kbps
Width                                    : 1 920 pixels
Height                                   : 1 080 pixels
Display aspect ratio                     : 16:9
Frame rate mode                          : Constant
Frame rate                               : 10.000 fps
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Progressive
Bits/(Pixel*Frame)                       : 0.181
Stream size                              : 27.9 MiB (100%)
Language                                 : English
Encoded date                             : UTC 2017-11-14 11:05:13
Tagged date                              : UTC 2017-11-14 11:05:13
Color primaries                          : BT.709
Transfer characteristics                 : BT.709
Matrix coefficients                      : BT.709

and I think it transcodes the file:

$ docker run -p 8554:8554 -v /tmp/:/videos/ -e INPUT=/videos/legacy_openRTSP.mp4 -e RTSP_RESOLUTION=1920x1080 -e RTSP_FRAMERATE=10 -e RTSP_ROUTE=/feeding  ullaakut/rtspatt:1.3.2
Server configuration:
Address:    0.0.0.0
Port:       8554
Route:      /feeding
Username:   
Password:   
Auth method:    basic
Input:      /videos/legacy_openRTSP.mp4
Input type: file

H264 encoding with:
Framerate:  10
Resolution: 1920x1080

Launching stream with the following pipeline: ( appsrc name=mysrc ! decodebin ! videoscale ! video/x-raw,width=1920,height=1080 ! videorate ! video/x-raw,framerate=10/1 ! capsfilter ! queue ! x264enc speed-preset=superfast ! rtph264pay name=pay0 pt=96  )
Stream ready at rtsp://0.0.0.0:8554/feeding

Can you confirm or not that it is transcoding?

Also, the [default: 25] for RTSP_FRAMERATE is confusing, should I specify it if my video is not at 25FPS? Shouldn't be the default framerate the original framerate of the input video?

And the same for the resolution which seems to default to 1280x720, shouldn't it be the resolution of the input video by default?

Ullaakut commented 6 years ago

Yes, here it's going to transcode the video because the resolution and framerate options are specified.

I agree that it's super confusing, especially that currently if RTSP_FRAMERATE isnt specified, it just isn't modified, and is not set to 25fps like the documentation would suggest.

I will update the documentation to match reality and in the meantime, running:

docker run -p 8554:8554 -v /tmp/:/videos/ -e INPUT=/videos/legacy_openRTSP.mp4 -e RTSP_ROUTE=/feeding  ullaakut/rtspatt:latest

Should work without any transcoding.

frallain commented 6 years ago

@Ullaakut No it still transcodes due to the default resolution of 1280*720 :

$ docker run -p 8554:8554 -v /var/log:/videos/ -e INPUT=/videos/legacy_openRTSP.mp4   -e RTSP_ROUTE=/feeding ullaakut/rtspatt:1.3.2

Server configuration:
Address:    0.0.0.0
Port:       8554
Route:      /feeding
Username:   
Password:   
Auth method:    basic
Input:      /videos/legacy_openRTSP.mp4
Input type: file

H264 encoding with:
Framerate:  25
Resolution: 1280x720

Launching stream with the following pipeline: ( appsrc name=mysrc ! decodebin ! videoscale ! video/x-raw,width=1280,height=720 ! videorate ! video/x-raw,framerate=25/1 ! capsfilter ! queue ! x264enc speed-preset=superfast ! rtph264pay name=pay0 pt=96  )
Stream ready at rtsp://0.0.0.0:8554/feeding
Ullaakut commented 6 years ago

Alright I found the issue! Thanks @frallain :) Will fix this later on today or tomorrow.

frallain commented 6 years ago

@Ullaakut Cool, glad to help.

Ullaakut commented 6 years ago

Actually after looking into it for a few hours here, didn't really find a way to consistently have working video without encoding. Will leave the forced encoding for now but remove the default WIDTH, HEIGHT and FRAMERATE values (except for videotestsrc, which requires dimensions to be built.)

I will add the help wanted label on the issue and hopefully someone else will be able to help. Until then, if you really need to avoid the encoding, I suggest using ffmpeg

Ullaakut commented 6 years ago

See https://github.com/Ullaakut/RTSPAllTheThings/pull/55 for an update on some fixes regarding this.

frallain commented 6 years ago

@ullakut some relevant information at https://stackoverflow.com/questions/29794053/streaming-mp4-video-file-on-gstreamer

enricomarchesin commented 5 years ago

This pull request might turn out to be useful:

Ullaakut commented 5 years ago

61 fixes this issue, thanks to @enricomarchesin ! Closing for now, but if that still doesn't work for you @frallain , let me know :)

enricomarchesin commented 5 years ago

Just a side note, I did a couple of tests to understand the actual performance improvement when no decoding and encoding is done on the source

Default pipeline

The original image, when idle (not streaming), was showing this with docker stats:

CONTAINER ID        NAME                    CPU %               MEM USAGE / LIMIT   MEM %               NET I/O             BLOCK I/O           PIDS
1a4995cbe07d        hardcore_visvesvaraya   10.71%              710MiB / 3.855GiB   17.99%              828B / 0B           1.89MB / 4MB        9

When streaming a Full HD H262 video, the CPU usage more than tripled (it's a 2.7 GHz Intel Core i7 with 4 cores assigned to Docker):

CONTAINER ID        NAME                    CPU %               MEM USAGE / LIMIT     MEM %               NET I/O             BLOCK I/O           PIDS
1a4995cbe07d        hardcore_visvesvaraya   35.32%              2.016GiB / 3.855GiB   52.30%              516kB / 33.9MB      2.97MB / 4.12MB     29

Custom pipeline

I then served the same video and passing a custom pipeline (inspired by the post linked above):

GST_PIPELINE="filesrc location=/tmp/video.mp4 ! qtdemux ! video/x-h264 ! rtph264pay pt=127 name=pay0"

This is the resource usage when idle:

CONTAINER ID        NAME                CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
f1cf254e0374        jolly_fermi         0.00%               7.68MiB / 3.855GiB   0.19%               758B / 0B           98MB / 3.7MB        1

And this is the stats when streaming:

CONTAINER ID        NAME                   CPU %               MEM USAGE / LIMIT    MEM %               NET I/O             BLOCK I/O           PIDS
f553127b7142        condescending_darwin   1.70%               7.93MiB / 3.855GiB   0.20%               593kB / 21.8MB      0B / 3.7MB          6

🤩 Amazing, isn't it?

Ullaakut commented 5 years ago

Yes, encoding is very resource-intensive, especially for high quality streams. It's very good indeed that it's now possible to have pipelines that work without encoding when it's not necessary :) I just wish I figured out how to fix the main pipelines though, as it's not easy for most users to write gstreamer pipelines (and to be honest, I haven't been using gstreamer much this past year, so I'm a bit rusty myself)