summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-x[-rw-r--r--]android/Android.mk31
-rw-r--r--android/gralloc.cpp1
-rw-r--r--android/libjpeg-encoder.cpp846
-rw-r--r--android/mce.cpp48
-rwxr-xr-xandroid/skia-encoder.cpp127
-rw-r--r--utils/loadsurface_yuv.h2
-rw-r--r--vaenc/Android.mk1
-rw-r--r--vaenc/Makefile4
-rw-r--r--vaenc/hevcencode.c938
-rw-r--r--vaenc/va_encode.c11
-rw-r--r--vaenc/va_encode.h1
-rw-r--r--vaenc/vp8encode.c8
-rw-r--r--yuvtool/main.c133
13 files changed, 1828 insertions, 323 deletions
diff --git a/android/Android.mk b/android/Android.mk
index d73c075..2566382 100644..100755
--- a/android/Android.mk
+++ b/android/Android.mk
@@ -26,3 +26,34 @@ LOCAL_MODULE_TAGS := optional
include $(BUILD_EXECUTABLE)
+
+
+###### Build imageencoder ######
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ skia-encoder.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+ libcutils \
+ libutils \
+ libbinder \
+ libskia \
+ libui \
+ libgui
+
+LOCAL_MODULE:= skia-encoder
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_C_INCLUDES += \
+ external/skia/include/core \
+ external/skia/include/effects \
+ external/skia/include/images \
+ external/skia/src/ports \
+ external/skia/include/utils
+
+include $(BUILD_EXECUTABLE)
+
+###### End build imageencoder ######
diff --git a/android/gralloc.cpp b/android/gralloc.cpp
index e8cf7ee..fcffc3f 100644
--- a/android/gralloc.cpp
+++ b/android/gralloc.cpp
@@ -51,7 +51,6 @@ static GraphicBuffer *GfxBuffer[32];
extern "C" int alloc_gralloc_buffer(int num_buffers, unsigned long *buffers,
int width, int height, int linear);
#endif
-
int alloc_gralloc_buffer(int num_buffers, unsigned long *buffers,
int width, int height, int linear)
{
diff --git a/android/libjpeg-encoder.cpp b/android/libjpeg-encoder.cpp
new file mode 100644
index 0000000..d22a79f
--- /dev/null
+++ b/android/libjpeg-encoder.cpp
@@ -0,0 +1,846 @@
+/*
+ * Copyright (c) 2007-2008 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.
+ *
+ * Authors:
+ * Sun, Jing <jing.a.sun@intel.com>
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <pthread.h>
+#include "jpeglib.h"
+
+inline unsigned long long int current_time(/*bool fixed*/)
+{
+#if 0
+ if (!fixed) {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ return (((unsigned long long)tv.tv_usec+(unsigned long long)tv.tv_sec*1000000) * 1000);
+ }
+ else {
+ unsigned a, d;
+
+ __asm__ volatile("rdtsc" : "=a" (a), "=d" (d));
+ return ((unsigned long long)a) | (((unsigned long long)d) << 32);
+ }
+#endif
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return (((unsigned long long)tv.tv_usec+(unsigned long long)tv.tv_sec*1000000) * 1000);
+}
+
+#define PERF_DEF(counter) unsigned long long int COUNTER_##counter=0;
+#define PERF_START(counter, fixed) { COUNTER_##counter = current_time(); }
+#define PERF_STOP(counter, fixed) { COUNTER_##counter = current_time() - COUNTER_##counter; }
+#define PERF_SET(counter, value) { COUNTER_##counter = value; }
+#define PERF_GET(counter) (COUNTER_##counter)
+
+#define DEFAULT_THREAD_COUNT 1
+#define MAX_THREAD_COUNT 8
+#define MAX_WIDTH 65536
+#define MAX_HEIGHT 65536
+#define DEFAULT_QUALITY 80
+#define NV12_SAMPLE_SIZE 1.5
+#define NV12_COMPONENTS 3
+#define NV12_MCU_SIZE 16
+#define MAX_MCU_SIZE 1170
+#define MAX_CODED_BUFFER_SIZE(width,height) ((((((width)+15)/16)*(((height)+15)/16)* MAX_MCU_SIZE/4+1024)+0xf)&~0xf)
+
+#define HEADER_TOTAL_LEN 623
+#define HEADER_SOS_LEN 14
+#define HEADER_EOI_LEN 2
+#define HEADER_HEIGHT_POS 163
+#define HEADER_WIDTH_POS 165
+
+typedef struct {
+ struct jpeg_destination_mgr pub; /* public fields */
+ JOCTET *buffer; /* start of buffer */
+ size_t size; /* size of buffer */
+}test_dest_mgr;
+
+typedef struct {
+ unsigned int id;
+ void *source_buffer;
+ int width;
+ int height;
+ int quality;
+ int sub_height;
+ int rows;
+ void *sub_output_buffer;
+ unsigned int sub_output_size;
+}thread_parameters;
+
+static void usage(const char* pname)
+{
+ fprintf(stderr,
+ "\n USAGE: %s -source [path] -width [value] -height [value] \n"
+ " -output [path] -quality [value] -thread [value] -fix\n\n"
+ " -source: declaring the source's file path (of NV12).\n"
+ " -width: declaring the source's raw data width (0, 65536].\n"
+ " -height: declaring the source's raw data height (0, 65536].\n"
+ " -output: specifying the output JPEG's file path (.JPG or .jpg).\n"
+ " -quality (optional): setting image quality [0, 100].\n"
+ " -thread (optional): setting the encoding threads [1, 8].\n"
+ " -fix (optional): fixing CPU frequency for evaluating performance.\n\n"
+ ,pname);
+}
+
+static bool match_key (char *arg, const char *keyword, int minchars)
+{
+ register int ca, ck;
+ register int nmatched = 0;
+
+ while ((ca = *arg++) != '\0') {
+ if ((ck = *keyword++) == '\0')
+ return false; /* arg longer than keyword, mismatch */
+ if (isupper(ca)) /* force arg to lcase (assume ck is already) */
+ ca = tolower(ca);
+ if (ca != ck)
+ return false; /* mismatch */
+ nmatched++; /* count matched characters */
+ }
+
+ if (nmatched < minchars)
+ return false; /* arg shorter than keyword, mismatch */
+
+ return true; /* Match */
+}
+
+/*
+ * Convert source samples from the interleaved NV12 format to YUV411 format
+ * for Libjpeg doesn't support encoding interleaved source directly.
+ */
+static void NV12_color_convert(JSAMPLE *source, int width, int height, JSAMPLE *dest)
+{
+ int i, j;
+ JSAMPLE *source_UV = NULL;
+ JSAMPLE *dest_U = NULL;
+ JSAMPLE *dest_V = NULL;
+
+ /* Copy the luminance component directly to destination*/
+ memcpy((void *)dest, (void *)source, width*height);
+
+ /* Deinterleave then copy the chrominance components to destination*/
+ source_UV = (JSAMPLE *)((unsigned int)source + width*height);
+ dest_U = (JSAMPLE *)((unsigned int)dest + width*height);
+ dest_V = (JSAMPLE *)((unsigned int)dest_U + (width*height)/4);
+ for(i=0,j=0; i<(width*height/2); i+=2,++j) {
+ dest_U[j] = source_UV[i];
+ dest_V[j] = source_UV[i+1];
+ }
+}
+
+/*
+ * Initialize destination --- called by jpeg_start_compress
+ * before any data is actually written.
+ */
+static void init_destination (j_compress_ptr cinfo)
+{
+ test_dest_mgr *dest_mgr_ptr = (test_dest_mgr *)cinfo->dest;
+
+ dest_mgr_ptr->pub.next_output_byte = dest_mgr_ptr->buffer;
+ dest_mgr_ptr->pub.free_in_buffer = dest_mgr_ptr->size;
+}
+
+
+/*
+ * Empty the output buffer --- called whenever buffer fills up.
+ */
+static boolean empty_output_buffer (j_compress_ptr cinfo)
+{
+ test_dest_mgr *dest_mgr_ptr = (test_dest_mgr *)cinfo->dest;
+ fprintf(stderr, "The coded buffer is too small (free_in_buffer: %d)!\n", dest_mgr_ptr->pub.free_in_buffer);
+ return FALSE;
+}
+
+
+/*
+ * Terminate destination --- called by jpeg_finish_compress
+ * after all data has been written. Usually needs to flush buffer.
+ */
+static void term_destination (j_compress_ptr cinfo)
+{
+ /* Need to do nothing while term */
+}
+
+
+/*
+ * Prepare for output to a stdio stream.
+ * The caller must have already opened the stream, and is responsible
+ * for closing it after finishing compression.
+ */
+static void setup_dest_mgr (j_compress_ptr cinfo, void *buffer, unsigned int size)
+{
+ test_dest_mgr *dest_mgr_ptr;
+
+ if (cinfo->dest == NULL) { /* first time for this JPEG object? */
+ cinfo->dest = (struct jpeg_destination_mgr *)
+ (*cinfo->mem->alloc_small)((j_common_ptr)cinfo, JPOOL_PERMANENT,
+ sizeof(test_dest_mgr));
+ }
+
+ dest_mgr_ptr = (test_dest_mgr *)cinfo->dest;
+ dest_mgr_ptr->pub.init_destination = init_destination;
+ dest_mgr_ptr->pub.empty_output_buffer = empty_output_buffer;
+ dest_mgr_ptr->pub.term_destination = term_destination;
+ dest_mgr_ptr->buffer = (JOCTET *)buffer;
+ dest_mgr_ptr->size = size;
+}
+
+void *encode_thread_fn(void *arg)
+{
+ int i = 0, sub_coded_size = 0;
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW Y_row[NV12_MCU_SIZE],U_row[NV12_MCU_SIZE],V_row[NV12_MCU_SIZE];
+ JSAMPARRAY source_array[NV12_COMPONENTS];
+ int uncoded_rows = 0, current_rows = 0;
+ test_dest_mgr *dest_mgr_ptr = NULL;
+ void *current_Y = NULL, *current_U = NULL, *current_V = NULL;
+ thread_parameters *p_para = (thread_parameters *)arg;
+
+ source_array[0] = Y_row;
+ source_array[1] = U_row;
+ source_array[2] = V_row;
+
+ uncoded_rows = p_para->rows;
+
+ /* Initialize the JPEG compression object with default error handling. */
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ /* Initialize JPEG parameters */
+ cinfo.in_color_space = JCS_YCbCr;
+ cinfo.image_width = p_para->width;
+ cinfo.image_height = uncoded_rows;
+ cinfo.input_components = NV12_COMPONENTS;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, p_para->quality, TRUE); /* TRUE for forcing baseline (8-bit sample depth) */
+ cinfo.raw_data_in = TRUE;
+
+ /* Specify data destination for compression */
+ setup_dest_mgr(&cinfo, p_para->sub_output_buffer, p_para->sub_output_size);
+ dest_mgr_ptr = (test_dest_mgr *)cinfo.dest;
+
+ /* Start compressor */
+ jpeg_start_compress(&cinfo, TRUE); /* TRUE for writing tables into dest */
+
+ /* Process data */
+ current_Y = (void *)((unsigned int)p_para->source_buffer +
+ p_para->id*p_para->width*p_para->sub_height);
+ current_U = (void *)((unsigned int)p_para->source_buffer + p_para->width*p_para->height +
+ p_para->id*p_para->width*p_para->sub_height/4);
+ current_V = (void *)((unsigned int)p_para->source_buffer + p_para->width*p_para->height*5/4 +
+ p_para->id*p_para->width*p_para->sub_height/4);
+ while (uncoded_rows > 0) {
+ current_rows = (uncoded_rows > NV12_MCU_SIZE)? NV12_MCU_SIZE : uncoded_rows;
+ for (i=0; i<current_rows; ++i) {
+ Y_row[i] = (JSAMPROW)(current_Y);
+ current_Y =(void *)((unsigned int)current_Y + p_para->width);
+ }
+ for (i=0; i<(current_rows/2); ++i) {
+ U_row[i] = (JSAMPROW)(current_U);
+ V_row[i] = (JSAMPROW)(current_V);
+ current_U =(void *)((unsigned int)current_U + p_para->width/2);
+ current_V =(void *)((unsigned int)current_V + p_para->width/2);
+ }
+ jpeg_write_raw_data(&cinfo, source_array, NV12_MCU_SIZE);
+ uncoded_rows -= current_rows;
+ }
+
+ /* Finish compression */
+ jpeg_finish_compress(&cinfo);
+
+ /* Check result */
+ if (jerr.num_warnings != 0) {
+ fprintf(stderr, "Thread %d: Libjpeg outputs %ld warnings!\n", p_para->id, jerr.num_warnings);
+ sub_coded_size = -1;
+ }
+ else {
+ sub_coded_size = dest_mgr_ptr->size - dest_mgr_ptr->pub.free_in_buffer;
+ }
+
+ /* Release memory */
+ jpeg_destroy_compress(&cinfo);
+
+ pthread_exit((void *)sub_coded_size);
+ return NULL;
+}
+
+int main(int argc, char** argv)
+{
+ const char *pname = argv[0];
+ int argn;
+ char *arg;
+
+ int i, j;
+ char *source_name = NULL;
+ char *output_name = "./output.jpg";
+ //char final_output_name[128] = "\0";
+ int source_fd = -1;
+ int output_fd = -1;
+ int quality = DEFAULT_QUALITY;
+ int width = 0, height = 0;
+ int thread = DEFAULT_THREAD_COUNT;
+ unsigned int source_size = 0, output_size = 0;
+ unsigned int read_size = 0, write_size = 0;
+ void *source_buffer = NULL, *converted_source_buffer = NULL, *output_buffer = NULL;
+ unsigned char *merged_output_buffer=NULL;
+ bool fix_cpu_frequency = false;
+
+ pthread_t *encode_thread = NULL;
+ thread_parameters *encode_thread_para = NULL;
+ int *sub_coded_size = NULL;
+ bool hasError = false;
+
+ FILE *cpu_online_nr_fd = NULL, *cpu_available_max_fd = NULL, *cpu_available_min_fd = NULL;
+ FILE *cpu_scaling_max_fd = NULL, *cpu_scaling_min_fd = NULL, *cpu_cur_fd = NULL;
+ unsigned int cpu_online_nr = 0, cpu_available_max = 1000000, cpu_available_min = 0, cpu_cur = 0;
+
+ unsigned long long int convert_time = 0;
+ unsigned long long int core_encoding_time = 0;
+ unsigned long long int subpictures_merging_time = 0;
+ unsigned long long int total_time = 0;
+
+ PERF_DEF(NV12_color_convert);
+ PERF_DEF(core_encoding);
+ PERF_DEF(subpictures_merging);
+
+ double compression_rate = 0;
+
+ if (1 >= argc) {
+ usage(pname); /* No argument */
+ return 1;
+ }
+
+ for (argn = 1; argn < argc; argn++) {
+ arg = argv[argn];
+ if (*arg != '-') {
+ /* Every argument should begin with a '-' */
+ usage(pname);
+ fprintf(stderr, "Every argument should begin with a '-'!\n");
+ return 1;
+ }
+ arg++;
+
+ if (match_key(arg, "width", strlen("width"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "-width" should be followed by a specified width value*/
+ fprintf(stderr, "-width should be followed by a specified width value!\n");
+ return 1;
+ }
+
+ if ((1 != sscanf(argv[argn], "%d", &width)) || (width <= 0)) {
+ usage(pname); /* Invalid width */
+ fprintf(stderr, "Invalid width!\n");
+ return 1;
+ }
+
+ if ((width>MAX_WIDTH) || (width%2)) {
+ usage(pname); /* Unsupported width */
+ fprintf(stderr, "Unsupported width: %d!\n", width);
+ return 1;
+ }
+
+ }
+ else if (match_key(arg, "height", strlen("height"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "-height" should be followed by a specified height value*/
+ fprintf(stderr, "-height should be followed by a specified height value!\n");
+ return 1;
+ }
+
+ if ((1 != sscanf(argv[argn], "%d", &height)) || (height <= 0)) {
+ usage(pname); /* Invalid height */
+ fprintf(stderr, "Invalid height!\n");
+ return 1;
+ }
+
+ if ((height>MAX_HEIGHT) || (height%2)) {
+ usage(pname); /* Unsupported height */
+ fprintf(stderr, "Unsupported height: %d!\n", height);
+ return 1;
+ }
+ }
+ else if (match_key(arg, "source", strlen("source"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "-source" should be followed by a specified source path */
+ fprintf(stderr, "-source should be followed by a specified source path!\n");
+ return 1;
+ }
+ source_name = argv[argn];
+ }
+ else if (match_key(arg, "output", strlen("output"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "-output" should be followed by a specified output file path */
+ fprintf(stderr, "-output should be followed by a specified output file path!\n");
+ return 1;
+ }
+
+ output_name = argv[argn];
+ if ((strlen(output_name) <= 4) ||
+ (strcmp(output_name+strlen(output_name)-4, ".jpg") &&
+ strcmp(output_name+strlen(output_name)-4, ".JPG"))) {
+ usage(pname); /* Invalid output file name */
+ fprintf(stderr, "Invalid output file name: %s!\n", output_name);
+ return 1;
+ }
+ }
+ else if (match_key(arg, "quality", strlen("quality"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "quality" should be followed by a quality value */
+ fprintf(stderr, "-quality should be followed by a specified quality value!\n");
+ return 1;
+ }
+ if ((1 != sscanf(argv[argn], "%d", &quality)) || (quality < 0) || (quality > 100)) {
+ usage(pname); /* Invalid quality value */
+ fprintf(stderr, "Invalid quality value!\n");
+ return 1;
+ }
+ }
+ else if (match_key(arg, "thread", strlen("thread"))) {
+ if (++argn >= argc) {
+ usage(pname); /* "thread" should be followed by a thread count */
+ fprintf(stderr, "-thread should be followed by a specified thread count!\n");
+ return 1;
+ }
+ if ((1 != sscanf(argv[argn], "%d", &thread)) || (thread < 1) || (thread > MAX_THREAD_COUNT)) {
+ usage(pname); /* Invalid thread count */
+ fprintf(stderr, "Invalid thread count!\n");
+ return 1;
+ }
+ }
+ else if (match_key(arg, "fix", strlen("fix"))) {
+ fix_cpu_frequency = true;
+ }
+ else {
+ usage(pname); /* Unsupported argument */
+ fprintf(stderr, "Unsupported argument: %s!\n", arg);
+ return 1;
+ }
+ }
+
+ if ((0 == width) || (0 == height)) {
+ usage(pname);
+ fprintf(stderr, "Width or height unset!\n");
+ return 1;
+ }
+
+ if (height < 240) {
+ printf("Height is too small to do multi-threading.\n"
+ "Force to run as single thread.\n");
+ thread = 1;
+ }
+
+ if (NULL == source_name) {
+ usage(pname);
+ fprintf(stderr, "Source file path unset!\n");
+ return 1;
+ }
+
+ source_fd = open(source_name, O_RDONLY, 0664);
+ if (-1 == source_fd){
+ fprintf(stderr, "Error opening source file: %s (%s)!\n", source_name, strerror(errno));
+ return 1;
+ }
+
+ source_size = width * height * NV12_SAMPLE_SIZE;
+ source_buffer = malloc(source_size);
+ if (NULL == source_buffer) {
+ fprintf(stderr, "Fail to allocate source buffer: %d(%s)!\n", errno, strerror(errno));
+ close(source_fd);
+ return 1;
+ }
+ memset(source_buffer, 0, source_size);
+
+ read_size = read(source_fd, source_buffer, source_size);
+ if (read_size != source_size) {
+ fprintf(stderr, "Incorrect source file size: %d(%s)!\n", read_size, strerror(errno));
+ fprintf(stderr, "The correct size should be : %d.\n", source_size);
+ close(source_fd);
+ free(source_buffer);
+ return 1;
+ }
+ close(source_fd);
+
+ //Fix CPUs' frequency to the maximum available
+ if (fix_cpu_frequency) {
+ cpu_online_nr_fd = fopen("/sys/devices/system/cpu/online", "r");
+ assert(cpu_online_nr_fd != NULL);
+ fscanf(cpu_online_nr_fd, "0-%u", &cpu_online_nr);
+ assert(cpu_online_nr != 0);
+ fclose(cpu_online_nr_fd);
+
+ cpu_available_max_fd = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
+ if(NULL == cpu_available_max_fd) {
+ unsigned char one_line[32] = {};
+ unsigned char one_segment[32] = {};
+ int readed = 0;
+
+ cpu_available_max_fd = fopen("/proc/cpuinfo", "r");
+ assert(cpu_available_max_fd != 0);
+
+ i = strlen("cpu MHz");
+ j = -1; //Haven't find the cpu MHz line
+ do {
+ if (fread(&one_line[0], 1, 1, cpu_available_max_fd) != 1) {
+ break;
+ }
+ else if ('\n' == one_line[0]) {
+ readed = fread(one_line, 1, 24, cpu_available_max_fd);
+ if ((24 == readed) && (0 == strncmp((const char *)one_line, (const char *)"cpu MHz", i))) {
+ //Find the cpu MHz line
+ j = 0;
+ break;
+ }
+ else if (readed > 0) {
+ fseek(cpu_available_max_fd, 0-readed, SEEK_CUR);
+ }
+ }
+ } while (1);
+
+ if (0 == j) {
+ while (one_line[i] != ':') {
+ ++i;
+ }
+ ++i; // The space bewteen ':' and a freq value
+ while (one_line[i] != '.') {
+ one_segment[j++] = one_line[i++];
+ }
+ one_segment[j] = '\0';
+ cpu_available_max = atoi((const char *)one_segment) * 1000;
+ }
+ fclose(cpu_available_max_fd);
+
+ if (0 == cpu_available_max) {
+ cpu_available_max = 1000000;
+ fprintf(stderr, "\nCan't find CPU frequecency value and we assume it to 1.0GHz.\n");
+ }
+
+ printf("\n%u CPU(s) online, whose unscalable frequency is: %u.\n",
+ cpu_online_nr+1, cpu_available_max);
+ }
+ else {
+ fscanf(cpu_available_max_fd, "%u", &cpu_available_max);
+ assert(cpu_available_max != 0);
+ fclose(cpu_available_max_fd);
+
+ cpu_available_min_fd = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq", "r");
+ assert(cpu_available_min_fd != NULL);
+ fscanf(cpu_available_min_fd, "%u", &cpu_available_min);
+ assert(cpu_available_min != 0);
+ fclose(cpu_available_min_fd);
+
+ printf("\n%u CPU(s) online, whose MAX/MIN available frequency is: %u/%u.\n",
+ cpu_online_nr+1, cpu_available_max, cpu_available_min);
+
+ for (i=0; i<=(int)cpu_online_nr; ++i) {
+ char fd_name[64];
+
+ sprintf(fd_name, "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_max_freq", i);
+ cpu_scaling_max_fd = fopen(fd_name, "w");
+ if (0 == i) {
+ assert(cpu_scaling_max_fd != NULL);
+ }
+ else if ((i>0) && (NULL==cpu_scaling_max_fd)) {
+ fprintf(stderr, "No sysfs attribute to fix cpu%u's frequency!\n", i);
+ break;
+ }
+ fprintf(cpu_scaling_max_fd, "%u", cpu_available_max);
+ fclose(cpu_scaling_max_fd);
+
+ sprintf(fd_name, "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_min_freq", i);
+ cpu_scaling_min_fd = fopen(fd_name, "w");
+ if (0 == i) {
+ assert(cpu_scaling_min_fd != NULL);
+ }
+ else if ((i>0) && (NULL== cpu_scaling_min_fd)) {
+ fprintf(stderr, "No sysfs attribute to fix cpu%u's frequency!\n", i);
+ break;
+ }
+ fprintf(cpu_scaling_min_fd, "%u", cpu_available_max);
+ fclose(cpu_scaling_min_fd);
+
+ sprintf(fd_name, "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_cur_freq", i);
+ cpu_cur_fd = fopen(fd_name, "r");
+ assert(cpu_cur_fd != NULL);
+ fscanf(cpu_cur_fd, "%u", &cpu_cur);
+ assert(cpu_cur == cpu_available_max);
+ fclose(cpu_cur_fd);
+
+ printf("cpu%u's frequency is fixed to %u.\n", i, cpu_available_max);
+
+ cpu_scaling_max_fd = cpu_scaling_min_fd = cpu_cur_fd = NULL;
+ cpu_cur = 0;
+ }
+ }
+ }
+ cpu_available_max = 1000000;
+ //Fixing is done.
+
+ printf("\n[INPUT]\n");
+ printf("Source: %s\n", source_name);
+ printf("Width: %d\n", width);
+ printf("Height: %d\n", height);
+ printf("Output: %s\n", output_name);
+ printf("Quality: %d\n", quality);
+ printf("Thread: %d\n", thread);
+ if (true == fix_cpu_frequency)
+ printf("Fix CPU frequency: true\n");
+ else
+ printf("Fix CPU frequency: false\n");
+
+ printf("\n[OUTPUT]\n");
+
+ converted_source_buffer = malloc(source_size);
+ if (NULL == converted_source_buffer) {
+ fprintf(stderr, "Fail to allocate converted source buffer: %d(%s)!\n", errno, strerror(errno));
+ return 1;
+ }
+ memset(converted_source_buffer, 0, source_size);
+
+ PERF_START(NV12_color_convert, fix_cpu_frequency);
+ NV12_color_convert((JSAMPLE *)source_buffer, width, height, (JSAMPLE *)converted_source_buffer);
+ PERF_STOP(NV12_color_convert, fix_cpu_frequency);
+ free(source_buffer);
+
+ output_size = MAX_CODED_BUFFER_SIZE(width, height);
+ output_buffer = malloc(output_size);
+ if (NULL == output_buffer) {
+ fprintf(stderr, "Fail to allocate output buffer: %d(%s)!\n", errno, strerror(errno));
+ free(converted_source_buffer);
+ return 1;
+ }
+ memset(output_buffer, 0, output_size);
+
+ encode_thread = (pthread_t *)malloc(sizeof(pthread_t) * thread);
+ if (NULL == encode_thread) {
+ fprintf(stderr, "Fail to allocate thread data: %d(%s)!\n", errno, strerror(errno));
+ free(converted_source_buffer);
+ free(output_buffer);
+ return 1;
+ }
+ encode_thread_para = (thread_parameters *)malloc(sizeof(thread_parameters) * thread);
+ if (NULL == encode_thread_para) {
+ fprintf(stderr, "Fail to allocate thread data: %d(%s)!\n", errno, strerror(errno));
+ free(converted_source_buffer);
+ free(output_buffer);
+ free(encode_thread);
+ return 1;
+ }
+ sub_coded_size = (int *)malloc(sizeof(int) * thread);
+ if (NULL == sub_coded_size) {
+ fprintf(stderr, "Fail to allocate thread data: %d(%s)!\n", errno, strerror(errno));
+ free(converted_source_buffer);
+ free(output_buffer);
+ free(encode_thread);
+ free(encode_thread_para);
+ return 1;
+ }
+
+
+ PERF_START(core_encoding, fix_cpu_frequency);
+ /* Create encoding threads */
+ for (i=0; i<thread; ++i) {
+ encode_thread_para[i].id = i;
+ encode_thread_para[i].width = width;
+ encode_thread_para[i].height = height;
+ encode_thread_para[i].quality = quality;
+ encode_thread_para[i].source_buffer = converted_source_buffer;
+ encode_thread_para[i].sub_height = ((height/thread+NV12_MCU_SIZE-1)
+ /NV12_MCU_SIZE)*NV12_MCU_SIZE;
+ encode_thread_para[i].rows = (i != (thread-1))?
+ encode_thread_para[i].sub_height:
+ (height-(encode_thread_para[i].sub_height*(thread-1)));
+ encode_thread_para[i].sub_output_size = output_size/thread;
+ encode_thread_para[i].sub_output_buffer = (void *)((unsigned int)output_buffer +
+ (output_size/thread)*i);
+
+ pthread_create(&encode_thread[i], NULL, encode_thread_fn, (void *)&encode_thread_para[i]);
+ }
+
+ /* Wait for encoding threads' completion */
+ for (i=0; i<thread; ++i) {
+ pthread_join(encode_thread[i], (void **)&sub_coded_size[i]);
+ if (sub_coded_size[i] <= 0) {
+ hasError = true;
+ }
+ }
+ free(converted_source_buffer);
+ if (hasError) {
+ free(output_buffer);
+ free(encode_thread);
+ free(encode_thread_para);
+ free(sub_coded_size);
+ return 1;
+ }
+ PERF_STOP(core_encoding, fix_cpu_frequency);
+
+ /* Dump each encoding thread's result */
+ for (i=0; i<thread; ++i) {
+ printf("Thread %d: the coded size is %d.\n", i, sub_coded_size[i]);
+ }
+ printf("\n");
+
+ /* Create the final output buffer to take merged coded data */
+ merged_output_buffer = malloc(output_size);
+ if (NULL == merged_output_buffer) {
+ fprintf(stderr, "Fail to allocate merged output buffer: %d(%s)!\n", errno, strerror(errno));
+ free(output_buffer);
+ free(encode_thread);
+ free(encode_thread_para);
+ free(sub_coded_size);
+ return 1;
+ }
+ memset(merged_output_buffer, 0, output_size);
+
+ /* Merge those sub-pictures together */
+ PERF_START(subpictures_merging, fix_cpu_frequency);
+
+ /* Write the JPEG header */
+ memcpy(merged_output_buffer,
+ encode_thread_para[0].sub_output_buffer,
+ HEADER_TOTAL_LEN-HEADER_SOS_LEN);
+ output_size = HEADER_TOTAL_LEN - HEADER_SOS_LEN;
+
+ /* Update the width and height info */
+ merged_output_buffer[HEADER_HEIGHT_POS] = (height>>8) & 0xFF;
+ merged_output_buffer[HEADER_HEIGHT_POS+1] = (height) & 0xFF;
+ merged_output_buffer[HEADER_WIDTH_POS] = (width>>8) & 0xFF;
+ merged_output_buffer[HEADER_WIDTH_POS+1] = (width) & 0xFF;
+
+ /* Write the restarting interval */
+ if (thread > 1) {
+ unsigned int MCUs = (encode_thread_para[0].sub_height/NV12_MCU_SIZE) *
+ (width/NV12_MCU_SIZE);
+
+ merged_output_buffer[output_size++] = 0xFF;
+ merged_output_buffer[output_size++] = 0xDD;
+ merged_output_buffer[output_size++] = 0;
+ merged_output_buffer[output_size++] = 4;
+ merged_output_buffer[output_size++] = (MCUs>>8) & 0xFF;
+ merged_output_buffer[output_size++] = (MCUs) & 0xFF;
+ }
+
+ memcpy((void *)((unsigned int)merged_output_buffer+output_size),
+ (void *)((unsigned int)encode_thread_para[0].sub_output_buffer+HEADER_TOTAL_LEN-HEADER_SOS_LEN),
+ HEADER_SOS_LEN);
+ output_size += HEADER_SOS_LEN;
+
+ /* Write coded segments */
+ for (i=0; i<thread; ++i) {
+ memcpy((void *)((unsigned int)merged_output_buffer+output_size),
+ (void *)((unsigned int)encode_thread_para[i].sub_output_buffer+HEADER_TOTAL_LEN),
+ (sub_coded_size[i]-HEADER_TOTAL_LEN-HEADER_EOI_LEN));
+ output_size += (sub_coded_size[i]-HEADER_TOTAL_LEN-HEADER_EOI_LEN);
+
+ if (i != (thread-1)) {
+ merged_output_buffer[output_size++] = 0xFF;
+ merged_output_buffer[output_size++] = (i&0x7) | 0xD0;
+ }
+ }
+ /* Write EOI */
+ merged_output_buffer[output_size++]= 0xFF;
+ merged_output_buffer[output_size++]= 0xD9;
+
+ PERF_STOP(subpictures_merging, fix_cpu_frequency);
+
+ free(output_buffer);
+ free(encode_thread);
+ free(encode_thread_para);
+ free(sub_coded_size);
+
+ output_fd = open(output_name, O_WRONLY | O_CREAT | O_TRUNC, 0664);
+ if (-1 == output_fd) {
+ fprintf(stderr, "Error opening output file: %s (%s)!\n", output_name, strerror(errno));
+ free(merged_output_buffer);
+ return 1;
+ }
+
+ write_size = write(output_fd, merged_output_buffer, output_size);
+ if (write_size != output_size) {
+ fprintf(stderr, "Fail to write coded data to output file: %d(%s)!\n", write_size , strerror(errno));
+ close(output_fd);
+ free(merged_output_buffer);
+ return 1;
+ }
+
+ free(merged_output_buffer);
+ close(output_fd);
+ output_fd = -1;
+
+ convert_time = PERF_GET(NV12_color_convert);
+ core_encoding_time = PERF_GET(core_encoding);
+ subpictures_merging_time = PERF_GET(subpictures_merging);
+ total_time = convert_time + core_encoding_time + subpictures_merging_time;
+ printf("[SUM]Convert: %.3fms\n", ((double)convert_time)/cpu_available_max);
+ printf("[SUM]Core encoding: %.3fms\n", ((double)core_encoding_time)/cpu_available_max);
+ printf("[SUM]Sub-pictures merging: %.3fms\n", ((double)subpictures_merging_time)/cpu_available_max);
+ printf("[SUM]Total: %.3fms\n", ((double)total_time)/cpu_available_max);
+
+ compression_rate = ((double)output_size) / ((double)source_size);
+ compression_rate = (1 - compression_rate) * 100;
+ printf("[SUM]Compression rate: %.2f%% (%d bytes : %d bytes)\n", compression_rate, output_size, source_size);
+
+ //Restore CPUs' frequency
+ if (fix_cpu_frequency) {
+ if (cpu_available_min != 0) {
+ for (i=0; i<=(int)cpu_online_nr; ++i) {
+ char fd_name[64];
+
+ sprintf(fd_name, "/sys/devices/system/cpu/cpu%u/cpufreq/scaling_min_freq", i);
+ cpu_scaling_min_fd = fopen(fd_name, "w");
+ if (0 == i) {
+ assert(cpu_scaling_min_fd != NULL);
+ }
+ else if ((i>0) && (NULL== cpu_scaling_min_fd)) {
+ fprintf(stderr, "No sysfs attribute to restore cpu%u's frequency!\n", i);
+ break;
+ }
+
+ fprintf(cpu_scaling_min_fd, "%u", cpu_available_min);
+ fclose(cpu_scaling_min_fd);
+
+ printf("cpu%u's frequency is restored.\n", i);
+
+ cpu_scaling_min_fd = NULL;
+ }
+ }
+ }
+ //Restoring is done
+
+ return 0;
+}
diff --git a/android/mce.cpp b/android/mce.cpp
index 1bd3bee..84d8765 100644
--- a/android/mce.cpp
+++ b/android/mce.cpp
@@ -26,7 +26,6 @@
Chang, Ying<ying.chang@intel.com>
Wang, Elaine<elaine.wang@intel.com>
*/
-
//#define LOG_NDEBUG 0
#define LOG_TAG "mce"
#include <utils/Log.h>
@@ -55,10 +54,11 @@
#include "vpx/vp8cx.h"
#define fourcc 0x30385056
+#define vp9_fourcc 0x30395056
using namespace android;
-static int64_t kTimeout = 50000ll;
+static int64_t kTimeout = 5000000ll;
static void usage(const char *me) {
fprintf(stderr, "MediCodec Encoder\n"
@@ -66,7 +66,7 @@ static void usage(const char *me) {
"\t\t-w width -h height\n"
"\t\t-f framerate -b bitreate -c color format{0 - nv12, 1 - i420}\n"
"\t\t-p output format{0 - es, 1 - muxed}\n"
- "\t\t-v mimetype{video/avc, video/x-vnd.on2.vp8, video/mp4v-es, video/3gpp}\n",
+ "\t\t-v mimetype{video/avc, video/x-vnd.on2.vp8, video/x-vnd.on2.vp9, video/mp4v-es, video/3gpp}\n",
me);
exit(1);
@@ -84,6 +84,30 @@ static void mem_put_le32(char *mem, unsigned int val) {
mem[3] = val>>24;
}
+static void write_vp9_file_header(FILE *outfile,
+ const vpx_codec_enc_cfg_t *cfg,
+ int frame_cnt) {
+ char header[32];
+
+ if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
+ return;
+ header[0] = 'D';
+ header[1] = 'K';
+ header[2] = 'I';
+ header[3] = 'F';
+ mem_put_le16(header+4, 0); /* version */
+ mem_put_le16(header+6, 32); /* headersize */
+ mem_put_le32(header+8, vp9_fourcc); /* headersize */
+ mem_put_le16(header+12, cfg->g_w); /* width */
+ mem_put_le16(header+14, cfg->g_h); /* height */
+ mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
+ mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
+ mem_put_le32(header+24, frame_cnt); /* length */
+ mem_put_le32(header+28, 0); /* unused */
+
+ (void) fwrite(header, 1, 32, outfile);
+}
+
static void write_ivf_file_header(FILE *outfile,
const vpx_codec_enc_cfg_t *cfg,
int frame_cnt) {
@@ -142,6 +166,7 @@ int main(int argc, char **argv) {
vpx_codec_cx_pkt_t pkt;
vpx_codec_enc_cfg_t cfg;
bool is_vpx = false;
+ bool is_vp9 = false;
while ((res = getopt(argc, argv, "i:o:f:b:w:h:c:v:p:n:")) >= 0) {
switch (res) {
@@ -216,7 +241,8 @@ int main(int argc, char **argv) {
"mimetype %s, input %s, output %s\n", width, height, bitrate, framerate, mime, input, output);
is_vpx = (strncmp(mime, "video/x-vnd.on2.vp8", 19) == 0);
- if (is_vpx) {
+ is_vp9 = (strncmp(mime, "video/x-vnd.on2.vp9", 19) == 0);
+ if (is_vpx || is_vp9) {
cfg.g_w = width;
cfg.g_h = height;
cfg.g_timebase.den = framerate ;
@@ -258,8 +284,9 @@ int main(int argc, char **argv) {
fIn = fopen(input, "r");
if(outputFormat) {
- pMuxer = new MediaMuxer(output,
- is_vpx ? MediaMuxer::OUTPUT_FORMAT_WEBM : MediaMuxer::OUTPUT_FORMAT_MPEG_4);
+ fOut = fopen(output, "w");
+ pMuxer = new MediaMuxer(fileno(fOut),
+ (is_vpx||is_vp9) ? MediaMuxer::OUTPUT_FORMAT_WEBM : MediaMuxer::OUTPUT_FORMAT_MPEG_4);
} else {
fOut = fopen(output, "w");
}
@@ -271,6 +298,8 @@ int main(int argc, char **argv) {
if (is_vpx && !outputFormat)
write_ivf_file_header(fOut, &cfg, 0);
+ if (is_vp9 && !outputFormat)
+ write_vp9_file_header(fOut, &cfg, 0);
err = codec->configure(format, NULL, NULL, MediaCodec::CONFIGURE_FLAG_ENCODE);
CHECK_EQ(err, (status_t)OK);
@@ -312,7 +341,7 @@ again:
sawOutputEOS = true;
} else {
if (!outputFormat) {
- if (is_vpx) {
+ if (is_vpx || is_vp9) {
pkt.data.frame.sz = size;
pkt.data.frame.pts = frame_cnt;
pkt.kind = VPX_CODEC_CX_FRAME_PKT;
@@ -355,8 +384,13 @@ again:
if(!fseek(fOut, 0, SEEK_SET))
write_ivf_file_header(fOut, &cfg, frame_cnt);
}
+ if (is_vp9) {
+ if(!fseek(fOut, 0, SEEK_SET))
+ write_vp9_file_header(fOut, &cfg, frame_cnt);
+ }
fclose(fOut);
} else {
+ fclose(fOut);
err = pMuxer->stop();
CHECK_EQ(err, (status_t)OK);
}
diff --git a/android/skia-encoder.cpp b/android/skia-encoder.cpp
new file mode 100755
index 0000000..1a405bb
--- /dev/null
+++ b/android/skia-encoder.cpp
@@ -0,0 +1,127 @@
+#include <getopt.h>
+#include <stdio.h>
+
+#include "SkBitmap.h"
+#include "SkPaint.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkString.h"
+#include "SkImageEncoder.h"
+#include "SkImageDecoder.h"
+
+static SkImageEncoder::Type image_type;
+static char* src_image = NULL;
+static char* dst_image = NULL;
+
+static void usage(const char* pname)
+{
+ fprintf(stderr,
+ "\n USAGE: %s -src [path] -dst [path] \n"
+ "\n Image Support .PNG(.png), .WEBP(.webp) or .JPEG(.jpeg) Format Only.\n"
+ ,pname);
+}
+
+
+static int process_cmdline(int argc, char *argv[])
+{
+ char c;
+
+#if 0
+ int i;
+ printf("Argumen Num = %d\n", argc);
+ for (i = 0; i < argc; i++) {
+ printf("Argument %d:%s\n", i, argv[i]);
+ }
+ printf("==>%s:%d\n", __FUNCTION__, __LINE__);
+#endif
+
+ const struct option long_opts[] = {
+ {"help", no_argument, NULL, 0 },
+ {"src", required_argument, NULL, 1 },
+ {"dst", required_argument, NULL, 2 },
+ {NULL, 0, 0, 0}};
+
+ if (argc <= 1) {
+ usage(argv[0]); /* No argument */
+ return 1;
+ }
+
+ while ((c = getopt_long_only(argc,argv,"?",long_opts,NULL)) != EOF) {
+ switch (c) {
+ case '?':
+ goto out;
+ break;
+
+ case 0:
+ goto out;
+ break;
+
+ case 1:
+ src_image = strdup(optarg);
+ break;
+
+ case 2:
+ dst_image = strdup(optarg);
+ break;
+
+ default:
+ goto out;
+ break;
+ }
+ }
+
+ if ((NULL == src_image) || (NULL == dst_image)) {
+ goto out;
+ }
+
+ if ((NULL != strstr(dst_image, ".PNG")) || (NULL != strstr(dst_image, ".png"))) {
+ image_type = SkImageEncoder::kPNG_Type;
+ } else if ((NULL != strstr(dst_image, ".WEBP")) || (NULL != strstr(dst_image, ".webp"))) {
+ image_type = SkImageEncoder::kWEBP_Type;
+ } else if ((NULL != strstr(dst_image, ".JPEG")) || (NULL != strstr(dst_image, ".jpeg"))) {
+ image_type = SkImageEncoder::kJPEG_Type;
+ } else {
+ goto out;
+ }
+
+ printf("============= Start Encode ==============\n");
+ if (SkImageEncoder::kPNG_Type == image_type) {
+ printf("INPUT: IMAGE TYPE : PNG IMAGE\n");
+ } else if (SkImageEncoder::kWEBP_Type == image_type) {
+ printf("INPUT: IMAGE TYPE : WEBP IMAGE\n");
+ } else if (SkImageEncoder::kJPEG_Type == image_type) {
+ printf("INPUT: IMAGE TYPE : JPEG IMAGE\n");
+ }
+
+ printf("INPUT: Src IMAGE : %s\n", src_image);
+ printf("INPUT: Dest IMAGE : %s\n", dst_image);
+
+ return 1;
+
+out:
+ usage(argv[0]);
+ exit(0);
+}
+
+
+int main(int argc, char* argv[])
+{
+ int ret = -1;
+ int i = 0;
+
+ process_cmdline(argc, argv);
+
+ SkBitmap srcImage;
+
+ ret = SkImageDecoder::DecodeFile(src_image, &srcImage);
+ printf("Decode is successful? %s \n", (ret ? "Yes" : "No"));
+
+ ret =SkImageEncoder::EncodeFile(dst_image, srcImage, image_type, 100);
+ printf("Encode is successful? %s \n", (ret ? "Yes" : "No"));
+
+ printf("============= Finish Encode ==============\n");
+
+ return 0;
+}
+
+
diff --git a/utils/loadsurface_yuv.h b/utils/loadsurface_yuv.h
index 0b466c1..05852dc 100644
--- a/utils/loadsurface_yuv.h
+++ b/utils/loadsurface_yuv.h
@@ -28989,7 +28989,6 @@ static int yuvgen_planar(int width, int height,
/* copy UV data */
for( row =0; row < height/2; row++) {
-
/* fill garbage data into the other field */
if (((field == VA_TOP_FIELD) && (row &1))
|| ((field == VA_BOTTOM_FIELD) && ((row &1)==0))) {
@@ -29003,6 +29002,7 @@ static int yuvgen_planar(int width, int height,
memset(U_row, uv_value, width);
break;
case VA_FOURCC_YV12:
+ case VA_FOURCC_IYUV:
memset (U_row,uv_value,width/2);
memset (V_row,uv_value,width/2);
break;
diff --git a/vaenc/Android.mk b/vaenc/Android.mk
index db9dd48..623ea8f 100644
--- a/vaenc/Android.mk
+++ b/vaenc/Android.mk
@@ -8,6 +8,7 @@ LOCAL_SRC_FILES := \
va_encode.c va_surface.c h264encode.c \
mpeg4encode.c h263encode.c vp8encode.c \
jpegencode.c jpegtables.c mpeg2encode.c \
+ hevcencode.c \
codedmeta.c ../utils/configrc.lex.l ../utils/configrc.yacc.y \
../android/gralloc.cpp ../utils/psnr.c ../utils/ssim.c
diff --git a/vaenc/Makefile b/vaenc/Makefile
index 87f431f..3b1f5c8 100644
--- a/vaenc/Makefile
+++ b/vaenc/Makefile
@@ -1,7 +1,7 @@
all: va_encode
-srcs=va_encode.c h264encode.c mpeg4encode.c h263encode.c vp8encode.c jpegencode.c jpegtables.c mpeg2encode.c va_surface.c codedmeta.c configrc.lex.c configrc.yacc.c ../common/va_display.c ../common/va_display_drm.c ../common/va_display_x11.c ../utils/ssim.c ../utils/psnr.c
-objs=va_encode.o h264encode.o mpeg4encode.o h263encode.o vp8encode.o jpegencode.o jpegtables.o mpeg2encode.o va_surface.o codedmeta.o configrc.lex.o configrc.yacc.o ../common/va_display.o ../common/va_display_drm.o ../common/va_display_x11.o ../utils/ssim.o ../utils/psnr.o
+srcs=va_encode.c h264encode.c mpeg4encode.c h263encode.c vp8encode.c hevcencode.c jpegencode.c jpegtables.c mpeg2encode.c va_surface.c codedmeta.c configrc.lex.c configrc.yacc.c ../common/va_display.c ../common/va_display_drm.c ../common/va_display_x11.c ../utils/ssim.c ../utils/psnr.c
+objs=va_encode.o h264encode.o mpeg4encode.o h263encode.o vp8encode.o hevcencode.o jpegencode.o jpegtables.o mpeg2encode.o va_surface.o codedmeta.o configrc.lex.o configrc.yacc.o ../common/va_display.o ../common/va_display_drm.o ../common/va_display_x11.o ../utils/ssim.o ../utils/psnr.o
headers=va_encode.h
cflags=-D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
diff --git a/vaenc/hevcencode.c b/vaenc/hevcencode.c
index 8079075..af9d3f0 100644
--- a/vaenc/hevcencode.c
+++ b/vaenc/hevcencode.c
@@ -46,6 +46,17 @@
#define NAL_PPS 8
#define NAL_SEI 6
+#define NAL_VPS_HEVC 0x20
+#define NAL_SPS_HEVC 0x21
+#define NAL_PPS_HEVC 0x22
+#define NAL_AUD_HEVC 0x09
+
+#define TRAIL_R 1
+#define IDR_W_RADL 19
+#define IDR_N_LP 20
+#define BLA_W_LP 16
+#define RSV_IRAP_VCL23 23
+
#define SLICE_TYPE_P 0
#define SLICE_TYPE_B 1
#define SLICE_TYPE_I 2
@@ -59,10 +70,13 @@
#define BITSTREAM_ALLOCATE_STEPPING 4096
+#define NUM_MAX_REF_FRAME_HEVC 15
+
static VAConfigAttrib hevc_attrib[VAConfigAttribTypeMax];
static VAEncSequenceParameterBufferHEVC seq_param;
-static VAPictureParameterBufferHEVC pic_param;
+static VAEncPictureParameterBufferHEVC pic_param;
+static VAEncSliceParameterBufferHEVC slc_param;
static VAPictureHEVC CurrentCurrPic;
static VAPictureHEVC ReferenceFrames[16], RefPicList0_P[32], RefPicList0_B[32], RefPicList1_B[32];
@@ -75,14 +89,20 @@ static unsigned int num_ref_frames = 2;
static unsigned int numShortTerm = 0;
static int constraint_set_flag = 0;
static int hevc_packedheader = 0; /* support pack header? */
-static int hevc_maxref = (1<<16|1);
+static int hevc_maxref = 15;
static int hevc_autoref = 0;
+static int frame_poc = 0;
+
static VAProfile hevc_profile = -1;
int hevc_entropy_mode = 1; /* cabac */
int hevc_8x8_dct = 0;
+#define LCU_SIZE 32
+#define ALIGN(x, align) (((x) + (align) - 1 ) & (~((align) - 1)))
+#define GET_CTU_NUM(x, LCU_SIZE) ((ALIGN(x, LCU_SIZE))/LCU_SIZE)
+
struct __bitstream {
unsigned int *buffer;
int bit_offset;
@@ -205,149 +225,253 @@ rbsp_trailing_bits(bitstream *bs)
bitstream_byte_aligning(bs, 0);
}
-static void nal_start_code_prefix(bitstream *bs)
+static unsigned char get_va_frame_type(int frame_type) {
+ switch (frame_type) {
+ case FRAME_IDR:
+ return 7;
+ case FRAME_I:
+ return 2;
+ case FRAME_P:
+ return 0;
+ case FRAME_B:
+ return 1;
+ default:
+ fprintf(stderr, "%s Invalid frame type:%d\n", __FUNCTION__, frame_type);
+ return 0;
+ }
+}
+
+
+static void nal_start_code_prefix_HEVC(bitstream *bs, bool flag)
{
- bitstream_put_ui(bs, 0x00000001, 32);
+ if (!flag)
+ bitstream_put_ui(bs, 0x00, 8);
+ bitstream_put_ui(bs, 0x000001, 24);
}
-static void nal_header(bitstream *bs, int nal_ref_idc, int nal_unit_type)
+static void nal_header_HEVC(bitstream *bs, int nal_ref_idc, int nal_unit_type)
{
bitstream_put_ui(bs, 0, 1); /* forbidden_zero_bit: 0 */
- bitstream_put_ui(bs, nal_ref_idc, 2);
- bitstream_put_ui(bs, nal_unit_type, 5);
+ bitstream_put_ui(bs, nal_unit_type, 6);
+ bitstream_put_ui(bs, 0, 6);
+ bitstream_put_ui(bs, 1, 3);
}
-static void sps_rbsp(bitstream *bs)
+static void profile_tier_level(bitstream *bs)
{
- int profile_idc = PROFILE_IDC_BASELINE;
-
- bitstream_put_ui(bs, 0, 32);
- bitstream_put_ui(bs, 0, 32);
-
- //profile_tier_level(0)
-
- bitstream_put_ui(bs, seq_param.general_profile_idc, 8); //general_profile_idc = 1;
- bitstream_put_ui(bs, 0, 32); //eneral_profile_compatibility_flag[] = 0;
- //general_progressive_source_flag = 1 general_interlaced_source_flag = 0
- //general_non_packed_constraint_flag = 1 general_frame_only_constraint_flag = 0
- bitstream_put_ui(bs, 0xb<<4, 8);
- bitstream_put_ui(bs, 0, 32);
- bitstream_put_ui(bs, 0, 8);
- //general_level_idc = 123, i.e. L4.1
- bitstream_put_ui(bs, seq_param.general_level_idc * 30, 8);
- bitstream_put_ue(bs, 0); //sps_seq_parameter_set_id
- bitstream_put_ue(bs, seq_param.seq_fields.chroma_format_idc); //chroma_format_idc
-
- bitstream_put_ue(bs, frame_width_mbaligned);
- bitstream_put_ue(bs, frame_height_mbaligned);
-
- //conformance_window_flag = 0
- bitstream_put_ui(bs, seq_param.frame_cropping_flag, 1); /* frame_cropping_flag */
-
- if (seq_param.frame_cropping_flag) {
- bitstream_put_ue(bs, seq_param.frame_crop_left_offset); /* frame_crop_left_offset */
- bitstream_put_ue(bs, seq_param.frame_crop_right_offset); /* frame_crop_right_offset */
- bitstream_put_ue(bs, seq_param.frame_crop_top_offset); /* frame_crop_top_offset */
- bitstream_put_ue(bs, seq_param.frame_crop_bottom_offset); /* frame_crop_bottom_offset */
- }
-
- //bit_depth_luma_minus8 bit_depth_chroma_minus8
- bitstream_put_ue(bs, 0);
- bitstream_put_ue(bs, 0);
-
- bitstream_put_ue(bs, seq_param.seq_fields.bits.log2_max_pic_order_cnt_cnt_lsb_minus4);
-
- //sps_sub_layer_ordering_info_present_flag
+ int i = 0;
+ bitstream_put_ui(bs, 0, 2);
bitstream_put_ui(bs, 0, 1);
- //log2_min_luma_coding_block_size_minus3
- bitstream_put_ue(bs, 1);
- bitstream_put_ue(bs, 0);
- bitstream_put_ue(bs, 1);
- bitstream_put_ue(bs, 0);
- bitstream_put_ue(bs, 1);
- bitstream_put_ue(bs, 1);
+ bitstream_put_ui(bs, 1, 5);
+ for(i = 0; i < 32; i++)
+ bitstream_put_ui(bs, 0, 1);
- bitstream_put_ui(bs, 0, 4);
+ bitstream_put_ui(bs, 1, 1);
+ bitstream_put_ui(bs, 0, 1);
+ bitstream_put_ui(bs, 0, 1);
+ bitstream_put_ui(bs, 1, 1);
+ bitstream_put_ui(bs, 0/*ps.general_reserved_zero_44bits*/, 44);
+ bitstream_put_ui(bs, 51*3, 8);
+}
+
+static void sps_rbsp(bitstream *bs)
+{
+ int conformance_window_flag = 0;
+ bitstream_put_ui(bs, 0, 4); //sps_video_parameter_set_id
+ bitstream_put_ui(bs, 0, 3);
+ bitstream_put_ui(bs, 1, 1); //sps_temporal_id_nesting_flag
+ profile_tier_level(bs);
- //num_short_term_ref_pic_sets
bitstream_put_ue(bs, 0);
- //num_long_term_ref_pic_sets
- bitstream_put_ue(bs, 0);
-
- //sps_temporal_mvp_enabled_flag strong_intra_smoothing_enabled_flag
- //vui_parameters_present_flag
- bitstream_put_ui(bs, 0, 3);
-
+ bitstream_put_ue(bs, 1); //4:2:0 seq_param.seq_fields.bits.chroma_format_idc
+ if (seq_param.seq_fields.bits.chroma_format_idc == 3)
+ bitstream_put_ui(bs, 0, 1);
+
+ int wFrameWidthInMinCbMinus1 = (ALIGN(frame_width, 16) >> 3) - 1;
+ seq_param.pic_width_in_luma_samples = (wFrameWidthInMinCbMinus1 + 1) * (1 << 3);
+ bitstream_put_ue(bs, seq_param.pic_width_in_luma_samples);
+ int wFrameHeightInMinCbMinus1 = (ALIGN(frame_height, 16) >> 3) - 1;
+ seq_param.pic_height_in_luma_samples = (wFrameHeightInMinCbMinus1 + 1) * (1 << 3);
+ bitstream_put_ue(bs, seq_param.pic_height_in_luma_samples);
+
+ if((ALIGN(frame_width, 16) != frame_width) || (ALIGN(frame_height, 16) != frame_height))
+ {
+ conformance_window_flag = 1;
+ bitstream_put_ui(bs, conformance_window_flag, 1); //conformance_window_flag
+ bitstream_put_ue(bs, 0); //conf_win_left_offset
+ //bitstream_put_ue(bs, (frame_width_mbaligned - frame_width)/2);
+ bitstream_put_ue(bs, (ALIGN(frame_width, 16) - frame_width)/2); //conf_win_right_offset
+ bitstream_put_ue(bs, 0); // conf_win_top_offset
+ //bitstream_put_ue(bs, (frame_height_mbaligned - frame_height)/2);
+ bitstream_put_ue(bs, (ALIGN(frame_height, 16) - frame_height)/2); // conf_win_bottom_offset
+ }
+ else
+ bitstream_put_ui(bs, conformance_window_flag, 1); //conformance_window_flag
+
+ bitstream_put_ue(bs, 0); //seq_fields.bits.bit_depth_luma_minus8
+ bitstream_put_ue(bs, 0); //seq_fields.bits.bit_depth_chroma_minus8
+ bitstream_put_ue(bs, 0); // log2_max_pic_order_cnt_lsb_minus4);
+ bitstream_put_ui(bs, 0, 1); //sps_sub_layer_ordering_info_present_flag
+
+ bitstream_put_ue(bs, 6); // sps_max_dec_pic_buffering[0]
+ bitstream_put_ue(bs, 0); //sps.sps_num_reorder_pics[0]);
+ bitstream_put_ue(bs, 0); //sps.sps_max_latency_increase[0]);
+
+ bitstream_put_ue(bs, 0);// seq_param.log2_min_luma_coding_block_size_minus3);
+ bitstream_put_ue(bs, 2); //seq_param.log2_diff_max_min_luma_coding_block_size);
+ bitstream_put_ue(bs, 0); //seq_param.log2_min_transform_block_size_minus2);
+ bitstream_put_ue(bs, 3); //seq_param.log2_diff_max_min_transform_block_size);
+ bitstream_put_ue(bs, 2); //seq_param.max_transform_hierarchy_depth_inter);
+ bitstream_put_ue(bs, 2); //seq_param.max_transform_hierarchy_depth_intra);
+
+ bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.scaling_list_enabled_flag, 1);
+ bitstream_put_ui(bs, 1, 1); //seq_param.seq_fields.bits.amp_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.sample_adaptive_offset_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.pcm_enabled_flag, 1);
+
+ bitstream_put_ue(bs, 1); //sps.num_short_term_ref_pic_sets);
+ bitstream_put_ue(bs, 1); // num_negative_pics port from short_term_ref_pic_set()
+ bitstream_put_ue(bs, 0); // ps.num_positive_pics[refIdx==0?0:1]
+ bitstream_put_ue(bs, 0); // ps.delta_poc_s0_minus1[refIdx]
+ bitstream_put_ui(bs, 1, 1); // ps.used_by_curr_pic_s0_flag[refIdx], 1)
+
+ bitstream_put_ui(bs, 0, 1); //sps.long_term_ref_pics_present_flag, 1);
+ bitstream_put_ui(bs, 1, 1); //seq_param.seq_fields.bits.sps_temporal_mvp_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //seq_param.seq_fields.bits.strong_intra_smoothing_enabled_flag , 1);
+ bitstream_put_ui(bs, 0, 1); //seq_param.vui_parameters_present_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //sps.sps_extension_flag, 1);
- rbsp_trailing_bits(bs); /* rbsp_trailing_bits */
+ rbsp_trailing_bits(bs);
}
static void pps_rbsp(bitstream *bs)
{
- bitstream_put_ue(bs, pic_param.pic_parameter_set_id); /* pic_parameter_set_id */
- bitstream_put_ue(bs, pic_param.seq_parameter_set_id); /* seq_parameter_set_id */
+ bitstream_put_ue(bs, 0); //pps.pic_parameter_set_id);
+ bitstream_put_ue(bs, 0); //sps.sps_seq_parameter_set_id);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.dependent_slice_segments_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pps.output_flag_present_flag, 1);
+ bitstream_put_ui(bs, 0, 3); //pps.num_extra_slice_header_bits, 3);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.sign_data_hiding_enabled_flag, 1);
+ bitstream_put_ui(bs, 1, 1); //pps.cabac_init_present_flag, 1);
+
+ bitstream_put_ue(bs, 0); //pps.num_ref_idx_l0_default_active_minus1);
+ bitstream_put_ue(bs, 0); //pic_param.num_ref_idx_l1_default_active_minus1);
+ bitstream_put_se(bs, 2); //pic_param.pic_init_qp
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.constrained_intra_pred_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.transform_skip_enabled_flag , 1);
+ if (rc_mode == VA_RC_CQP)
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.cu_qp_delta_enabled_flag , 1);
+ else
+ {
+ bitstream_put_ui(bs, 1, 1);
+ bitstream_put_ue(bs, 0); //pic_param.diff_cu_qp_delta_depth);
+ }
- bitstream_put_ui(bs, pic_param.pic_fields.dependent_slice_segments_enabled_flag, 1);
+ bitstream_put_se(bs, 0); //pic_param.pps_cb_qp_offset);
+ bitstream_put_se(bs, 0); //pic_param.pps_cr_qp_offset);
+ bitstream_put_ui(bs, 0, 1); //pps.pps_slice_chroma_qp_offsets_present_flag, 1)
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.weighted_pred_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.weighted_bipred_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.transquant_bypass_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.tiles_enabled_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.entropy_coding_sync_enabled_flag, 1);
- bitstream_put_ui(bs, 0, 4);
+ /* skip pic_param.pic_fields.bits.tiles_enabled_fla part */
- bitstream_put_ui(bs, pic_param.pic_fields.sign_data_hiding_enabled_flag);
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.pps_loop_filter_across_slices_enabled_flag, 1);
+ bitstream_put_ui(bs, 1, 1); //pps.deblocking_filter_control_present_flag, 1);
- //cabac_init_present_flag
- bitstream_put_ui(bs, 1, 1);
- bitstream_put_ue(bs, pic_param.num_ref_idx_l0_active_minus1); /* num_ref_idx_l0_active_minus1 */
- bitstream_put_ue(bs, pic_param.num_ref_idx_l1_active_minus1); /* num_ref_idx_l1_active_minus1 1 */
+ bitstream_put_ui(bs, 1, 1); //pps.deblocking_filter_override_enabled_flag, 1);
+ bitstream_put_ui(bs, 1, 1); //pps.disable_deblocking_filter_flag, 1);
- bitstream_put_se(bs, pic_param.pic_init_qp - 26); /* pic_init_qp_minus26 */
+ bitstream_put_ui(bs, 0, 1); //pic_param.pic_fields.bits.scaling_list_data_present_flag, 1);
- bitstream_put_ui(bs, pic_param.pic_fields.constrained_intra_pred_flag, 1);
- bitstream_put_ui(bs, pic_param.pic_fields.transform_skip_enabled_flag, 1);
- bitstream_put_ui(bs, pic_param.pic_fields.cu_qp_delta_enabled_flag, 1);
- bitstream_put_ui(bs, pic_param.pic_fields.bits.entropy_coding_mode_flag, 1); /* entropy_coding_mode_flag */
- if (pic_param.pic_fields.bits.entropy_coding_mode_flag)
- bitstream_put_ue(bs, pic_param.diff_cu_qp_delta_depth);
- bitstrea_put_se(se, pic_param.pps_cb_qp_offset);
- bitstrea_put_se(se, pic_param.pps_cr_qp_offset);
+ bitstream_put_ui(bs, 0, 1); //pps.lists_modification_present_flag, 1);
+ bitstream_put_ue(bs, 0); //pic_param.log2_parallel_merge_level_minus2);
+ bitstream_put_ui(bs, 0, 1); //pps.slice_segment_header_extension_present_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //pps.pps_extension_flag, 1);
- //pps_slice_chroma_qp_offsets_present_flag
- bitstream_put_ui(bs, 0, 1);
- //weighted_pred_flag
- bitstream_put_ui(bs, pic_param.pic_fields.weighted_pred_flag, 1);
- //weighted_bipred_flag
- bitstream_put_ui(bs, 0, 1);
+ rbsp_trailing_bits(bs);
+}
- bitstream_put_ui(bs,pic_param.pic_fields.transquant_bypass_enabled_flag, 1);
- bitstream_put_ui(bs,pic_param.pic_fields.tiles_enabled_flag, 1);
- bitstream_put_ui(bs,pic_param.pic_fields.entropy_coding_sync_enabled_flag, 1);
-
- if (pic_param.pic_fields.tiles_enabled_flag) {
- bitstream_put_ue(bs, pic_param.num_tile_columns_minus1);
- bitstream_put_ue(bs, pic_param.num_tile_rows_minus1);
- //uniform_spacing_flag
- bitstream_put_ui(bs, 0, 1);
- for( i = 0; i < pic_param.num_tile_columns_minus1; i++ )
- bitstream_put_ue(bs, pic_param.column_width_minus1[i]);
-
- for( i = 0; i < pic_param.num_tile_rows_minus1; i++ )
- bitstream_put_ue(bs, pic_param.row_height_minus1[i]);
- bistream_put_ui(bs, pic_param.pic_fields.loop_filter_across_tiles_enabled_flag, 1);
+static void slice_rbsp(bitstream *bs)
+{
+ unsigned char frame_type = get_va_frame_type(current_frame_type);
+ unsigned char slice_type = (frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type;
+ unsigned char nal_type = (frame_type == FRAME_IDR) ? IDR_W_RADL : TRAIL_R;
+
+ bitstream_put_ui(bs, 1, 1); // sliceps.first_slice_in_pic_flag, 1);
+
+ if (nal_type >= BLA_W_LP && nal_type <= RSV_IRAP_VCL23)
+ bitstream_put_ui(bs, 0, 1); //sliceps.no_output_of_prior_pics_flag, 1);
+
+ bitstream_put_ue(bs, 0); //slc_param.slice_pic_parameter_set_id);
+
+ bitstream_put_ue(bs, slice_type); //sliceps.slice_type);
+
+ if (nal_type != IDR_W_RADL && nal_type != IDR_N_LP)
+ {
+ bitstream_put_ui(bs, frame_poc, 4); // or 8 sliceps.pic_order_cnt_lsb/2, (sps.log2_max_pic_order_cnt_lsb_minus4+4));
+ bitstream_put_ui(bs, 1, 1); //sliceps.short_term_ref_pic_set_sps_flag, 1);
+
+ bitstream_put_ui(bs, 1, 1); //sliceps.slice_fields.bits.slice_temporal_mvp_enabled_flag, 1);
}
- //pps_loop_filter_across_slices_enabled_flag
- //deblocking_filter_control_present_flag
- //pps_scaling_list_data_present_flag
- //lists_modification_present_flag
- bitstream_put_ui(bs, 0, 4);
- bitstream_put_ue(bs, pic_param.log2_parallel_merge_level_minus2);
- //slice_segment_header_extension_present_flag
- //pps_extension_flag
- bitstream_put_ui(bs, 0, 2);
+ /* skip seq_fields.bits.sample_adaptive_offset_enabled part */
+
+ if (slice_type == SLICE_TYPE_P)
+ {
+ bitstream_put_ui(bs, 0, 1); //slc_param.slice_fields.bits.num_ref_idx_active_override_flag/*0*/, 1);
+ if (slice_type == SLICE_TYPE_P)
+ bitstream_put_ui(bs, 0, 1);//slc_param.slice_fields.bits.mvd_l1_zero_flag, 1);
+
+ bitstream_put_ui(bs, 0, 1); //.slice_fields.bits.cabac_init_flag
+ bitstream_put_ui(bs, 1, 1);//slc_param.slice_fields.bits.collocated_from_l0_flag, 1);
+
+ bitstream_put_ue(bs, 0);//5 - sliceps.max_num_merge_cand
+ }
+
+
+ bitstream_put_se(bs, 0); //slc_param.slice_qp_delta);
+
+ bitstream_put_ui(bs, 1, 1); //sliceps.deblocking_filter_override_flag, 1);
+ bitstream_put_ui(bs, 0, 1); //slc_param.slice_fields.bits.slice_deblocking_filter_disabled_flag, 1);
+ bitstream_put_se(bs, 0); //slc_param.slice_beta_offset_div2);
+ bitstream_put_se(bs, 0); //slc_param.slice_tc_offset_div2);
rbsp_trailing_bits(bs);
+ frame_poc++;
}
+static void vps_rbsp(bitstream *bs)
+{
+ bitstream_put_ui(bs, 0, 4);
+ bitstream_put_ui(bs, 3, 2);
+ bitstream_put_ui(bs, 0, 6); //vps.vps_max_layers_minus1,
+ bitstream_put_ui(bs, 0, 3); //vps.vps_max_sub_layers_minus1, 3);
+ bitstream_put_ui(bs, 1, 1); //vps.vps_temporal_id_nesting_flag, 1);
+ bitstream_put_ui(bs, 0xFFFF, 16);
+
+ profile_tier_level(bs);
+ bitstream_put_ui(bs, 0, 1); //vps.vps_sub_layer_ordering_info_present_flag, 1);
+
+ bitstream_put_ue(bs, 6); //?vps.vps_max_dec_pic_buffering[i]);
+ bitstream_put_ue(bs, 0); //vps.vps_num_reorder_pics[i]);
+ bitstream_put_ue(bs, 0); //vps.vps_max_latency_increase[i]);
+
+ bitstream_put_ui(bs, 0, 6); //vps.max_nuh_reserved_zero_layer_id, 6);
+ bitstream_put_ue(bs, 0); //vps.max_op_sets-1);
+
+ bitstream_put_ui(bs, 0, 1); //vps.vps_timing_info_present_flag, 1);
+
+ /* skip vps_timing_info_present_flag part */
+
+ bitstream_put_ui(bs, 0, 1);
+
+ rbsp_trailing_bits(bs);
+}
static int
build_packed_pic_buffer(unsigned char **header_buffer)
@@ -355,8 +479,8 @@ build_packed_pic_buffer(unsigned char **header_buffer)
bitstream bs;
bitstream_start(&bs);
- nal_start_code_prefix(&bs);
- nal_header(&bs, NAL_REF_IDC_HIGH, NAL_PPS);
+ nal_start_code_prefix_HEVC(&bs, false);
+ nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_PPS_HEVC);
pps_rbsp(&bs);
bitstream_end(&bs);
@@ -370,8 +494,8 @@ build_packed_seq_buffer(unsigned char **header_buffer)
bitstream bs;
bitstream_start(&bs);
- nal_start_code_prefix(&bs);
- nal_header(&bs, NAL_REF_IDC_HIGH, NAL_SPS);
+ nal_start_code_prefix_HEVC(&bs, false);
+ nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_SPS_HEVC);
sps_rbsp(&bs);
bitstream_end(&bs);
@@ -379,6 +503,38 @@ build_packed_seq_buffer(unsigned char **header_buffer)
return bs.bit_offset;
}
+static int
+build_packed_slice_buffer(unsigned char **header_buffer)
+{
+ unsigned char frame_type = get_va_frame_type(current_frame_type);
+ unsigned char nal_type = (frame_type == FRAME_IDR) ? IDR_W_RADL : TRAIL_R;
+ bitstream bs;
+
+ bitstream_start(&bs);
+ nal_start_code_prefix_HEVC(&bs, true);
+ nal_header_HEVC(&bs, NAL_REF_IDC_LOW, nal_type);
+ slice_rbsp(&bs);
+ bitstream_end(&bs);
+
+ *header_buffer = (unsigned char *)bs.buffer;
+ return bs.bit_offset;
+}
+
+static int
+build_packed_vps_buffer(unsigned char **header_buffer)
+{
+ bitstream bs;
+
+ bitstream_start(&bs);
+ nal_start_code_prefix_HEVC(&bs, false);
+ nal_header_HEVC(&bs, NAL_REF_IDC_LOW, NAL_VPS_HEVC);
+ vps_rbsp(&bs);
+ bitstream_end(&bs);
+
+ *header_buffer = (unsigned char *)bs.buffer;
+ return bs.bit_offset;
+}
+
static int
build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
unsigned int init_cpb_removal_delay,
@@ -415,8 +571,8 @@ build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
bitstream_start(&nal_bs);
- nal_start_code_prefix(&nal_bs);
- nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
+ nal_start_code_prefix_HEVC(&nal_bs, false);
+ nal_header_HEVC(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
/* Write the SEI buffer period data */
bitstream_put_ui(&nal_bs, 0, 8);
@@ -467,42 +623,42 @@ build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
} \
} \
-static void sort_one(VAPictureH264 ref[], int left, int right,
- int ascending, int frame_idx)
+static void sort_one(VAPictureHEVC ref[], int left, int right,
+ int ascending, int pic_order_cnt)
{
int i = left, j = right;
unsigned int key;
- VAPictureH264 tmp;
+ VAPictureHEVC tmp;
- if (frame_idx) {
- key = ref[(left + right) / 2].frame_idx;
- partition(ref, frame_idx, key, ascending);
+ if (pic_order_cnt) {
+ key = ref[(left + right) / 2].pic_order_cnt;
+ partition(ref, pic_order_cnt, key, ascending);
} else {
- key = ref[(left + right) / 2].TopFieldOrderCnt;
- partition(ref, TopFieldOrderCnt, (signed int)key, ascending);
+ key = ref[(left + right) / 2].pic_order_cnt;
+ partition(ref, pic_order_cnt, (signed int)key, ascending);
}
/* recursion */
if (left < j)
- sort_one(ref, left, j, ascending, frame_idx);
+ sort_one(ref, left, j, ascending, pic_order_cnt);
if (i < right)
- sort_one(ref, i, right, ascending, frame_idx);
+ sort_one(ref, i, right, ascending, pic_order_cnt);
}
-static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx,
+static void sort_two(VAPictureHEVC ref[], int left, int right, unsigned int key, unsigned int pic_order_cnt,
int partition_ascending, int list0_ascending, int list1_ascending)
{
int i = left, j = right;
- VAPictureH264 tmp;
+ VAPictureHEVC tmp;
- if (frame_idx) {
- partition(ref, frame_idx, key, partition_ascending);
+ if (pic_order_cnt) {
+ partition(ref, pic_order_cnt, key, partition_ascending);
} else {
- partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending);
+ partition(ref, pic_order_cnt, (signed int)key, partition_ascending);
}
- sort_one(ref, left, i-1, list0_ascending, frame_idx);
- sort_one(ref, j+1, right, list1_ascending, frame_idx);
+ sort_one(ref, left, i-1, list0_ascending, pic_order_cnt);
+ sort_one(ref, j+1, right, list1_ascending, pic_order_cnt);
}
static int update_ReferenceFrames(void)
@@ -512,7 +668,7 @@ static int update_ReferenceFrames(void)
if (current_frame_type == FRAME_B)
return 0;
- CurrentCurrPic.flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
+ CurrentCurrPic.flags = 0;//VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
numShortTerm++;
if (numShortTerm > num_ref_frames)
numShortTerm = num_ref_frames;
@@ -531,68 +687,80 @@ static int update_ReferenceFrames(void)
static int update_RefPicList(void)
{
- unsigned int current_poc = CurrentCurrPic.TopFieldOrderCnt;
-
+ unsigned int current_poc = CurrentCurrPic.pic_order_cnt;
+ int i = 0;
+
+ /* Init reference frame list */
+ for (i = 0; i < 15; i++) {
+ RefPicList0_P[i].picture_id = VA_INVALID_SURFACE;
+ RefPicList0_P[i].flags = VA_PICTURE_HEVC_INVALID;
+ RefPicList0_B[i].picture_id = VA_INVALID_SURFACE;
+ RefPicList0_B[i].flags = VA_PICTURE_HEVC_INVALID;
+ RefPicList1_B[i].picture_id = VA_INVALID_SURFACE;
+ RefPicList1_B[i].flags = VA_PICTURE_HEVC_INVALID;
+ }
+
if (current_frame_type == FRAME_P) {
- memcpy(RefPicList0_P, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
+ memcpy(RefPicList0_P, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC));
sort_one(RefPicList0_P, 0, numShortTerm-1, 0, 1);
}
if (current_frame_type == FRAME_B) {
- memcpy(RefPicList0_B, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
- sort_two(RefPicList0_B, 0, numShortTerm-1, current_poc, 0,
- 1, 0, 1);
+ memcpy(RefPicList0_B, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC));
+ sort_two(RefPicList0_B, 0, numShortTerm-1, current_poc, 0, 1, 0, 1);
- memcpy(RefPicList1_B, ReferenceFrames, numShortTerm * sizeof(VAPictureH264));
- sort_two(RefPicList1_B, 0, numShortTerm-1, current_poc, 0,
- 0, 1, 0);
+ memcpy(RefPicList1_B, ReferenceFrames, numShortTerm * sizeof(VAPictureHEVC));
+ sort_two(RefPicList1_B, 0, numShortTerm-1, current_poc, 0, 0, 1, 0);
}
-
+
return 0;
}
-static int render_sequence(rc_param_t *rc_param)
+static int render_sequence(struct rc_param_t *rc_param)
{
VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2];
VAStatus va_status;
VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterRateControl *misc_rate_ctrl;
- seq_param.general_profile_idc = 1 /* 1: main profile 2: main 10 profile*/;
- seq_param.general_level_idc = 3 * 30 /* level 3 */
+ seq_param.general_profile_idc = 1; /* 1: main profile 2: main 10 profile*/
+ seq_param.general_level_idc = 51; /* level 3 */
seq_param.general_tier_flag = 0;
seq_param.intra_period = intra_period;
- seq_param.intra_idr_period = (intra_period == 0) ? 0 : (intra_idr_period / intra_period);
- seq_param.ip_period = 1;
+ seq_param.intra_idr_period = intra_idr_period; //(intra_period == 0) ? 0 : (intra_idr_period / intra_period);
+ seq_param.ip_period = ip_period; //1;
seq_param.bits_per_second = rc_param->bits_per_second;
-
- seq_param.picture_width_in_min_cu_minus1 = frame_width_mbaligned / 8;
- seq_param.picture_height_in_min_cu_minus1 = frame_height_mbaligned / 8;
- seq_param.seq_fields.chroma_format_idc = 1; /* 420 */
- seq_param.seq_fields.separate_colour_plane_flag = 0;
- //seq_param.seq_fields.bit_depth_luma_minus8 = 0;
- //seq_param.seq_fields.bit_depth_chroma_minus8 = 0;
+ seq_param.seq_fields.bits.chroma_format_idc = 1; /* 420 */
seq_param.log2_min_luma_coding_block_size_minus3 = 0; //min CU = 8;
- seq_param.log2_max_luma_coding_block_size_minus3 = 3;//max CU = 64;
+ seq_param.log2_diff_max_min_luma_coding_block_size = 2;
seq_param.log2_min_transform_block_size_minus2 = 0;
- seq_param.log2_max_transform_block_size_minus2 = 3;
-
- seq_param.max_num_ref_frames = num_ref_frames;
- seq_param.seq_fields.bits.frame_mbs_only_flag = 1;
- seq_param.vui_time_scale = frame_rate * 2;
- seq_param.vui_num_units_in_tick = 2; /* Tc = num_units_in_tick / time_sacle */
-
- if (frame_width != frame_width_mbaligned ||
- frame_height != frame_height_mbaligned) {
- seq_param.frame_cropping_flag = 1;
- seq_param.frame_crop_left_offset = 0;
- seq_param.frame_crop_right_offset = (frame_width_mbaligned - frame_width)/2;
- seq_param.frame_crop_top_offset = 0;
- seq_param.frame_crop_bottom_offset = (frame_height_mbaligned - frame_height)/2;
- }
+ seq_param.log2_diff_max_min_transform_block_size = 3;
+ seq_param.max_transform_hierarchy_depth_inter = 2;
+ seq_param.max_transform_hierarchy_depth_intra= 2;
+
+ seq_param.pic_width_in_luma_samples = ALIGN(frame_width, 16); //frame_width_mbaligned;
+ seq_param.pic_height_in_luma_samples = ALIGN(frame_height, 16); //frame_height_mbaligned;
+ seq_param.seq_fields.bits.separate_colour_plane_flag = 0;
+ seq_param.seq_fields.bits.bit_depth_luma_minus8 = 0;
+ seq_param.seq_fields.bits.bit_depth_chroma_minus8 = 0;
+ seq_param.seq_fields.bits.scaling_list_enabled_flag = 0;
+ seq_param.seq_fields.bits.strong_intra_smoothing_enabled_flag = 0;
+ seq_param.seq_fields.bits.amp_enabled_flag = 1;
+ seq_param.seq_fields.bits.sample_adaptive_offset_enabled_flag = 0;
+ seq_param.seq_fields.bits.pcm_enabled_flag = 0;
+ seq_param.seq_fields.bits.pcm_loop_filter_disabled_flag = 1;
+ seq_param.seq_fields.bits.sps_temporal_mvp_enabled_flag = 1;
+ seq_param.pcm_sample_bit_depth_luma_minus1 = 7;
+ seq_param.pcm_sample_bit_depth_chroma_minus1 = 7;
+ seq_param.log2_min_pcm_luma_coding_block_size_minus3 = 0;
+ seq_param.log2_max_pcm_luma_coding_block_size_minus3 = 0;
+
+ seq_param.vui_time_scale = 0;
+ seq_param.vui_num_units_in_tick = 0; /* Tc = num_units_in_tick / time_sacle */
+
va_status = vaCreateBuffer(va_dpy, context_id,
VAEncSequenceParameterBufferType,
sizeof(seq_param),1,&seq_param,&seq_param_buf);
@@ -600,20 +768,6 @@ static int render_sequence(rc_param_t *rc_param)
va_status = vaRenderPicture(va_dpy,context_id, &seq_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");;
-
- if (misc_priv_type != 0) {
- va_status = vaCreateBuffer(va_dpy, context_id,
- VAEncMiscParameterBufferType,
- sizeof(VAEncMiscParameterBuffer),
- 1, NULL, &misc_param_tmpbuf);
- CHECK_VASTATUS(va_status,"vaCreateBuffer");
- vaMapBuffer(va_dpy, misc_param_tmpbuf,(void **)&misc_param_tmp);
- misc_param_tmp->type = misc_priv_type;
- misc_param_tmp->data[0] = misc_priv_value;
- vaUnmapBuffer(va_dpy, misc_param_tmpbuf);
-
- va_status = vaRenderPicture(va_dpy,context_id, &misc_param_tmpbuf, 1);
- }
return va_status;
}
@@ -638,7 +792,9 @@ static int render_framerate()
misc_param->type = VAEncMiscParameterTypeFrameRate;
misc_frame_rate = (VAEncMiscParameterFrameRate *)misc_param->data;
- misc_frame_rate->framerate = frame_rate;
+ /* If framerate=30, the coded data is very big. */
+ /* Compare with mv_encode, which pass 3000 here */
+ misc_frame_rate->framerate = frame_rate * 100;
vaUnmapBuffer(va_dpy, frame_rate_param_buf);
@@ -674,7 +830,7 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param)
if (mask & RC_MASK_target_percentage)
misc_rate_ctrl->target_percentage = rc_param->target_percentage;
else
- misc_rate_ctrl->target_percentage = 66;
+ misc_rate_ctrl->target_percentage = 95;
if (mask & RC_MASK_window_size)
misc_rate_ctrl->window_size = rc_param->window_size;
@@ -684,7 +840,7 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param)
if (mask & RC_MASK_initial_qp)
misc_rate_ctrl->initial_qp = rc_param->initial_qp;
else
- misc_rate_ctrl->initial_qp = initial_qp;
+ misc_rate_ctrl->initial_qp = 28; // 28 for HEVC
if (mask & RC_MASK_min_qp)
misc_rate_ctrl->min_qp = rc_param->min_qp;
@@ -706,6 +862,79 @@ static int render_rcparam(unsigned int mask, struct rc_param_t *rc_param)
return 0;
}
+static int render_roi(void)
+{
+ VAStatus va_status;
+ VABufferID misc_roi_buf_id = VA_INVALID_ID;
+ VAEncMiscParameterBuffer *misc_param;
+ VAEncMiscParameterBufferROI *misc_roi_param;
+ VAEncROI encroi;
+
+ roi_rec_x = (!roi_rec_x)?frame_width / 3:roi_rec_x;
+ roi_rec_y = (!roi_rec_x)?frame_height / 3:roi_rec_y;
+ roi_rec_w = (!roi_rec_w)?frame_width / 3:roi_rec_w;
+ roi_rec_h = (!roi_rec_h)?frame_height / 3:roi_rec_h;
+
+ va_status = vaCreateBuffer(va_dpy, context_id,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterBufferROI),
+ 1,
+ NULL,
+ &misc_roi_buf_id);
+ CHECK_VASTATUS(va_status, "vaCreateBuffer");
+
+ vaMapBuffer(va_dpy,
+ misc_roi_buf_id,
+ (void **)&misc_param);
+
+ misc_param->type = VAEncMiscParameterTypeROI;
+ misc_roi_param = (VAEncMiscParameterBufferROI *)misc_param->data;
+
+ misc_roi_param->num_roi = 1;
+ misc_roi_param->max_delta_qp = roi_maxqp;
+ misc_roi_param->min_delta_qp = roi_minqp;
+
+ encroi.roi_rectangle.x = roi_rec_x;
+ encroi.roi_rectangle.y = roi_rec_y;
+ encroi.roi_rectangle.width = roi_rec_w;
+ encroi.roi_rectangle.height = roi_rec_h;
+
+ encroi.roi_value = roi_value;
+
+ misc_roi_param->roi = &encroi;
+
+ vaUnmapBuffer(va_dpy, misc_roi_buf_id);
+
+ va_status = vaRenderPicture(va_dpy, context_id, &misc_roi_buf_id, 1);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+
+ if (buf_destroy)
+ destroy_vabuffers(va_dpy, 1, misc_roi_buf_id);
+
+ return va_status;
+}
+
+static int render_qualitylevel(void)
+{
+ VAStatus va_status;
+ VABufferID misc_param_tmpbuf;
+ VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
+ VAEncMiscParameterBufferQualityLevel *misc_quality_param;
+
+ va_status = vaCreateBuffer(va_dpy, context_id,
+ VAEncMiscParameterBufferType,
+ sizeof(VAEncMiscParameterBuffer) + sizeof(VAEncMiscParameterBufferQualityLevel),
+ 1, NULL, &misc_param_tmpbuf);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+ vaMapBuffer(va_dpy, misc_param_tmpbuf,(void **)&misc_param_tmp);
+ misc_param_tmp->type = VAEncMiscParameterTypeQualityLevel;
+ misc_quality_param = (VAEncMiscParameterBufferQualityLevel *)misc_param_tmp->data;
+ misc_quality_param->quality_level = misc_tu_value;
+ vaUnmapBuffer(va_dpy, misc_param_tmpbuf);
+ va_status = vaRenderPicture(va_dpy,context_id, &misc_param_tmpbuf, 1);
+
+ return va_status;
+}
static int calc_poc(int pic_order_cnt_lsb)
{
@@ -739,62 +968,53 @@ static int calc_poc(int pic_order_cnt_lsb)
return TopFieldOrderCnt;
}
-static unsigned char get_va_frame_type(int frame_type) {
- switch (frame_type) {
- case FRAME_IDR:
- case FRAME_I:
- return 1;
- case FRAME_P:
- return 2;
- case FRAME_B:
- return 3;
- default:
- fprintf(stderr, "%s Invalid frame type:%d\n", __FUNCTION__, frame_type);
- return 1;
-}
-
static int render_picture(void)
{
VABufferID pic_param_buf;
VAStatus va_status;
int i = 0;
- pic_param.CurrPic.picture_id = ref_surface[current_slot];
- pic_param.CurrPic.flags = 0;
- pic_param.CurrPic.PicOrderCnt = calc_poc((current_frame_display - current_IDR_display) % MaxPicOrderCntLsb);
- CurrentCurrPic = pic_param.CurrPic;
+ pic_param.decoded_curr_pic.picture_id = ref_surface[current_slot];
+ pic_param.decoded_curr_pic.pic_order_cnt = current_frame_num;
+ pic_param.decoded_curr_pic.flags = 0;
+
+ CurrentCurrPic = pic_param.decoded_curr_pic;
if (getenv("TO_DEL")) { /* set RefPicList into ReferenceFrames */
update_RefPicList(); /* calc RefPicList */
- memset(pic_param.ReferenceFrames, 0xff, 16 * sizeof(VAPictureH264)); /* invalid all */
+ memset(pic_param.reference_frames, 0xff, 15 * sizeof(VAPictureHEVC)); /* invalid all */
if (current_frame_type == FRAME_P) {
- pic_param.ReferenceFrames[0] = RefPicList0_P[0];
+ pic_param.reference_frames[0] = RefPicList0_P[0];
} else if (current_frame_type == FRAME_B) {
- pic_param.ReferenceFrames[0] = RefPicList0_B[0];
- pic_param.ReferenceFrames[1] = RefPicList1_B[0];
+ pic_param.reference_frames[0] = RefPicList0_B[0];
+ pic_param.reference_frames[1] = RefPicList1_B[0];
}
} else {
if (hevc_autoref == 0) {
- memcpy(pic_param.ReferenceFrames, ReferenceFrames, numShortTerm*sizeof(VAPictureH264));
- for (i = numShortTerm; i < surface_num; i++) {
- pic_param.ReferenceFrames[i].picture_id = VA_INVALID_SURFACE;
- pic_param.ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
+ memcpy(pic_param.reference_frames, ReferenceFrames, numShortTerm*sizeof(VAPictureHEVC));
+ for (i = numShortTerm; i < 15; i++) {
+ pic_param.reference_frames[i].picture_id = VA_INVALID_SURFACE;
+ pic_param.reference_frames[i].flags = VA_PICTURE_HEVC_INVALID;
}
} else {
- for (i=0; i<surface_num; i++) {
- pic_param.ReferenceFrames[i].picture_id = ref_surface[i];
- pic_param.ReferenceFrames[i].flags = 0;
+ for (i = 0; i < 15; i++) {
+ pic_param.reference_frames[i].picture_id = ref_surface[i];
+ pic_param.reference_frames[i].flags = 0;//VA_PICTURE_HEVC_LONG_TERM_REFERENCE;
}
}
}
-
+
+ unsigned char frame_type = get_va_frame_type(current_frame_type);
+ unsigned char coding_type = (frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type;
+ pic_param.pic_fields.bits.cu_qp_delta_enabled_flag = 1;
+ pic_param.pic_fields.bits.screen_content_flag = 1;
+ pic_param.pic_init_qp = 28;
+ pic_param.last_picture = (current_frame_encoding == frame_count);
+ pic_param.pic_fields.bits.reference_pic_flag = (current_frame_type != FRAME_B);
+ pic_param.pic_fields.bits.coding_type = coding_type;
pic_param.pic_fields.bits.idr_pic_flag = (current_frame_type == FRAME_IDR);
pic_param.pic_fields.bits.reference_pic_flag = (current_frame_type != FRAME_B);
- pic_param.pic_fields.bits.transform_8x8_mode_flag = hevc_8x8_dct;
pic_param.coded_buf = coded_buf[current_slot];
- pic_param.last_picture = (current_frame_encoding == frame_count);
- pic_param.pic_init_qp = initial_qp;
- pic_param.coding_type = get_va_frame_type(current_frame_type);
va_status = vaCreateBuffer(va_dpy, context_id,VAEncPictureParameterBufferType,
sizeof(pic_param),1,&pic_param, &pic_param_buf);
@@ -881,6 +1101,81 @@ static int render_packedpicture(void)
return 0;
}
+static int render_packedslice(void)
+{
+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
+ VABufferID packedslc_para_bufid, packedslc_data_bufid, render_id[2];
+ unsigned int length_in_bits;
+ unsigned char *packedslc_buffer = NULL;
+ VAStatus va_status;
+
+ length_in_bits = build_packed_slice_buffer(&packedslc_buffer);
+ packedheader_param_buffer.type = VAEncPackedHeaderSlice;
+ packedheader_param_buffer.bit_length = length_in_bits;
+ packedheader_param_buffer.has_emulation_bytes = 0;
+
+ va_status = vaCreateBuffer(va_dpy,
+ context_id,
+ VAEncPackedHeaderParameterBufferType,
+ sizeof(packedheader_param_buffer), 1, &packedheader_param_buffer,
+ &packedslc_para_bufid);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+ va_status = vaCreateBuffer(va_dpy,
+ context_id,
+ VAEncPackedHeaderDataBufferType,
+ (length_in_bits + 7) / 8, 1, packedslc_buffer,
+ &packedslc_data_bufid);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+ render_id[0] = packedslc_para_bufid;
+ render_id[1] = packedslc_data_bufid;
+ va_status = vaRenderPicture(va_dpy,context_id, render_id, 2);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+
+ free(packedslc_buffer);
+
+ return 0;
+}
+
+static int render_packedvps(void)
+{
+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
+ VABufferID packedvps_para_bufid, packedvps_data_bufid, render_id[2];
+ unsigned int length_in_bits;
+ unsigned char *packedvps_buffer = NULL;
+ VAStatus va_status;
+
+ length_in_bits = build_packed_vps_buffer(&packedvps_buffer);
+ packedheader_param_buffer.type = VAEncPackedHeaderSequence;
+ packedheader_param_buffer.bit_length = length_in_bits;
+ packedheader_param_buffer.has_emulation_bytes = 0;
+
+ va_status = vaCreateBuffer(va_dpy,
+ context_id,
+ VAEncPackedHeaderParameterBufferType,
+ sizeof(packedheader_param_buffer), 1, &packedheader_param_buffer,
+ &packedvps_para_bufid);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+ va_status = vaCreateBuffer(va_dpy,
+ context_id,
+ VAEncPackedHeaderDataBufferType,
+ (length_in_bits + 7) / 8, 1, packedvps_buffer,
+ &packedvps_data_bufid);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+ render_id[0] = packedvps_para_bufid;
+ render_id[1] = packedvps_data_bufid;
+ va_status = vaRenderPicture(va_dpy,context_id, render_id, 2);
+ CHECK_VASTATUS(va_status,"vaRenderPicture");
+
+ free(packedvps_buffer);
+
+ return 0;
+}
+
+
static void render_packedsei(void)
{
VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
@@ -912,7 +1207,7 @@ static void render_packedsei(void)
&packed_sei_buffer);
//offset_in_bytes = 0;
- packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
+ packed_header_param_buffer.type = VAEncPackedHeaderHEVC_SEI;
packed_header_param_buffer.bit_length = length_in_bits;
packed_header_param_buffer.has_emulation_bytes = 0;
@@ -1031,10 +1326,10 @@ static int render_hrd(void)
misc_hrd_param->initial_buffer_fullness = misc_hrd_param->buffer_size * 0.875;
} else {
if (windows_size != 0) {
- misc_hrd_param->buffer_size = (uint32_t)((bits_size * (uint64_t)windows_size) / 1000);
+ misc_hrd_param->buffer_size = 0; //(uint32_t)((bits_size * (uint64_t)windows_size) / 1000);
} else
misc_hrd_param->buffer_size = frame_bitrate;
- misc_hrd_param->initial_buffer_fullness = misc_hrd_param->buffer_size * 0.875;
+ misc_hrd_param->initial_buffer_fullness = 0; //misc_hrd_param->buffer_size * 0.875;
}
vaUnmapBuffer(va_dpy, misc_parameter_hrd_buf_id);
@@ -1047,73 +1342,88 @@ static int render_hrd(void)
static int render_slice(void)
{
- VABufferID slice_param_buf;
+ VABufferID slice_param_buf_id = VA_INVALID_ID;
VAStatus va_status;
- VAEncSliceParameterBufferH264 *slice_param, *current_slice;
+ VAEncSliceParameterBufferHEVC *slice_param, *current_slice;
int i, j, frame_slice_cc = frame_slice_count;
int mb_rendered = 0;
+ slc_param.slice_beta_offset_div2 = 2;
+ slc_param.slice_fields.bits.slice_temporal_mvp_enabled_flag = 1;
+ slc_param.slice_fields.bits.collocated_from_l0_flag = 1;
+ slc_param.max_num_merge_cand = 5;
+
va_status = vaCreateBuffer(va_dpy, context_id, VAEncSliceParameterBufferType,
- sizeof(VAEncSliceParameterBufferH264), frame_slice_count, NULL, &slice_param_buf);
+ sizeof(VAEncSliceParameterBufferHEVC), frame_slice_count, &slc_param, &slice_param_buf_id);
CHECK_VASTATUS(va_status,"vaCreateBuffer");
- va_status = vaMapBuffer(va_dpy, slice_param_buf,
+ va_status = vaMapBuffer(va_dpy, slice_param_buf_id,
(void **)&slice_param);
CHECK_VASTATUS(va_status,"vaMapBuffer");
- memset((void *)slice_param, 0, sizeof(VAEncSliceParameterBufferH264) * frame_slice_count);
-
+
update_RefPicList();
for (j = 0; j < frame_slice_cc; j++) {
current_slice = slice_param + j;
- current_slice->disable_deblocking_filter_idc = 1;
- current_slice->macroblock_address = mb_rendered;
+ current_slice->slice_segment_address = mb_rendered;
if (j == frame_slice_cc - 1) {
- current_slice->num_macroblocks = (frame_width_mbaligned * frame_height_mbaligned) / (16 * 16) - mb_rendered;
+ // current_slice->num_ctu_in_slice = GET_CTU_NUM(frame_width_mbaligned, 32) * GET_CTU_NUM(frame_height_mbaligned, 32) - mb_rendered;
+ current_slice->num_ctu_in_slice = (frame_width_mbaligned * frame_height_mbaligned) / (32 * 32) - mb_rendered;
} else {
- current_slice->num_macroblocks = (frame_width_mbaligned * frame_slice_height) / (16 * 16);
- mb_rendered += current_slice->num_macroblocks;
+ //current_slice->num_ctu_in_slice = GET_CTU_NUM(frame_width_mbaligned, 32) * GET_CTU_NUM(frame_height_mbaligned, 32);
+ current_slice->num_ctu_in_slice = (frame_width_mbaligned * frame_slice_height) / (32 * 32);
+ mb_rendered += current_slice->num_ctu_in_slice;
}
- current_slice->slice_type = (current_frame_type == FRAME_IDR)? 2 : current_frame_type;
- if (current_frame_type == FRAME_IDR) {
- if (current_frame_encoding != 0)
- ++current_slice->idr_pic_id;
+
+ current_slice->slice_type = (current_frame_type == FRAME_IDR)? SLICE_TYPE_I : current_frame_type;
+ if ((current_frame_type == FRAME_IDR) || (current_frame_type == FRAME_I)) {
+ /* Reset reference for IDR also */
+ for (i = 0; i < 15; i++) {
+ current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
+ current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
+ }
} else if (current_frame_type == FRAME_P) {
int refpiclist0_max = hevc_maxref & 0xffff;
- memcpy(current_slice->RefPicList0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureH264));
+ //printf("refpiclist0_max %d\n", refpiclist0_max);
+ memcpy(current_slice->ref_pic_list0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureHEVC));
- for (i = refpiclist0_max; i < 32; i++) {
- current_slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
- current_slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
+ for (i = refpiclist0_max; i < 15; i++) {
+ current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
+ }
+
+ for (i = 0; i < 15; i++) {
+ current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
}
} else if (current_frame_type == FRAME_B) {
int refpiclist0_max = hevc_maxref & 0xffff;
int refpiclist1_max = (hevc_maxref >> 16) & 0xffff;
- memcpy(current_slice->RefPicList0, RefPicList0_B, refpiclist0_max*sizeof(VAPictureH264));
- for (i = refpiclist0_max; i < 32; i++) {
- current_slice->RefPicList0[i].picture_id = VA_INVALID_SURFACE;
- current_slice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
+ memcpy(current_slice->ref_pic_list0, RefPicList0_B, refpiclist0_max*sizeof(VAPictureHEVC));
+ for (i = refpiclist0_max; i < 15; i++) {
+ current_slice->ref_pic_list0[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list0[i].flags = VA_PICTURE_HEVC_INVALID;
}
- memcpy(current_slice->RefPicList1, RefPicList1_B, refpiclist1_max*sizeof(VAPictureH264));
- for (i = refpiclist1_max; i < 32; i++) {
- current_slice->RefPicList1[i].picture_id = VA_INVALID_SURFACE;
- current_slice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
+ memcpy(current_slice->ref_pic_list1, RefPicList1_B, refpiclist1_max*sizeof(VAPictureHEVC));
+ for (i = refpiclist1_max; i < 15; i++) {
+ current_slice->ref_pic_list1[i].picture_id = VA_INVALID_SURFACE;
+ current_slice->ref_pic_list1[i].flags = VA_PICTURE_HEVC_INVALID;
}
}
- current_slice->slice_alpha_c0_offset_div2 = 0;
current_slice->slice_beta_offset_div2 = 0;
- current_slice->direct_spatial_mv_pred_flag = 1;
- current_slice->pic_order_cnt_lsb = (current_frame_display - current_IDR_display) % MaxPicOrderCntLsb;
}
- va_status = vaUnmapBuffer(va_dpy, slice_param_buf);
+ va_status = vaUnmapBuffer(va_dpy, slice_param_buf_id);
CHECK_VASTATUS(va_status,"vaUnmapBuffer");
- va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf, 1);
+ va_status = vaRenderPicture(va_dpy, context_id, &slice_param_buf_id, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
+
return 0;
}
@@ -1159,15 +1469,20 @@ static VAStatus hevc_render_frame(unsigned int mask, struct rc_param_t *rc_param
numShortTerm = 0;
current_frame_num = 0;
current_IDR_display = current_frame_display;
+ frame_poc = 0;
}
if (current_frame_type == FRAME_IDR) {
- render_framerate();
- render_sequence(rc_param);
- render_picture();
if (hevc_packedheader) {
+ render_packedvps();
render_packedsequence();
render_packedpicture();
}
+ render_sequence(rc_param);
+ render_picture();
+ render_hrd();
+ render_rcparam(mask, rc_param);
+ render_framerate();
+ render_qualitylevel();
if (rc_mode == VA_RC_CBR) {
//render_packedsei();
render_hrd();
@@ -1181,20 +1496,23 @@ static VAStatus hevc_render_frame(unsigned int mask, struct rc_param_t *rc_param
if (max_slice_size) {
render_max_slice_size();
}
+ if (roi_enable)
+ render_roi();
} else {
- //render_sequence();
+ render_packedpicture();
+ //render_sequence(rc_param);
render_picture();
- //if (rc_mode == VA_RC_CBR)
- // render_packedsei();
- //render_hrd();
+ if (roi_enable)
+ render_roi();
}
if (mask)
render_rcparam(mask, rc_param);
+ render_packedslice();
render_slice();
-
- update_ReferenceFrames();
-
+
+ update_ReferenceFrames();
+
return VA_STATUS_SUCCESS;
}
@@ -1207,14 +1525,15 @@ static VAStatus hevc_get_config(void)
int support_encode = 0;
VAStatus va_status;
unsigned int i;
+ unsigned int rc_value = 0;
if (va_profile_str) {
if (strncmp(va_profile_str, "MP", 2) == 0)
hevc_profile = VAProfileHEVCMain;
- else if (strncmp(va_profile_str, "MP10", 2) == 0)
+ else if (strncmp(va_profile_str, "MP10", 4) == 0)
hevc_profile = VAProfileHEVCMain10;
}
-
+
/* use the highest profile */
for (i = 0; i < sizeof(profile_list)/sizeof(profile_list[0]); i++) {
if ((hevc_profile != -1) && hevc_profile != profile_list[i])
@@ -1223,7 +1542,8 @@ static VAStatus hevc_get_config(void)
hevc_profile = profile_list[i];
vaQueryConfigEntrypoints(va_dpy, hevc_profile, entrypoints, &num_entrypoints);
for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
- if (entrypoints[slice_entrypoint] == VAEntrypointEncSlice) {
+ printf("entrypoint support %d\n", entrypoints[slice_entrypoint]);
+ if (entrypoints[slice_entrypoint] == va_entrypoint) {
support_encode = 1;
break;
}
@@ -1296,12 +1616,39 @@ static VAStatus hevc_get_config(void)
printf("Desired rc mode %s is not supported, exit\n", rc_to_string(rc_mode));
exit(1);
}
-
+
config_attrib[config_attrib_num].type = VAConfigAttribRateControl;
- config_attrib[config_attrib_num].value = rc_mode;
+ if (rc_mode == VA_RC_CBR || rc_mode == VA_RC_VBR)
+ rc_value = VA_RC_MB | rc_mode;
+ else
+ rc_value = rc_mode;
+ config_attrib[config_attrib_num].value = rc_value; //rc_mode;
config_attrib_num++;
}
+ if (hevc_attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support %d slices\n", hevc_attrib[VAConfigAttribEncMaxSlices].value);
+ config_attrib[config_attrib_num].type = VAConfigAttribEncMaxSlices;
+ config_attrib[config_attrib_num].value = 256;
+ config_attrib_num++;
+ }
+
+ if (hevc_attrib[VAConfigAttribEncSliceStructure].value != VA_ATTRIB_NOT_SUPPORTED) {
+ int tmp = hevc_attrib[VAConfigAttribEncSliceStructure].value;
+
+ printf("Support VAConfigAttribEncSliceStructure\n");
+ config_attrib[config_attrib_num].type = VAConfigAttribEncSliceStructure;
+ config_attrib[config_attrib_num].value = VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS;
+ config_attrib_num++;
+#if 0
+ if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS)
+ printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS\n");
+ if (tmp & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS)
+ printf("Support VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS\n");
+ if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS)
+ printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS\n");
+#endif
+ }
if (hevc_attrib[VAConfigAttribEncPackedHeaders].value != VA_ATTRIB_NOT_SUPPORTED) {
int tmp = hevc_attrib[VAConfigAttribEncPackedHeaders].value;
@@ -1359,32 +1706,40 @@ static VAStatus hevc_get_config(void)
printf("Support %d RefPicList0 and %d RefPicList1\n",
hevc_maxref & 0xffff, (hevc_maxref >> 16) & 0xffff );
+ config_attrib[config_attrib_num].type = VAConfigAttribEncMaxRefFrames;
+ config_attrib[config_attrib_num].value = hevc_maxref;
+ config_attrib_num++;
}
- if (hevc_attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED)
- printf("Support %d slices\n", hevc_attrib[VAConfigAttribEncMaxSlices].value);
-
- if (hevc_attrib[VAConfigAttribEncSliceStructure].value != VA_ATTRIB_NOT_SUPPORTED) {
- int tmp = hevc_attrib[VAConfigAttribEncSliceStructure].value;
-
- printf("Support VAConfigAttribEncSliceStructure\n");
+ if (hevc_attrib[VAConfigAttribEncQualityRange].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support VAConfigAttribEncQualityRange\n");
+ config_attrib[config_attrib_num].type = VAConfigAttribEncQualityRange;
+ config_attrib[config_attrib_num].value = 7;
+ config_attrib_num++;
+ }
- if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS)
- printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS\n");
- if (tmp & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS)
- printf("Support VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS\n");
- if (tmp & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS)
- printf("Support VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS\n");
+ if (hevc_attrib[VAConfigAttribEncIntraRefresh].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support VAConfigAttribEncIntraRefresh\n");
+ config_attrib[config_attrib_num].type = VAConfigAttribEncIntraRefresh;
+ config_attrib_num++;
}
- if (hevc_attrib[VAConfigAttribEncMacroblockInfo].value != VA_ATTRIB_NOT_SUPPORTED) {
- printf("Support VAConfigAttribEncMacroblockInfo\n");
+ if (hevc_attrib[VAConfigAttribEncROI].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support VAConfigAttribEncROI\n");
+ config_attrib[config_attrib_num].type = VAConfigAttribEncROI;
+ config_attrib_num++;
+ }
+
+ if (hevc_attrib[VAConfigAttribEncFunctionTypeIntel].value != VA_ATTRIB_NOT_SUPPORTED) {
+ printf("Support VAConfigAttribEncFunctionTypeIntel\n");
+ config_attrib[config_attrib_num].type = VAConfigAttribEncFunctionTypeIntel;
+ config_attrib_num++;
}
if (hevc_attrib[VAConfigAttribEncAutoReference].value != VA_ATTRIB_NOT_SUPPORTED) {
printf("Support VAConfigAttribEncAutoReference\n");
hevc_autoref = 1;
}
-
+
va_profile = hevc_profile;
va_entrypoint = VAEntrypointEncSlice;
@@ -1412,6 +1767,7 @@ static int hevc_save_codeddata(FILE *coded_fp, VACodedBufferSegment *buf_list,
while (p != NULL) {
*rec_surfaceid = ref_surface[p->reserved];
+
coded_size += fwrite(p->buf, 1, p->size, coded_fp);
p = (VACodedBufferSegment *) p->next;
}
diff --git a/vaenc/va_encode.c b/vaenc/va_encode.c
index 4fb4ae8..e5cadb7 100644
--- a/vaenc/va_encode.c
+++ b/vaenc/va_encode.c
@@ -316,7 +316,7 @@ static int print_help(void)
{
printf("./va_encode <options>\n");
printf(" -i : interactive mode, stop at every frame encoding\n");
- printf(" -t <H264|MPEG4|H263|JPEG|VP8>\n");
+ printf(" -t <H264|MPEG4|H263|JPEG|VP8|HEVC>\n");
printf(" -w <width> -h <height>\n");
printf(" -framecount <frame number>\n");
printf(" -n <frame number>\n");
@@ -497,6 +497,8 @@ static int process_cmdline(int argc, char *argv[])
current_codec = &h264_codec;
else if (!strncmp(optarg, "JPEG", 4))
current_codec = &jpeg_codec;
+ else if (!strncmp(optarg, "HEVC", 4))
+ current_codec = &hevc_codec;
else {
print_help();
exit(0);
@@ -667,6 +669,7 @@ static int process_cmdline(int argc, char *argv[])
riff_file = 0;
break;
case 37:
+ ivf_file = 0;
riff_file = 1;
frame_count = 1;
break;
@@ -911,6 +914,10 @@ static int process_cmdline(int argc, char *argv[])
if (current_codec != &vp8_codec) {
frame_width_mbaligned = (frame_width + 15) & (~15);
frame_height_mbaligned = (frame_height + 15) & (~15);
+ if (current_codec == &hevc_codec) {
+ frame_width_mbaligned = (frame_width + 31) & (~31);
+ frame_height_mbaligned = (frame_height + 31) & (~31);
+ }
} else {
frame_width_mbaligned = frame_width;
frame_height_mbaligned = frame_height;
@@ -1236,7 +1243,7 @@ static int save_codeddata(unsigned int display_order, unsigned int encode_order,
if (coded_fp == NULL)
printf("Open file %s error (%s)\n", fn, strerror(errno));
}
-
+
if ((dump_frame == 0) && current_codec->save_codeddata) {
coded_size = current_codec->save_codeddata(coded_fp, buf_list, rec_surfaceid);
save_frame_size_log(encode_order, coded_size);
diff --git a/vaenc/va_encode.h b/vaenc/va_encode.h
index 0341692..02be4e7 100644
--- a/vaenc/va_encode.h
+++ b/vaenc/va_encode.h
@@ -311,4 +311,5 @@ extern struct codec_table_t mpeg4_codec;
extern struct codec_table_t h263_codec;
extern struct codec_table_t vp8_codec;
extern struct codec_table_t jpeg_codec;
+extern struct codec_table_t hevc_codec;
static struct codec_table_t *current_codec = &h264_codec;
diff --git a/vaenc/vp8encode.c b/vaenc/vp8encode.c
index 068eccd..eb00548 100644
--- a/vaenc/vp8encode.c
+++ b/vaenc/vp8encode.c
@@ -184,6 +184,8 @@ static VAStatus render_picture(struct rc_param_t *rc_param, int num)
pic_vp8.coded_buf = coded_buf[current_slot];
pic_vp8.pic_flags.value = 0;
pic_vp8.pic_flags.bits.frame_type = (current_frame_type != FRAME_IDR);
+ if (riff_file)
+ pic_vp8.pic_flags.bits.show_frame = 1;
#if 0
pic_vp8.pic_flags.bits.no_ref_arf = 1;
pic_vp8.pic_flags.bits.no_ref_gf = 1;
@@ -521,7 +523,7 @@ static VAStatus vp8_render_frame(unsigned int mask, struct rc_param_t *rc_param)
render_framerate_param(mask, rc_param, i);
render_rcparam(mask, rc_param, i);
render_hrdparam();
- render_max_framesize_param();
+ //render_max_framesize_param();
if (layer_num > 1) {
render_layer_structure_param();
for (i = 0; i < layer_num; i++) {
@@ -619,7 +621,7 @@ static int vp8_save_codeddata(FILE *coded_fp, VACodedBufferSegment *buf_list,
riff_header[9] = 'E';
riff_header[10] = 'B';
riff_header[11] = 'P';
- mem_put_le32(riff_header+12, 0x20385056); // raw video format
+ mem_put_le32(riff_header+12, 0x20385056); // raw video format "VP8 "
mem_put_le32(riff_header+16, frame_length); // frame_size
coded_size += fwrite(riff_header, 1, 20, coded_fp);
}
@@ -628,7 +630,7 @@ static int vp8_save_codeddata(FILE *coded_fp, VACodedBufferSegment *buf_list,
p = buf_list;
if(p!=NULL)
*rec_surfaceid = p->reserved;
-
+
/* write the data */
while (p != NULL) {
coded_size += fwrite(p->buf, 1, p->size, coded_fp);
diff --git a/yuvtool/main.c b/yuvtool/main.c
index 964d54f..1e7e3a7 100644
--- a/yuvtool/main.c
+++ b/yuvtool/main.c
@@ -47,6 +47,7 @@
#include <sys/shm.h>
#include <sys/time.h>
#include <assert.h>
+#include <errno.h>
#include <../utils/va_wrapper.h>
#include <../utils/loadsurface_yuv.h>
@@ -71,6 +72,7 @@ static int frame_rate=30,frame_num=1;
static struct timeval tftarget;
static int output_psnr_file = 0;
static int rotate_degree = 90;
+static int psnr_each_frame = 0;
static int GetPortId(Display *dpy)
{
@@ -736,16 +738,18 @@ static int rotate_yuv(void)
static int exit_with_help(void)
{
- printf("yuvtool <display|convert|psnr|ssim|create|rotate> <options>\n");
+ printf("yuvtool <display|convert|psnr|ssim|create|rotate|md5> <options>\n");
printf(" for display, options is: -s <widthxheight> -i <input YUV file> -ifourcc <input fourcc> -path <output path>\n");
printf(" for create, options is: -s <widthxheight> -n <frame number> -i <input YUV file> -ifourcc <input fourcc>\n");
printf(" for convert, options is: -s <widthxheight> -i <input YUV file> -ifourcc <input fourcc>\n");
printf(" -o <output YUV file> -ofourcc <output fourcc>\n");
printf(" currently, support NV12<->I420/YV12 BMP->NV12 conversion\n");
- printf(" for psnr, options is: -s <widthxheight> -i <input YUV file> -o <output YUV file> -n <frame number>\n");
+ printf(" for psnr, options is: -s <widthxheight> -i <input YUV file> -o <output YUV file> -n <frame number> -e\n");
printf(" The two files should be same with width same FOURCC and resolution\n");
+ printf(" -e will calculate each frame psnr\n");
printf(" for ssim, options is: -s <widthxheight> -i <reference YUV file> -o <reconstructed YUV file> -n <frame number>\n");
- printf(" The two files should be same with width same FOURCC and resolution\n");
+ printf(" for md5, options is: -s <widthxheight> -i <reference YUV file> -ifourcc <input fourcc>\n");
+ printf(" Calculate the MD5 of each frame for static frame analyze\n");
printf(" for crc, options is:-s widthxheight -i <input YUV file>\n");
printf(" for scale, options is:-s widthxheight -i <input YUV file> -ifourcc <input fourcc> \n");
printf(" -S widthxheight -o <output YUV file>\n");
@@ -789,14 +793,32 @@ static int psnr_yuv(void)
{
double psnr = 0, mse = 0;
double psnr_y, psnr_u, psnr_v;
-
+ int i;
+
fprintf(stdout,"Calculate PSNR %s vs %s, (%dx%d, %d frames)\n",
input_fn, output_fn, width, height, frame_num);
- calc_PSNR(input_fp, output_fp, width, height, frame_num,
- &psnr, &psnr_y, &psnr_u, &psnr_v, &mse);
+
+ if (psnr_each_frame == 0) {
+ calc_PSNR(input_fp, output_fp, width, height, frame_num,
+ &psnr, &psnr_y, &psnr_u, &psnr_v, &mse);
+
+ printf("PSNR: %.2f (Y=%.2f,U=%.2f, V=%.2f)\n", psnr, psnr_y, psnr_u, psnr_v);
+ return 0;
+ }
+
+
+ for (i=0; i<frame_num; i++) {
+ psnr_y = psnr_u = psnr_v = psnr = mse = 0;
+ calc_PSNR(input_fp, output_fp, width, height, 1,
+ &psnr, &psnr_y, &psnr_u, &psnr_v, &mse);
+ fseek(input_fp, width*height*1.5, SEEK_CUR);
+ fseek(output_fp, width*height*1.5, SEEK_CUR);
+
+ printf("Frame %d: PSNR: %.2f (Y=%.2f,U=%.2f, V=%.2f)\n", i, psnr, psnr_y, psnr_u, psnr_v);
- printf("PSNR: %.2f (Y=%.2f,U=%.2f, V=%.2f\n", psnr, psnr_y, psnr_u, psnr_v);
+ }
+
return 0;
}
@@ -816,6 +838,78 @@ static int ssim_yuv(void)
}
+static int md5_yuv(void)
+{
+ unsigned int frame_size = width * height * 1.5;
+ char tmp_template[32] = { 'm', 'd', '5', 'X','X','X','X','X','X' };
+ char *tmp_fn, *one_frame, popen_cmd[64];
+ FILE *tmp_fp;
+ int current_frame = 0;
+
+ fprintf(stdout, "Calculate each frame MD5, (%dx%d, %d frames)\n",
+ width, height, frame_num);
+
+ tmp_fn = mktemp(tmp_template);
+ tmp_fp = fopen(tmp_fn, "w+");
+ if (tmp_fp == NULL) {
+ printf("Open temp file %s failed (%s)\n", tmp_fn, strerror(errno));
+ exit(1);
+ }
+
+ one_frame = malloc(frame_size);
+ if (one_frame == NULL) {
+ printf("malloc error %s, exit\n", strerror(errno));
+ exit(1);
+ }
+
+ sprintf(popen_cmd, "md5sum %s", tmp_fn);
+ while (frame_num-- > 0) {
+ char last_md5sum_output[256];
+ char md5sum_output[256];
+
+ FILE *popen_fp;
+ int i;
+
+ fread(one_frame, frame_size, 1, input_fp);
+
+ rewind(tmp_fp);
+ fwrite(one_frame, frame_size, 1, tmp_fp);
+ fflush(tmp_fp);
+ fsync(fileno(tmp_fp));
+
+ popen_fp = popen(popen_cmd, "r");
+ if (popen_fp == NULL) {
+ printf("Failed to md5sum command\n" );
+ exit(1);
+ }
+ fgets(md5sum_output, sizeof(md5sum_output), popen_fp);
+ pclose(popen_fp);
+
+ printf("Frame %d md5: ", current_frame);
+
+ for (i=0; i<sizeof(md5sum_output); i++) {
+ if (md5sum_output[i] == ' ')
+ md5sum_output[i] = '\0';
+ }
+ if ((current_frame > 0) &&
+ (strcmp(md5sum_output, last_md5sum_output) == 0))
+ printf("***identicle***");
+ else
+ printf(md5sum_output);
+
+ current_frame ++;
+ strcpy(last_md5sum_output, md5sum_output);
+
+ printf("\n");
+ }
+
+ free(one_frame);
+ fclose(tmp_fp);
+
+ return 0;
+}
+
+
static int scale_yuv(void)
{
int tmp=0,i=0;
@@ -932,22 +1026,22 @@ static int YUV_Generator_Planar(int width, int height,
unsigned char *Y_start, int Y_pitch,
unsigned char *U_start, int U_pitch,
unsigned char *V_start, int V_pitch,
- int UV_interleave)
+ unsigned int fourcc)
{
static int row_shift = 0;
int box_width = 8;
- row_shift++;
if (row_shift == 16) row_shift = 0;
- V_start = U_start + 1;
yuvgen_planar(width, height,
Y_start, Y_pitch,
U_start, U_pitch,
V_start, V_pitch,
- VA_FOURCC_NV12, box_width, row_shift,
+ fourcc, box_width, row_shift,
0);
+ row_shift++;
+
return 0;
}
@@ -969,7 +1063,7 @@ static int create_yuv(void)
one_frame, width,
one_frame + width*height, width/2,
one_frame + width*height + (width/2)*(height/2), width/2,
- 0);
+ ifourcc);
fwrite(one_frame, width*height*1.5, 1, input_fp);
}
} else if ((ifourcc == VA_FOURCC_YV12)) {
@@ -978,7 +1072,7 @@ static int create_yuv(void)
one_frame, width,
one_frame + width*height + (width/2)*(height/2), width/2,
one_frame + width*height, width/2,
- 0);
+ ifourcc);
fwrite(one_frame, width*height*1.5, 1, input_fp);
}
} else if (ifourcc == VA_FOURCC_NV12) {
@@ -987,7 +1081,7 @@ static int create_yuv(void)
one_frame, width,
one_frame + width*height, width,
one_frame + width*height, width,
- 1);
+ ifourcc);
fwrite(one_frame, width*height*1.5, 1, input_fp);
}
} else {
@@ -1007,7 +1101,8 @@ static enum {
SSIM,
CREATE,
SCALE,
- ROTATE
+ ROTATE,
+ MD5
} operation;
@@ -1047,6 +1142,8 @@ int main(int argc, char **argv)
operation = SCALE;
else if (strcmp(argv[1],"rotate") == 0)
operation = ROTATE;
+ else if (strcmp(argv[1],"md5") == 0)
+ operation = MD5;
else {
printf("ERROR:The first parameter isn't <scale|display|convert|psnr|create|crc>, exit\n");
exit_with_help();
@@ -1056,7 +1153,7 @@ int main(int argc, char **argv)
argc--;
argv++;
- while ((c=getopt_long_only(argc,argv,"fn:s:S:i:d:o:h?",long_opts,&long_index)) != -1) {
+ while ((c=getopt_long_only(argc,argv,"fen:s:S:i:d:o:h?",long_opts,&long_index)) != -1) {
switch (c) {
case 'h':
case '?':
@@ -1066,6 +1163,9 @@ int main(int argc, char **argv)
case 'f':
output_psnr_file = 1;
break;
+ case 'e':
+ psnr_each_frame = 1;
+ break;
case 'n':
input_frame_num = atoi(optarg);
break;
@@ -1188,6 +1288,7 @@ int main(int argc, char **argv)
if (operation == ROTATE) rotate_yuv();
if (operation == PSNR) psnr_yuv();
if (operation == SSIM) ssim_yuv();
+ if (operation == MD5) md5_yuv();
if (operation == CONVERT && ifourcc == VA_FOURCC_BMP24)
bmp2yuv(input_fp, output_fp, ofourcc);
else if (operation == CONVERT)