summaryrefslogtreecommitdiff
path: root/test/encode/jpegenc.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/encode/jpegenc.c')
-rw-r--r--test/encode/jpegenc.c1001
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;
-}
-