Different aspect ratios being displayed from different types of h264 encoders


When I run this pipeline using different h264 encoders I’m seeing different aspect ratios when viewing the output on VLC.

  • gst-launch-1.0 filesrc location=video.ts ! tsdemux ! h264parse ! (h264 decoders) ! videoconvert ! videoscale ! video/x-raw, width=640, height=480 ! (h264 encoders) bitrate=3000 ! mpegtsmux ! queue ! filesink location=out.ts

I’m mainly more focused on utilizing the openh264enc, nvh264enc, and qsvh264enc. From my experience using these 3 encoders I notice the pixel resolution is the same, but the aspect ratio appears different when I view the output from each encoder.

I have already tested using the same matching decoders & encoders, and I have also tested using the same decoder for all 3 encoders which all results in different aspect ratios for each test scenario.

I was wondering if anyone has ideas why this is happening?

How exactly are they different? (input resolution/aspect-ratio and encoded aspect ratio)

openh264enc does not write pixel-aspect-ratio into bitstream. So, unless aspect-ratio is written in container, we will lose aspect-ratio info, meaning that displayed aspect ratio will be wrong if it was not 1/1.

NVENC API requires display aspect ratio, not pixel-aspect-ratio. Then NVENC runtime will convert it to pixel-aspect-ratio and write it into bitstream. I’m not sure why the API was designed like that. Anyway, because of the par ↔ dar conversion, rounding error might happen.

In case of QSV, we pass pixel-aspect-ratio directly to QSV runtime. I think QSV will always preserve input pixel-aspect-ratio unless aspect ratio is so funny value (e.g., MAX_UINT16 overflow)

File source resolution is 720x480 (3:2).
Using videoscale my target resolution is 640x480 (4:3).

  • openh264enc is able to encode to a 4:3 aspect ratio

  • nvh264enc, and qsvh264enc come out wider than 4:3

This is all observed on VLC. Also I know opehn264enc comes out to 4:3 correctly, because when changing the aspect ratio option on VLC to 4:3. The video from the openh264enc stays the same, but nvh264enc and qsvh264enc video shrinks down to match the 4:3 option.

that explains aspect-ratio related bug/missing-feature in openh264enc. don’t forget that pixel aspect ratio is different from display aspect ratio.

see your pipeline, I assume original 720x480 (3:2 display aspect ratio) stream’s pixel aspect ratio is 1:1. Then output pixel aspect ratio of videoconvert ! videoscale will not be 1/1 because you didn’t specify it. Then the non-1/1 pixel aspect ratio should be written in bitstream (NVENC/QSV do it correctly, openh264enc does not)

Now you are applying non-1/1 aspect ratio option in vlc, and resulting final display aspect ratio is supposed to be different from the correct one (derived display aspect ratio by using resolution and pixel aspect ratio).

In short, openh264enc is wrong.

How would I be able to specify it? The add-borders property on videoconvert and videoscale?

default add-borders is true already.

What you need is pixel-aspect-ratio filed after convert/scale, for example ... ! videoconvert ! videoscale ! video/x-raw,width=640,height=480,pixel-aspect-ratio=1/1 ! (your encoder) ! ..

After adding the PAR to the caps filter now every output from each decoder does look the same. However when in full screen it stays in it’s PAR which is correct I believe. Is there a way to stretch the videos to fill up more of the screen?

Output with PAR specified:

Sorry let me clarify my last post. I noticed that after adding the PAR to the capsfilter on my pipeline, the video output maintains black bars on the top and bottom of my video. But when I don’t include the PAR my video output doesn’t include the black bars on the top and bottom.

My question is why is it when I don’t include the PAR on the capsfilter do I not get black bars on my output?

Output with PAR not specified:

Output with PAR specified:

the black borders is unavoidable when you do resizing video to different display aspect ratio with identical pixel aspect ratio (1:1).

You can do add-borders=false if you don’t want the borders. Then videoscale will stretch image without borders (aspect ratio is not preserved)