diff options
Diffstat (limited to 'test/encode/jpegenc.c')
-rw-r--r-- | test/encode/jpegenc.c | 1001 |
1 files changed, 0 insertions, 1001 deletions
diff --git a/test/encode/jpegenc.c b/test/encode/jpegenc.c deleted file mode 100644 index b68bb2e..0000000 --- a/test/encode/jpegenc.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * Copyright (c) 2014 Intel Corporation. All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sub license, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR - * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -/* - * 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(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> -#include <string.h> -#include <stdlib.h> -#include <getopt.h> -#include <unistd.h> - -#include <sys/time.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> -#include <assert.h> -#include <time.h> - -#include <pthread.h> - -#include <va/va.h> -#include <va/va_enc_jpeg.h> -#include "va_display.h" -#include "jpegenc_utils.h" - -#ifndef VA_FOURCC_I420 -#define VA_FOURCC_I420 0x30323449 -#endif - -#define CHECK_VASTATUS(va_status,func) \ - if (va_status != VA_STATUS_SUCCESS) { \ - fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \ - exit(1); \ - } - - -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(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; -} - - -void jpegenc_pic_param_init(VAEncPictureParameterBufferJPEG *pic_param,int width,int height,int quality, YUVComponentSpecs yuvComp) -{ - assert(pic_param); - - pic_param->picture_width = width; - pic_param->picture_height = height; - pic_param->quality = quality; - - pic_param->pic_flags.bits.profile = 0; //Profile = Baseline - pic_param->pic_flags.bits.progressive = 0; //Sequential encoding - pic_param->pic_flags.bits.huffman = 1; //Uses Huffman coding - pic_param->pic_flags.bits.interleaved = 0; //Input format is interleaved (YUV) - pic_param->pic_flags.bits.differential = 0; //non-Differential Encoding - - pic_param->sample_bit_depth = 8; //only 8 bit sample depth is currently supported - pic_param->num_scan = 1; - pic_param->num_components = yuvComp.num_components; // Supporting only upto 3 components maximum - //set component_id Ci and Tqi - if(yuvComp.fourcc_val == VA_FOURCC_Y800) { - pic_param->component_id[0] = 0; - pic_param->quantiser_table_selector[0] = 0; - } 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->quality = quality; -} - -void jpegenc_qmatrix_init(VAQMatrixBufferJPEG *quantization_param, YUVComponentSpecs yuvComp) -{ - int i=0; - quantization_param->load_lum_quantiser_matrix = 1; - - //LibVA expects the QM in zigzag order - for(i=0; i<NUM_QUANT_ELEMENTS; i++) { - quantization_param->lum_quantiser_matrix[i] = jpeg_luma_quant[jpeg_zigzag[i]]; - } - - - if(yuvComp.fourcc_val == VA_FOURCC_Y800) { - quantization_param->load_chroma_quantiser_matrix = 0; - } else { - quantization_param->load_chroma_quantiser_matrix = 1; - for(i=0; i<NUM_QUANT_ELEMENTS; i++) { - quantization_param->chroma_quantiser_matrix[i] = jpeg_chroma_quant[jpeg_zigzag[i]]; - } - } - -} - -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 { - hufftable_param->load_huffman_table[1] = 1; //Load Chroma Hufftable for other formats - } - - //Load Luma hufftable values - //Load DC codes - memcpy(hufftable_param->huffman_table[0].num_dc_codes, jpeg_hufftable_luma_dc+1, 16); - //Load DC Values - memcpy(hufftable_param->huffman_table[0].dc_values, jpeg_hufftable_luma_dc+17, 12); - //Load AC codes - memcpy(hufftable_param->huffman_table[0].num_ac_codes, jpeg_hufftable_luma_ac+1, 16); - //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) { - //Load DC codes - memcpy(hufftable_param->huffman_table[1].num_dc_codes, jpeg_hufftable_chroma_dc+1, 16); - //Load DC Values - memcpy(hufftable_param->huffman_table[1].dc_values, jpeg_hufftable_chroma_dc+17, 12); - //Load AC codes - memcpy(hufftable_param->huffman_table[1].num_ac_codes, jpeg_hufftable_chroma_ac+1, 16); - //Load AC Values - memcpy(hufftable_param->huffman_table[1].ac_values, jpeg_hufftable_chroma_ac+17, 162); - memset(hufftable_param->huffman_table[1].pad, 0, 2); - - } - -} - -void jpegenc_slice_param_init(VAEncSliceParameterBufferJPEG *slice_param, YUVComponentSpecs yuvComp) -{ - slice_param->restart_interval = 0; - - slice_param->num_components = yuvComp.num_components; - - slice_param->components[0].component_selector = 1; - slice_param->components[0].dc_table_selector = 0; - slice_param->components[0].ac_table_selector = 0; - - if(yuvComp.num_components > 1) { - slice_param->components[1].component_selector = 2; - slice_param->components[1].dc_table_selector = 1; - slice_param->components[1].ac_table_selector = 1; - - slice_param->components[2].component_selector = 3; - slice_param->components[2].dc_table_selector = 1; - slice_param->components[2].ac_table_selector = 1; - } -} - - -void populate_quantdata(JPEGQuantSection *quantVal, int type) -{ - uint8_t zigzag_qm[NUM_QUANT_ELEMENTS]; - int i; - - quantVal->DQT = DQT; - quantVal->Pq = 0; - quantVal->Tq = type; - if(type == 0) { - for(i=0; i<NUM_QUANT_ELEMENTS; i++) { - zigzag_qm[i] = jpeg_luma_quant[jpeg_zigzag[i]]; - } - - memcpy(quantVal->Qk, zigzag_qm, NUM_QUANT_ELEMENTS); - } else { - for(i=0; i<NUM_QUANT_ELEMENTS; i++) { - zigzag_qm[i] = jpeg_chroma_quant[jpeg_zigzag[i]]; - } - memcpy(quantVal->Qk, zigzag_qm, NUM_QUANT_ELEMENTS); - } - quantVal->Lq = 3 + NUM_QUANT_ELEMENTS; -} - -void populate_frame_header(JPEGFrameHeader *frameHdr, YUVComponentSpecs yuvComp, int picture_width, int picture_height) -{ - int i=0; - - frameHdr->SOF = SOF0; - frameHdr->Lf = 8 + (3 * yuvComp.num_components); //Size of FrameHeader in bytes without the Marker SOF - frameHdr->P = 8; - frameHdr->Y = picture_height; - frameHdr->X = picture_width; - frameHdr->Nf = yuvComp.num_components; - - for(i=0; i<yuvComp.num_components; i++) { - frameHdr->JPEGComponent[i].Ci = i+1; - - if(i == 0) { - frameHdr->JPEGComponent[i].Hi = yuvComp.y_h_subsample; - frameHdr->JPEGComponent[i].Vi = yuvComp.y_v_subsample; - frameHdr->JPEGComponent[i].Tqi = 0; - - } 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 = yuvComp.u_h_subsample; - frameHdr->JPEGComponent[i].Vi = yuvComp.u_v_subsample; - frameHdr->JPEGComponent[i].Tqi = 1; - } - } -} - -void populate_huff_section_header(JPEGHuffSection *huffSectionHdr, int th, int tc) -{ - int i=0, totalCodeWords=0; - - huffSectionHdr->DHT = DHT; - huffSectionHdr->Tc = tc; - huffSectionHdr->Th = th; - - if(th == 0) { //If Luma - - //If AC - if(tc == 1) { - memcpy(huffSectionHdr->Li, jpeg_hufftable_luma_ac+1, NUM_AC_RUN_SIZE_BITS); - memcpy(huffSectionHdr->Vij, jpeg_hufftable_luma_ac+17, NUM_AC_CODE_WORDS_HUFFVAL); - } - - //If DC - if(tc == 0) { - memcpy(huffSectionHdr->Li, jpeg_hufftable_luma_dc+1, NUM_DC_RUN_SIZE_BITS); - memcpy(huffSectionHdr->Vij, jpeg_hufftable_luma_dc+17, NUM_DC_CODE_WORDS_HUFFVAL); - } - - for(i=0; i<NUM_AC_RUN_SIZE_BITS; i++) { - totalCodeWords += huffSectionHdr->Li[i]; - } - - huffSectionHdr->Lh = 3 + 16 + totalCodeWords; - - } else { //If Chroma - //If AC - if(tc == 1) { - memcpy(huffSectionHdr->Li, jpeg_hufftable_chroma_ac+1, NUM_AC_RUN_SIZE_BITS); - memcpy(huffSectionHdr->Vij, jpeg_hufftable_chroma_ac+17, NUM_AC_CODE_WORDS_HUFFVAL); - } - - //If DC - if(tc == 0) { - memcpy(huffSectionHdr->Li, jpeg_hufftable_chroma_dc+1, NUM_DC_RUN_SIZE_BITS); - memcpy(huffSectionHdr->Vij, jpeg_hufftable_chroma_dc+17, NUM_DC_CODE_WORDS_HUFFVAL); - } - - } -} - -void populate_scan_header(JPEGScanHeader *scanHdr, YUVComponentSpecs yuvComp) -{ - - scanHdr->SOS = SOS; - scanHdr->Ns = yuvComp.num_components; - - //Y Component - scanHdr->ScanComponent[0].Csj = 1; - scanHdr->ScanComponent[0].Tdj = 0; - scanHdr->ScanComponent[0].Taj = 0; - - if(yuvComp.num_components > 1) { - //U Component - scanHdr->ScanComponent[1].Csj = 2; - scanHdr->ScanComponent[1].Tdj = 1; - scanHdr->ScanComponent[1].Taj = 1; - - //V Component - scanHdr->ScanComponent[2].Csj = 3; - 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 - scanHdr->Al = 0; //0 for Baseline - - scanHdr->Ls = 3 + (yuvComp.num_components * 2) + 3; - -} - -// 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); - - //Add SOI - bitstream_put_ui(&bs, SOI, 16); - - //Add AppData - bitstream_put_ui(&bs, APP0, 16); //APP0 marker - bitstream_put_ui(&bs, 16, 16); //Length excluding the marker - bitstream_put_ui(&bs, 0x4A, 8); //J - bitstream_put_ui(&bs, 0x46, 8); //F - bitstream_put_ui(&bs, 0x49, 8); //I - bitstream_put_ui(&bs, 0x46, 8); //F - bitstream_put_ui(&bs, 0x00, 8); //0 - bitstream_put_ui(&bs, 1, 8); //Major Version - bitstream_put_ui(&bs, 1, 8); //Minor Version - bitstream_put_ui(&bs, 1, 8); //Density units 0:no units, 1:pixels per inch, 2: pixels per cm - bitstream_put_ui(&bs, 72, 16); //X density - 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 - quality = (quality < 50) ? (5000/quality) : (200 - (quality*2)); - - //Add QTable - Y - JPEGQuantSection quantLuma; - populate_quantdata(&quantLuma, 0); - - bitstream_put_ui(&bs, quantLuma.DQT, 16); - bitstream_put_ui(&bs, quantLuma.Lq, 16); - 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); - } - - //Add QTable - U/V - if(yuvComp.fourcc_val != VA_FOURCC_Y800) { - JPEGQuantSection quantChroma; - populate_quantdata(&quantChroma, 1); - - bitstream_put_ui(&bs, quantChroma.DQT, 16); - bitstream_put_ui(&bs, quantChroma.Lq, 16); - 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); - } - } - - //Add FrameHeader - JPEGFrameHeader frameHdr; - memset(&frameHdr,0,sizeof(JPEGFrameHeader)); - populate_frame_header(&frameHdr, yuvComp, picture_width, picture_height); - - bitstream_put_ui(&bs, frameHdr.SOF, 16); - bitstream_put_ui(&bs, frameHdr.Lf, 16); - bitstream_put_ui(&bs, frameHdr.P, 8); - bitstream_put_ui(&bs, frameHdr.Y, 16); - bitstream_put_ui(&bs, frameHdr.X, 16); - bitstream_put_ui(&bs, frameHdr.Nf, 8); - for(i=0; i<frameHdr.Nf;i++) { - bitstream_put_ui(&bs, frameHdr.JPEGComponent[i].Ci, 8); - bitstream_put_ui(&bs, frameHdr.JPEGComponent[i].Hi, 4); - bitstream_put_ui(&bs, frameHdr.JPEGComponent[i].Vi, 4); - bitstream_put_ui(&bs, frameHdr.JPEGComponent[i].Tqi, 8); - } - - //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); - - bitstream_put_ui(&bs, dcHuffSectionHdr.DHT, 16); - bitstream_put_ui(&bs, dcHuffSectionHdr.Lh, 16); - bitstream_put_ui(&bs, dcHuffSectionHdr.Tc, 4); - bitstream_put_ui(&bs, dcHuffSectionHdr.Th, 4); - for(j=0; j<NUM_DC_RUN_SIZE_BITS; j++) { - bitstream_put_ui(&bs, dcHuffSectionHdr.Li[j], 8); - } - - for(j=0; j<NUM_DC_CODE_WORDS_HUFFVAL; j++) { - bitstream_put_ui(&bs, dcHuffSectionHdr.Vij[j], 8); - } - - //Add AC component (Tc = 1) - populate_huff_section_header(&acHuffSectionHdr, i, 1); - - bitstream_put_ui(&bs, acHuffSectionHdr.DHT, 16); - bitstream_put_ui(&bs, acHuffSectionHdr.Lh, 16); - bitstream_put_ui(&bs, acHuffSectionHdr.Tc, 4); - bitstream_put_ui(&bs, acHuffSectionHdr.Th, 4); - for(j=0; j<NUM_AC_RUN_SIZE_BITS; j++) { - bitstream_put_ui(&bs, acHuffSectionHdr.Li[j], 8); - } - - for(j=0; j<NUM_AC_CODE_WORDS_HUFFVAL; j++) { - 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 - if(restart_interval != 0) { - JPEGRestartSection restartHdr; - restartHdr.DRI = DRI; - restartHdr.Lr = 4; - restartHdr.Ri = restart_interval; - - bitstream_put_ui(&bs, restartHdr.DRI, 16); - bitstream_put_ui(&bs, restartHdr.Lr, 16); - bitstream_put_ui(&bs, restartHdr.Ri, 16); - } - - //Add ScanHeader - JPEGScanHeader scanHdr; - populate_scan_header(&scanHdr, yuvComp); - - bitstream_put_ui(&bs, scanHdr.SOS, 16); - bitstream_put_ui(&bs, scanHdr.Ls, 16); - bitstream_put_ui(&bs, scanHdr.Ns, 8); - - for(i=0; i<scanHdr.Ns; i++) { - bitstream_put_ui(&bs, scanHdr.ScanComponent[i].Csj, 8); - bitstream_put_ui(&bs, scanHdr.ScanComponent[i].Tdj, 4); - bitstream_put_ui(&bs, scanHdr.ScanComponent[i].Taj, 4); - } - - bitstream_put_ui(&bs, scanHdr.Ss, 8); - bitstream_put_ui(&bs, scanHdr.Se, 8); - bitstream_put_ui(&bs, scanHdr.Ah, 4); - bitstream_put_ui(&bs, scanHdr.Al, 4); - - bitstream_end(&bs); - *header_buffer = (unsigned char *)bs.buffer; - - 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; - int y_size = picture_width * picture_height; - 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); - } while (n_items != 1); - - va_status = vaDeriveImage(va_dpy, surface_id, &surface_image); - CHECK_VASTATUS(va_status,"vaDeriveImage"); - - vaMapBuffer(va_dpy, surface_image.buf, &surface_p); - assert(VA_STATUS_SUCCESS == va_status); - - y_src = newImageBuffer; - u_src = newImageBuffer + y_size; /* UV offset for NV12 */ - v_src = newImageBuffer + y_size + u_size; - - y_dst = surface_p + surface_image.offsets[0]; - u_dst = surface_p + surface_image.offsets[1]; /* UV offset for NV12 */ - - if((yuvComp.fourcc_val == VA_FOURCC_NV12) || (yuvComp.fourcc_val == VA_FOURCC_I420) || - (yuvComp.fourcc_val == VA_FOURCC_Y800) ) { - - /* 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.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; - } - - 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; - } - - } 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); - -} - - - -void init_yuv_component(YUVComponentSpecs *yuvComponent, int yuv_type, int *surface_type, VASurfaceAttrib *fourcc) -{ - - //<fourcc value 0(I420)/1(NV12)/2(UYVY)/3(YUY2)/4(Y8)/5(RGBA)> - switch(yuv_type) - { - case 0 : //I420 - case 1 : { //NV12 - yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_YUV420; - if(yuv_type == 0) { - yuvComponent->fourcc_val = VA_FOURCC_I420; - fourcc->value.value.i = VA_FOURCC_NV12; - } else { - yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_NV12; - } - yuvComponent->num_components = 3; - yuvComponent->y_h_subsample = 2; - yuvComponent->y_v_subsample = 2; - yuvComponent->u_h_subsample = 1; - yuvComponent->u_v_subsample = 1; - yuvComponent->v_h_subsample = 1; - yuvComponent->v_v_subsample = 1; - break; - } - - case 2: { //UYVY - yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_YUV422; - yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_UYVY; - yuvComponent->num_components = 3; - yuvComponent->y_h_subsample = 2; - yuvComponent->y_v_subsample = 1; - yuvComponent->u_h_subsample = 1; - yuvComponent->u_v_subsample = 1; - yuvComponent->v_h_subsample = 1; - yuvComponent->v_v_subsample = 1; - break; - } - - case 3: { //YUY2 - yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_YUV422; - yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_YUY2; - yuvComponent->num_components = 3; - yuvComponent->y_h_subsample = 2; - yuvComponent->y_v_subsample = 1; - yuvComponent->u_h_subsample = 1; - yuvComponent->u_v_subsample = 1; - yuvComponent->v_h_subsample = 1; - yuvComponent->v_v_subsample = 1; - break; - } - - case 4: { //Y8 - yuvComponent->va_surface_format = (*surface_type) = VA_RT_FORMAT_YUV400; - yuvComponent->fourcc_val = fourcc->value.value.i = VA_FOURCC_Y800; - yuvComponent->num_components = 1; - yuvComponent->y_h_subsample = 1; - yuvComponent->y_v_subsample = 1; - yuvComponent->u_h_subsample = 0; - yuvComponent->u_v_subsample = 0; - yuvComponent->v_h_subsample = 0; - yuvComponent->v_v_subsample = 0; - break; - } - - 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; - yuvComponent->u_h_subsample = 1; - yuvComponent->u_v_subsample = 1; - yuvComponent->v_h_subsample = 1; - yuvComponent->v_v_subsample = 1; - break; - } - - default: { - printf("Unsupported format:\n"); - show_help(); - break; - } - - } - -} - -int encode_input_image(FILE *yuv_fp, FILE *jpeg_fp, int picture_width, int picture_height, int frame_size, int yuv_type, int quality) -{ - int num_entrypoints,enc_entrypoint; - int major_ver, minor_ver; - int surface_type; - VAEntrypoint entrypoints[5]; - VASurfaceAttrib fourcc; - VAConfigAttrib attrib[2]; - VADisplay va_dpy; - VAStatus va_status; - VAConfigID config_id; - VASurfaceID surface_id; - VAContextID context_id; - VABufferID pic_param_buf_id; /* Picture parameter id*/ - VABufferID slice_param_buf_id; /* Slice parameter id, only 1 slice per frame in jpeg encode */ - VABufferID codedbuf_buf_id; /* Output buffer id, compressed data */ - VABufferID packed_raw_header_param_buf_id; /* Header parameter buffer id */ - VABufferID packed_raw_header_buf_id; /* Header buffer id */ - VABufferID qmatrix_buf_id; /* Quantization Matrix id */ - VABufferID huffmantable_buf_id; /* Huffman table id*/ - VAEncPictureParameterBufferJPEG pic_param; /* Picture parameter buffer */ - VAEncSliceParameterBufferJPEG slice_param; /* Slice parameter buffer */ - VAQMatrixBufferJPEG quantization_param; /* Quantization Matrix buffer */ - VAHuffmanTableBufferJPEGBaseline hufftable_param; /* Huffmantable buffer */ - YUVComponentSpecs yuvComponent; - int writeToFile = 1; - - //Clamp the quality factor value to [1,100] - if(quality >= 100) quality=100; - if(quality <= 0) quality=1; - - fourcc.type =VASurfaceAttribPixelFormat; - fourcc.flags=VA_SURFACE_ATTRIB_SETTABLE; - fourcc.value.type=VAGenericValueTypeInteger; - - init_yuv_component(&yuvComponent, yuv_type, &surface_type, &fourcc); - - /* 1. Initialize the va driver */ - va_dpy = va_open_display(); - va_status = vaInitialize(va_dpy, &major_ver, &minor_ver); - assert(va_status == VA_STATUS_SUCCESS); - - /* 2. Query for the entrypoints for the JPEGBaseline profile */ - va_status = vaQueryConfigEntrypoints(va_dpy, VAProfileJPEGBaseline, entrypoints, &num_entrypoints); - CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); - // We need picture level encoding (VAEntrypointEncPicture). Find if it is supported. - for (enc_entrypoint = 0; enc_entrypoint < num_entrypoints; enc_entrypoint++) { - if (entrypoints[enc_entrypoint] == VAEntrypointEncPicture) - break; - } - if (enc_entrypoint == num_entrypoints) { - /* No JPEG Encode (VAEntrypointEncPicture) entry point found */ - assert(0); - } - - /* 3. Query for the Render Target format supported */ - attrib[0].type = VAConfigAttribRTFormat; - attrib[1].type = VAConfigAttribEncJPEG; - 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) || (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 */ - assert(0); - } - - VAConfigAttribValEncJPEG jpeg_attrib_val; - jpeg_attrib_val.value = attrib[1].value; - - /* Set JPEG profile attribs */ - jpeg_attrib_val.bits.arithmatic_coding_mode = 0; - jpeg_attrib_val.bits.progressive_dct_mode = 0; - jpeg_attrib_val.bits.non_interleaved_mode = 1; - jpeg_attrib_val.bits.differential_mode = 0; - - attrib[1].value = jpeg_attrib_val.value; - - /* 4. Create Config for the profile=VAProfileJPEGBaseline, entrypoint=VAEntrypointEncPicture, - * with RT format attribute */ - va_status = vaCreateConfig(va_dpy, VAProfileJPEGBaseline, VAEntrypointEncPicture, - &attrib[0], 2, &config_id); - CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints"); - - /* 5. Create Surface for the input picture */ - va_status = vaCreateSurfaces(va_dpy, surface_type, picture_width, picture_height, - &surface_id, 1, &fourcc, 1); - CHECK_VASTATUS(va_status, "vaCreateSurfaces"); - - //Map the input yuv file to the input surface created with the surface_id - upload_yuv_to_surface(va_dpy, yuv_fp, surface_id, yuvComponent, picture_width, picture_height, frame_size); - - /* 6. Create Context for the encode pipe*/ - va_status = vaCreateContext(va_dpy, config_id, picture_width, picture_height, - VA_PROGRESSIVE, &surface_id, 1, &context_id); - CHECK_VASTATUS(va_status, "vaCreateContext"); - - /* Create buffer for Encoded data to be stored */ - va_status = vaCreateBuffer(va_dpy, context_id, VAEncCodedBufferType, - frame_size, 1, NULL, &codedbuf_buf_id); - CHECK_VASTATUS(va_status,"vaCreateBuffer"); - - //Initialize the picture parameter buffer - pic_param.coded_buf = codedbuf_buf_id; - jpegenc_pic_param_init(&pic_param, picture_width, picture_height, quality, yuvComponent); - - /* 7. Create buffer for the picture parameter */ - va_status = vaCreateBuffer(va_dpy, context_id, VAEncPictureParameterBufferType, - sizeof(VAEncPictureParameterBufferJPEG), 1, &pic_param, &pic_param_buf_id); - CHECK_VASTATUS(va_status,"vaCreateBuffer"); - - //Load the QMatrix - jpegenc_qmatrix_init(&quantization_param, yuvComponent); - - /* 8. Create buffer for Quantization Matrix */ - va_status = vaCreateBuffer(va_dpy, context_id, VAQMatrixBufferType, - sizeof(VAQMatrixBufferJPEG), 1, &quantization_param, &qmatrix_buf_id); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - //Load the Huffman Tables - jpegenc_hufftable_init(&hufftable_param, yuvComponent); - - /* 9. Create buffer for Huffman Tables */ - va_status = vaCreateBuffer(va_dpy, context_id, VAHuffmanTableBufferType, - sizeof(VAHuffmanTableBufferJPEGBaseline), 1, &hufftable_param, &huffmantable_buf_id); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - //Initialize the slice parameter buffer - jpegenc_slice_param_init(&slice_param, yuvComponent); - - /* 10. Create buffer for slice parameter */ - va_status = vaCreateBuffer(va_dpy, context_id, VAEncSliceParameterBufferType, - sizeof(slice_param), 1, &slice_param, &slice_param_buf_id); - CHECK_VASTATUS(va_status, "vaCreateBuffer"); - - //Pack headers and send using Raw data buffer - VAEncPackedHeaderParameterBuffer packed_header_param_buffer; - 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, quality); - packed_header_param_buffer.type = VAEncPackedHeaderRawData; - packed_header_param_buffer.bit_length = length_in_bits; - packed_header_param_buffer.has_emulation_bytes = 0; - - /* 11. Create raw buffer for header */ - va_status = vaCreateBuffer(va_dpy, - context_id, - VAEncPackedHeaderParameterBufferType, - sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer, - &packed_raw_header_param_buf_id); - CHECK_VASTATUS(va_status,"vaCreateBuffer"); - - va_status = vaCreateBuffer(va_dpy, - context_id, - VAEncPackedHeaderDataBufferType, - (length_in_bits + 7) / 8, 1, packed_header_buffer, - &packed_raw_header_buf_id); - CHECK_VASTATUS(va_status,"vaCreateBuffer"); - - /* 12. Begin picture */ - va_status = vaBeginPicture(va_dpy, context_id, surface_id); - CHECK_VASTATUS(va_status, "vaBeginPicture"); - - /* 13. Render picture for all the VA buffers created */ - va_status = vaRenderPicture(va_dpy,context_id, &pic_param_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va_dpy,context_id, &qmatrix_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va_dpy,context_id, &huffmantable_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va_dpy,context_id, &packed_raw_header_param_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaRenderPicture(va_dpy,context_id, &packed_raw_header_buf_id, 1); - CHECK_VASTATUS(va_status, "vaRenderPicture"); - - va_status = vaEndPicture(va_dpy,context_id); - CHECK_VASTATUS(va_status, "vaEndPicture"); - - if (writeToFile) { - VASurfaceStatus surface_status; - size_t w_items; - VACodedBufferSegment *coded_buffer_segment; - unsigned char *coded_mem; - int slice_data_length; - - va_status = vaSyncSurface(va_dpy, surface_id); - CHECK_VASTATUS(va_status, "vaSyncSurface"); - - surface_status = 0; - va_status = vaQuerySurfaceStatus(va_dpy, surface_id, &surface_status); - CHECK_VASTATUS(va_status,"vaQuerySurfaceStatus"); - - va_status = vaMapBuffer(va_dpy, codedbuf_buf_id, (void **)(&coded_buffer_segment)); - CHECK_VASTATUS(va_status,"vaMapBuffer"); - - coded_mem = coded_buffer_segment->buf; - - if (coded_buffer_segment->status & VA_CODED_BUF_STATUS_SLICE_OVERFLOW_MASK) { - vaUnmapBuffer(va_dpy, codedbuf_buf_id); - printf("ERROR......Coded buffer too small\n"); - } - - - slice_data_length = coded_buffer_segment->size; - - do { - w_items = fwrite(coded_mem, slice_data_length, 1, jpeg_fp); - } while (w_items != 1); - - va_status = vaUnmapBuffer(va_dpy, codedbuf_buf_id); - CHECK_VASTATUS(va_status, "vaUnmapBuffer"); - } - - vaDestroyBuffer(va_dpy, pic_param_buf_id); - vaDestroyBuffer(va_dpy, qmatrix_buf_id); - vaDestroyBuffer(va_dpy, slice_param_buf_id); - vaDestroyBuffer(va_dpy, huffmantable_buf_id); - vaDestroyBuffer(va_dpy, codedbuf_buf_id); - vaDestroyBuffer(va_dpy, packed_raw_header_param_buf_id); - vaDestroyBuffer(va_dpy, packed_raw_header_buf_id); - vaDestroySurfaces(va_dpy,&surface_id,1); - vaDestroyContext(va_dpy,context_id); - vaDestroyConfig(va_dpy,config_id); - vaTerminate(va_dpy); - va_close_display(va_dpy); - - return 0; -} - - -int main(int argc, char *argv[]) -{ - FILE *yuv_fp; - FILE *jpeg_fp; - off_t file_size; - clock_t start_time, finish_time; - unsigned int duration; - unsigned int yuv_type = 0; - int quality = 0; - unsigned int picture_width = 0; - unsigned int picture_height = 0; - unsigned int frame_size = 0; - - va_init_display_args(&argc, argv); - - if(argc != 7) { - show_help(); - return -1; - } - - picture_width = atoi(argv[1]); - picture_height = atoi(argv[2]); - yuv_type = atoi(argv[5]); - quality = atoi(argv[6]); - - yuv_fp = fopen(argv[3],"rb"); - if ( yuv_fp == NULL){ - printf("Can't open input YUV file\n"); - return -1; - } - - 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(RGBA)> - switch(yuv_type) - { - case 0 : //I420 - case 1 : { //NV12 - frame_size = picture_width * picture_height + ((picture_width * picture_height) >> 1) ; - break; - } - - case 2: //UYVY - case 3: { //YUY2 - frame_size = 2 * (picture_width * picture_height); - break; - } - - case 4: { //Y8 - frame_size = picture_width * picture_height; - break; - } - - case 5: { //RGBA - frame_size = 4 * (picture_width * picture_height) ; - break; - } - - default: { - printf("Unsupported format:\n"); - show_help(); - return -1; - } - - } - - if ( (file_size < frame_size) || (file_size % frame_size) ) { - fclose(yuv_fp); - printf("The YUV file's size is not correct: file_size=%zd, frame_size=%d\n", file_size, frame_size); - return -1; - } - - fseeko(yuv_fp, (off_t)0, SEEK_SET); - - jpeg_fp = fopen(argv[4], "wb"); - if ( jpeg_fp == NULL) { - fclose(yuv_fp); - printf("Can't open output destination jpeg file\n"); - return -1; - } - - start_time = clock(); - encode_input_image(yuv_fp, jpeg_fp, picture_width, picture_height, frame_size, yuv_type, quality); - if(yuv_fp != NULL) fclose(yuv_fp); - if(jpeg_fp != NULL) fclose(jpeg_fp); - finish_time = clock(); - duration = finish_time - start_time; - printf("Encoding finished in %u ticks\n", duration); - - return 0; -} - |