Page 1 of 1

Stream transcoding, closed GOP and HLS

Posted: 20 May 2014 16:36
by benou
Hello everyone,

I need to transcode an input stream to 25 fps H264, with closed GOPs each 1 second-long (=25 frames), and then stream this using HLS protocol, with 5 second segments each of them containing 5 GOPs. Here's is the command-line I thought of :

Code: Select all

cvlc -vvv <my-input-stream> --no-sout-audio --sout='#transcode{width=854,height=480,fps=25,vcodec=h264,vb=800,venc=x264{profile=main,level=30,keyint=25,min-keyint=25,opengop=false}}:std{access=livehttp{seglen=5,delsegs=false,numsegs=0,index=/home/www/test/mystream.m3u8,index-url=http://<my-IP>/test/mystream-########.ts},mux=ts{use-key-frames},dst=/home/www/test/mystream-########.ts}'
Remarks :
- I disabled audio for debugging purposes
- I set min-keyint an keyint to 25 to force the GOP size to exactly 25 frames

However the output does not fulfill my requirements. The major issue is that my HLS segments have a variable duration, which is always less than the expected 5 seconds. Can anyone help me with this issue ?

Re: Stream transcoding, closed GOP and HLS

Posted: 21 Jul 2014 13:43
by sharbatgula
Same here, with very similar syntax:

:sout=#transcode{vcodec=h264,venc=x264{aud,profile=baseline,keyint=50,vbv-maxrate=700,vbv-bufsize=1000,fps=25},ab=64k,channels=2,samplerate=44100,audio-sync,deinterlace{deinterlace=linear},fps=25,width=640,height=480,acodec=mp4a,aenc=ffmpeg{strict=-2}}:duplicate{dst=std{access=livehttp{seglen=10,delsegs=true,numsegs=10,index=S:\hlsResources\_test\test.m3u8,index-url=test-########.ts},mux=ts{use-key-frames},dst=S:\hlsResources\_test\test-########.ts}} :sout-keep

chunks start with IDR frame indeed, frame-rate appears to be constant (i'm checking with quicktime player) but chunks are never exactly 10 seconds long. Mostly 9 seconds plus a fraction but sometimes around 8 or 10s.

Re: Stream transcoding, closed GOP and HLS

Posted: 21 Jul 2014 17:57
by sharbatgula
OK, I figured out what's actually going on. The reason for non-fixed length of chunks is the fact that on scene cuts, x264 could generate IDR frame before the next expected fixed position of the IDR frames governed by keyint and min-keyint. This resets the keyint and min-keyint counters and now instead of expecting the IDRs on each n x keyint frame, it happens some frames later thus varying the length of the chunks. Note that the HLS packager has to wait for the next IDR to place it as the first frame in the next chunk.

I guess the way around this is to disable scenecuts with no-scenecut, but this is expected to degrade the quality of picture.

But, I don't understand why the encoder is always placing IDR frames and never I frames, despite the following x264 definition:

scenecut
Default: 40
Sets the threshold for I/IDR frame placement (read: scene change detection).
x264 calculates a metric for every frame to estimate how different it is from the previous frame. If the value is lower than scenecut, a 'scenecut' is detected. An I-frame is placed if it has been less than --min-keyint frames since the last IDR-frame, otherwise an IDR-frame is placed.

That said, setting keyint and min-keyint the same, should force I frames on scenecuts always, but this is not true in my tests.
Anyway, if variable length behaviour is not viloating HLS specs and the playback is flawless, I would not care about it, but in my case, when playing the stream, for the first 10 seconds I see only a static picture and sound, then the playback resumes.

I'm either missing something or I've bumped into a bug.

Any ideas?