[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