T.E.D.
T.E.D.

Reputation: 44814

VLC 2.2 and Levels

I have an application I've written to provide simulated MP4 camera streams to a "black box". I use irony quotes because I don't have access to its sources, but we do have a support contract with the vendor who makes it.

This black box supports h.264 Level 2.2. It does not use anything like an SDP, but just expects the camera streams to be 640x480 @ 30hz. I understand this is reasonably standard output for surveillance cameras.

So my application is using vlc (libVlc to be specific) to stream MP4 files to this device. I have this working fine (with one minor exception, but that's a separate issue). However, that is with Vlc 2.1.5. When I tried upgrading to the latest 2.2.1, instead of the videos on the other side of our black box we are just seeing whiteish-gray squares.

Our vendor looked over wireshark dumps, and told me that the vlc 2.2.1 stream is reporting itself as Level 5.1 instead of 2.2, and that its now using High Profile instead of Baseline or Main. It almost looks like VLC is trying to "upgrade" (transcode?) my video on me, and that's messing up the reader on that black box.

Is there any way to get the old behavior from vlc 2.1.5 back, or force it to use the Level and Profile of my choosing?

Upvotes: 0

Views: 2922

Answers (1)

aergistal
aergistal

Reputation: 31229

H.264 Profiles

Profiles are sets of capabilities. If your black box only supports the Baseline profile it'll not be able to decode a stream using High capabilities.

In VLC you can set the H.264 profile to be used by the x264 encoder like this:

--sout="#transcode{vcodec=h264,venc=x264{profile=baseline}...

H.264 Levels

Think of levels as a constraint/indicator of required decoder performance. If a decoder supports a certain level for a certain profile then it must be able to decode streams at that level and any of the lower levels.

First of all, the level for 640x480 @ 30 fps is 3 and not 2.2.

You can calculate this as following:

macrobolocks = ceil(640/16) * ceil(480/16) = 1200
macroblocks/s = macroblocks * 30 = 36000

The reason for ceil is that non-mod16 resolution are padded to a multiple of 16.

You then take a look at the H.264 Levels. You are within the frame size limit for 2.2 which is 1620 but the max decoding speed is greater than 20252 so you have to choose the next level wich is 3. You'll also have to consider the maximum bitrate for the Baseline profile in that table.

If you have an Android device you can download my H.264 Calculator app from the Amazon App Store (I can send you the apk if you don't like their Orwellian app permissions)

The x264 encoder will automatically choose a level based on your encoding parameters. With VLC you can actually set the flag yourself using something like:

--sout="#transcode{vcodec=h264,venc=x264{profile=baseline,level=22}"...

Beware, this sets the encoder output flag and doesn't actually produce a Level 2.2 stream. You can put any values you want, so it's possible to mark a Full HD stream at 60 fps as Level 2.2 even if it's nowhere the level limits.

VLC Transcoding

If you want to make sure you're sending a correct stream you'll need to transcode the source material. This is an example for 640x480 @ 30 fps which results in a Level 3 H.264 stream like I showed you above. If you want Level 2.2 you'll need to lower the resolution or framerate or both. Your video bitrate can go lower too in that case.

cvlc input.mp4 --sout="#transcode{vcodec=h264,venc=x264{profile=baseline},fps=30,width=640,height=480,vb=1372,acodec=mpga,ab=128,channels=2,samplerate=44100}:rtp{...}

Mediainfo

Mediainfo is a great tool to get information about a media file. You can check the specs of your input files, but it won't help you detect a wrong level which was forced into or wrongfully chosen by the encoder. The safest way is to re-encode.

Upvotes: 3

Related Questions