[Libva] [PATCH] JPEG Encode: Added support for UYVY/YUY2/Y8 formats
Xiang, Haihao
haihao.xiang at intel.com
Sat Dec 13 06:24:45 PST 2014
Applied
Thanks
Haihao
>-----Original Message-----
>From: Libva [mailto:libva-bounces at lists.freedesktop.org] On Behalf Of Sirisha
>Muppavarapu
>Sent: Wednesday, December 10, 2014 5:11 AM
>To: Muppavarapu, Sirisha; libva at lists.freedesktop.org
>Subject: [Libva] [PATCH] JPEG Encode: Added support for UYVY/YUY2/Y8
>formats
>
>---
> 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
>
>_______________________________________________
>Libva mailing list
>Libva at lists.freedesktop.org
>http://lists.freedesktop.org/mailman/listinfo/libva
More information about the Libva
mailing list