[Libva] [PATCH] JPEG Encode: Added support for UYVY/YUY2/Y8 formats

Sirisha Muppavarapu sirisha.muppavarapu at intel.com
Tue Dec 9 13:10:32 PST 2014


---
 test/encode/jpegenc.c       | 181 +++++++++++++++++++-------------------------
 test/encode/jpegenc_utils.h |   6 +-
 2 files changed, 81 insertions(+), 106 deletions(-)

diff --git a/test/encode/jpegenc.c b/test/encode/jpegenc.c
index dababdc..cfe56f8 100644
--- a/test/encode/jpegenc.c
+++ b/test/encode/jpegenc.c
@@ -25,8 +25,8 @@
  * Simple JPEG encoder based on libVA.
  *
  * Usage:
- * ./jpegenc <width> <height> <input file> <output file> <input filetype 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGB)> q <quality>
- * Currently supporting only I420 and NV12 input file formats.
+ * ./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.
  */  
 
 #include "sysdeps.h"
@@ -63,8 +63,8 @@
 
 void show_help()
 {
-    printf("Usage: ./jpegenc <width> <height> <input file> <output file> <fourcc value 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGB)> q <quality>\n");
-    printf("Currently supporting only I420 and NV12 input file formats.\n"); 
+    printf("Usage: ./jpegenc <width> <height> <input file> <output file> <fourcc value 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)> q <quality>\n");
+    printf("Currently supporting only I420/NV12/UYVY/YUY2/Y8 input file formats.\n"); 
     printf("Example: ./jpegenc 1024 768 input_file.yuv output.jpeg 0 50\n\n"); 
     return;
 }
@@ -94,8 +94,7 @@ void jpegenc_pic_param_init(VAEncPictureParameterBufferJPEG *pic_param,int width
     } else {
         pic_param->component_id[0] = pic_param->quantiser_table_selector[0] = 0;
         pic_param->component_id[1] = pic_param->quantiser_table_selector[1] = 1;
-        pic_param->component_id[2] = 2;
-        pic_param->quantiser_table_selector[2] = 1;
+        pic_param->component_id[2] = 2; pic_param->quantiser_table_selector[2] = 1;
     }
     
     pic_param->quality = quality;
