Media (Intel® Video Processing Library, Intel Media SDK)
Access community support with transcoding, decoding, and encoding in applications using media tools like Intel® oneAPI Video Processing Library and Intel® Media SDK
Announcements
The Intel Media SDK project is no longer active. For continued support and access to new features, Intel Media SDK users are encouraged to read the transition guide on upgrading from Intel® Media SDK to Intel® Video Processing Library (VPL), and to move to VPL as soon as possible.
For more information, see the VPL website.

Per-slice QP (Quantizer Parameter) is always zero

Oleksandr_T_
Beginner
1,471 Views

Hello,

I am experimenting with hardware H.264 encoding using ffmpeg's QSV encoder. Encoding seems to work fine but I can not get quality information from the generated bitstream. pic_init_qp_minus26 is set to 0, which is expected for bitrate-controlled quality I guess and slice_qp_delta is always zero regardless of the combination of bitrate/reolution set.  I tried both CBR and VBR rate control algorithms. I use SDK2017Production16.5.

How do I make QSV provide per-slice QP?

I just started working with H.264, so if the question is totally off - I'd appreciate any other pointers for measuring quality of encoded stream. Thank you

0 Kudos
1 Solution
Mark_T_
Novice
1,471 Views
Hi Oleksandr, pic_init_qp_minus26 and slice_qp_delta are not sufficient to retrieve the information you're trying to find - the QP can also vary per-macroblock in bitrate-targetted RC modes. You need to look at mb_qp_delta as well. - Mark

View solution in original post

0 Kudos
7 Replies
Anna_B_Intel
Employee
1,471 Views

Hi Oleksandr, 

How do you try to get quality information?

Best wishes, 

Anna

0 Kudos
Oleksandr_T_
Beginner
1,471 Views

Hi Anna,

I perform following steps:

- Encode frame
- Parse generated bitstream
- Get pps.pic_init_qp_minus26
- Get slice_qp_delta for every slice
- Calculate actual slice's QP value: 26 + pps.pic_init_qp_minus26 + slice_qp_delta. Use this value as a quality indicator

The problem is  pps.pic_init_qp_minus26 and slice_qp_delta are always zero regardless of actual compressed image quality. I used low bitrate for high-resolution frames to get bad quality, still no difference from high-bitrate case.  

Thank you

0 Kudos
Anna_B_Intel
Employee
1,471 Views

Hi Oleksandr, 

pic_init_qp_minus26 is the default qp value. Its expected behavior that its 0.

I experimented with qp values using sample_encode from Media Server Studio samples package:  ./sample_encode h264 -i ../content/test_stream_176x96.yuv -o out.h264 -w 176 -h 96 -cqp -qpi 51 -qpp 51 -qpb 51

So the result was expected: slice_qp_delta=25, the encoded frames are blurred. It seems like you problem on ffmpeg side - I recommend you to address it to ffmpeg community.

Best wishes, Anna

 

0 Kudos
Oleksandr_T_
Beginner
1,471 Views

Hi Anna,

QP value is set in bitstream for QP-controlled rate control methods like CQP. I am talking about bitrate-controlled rate methods like VBR and CBR. In this case input parameter for encoder is bitrate or range of bitrates  and QP changes from picture to picture or from slice to slice to produce stream with bitrate close to requested. At least this is my understanding based on this whitepaper: http://www.pixeltools.com/rate_control_paper.html

WebRTC uses this approach to get best available quality for H.264. It goes something like this:
- Media stream sets initial bitrate and image size based on some guesstimate
- After each encoded frame it gets QP from last slice and averages this value over some period of time (500ms or close to that)
- If QP is less than QPhighquality(24) - stream either steps up bitrate or increases picture resolution
- If QP is more than QPlowquality(31) -  stream either steps down bitrate or decreases picture resolution

Default encoder in WebRTC code is OpenH264 and per-slice QP value in generated bitstream varies. Bitstream generated by QSV encoder produces constant QP, 26. I tried to reproduce this situation using sample_encode tool:

./sample_encode h264 -i serenity.yuv  -o out.7000.h264 -w 1280 -h 720 -b 7000
./sample_encode h264 -i serenity.yuv  -o out.300.h264 -w 1280 -h 720 -b 300

Then I analyzed generated bitstreams:
% ./h264_analyze out.7000.h264  | grep -E 'slice_qp_delta|pic_init_qp_minus26' | sort -u
2.6: pps->pic_init_qp_minus26: 0
3.1: sh->slice_qp_delta: 0
4.8: sh->slice_qp_delta: 0

% ./h264_analyze /scratch/export/ovtymo/root2/out.300.h264  | grep -E 'slice_qp_delta|pic_init_qp_minus26' | sort -u
2.6: pps->pic_init_qp_minus26: 0
3.1: sh->slice_qp_delta: 0
4.8: sh->slice_qp_delta: 0

Despite the difference in visual quality, QP values are the same (26, when calculated according to spec) for all slices in both streams: 300Kbit and 7000Kbit. 

0 Kudos
Anna_B_Intel
Employee
1,471 Views

Hi Oleksandr, 

QP is not a real quality metric, quality also depends on encoder and its motion prediction. What is you final goal here? Are you trying to achieve some constant encoding quality? What is the use case (Is it streaming or encoding to a file for storage)?

Best wishes,

Anna 

0 Kudos
Mark_T_
Novice
1,472 Views
Hi Oleksandr, pic_init_qp_minus26 and slice_qp_delta are not sufficient to retrieve the information you're trying to find - the QP can also vary per-macroblock in bitrate-targetted RC modes. You need to look at mb_qp_delta as well. - Mark
0 Kudos
Oleksandr_T_
Beginner
1,471 Views

Thanks Mark! That was it, I checked per-MB QP in generated stream and  and it seams to be exactly what I need. I completely overlooked it.

0 Kudos
Reply