[Libva] [PATCH] Added normalization and scaling of the quality factor and Quantization tables

Xiang, Haihao haihao.xiang at intel.com
Mon Mar 23 22:18:31 PDT 2015


On Mon, 2015-03-23 at 14:12 -0700, Sirisha Muppavarapu wrote:
> When the header is packed before sending to the driver through LibVA,
> It is neccesary to normalize the quality factor and scale the Quantization
> tables based on this quality factor.
> ---
>  test/encode/jpegenc.c | 38 ++++++++++++++++++++++++++++++++++----
>  1 file changed, 34 insertions(+), 4 deletions(-)
> 
> diff --git a/test/encode/jpegenc.c b/test/encode/jpegenc.c
> index ff7a45a..9179b70 100644
> --- a/test/encode/jpegenc.c
> +++ b/test/encode/jpegenc.c
> @@ -27,7 +27,10 @@
>   * Usage:
>   * ./jpegenc <width> <height> <input file> <output file> <input filetype 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)> q <quality>
>   * Currently supporting only I420/NV12/UYVY/YUY2/Y8 input file formats.
> - */  
> + * 
> + * NOTE: The intel-driver expects a packed header sent to it. So, the app is responsible to pack the header
> + * and send to the driver through LibVA. This unit test also showcases how to send the header to the driver.
> + */
>  
>  #include "sysdeps.h"
>  #include <stdio.h>
> @@ -310,11 +313,15 @@ void populate_scan_header(JPEGScanHeader *scanHdr, YUVComponentSpecs yuvComp)
>      
>  }
>  
> -
> -int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentSpecs yuvComp, int picture_width, int picture_height, uint16_t restart_interval)
> +// This method packs the header information which is to be sent to the driver through LibVA.
> +// All the information that needs to be inserted in the encoded buffer should be built and sent.
> +// It is the responsibility of the app talking to LibVA to build this header and send it.
> +// This includes Markers, Quantization tables (normalized with quality factor), Huffman tables,etc.
> +int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentSpecs yuvComp, int picture_width, int picture_height, uint16_t restart_interval, int quality)
>  {
>      bitstream bs;
>      int i=0, j=0;
> +    uint32_t temp=0;
>      
>      bitstream_start(&bs);
>      
> @@ -336,6 +343,17 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
>      bitstream_put_ui(&bs, 72, 16);    //Y density
>      bitstream_put_ui(&bs, 0, 8);      //Thumbnail width
>      bitstream_put_ui(&bs, 0, 8);      //Thumbnail height
> +
> +    // Regarding Quantization matrices: As per JPEG Spec ISO/IEC 10918-1:1993(E), Pg-19:
> +    // "applications may specify values which customize picture quality for their particular
> +    // image characteristics, display devices, and viewing conditions"
> +
> +
> +    //Normalization of quality factor
> +    if(quality >= 100) quality=100;
> +    if(quality <= 0) quality=1;
> +

I just noticed quality in this example is int, which is inconsistent
with JPEG encode structure. You should do the similar thing in
jpegenc_pic_param_init(), or clamp quality to [1, 100] before
jpegenc_pic_param_init().


> +    quality = (quality < 50) ? (5000/quality) : (200 - (quality*2));
>      
>      //Add QTable - Y
>      JPEGQuantSection quantLuma;
> @@ -346,6 +364,12 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
>      bitstream_put_ui(&bs, quantLuma.Pq, 4);
>      bitstream_put_ui(&bs, quantLuma.Tq, 4);
>      for(i=0; i<NUM_QUANT_ELEMENTS; i++) {
> +        //scale the quantization table with quality factor
> +        temp = (quantLuma.Qk[i] * quality)/100;
> +        //clamp to range [1,255]
> +        temp = (temp > 255) ? 255 : temp;
> +        temp = (temp < 1) ? 1 : temp;
> +        quantLuma.Qk[i] = (unsigned char)temp;
>          bitstream_put_ui(&bs, quantLuma.Qk[i], 8);
>      }
>  
> @@ -359,6 +383,12 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
>          bitstream_put_ui(&bs, quantChroma.Pq, 4);
>          bitstream_put_ui(&bs, quantChroma.Tq, 4);
>          for(i=0; i<NUM_QUANT_ELEMENTS; i++) {
> +            //scale the quantization table with quality factor
> +            temp = (quantChroma.Qk[i] * quality)/100;
> +            //clamp to range [1,255]
> +            temp = (temp > 255) ? 255 : temp;
> +            temp = (temp < 1) ? 1 : temp;
> +            quantChroma.Qk[i] = (unsigned char)temp;
>              bitstream_put_ui(&bs, quantChroma.Qk[i], 8);
>          }
>      }
> @@ -778,7 +808,7 @@ int encode_input_image(FILE *yuv_fp, FILE *jpeg_fp, int picture_width, int pictu
>      unsigned int length_in_bits;
>      unsigned char *packed_header_buffer = NULL;
>  
> -    length_in_bits = build_packed_jpeg_header_buffer(&packed_header_buffer, yuvComponent, picture_width, picture_height, slice_param.restart_interval);
> +    length_in_bits = build_packed_jpeg_header_buffer(&packed_header_buffer, yuvComponent, picture_width, picture_height, slice_param.restart_interval, quality);
>      packed_header_param_buffer.type = VAEncPackedHeaderRawData;
>      packed_header_param_buffer.bit_length = length_in_bits;
>      packed_header_param_buffer.has_emulation_bytes = 0;




More information about the Libva mailing list