@@ -125,8 +124,8 @@ void jpegenc_qmatrix_init(VAQMatrixBufferJPEG *quantization_param, YUVComponentS
 
 void jpegenc_hufftable_init(VAHuffmanTableBufferJPEGBaseline *hufftable_param, YUVComponentSpecs yuvComp)
 {
-    
     hufftable_param->load_huffman_table[0] = 1; //Load Luma Hufftable
+
     if(yuvComp.fourcc_val == VA_FOURCC_Y800) {
         hufftable_param->load_huffman_table[1] = 0; //Do not load Chroma Hufftable for Y8
     } else {
@@ -143,7 +142,6 @@ void jpegenc_hufftable_init(VAHuffmanTableBufferJPEGBaseline *hufftable_param, Y
    //Load AC Values
    memcpy(hufftable_param->huffman_table[0].ac_values, jpeg_hufftable_luma_ac+17, 162);
    memset(hufftable_param->huffman_table[0].pad, 0, 2);
-      
    
    //Load Chroma hufftable values if needed
    if(yuvComp.fourcc_val != VA_FOURCC_Y800) {
@@ -180,6 +178,7 @@ void jpegenc_slice_param_init(VAEncSliceParameterBufferJPEG *slice_param, YUVCom
         slice_param->components[2].dc_table_selector = 1;
         slice_param->components[2].ac_table_selector = 1;        
     }
+ 
 }
 
 
@@ -228,8 +227,8 @@ void populate_frame_header(JPEGFrameHeader *frameHdr, YUVComponentSpecs yuvComp,
         } else {
             //Analyzing the sampling factors for U/V, they are 1 for all formats except for Y8. 
             //So, it is okay to have the code below like this. For Y8, we wont reach this code.
-            frameHdr->JPEGComponent[i].Hi = 1;  
-            frameHdr->JPEGComponent[i].Vi = 1;
+            frameHdr->JPEGComponent[i].Hi = yuvComp.u_h_subsample;  
+            frameHdr->JPEGComponent[i].Vi = yuvComp.u_v_subsample;
             frameHdr->JPEGComponent[i].Tqi = 1;
         }
     }
@@ -301,7 +300,7 @@ void populate_scan_header(JPEGScanHeader *scanHdr, YUVComponentSpecs yuvComp)
         scanHdr->ScanComponent[2].Tdj = 1;
         scanHdr->ScanComponent[2].Taj = 1;
     }
-    
+ 
     scanHdr->Ss = 0;  //0 for Baseline
     scanHdr->Se = 63; //63 for Baseline
     scanHdr->Ah = 0;  //0 for Baseline
@@ -384,7 +383,7 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
 
     //Add HuffTable AC and DC for Y,U/V components
     JPEGHuffSection acHuffSectionHdr, dcHuffSectionHdr;
-        
+
     for(i=0; (i<yuvComp.num_components && (i<=1)); i++) {
         //Add DC component (Tc = 0)
         populate_huff_section_header(&dcHuffSectionHdr, i, 0); 
@@ -416,6 +415,8 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
             bitstream_put_ui(&bs, acHuffSectionHdr.Vij[j], 8);
         }
 
+        if((yuvComp.fourcc_val == VA_FOURCC_Y800) )
+            break;
     }
     
     //Add Restart Interval if restart_interval is not 0
@@ -455,21 +456,24 @@ int build_packed_jpeg_header_buffer(unsigned char **header_buffer, YUVComponentS
     return bs.bit_offset;
 }
 
+
 //Upload the yuv image from the file to the VASurface
 void upload_yuv_to_surface(VADisplay va_dpy, FILE *yuv_fp, VASurfaceID surface_id, YUVComponentSpecs yuvComp, int picture_width, int picture_height, int frame_size)
 {
-
     VAImage surface_image;
     VAStatus va_status;
     void *surface_p = NULL;
     unsigned char newImageBuffer[frame_size];
     unsigned char *y_src, *u_src, *v_src;
-    unsigned char *y_dst, *u_dst, *v_dst;
+    unsigned char *y_dst, *u_dst;
     int y_size = picture_width * picture_height;
-    int u_size = (picture_width >> 1) * (picture_height >> 1);
+    int u_size = 0;
     int row, col;
     size_t n_items;
-    
+
+    //u_size is used for I420, NV12 formats only
+    u_size = ((picture_width >> 1) * (picture_height >> 1));
+
     memset(newImageBuffer,0,frame_size);
     do {
         n_items = fread(newImageBuffer, frame_size, 1, yuv_fp);
@@ -487,89 +491,60 @@ void upload_yuv_to_surface(VADisplay va_dpy, FILE *yuv_fp, VASurfaceID surface_i
 
     y_dst = surface_p + surface_image.offsets[0];
     u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */
-    v_dst = surface_p + surface_image.offsets[2];
 
-    /* Y plane */
-    for (row = 0; row < surface_image.height; row++) {
-        memcpy(y_dst, y_src, surface_image.width);
-        y_dst += surface_image.pitches[0];
-        y_src += picture_width;
-    }
+    if((yuvComp.fourcc_val == VA_FOURCC_NV12) || (yuvComp.fourcc_val == VA_FOURCC_I420) || 
+       (yuvComp.fourcc_val == VA_FOURCC_Y800) ) {
 
-    if(yuvComp.num_components > 1 ) {
+        /* Y plane */
+        for (row = 0; row < surface_image.height; row++) {
+            memcpy(y_dst, y_src, surface_image.width);
+            y_dst += surface_image.pitches[0];
+            y_src += picture_width;
+        }
         
-        switch(yuvComp.fourcc_val) {
-            
-            case VA_FOURCC_NV12: {
-                for (row = 0; row < surface_image.height/2; row++) {
-                    memcpy(u_dst, u_src, surface_image.width);
-                    u_dst += surface_image.pitches[1];
-                    u_src += (picture_width);
-                }
-                break;
-            }
-
-            case VA_FOURCC_I420: {
-                for (row = 0; row < surface_image.height / 2; row++) {
-                    for (col = 0; col < surface_image.width / 2; col++) {
-                    u_dst[col * 2] = u_src[col];
-                    u_dst[col * 2 + 1] = v_src[col];
-                    }  
-
-                    u_dst += surface_image.pitches[1];
-                    u_src += (picture_width / 2);
-                    v_src += (picture_width / 2);
+        if(yuvComp.num_components > 1) {
+
+            switch(yuvComp.fourcc_val) {
+                case VA_FOURCC_NV12: {
+                    for (row = 0; row < surface_image.height/2; row++) {
+                        memcpy(u_dst, u_src, surface_image.width);
+                        u_dst += surface_image.pitches[1];
+                        u_src += (picture_width);
+                    }
+                    break;
                 }
 
-                break;
-            }
-    
-            //TO DO: Code for below formats needs to be fixed.
-            //This will come as enhancement to the feature.        
-            case VA_FOURCC_UYVY:
-            case VA_FOURCC_YUY2: {
-                const int U = 1;
-                const int V = 2;
-
-                u_dst = surface_p + surface_image.offsets[U];
-                v_dst = surface_p + surface_image.offsets[V];
-
-                for (row = 0; row < surface_image.height / 2; row++) {
-                    memcpy(u_dst, u_src, surface_image.width / 2);
-                    memcpy(v_dst, v_src, surface_image.width / 2);
-                    u_dst += surface_image.pitches[U];
-                    v_dst += surface_image.pitches[V];
-                    u_src += (picture_width / 2);
-                    v_src += (picture_width / 2);
+                case VA_FOURCC_I420: {
+                    for (row = 0; row < surface_image.height / 2; row++) {
+                        for (col = 0; col < surface_image.width / 2; col++) {
+                             u_dst[col * 2] = u_src[col];
+                             u_dst[col * 2 + 1] = v_src[col];
+                         }  
+
+                         u_dst += surface_image.pitches[1];
+                         u_src += (picture_width / 2);
+                         v_src += (picture_width / 2);
+                    }
+                    break;
                 }
+            }//end of switch
+       }//end of if check
+    } else if((yuvComp.fourcc_val == VA_FOURCC_UYVY) || (yuvComp.fourcc_val == VA_FOURCC_YUY2)) {
+                
+        for(row = 0; row < surface_image.height; row++) {
+            memcpy(y_dst, y_src, surface_image.width*2);
+            y_dst += surface_image.pitches[0];
+            y_src += picture_width*2;
+        }
              
-                break;
-            }
-            
-            case VA_FOURCC_444P: {
-                const int U = 1;
-                const int V = 2;
-
-                u_dst = surface_p + surface_image.offsets[U];
-                v_dst = surface_p + surface_image.offsets[V];
-
-                for (row = 0; row < surface_image.height; row++) {
-                    memcpy(u_dst, u_src, surface_image.width);
-                    memcpy(v_dst, v_src, surface_image.width);
-                    u_dst += surface_image.pitches[U];
-                    v_dst += surface_image.pitches[V];
-                    u_src += (picture_width);
-                    v_src += (picture_width);
-                }
-                break;
-            }
-            
-            default: {
-                //processing like Y8   
-                break;
-            }
-        } //end of switch
-    } //end of if
+    } else if(yuvComp.fourcc_val == VA_FOURCC_RGBA) {
+
+        for (row = 0; row < surface_image.height; row++) {
+            memcpy(y_dst, y_src, surface_image.width*4);
+            y_dst += surface_image.pitches[0];
+            y_src += picture_width*4;
+        }
+    }
     
     vaUnmapBuffer(va_dpy, surface_image.buf);
     vaDestroyImage(va_dpy, surface_image.image_id);
@@ -581,7 +556,7 @@ void upload_yuv_to_surface(VADisplay va_dpy, FILE *yuv_fp, VASurfaceID surface_i
 void init_yuv_component(YUVComponentSpecs *yuvComponent, int yuv_type, int *surface_type, VASurfaceAttrib *fourcc)
 {
     
-    //<fourcc value 0(NV12)/1(UYVY)/2(YUY2)/3(Y8)/4(RGB)>     
+    //<fourcc value 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)>     
     switch(yuv_type)
     {
         case 0 :   //I420
@@ -634,7 +609,7 @@ void init_yuv_component(YUVComponentSpecs *yuvComponent, int yuv_type, int *surf
             yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_Y800;
             yuvComponent->num_components = 1;
             yuvComponent->y_h_subsample = 1;
-            yuvComponent->y_v_subsample = 0;
+            yuvComponent->y_v_subsample = 1;
             yuvComponent->u_h_subsample = 0;
             yuvComponent->u_v_subsample = 0;
             yuvComponent->v_h_subsample = 0;
@@ -642,9 +617,9 @@ void init_yuv_component(YUVComponentSpecs *yuvComponent, int yuv_type, int *surf
             break;
         }
         
-        case 5: { //RGB or YUV444
-            yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_YUV444;
-            yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_444P;
+        case 5: { //RGBA 
+            yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_RGB32;
+            yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_RGBA;
             yuvComponent->num_components = 3;
             yuvComponent->y_h_subsample = 1;
             yuvComponent->y_v_subsample = 1;
@@ -654,7 +629,7 @@ void init_yuv_component(YUVComponentSpecs *yuvComponent, int yuv_type, int *surf
             yuvComponent->v_v_subsample = 1;
             break;
         }
-        
+
         default: {
             printf("Unsupported format:\n");
             show_help();
@@ -723,7 +698,7 @@ int encode_input_image(FILE *yuv_fp, FILE *jpeg_fp, int picture_width, int pictu
     vaGetConfigAttributes(va_dpy, VAProfileJPEGBaseline, VAEntrypointEncPicture, &attrib[0], 2);
 
     // RT should be one of below.
-    if(!((attrib[0].value & VA_RT_FORMAT_YUV420) || (attrib[0].value & VA_RT_FORMAT_YUV422) 
+    if(!((attrib[0].value & VA_RT_FORMAT_YUV420) || (attrib[0].value & VA_RT_FORMAT_YUV422) || (attrib[0].value & VA_RT_FORMAT_RGB32) 
         ||(attrib[0].value & VA_RT_FORMAT_YUV444) || (attrib[0].value & VA_RT_FORMAT_YUV400))) 
     {
         /* Did not find the supported RT format */
@@ -935,7 +910,7 @@ int main(int argc, char *argv[])
     fseeko(yuv_fp, (off_t)0, SEEK_END);
     file_size = ftello(yuv_fp);
     
-    //<input file type: 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGB)>     
+    //<input file type: 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)>     
     switch(yuv_type)
     {
         case 0 :   //I420 
@@ -955,8 +930,8 @@ int main(int argc, char *argv[])
             break;
         }
         
-        case 5: { //RGB or YUV444
-            frame_size = 3 * (picture_width * picture_height) ;
+        case 5: { //RGBA
+            frame_size = 4 * (picture_width * picture_height) ;
             break;
         }
         
@@ -970,7 +945,7 @@ int main(int argc, char *argv[])
     
     if ( (file_size < frame_size) || (file_size % frame_size) ) {
         fclose(yuv_fp);
-        printf("The YUV file's size is not correct\n");
+        printf("The YUV file's size is not correct: file_size=%zd, frame_size=%d\n", file_size, frame_size);
         return -1;
     }
     
diff --git a/test/encode/jpegenc_utils.h b/test/encode/jpegenc_utils.h
index ce6a476..e003c7e 100644
--- a/test/encode/jpegenc_utils.h
+++ b/test/encode/jpegenc_utils.h
@@ -330,11 +330,11 @@ uint8_t jpeg_hufftable_chroma_ac[] = {
 };
 
 typedef struct _YUVComponentSpecs {
-    //One of 0(NV12)/1(UYVY)/2(YUY2)/3(Y8)/4(RGB)>
+    //One of 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)>
     unsigned int yuv_type;
-    // One of VA_RT_FORMAT_YUV420, VA_RT_FORMAT_YUV422, VA_RT_FORMAT_YUV400, VA_RT_FORMAT_YUV444
+    // One of VA_RT_FORMAT_YUV420, VA_RT_FORMAT_YUV422, VA_RT_FORMAT_YUV400, VA_RT_FORMAT_YUV444, VA_RT_FORMAT_RGB32
     unsigned int va_surface_format;
-    //One of VA_FOURCC_I420, VA_FOURCC_NV12, VA_FOURCC_UYVY, VA_FOURCC_YUY2, VA_FOURCC_Y800, VA_FOURCC_444P
+    //One of VA_FOURCC_I420, VA_FOURCC_NV12, VA_FOURCC_UYVY, VA_FOURCC_YUY2, VA_FOURCC_Y800, VA_FOURCC_444P, VA_FOURCC_RGBA
     unsigned int fourcc_val; //Using this field to evaluate the input file type.
     //no.of. components
     unsigned int num_components;
-- 
2.1.0



More information about the Libva mailing list