summaryrefslogtreecommitdiff
path: root/test/encode
diff options
context:
space:
mode:
authorAustin Yuan <shengquan.yuan@intel.com>2013-05-22 11:02:34 +0800
committerbuildbot <buildbot@intel.com>2013-05-28 04:04:40 -0700
commit2efbafef6046e1d9372c58de2b0d7b03377c686c (patch)
tree8e745dbdae309f8d2f09969f61d5ba345bf6a9da /test/encode
parent6044ab9a375eb73b08f45d87966652f98f918668 (diff)
downloadlibva-2efbafef6046e1d9372c58de2b0d7b03377c686c.tar.gz
rebase libva to latest staging
BZ: 109833 The rebase is trying to fix some "medium" KW issue, and bugs of vatrace to help dubugging Change-Id: Ibd9b86eb98d4a79f4452bee2dff7960d8d54ffd5 Signed-off-by: Austin Yuan <shengquan.yuan@intel.com> Reviewed-on: http://android.intel.com:8080/109154 Reviewed-by: Shi, PingX <pingx.shi@intel.com> Tested-by: Shi, PingX <pingx.shi@intel.com> Reviewed-by: buildbot <buildbot@intel.com> Tested-by: buildbot <buildbot@intel.com>
Diffstat (limited to 'test/encode')
-rwxr-xr-xtest/encode/Android.mk2
-rw-r--r--test/encode/Makefile.am2
-rw-r--r--test/encode/h264encode.c464
3 files changed, 312 insertions, 156 deletions
diff --git a/test/encode/Android.mk b/test/encode/Android.mk
index 58e9bb6..4cba3c3 100755
--- a/test/encode/Android.mk
+++ b/test/encode/Android.mk
@@ -21,7 +21,7 @@ LOCAL_C_INCLUDES += \
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := h264encode
-LOCAL_SHARED_LIBRARIES := libva-android libva libdl libdrm libcutils libutils libgui
+LOCAL_SHARED_LIBRARIES := libva-android libva libdl libdrm libcutils libutils libgui libm
include $(BUILD_EXECUTABLE)
diff --git a/test/encode/Makefile.am b/test/encode/Makefile.am
index b48e8ae..a76509c 100644
--- a/test/encode/Makefile.am
+++ b/test/encode/Makefile.am
@@ -33,7 +33,7 @@ h264encode_CFLAGS = -I$(top_srcdir)/test/common -g
h264encode_LDADD = \
$(top_builddir)/va/libva.la \
$(top_builddir)/test/common/libva-display.la \
- -lpthread
+ -lpthread -lm
avcenc_SOURCES = avcenc.c
avcenc_CFLAGS = -I$(top_srcdir)/test/common -g
diff --git a/test/encode/h264encode.c b/test/encode/h264encode.c
index c39dcd1..b862393 100644
--- a/test/encode/h264encode.c
+++ b/test/encode/h264encode.c
@@ -30,9 +30,12 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
+#include <sys/mman.h>
#include <fcntl.h>
#include <assert.h>
#include <pthread.h>
+#include <errno.h>
+#include <math.h>
#include <va/va.h>
#include <va/va_enc_h264.h>
#include "va_display.h"
@@ -69,11 +72,10 @@
#define BITSTREAM_ALLOCATE_STEPPING 4096
-
#define SURFACE_NUM 16 /* 16 surfaces for source YUV */
#define SURFACE_NUM 16 /* 16 surfaces for reference */
static VADisplay va_dpy;
-static VAProfile h264_profile;
+static VAProfile h264_profile = ~0;
static VAConfigAttrib attrib[VAConfigAttribTypeMax];
static VAConfigAttrib config_attrib[VAConfigAttribTypeMax];
static int config_attrib_num = 0;
@@ -98,20 +100,25 @@ static unsigned int numShortTerm = 0;
static int constraint_set_flag = 0;
static int h264_packedheader = 0; /* support pack header? */
static int h264_maxref = (1<<16|1);
+static int h264_entropy_mode = 1; /* cabac */
+
static char *coded_fn = NULL, *srcyuv_fn = NULL, *recyuv_fn = NULL;
static FILE *coded_fp = NULL, *srcyuv_fp = NULL, *recyuv_fp = NULL;
static unsigned long long srcyuv_frames = 0;
static int srcyuv_fourcc = VA_FOURCC_NV12;
+static int calc_psnr = 0;
static int frame_width = 176;
static int frame_height = 144;
+static int frame_width_mbaligned;
+static int frame_height_mbaligned;
static int frame_rate = 30;
static unsigned int frame_count = 60;
static unsigned int frame_coded = 0;
static unsigned int frame_bitrate = 0;
static unsigned int frame_slices = 1;
static double frame_size = 0;
-static int initial_qp = 28;
+static int initial_qp = 26;
static int minimal_qp = 0;
static int intra_period = 30;
static int intra_idr_period = 60;
@@ -120,10 +127,16 @@ static int rc_mode = VA_RC_VBR;
static unsigned long long current_frame_encoding = 0;
static unsigned long long current_frame_display = 0;
static unsigned long long current_IDR_display = 0;
-static int current_frame_num = 0;
+static unsigned int current_frame_num = 0;
static int current_frame_type;
#define current_slot (current_frame_display % SURFACE_NUM)
+static int misc_priv_type = 0;
+static int misc_priv_value = 0;
+
+#define MIN(a, b) ((a)>(b)?(b):(a))
+#define MAX(a, b) ((a)>(b)?(a):(b))
+
/* thread to save coded data/upload source YUV */
struct storage_task_t {
void *next;
@@ -691,7 +704,9 @@ static int print_help(void)
{
printf("./h264encode <options>\n");
printf(" -w <width> -h <height>\n");
+ printf(" -framecount <frame number>\n");
printf(" -n <frame number>\n");
+ printf(" if set to 0 and srcyuv is set, the frame count is from srcuv file\n");
printf(" -o <coded file>\n");
printf(" -f <frame rate>\n");
printf(" --intra_period <number>\n");
@@ -703,8 +718,11 @@ static int print_help(void)
printf(" --rcmode <NONE|CBR|VBR|VCM|CQP|VBR_CONTRAINED>\n");
printf(" --syncmode: sequentially upload source, encoding, save result, no multi-thread\n");
printf(" --srcyuv <filename> load YUV from a file\n");
- printf(" --fourcc <NV12|IYUV|I420|YV12> source YUV fourcc\n");
-
+ printf(" --fourcc <NV12|IYUV|YV12> source YUV fourcc\n");
+ printf(" --recyuv <filename> save reconstructed YUV into a file\n");
+ printf(" --enablePSNR calculate PSNR of recyuv vs. srcyuv\n");
+ printf(" --entropy <0|1>, 1 means cabac, 0 cavlc\n");
+ printf(" --profile <BP|MP|HP>\n");
return 0;
}
@@ -712,6 +730,7 @@ static int process_cmdline(int argc, char *argv[])
{
char c;
const struct option long_opts[] = {
+ {"help", no_argument, NULL, 0 },
{"bitrate", required_argument, NULL, 1 },
{"minqp", required_argument, NULL, 2 },
{"initialqp", required_argument, NULL, 3 },
@@ -720,8 +739,15 @@ static int process_cmdline(int argc, char *argv[])
{"ip_period", required_argument, NULL, 6 },
{"rcmode", required_argument, NULL, 7 },
{"srcyuv", required_argument, NULL, 9 },
- {"fourcc", required_argument, NULL, 10 },
- {"syncmode", no_argument, NULL, 11 },
+ {"recyuv", required_argument, NULL, 10 },
+ {"fourcc", required_argument, NULL, 11 },
+ {"syncmode", no_argument, NULL, 12 },
+ {"enablePSNR", no_argument, NULL, 13 },
+ {"prit", required_argument, NULL, 14 },
+ {"priv", required_argument, NULL, 15 },
+ {"framecount", required_argument, NULL, 16 },
+ {"entropy", required_argument, NULL, 17 },
+ {"profile", required_argument, NULL, 18 },
{NULL, no_argument, NULL, 0 }};
int long_index;
@@ -734,6 +760,7 @@ static int process_cmdline(int argc, char *argv[])
frame_height = atoi(optarg);
break;
case 'n':
+ case 16:
frame_count = atoi(optarg);
break;
case 'f':
@@ -742,6 +769,9 @@ static int process_cmdline(int argc, char *argv[])
case 'o':
coded_fn = strdup(optarg);
break;
+ case 0:
+ print_help();
+ exit(0);
case 1:
frame_bitrate = atoi(optarg);
break;
@@ -771,15 +801,40 @@ static int process_cmdline(int argc, char *argv[])
srcyuv_fn = strdup(optarg);
break;
case 10:
+ recyuv_fn = strdup(optarg);
+ break;
+ case 11:
srcyuv_fourcc = string_to_fourcc(optarg);
if (srcyuv_fourcc <= 0) {
print_help();
exit(1);
}
break;
- case 11:
+ case 12:
encode_syncmode = 1;
break;
+ case 13:
+ calc_psnr = 1;
+ break;
+ case 14:
+ misc_priv_type = strtol(optarg, NULL, 0);
+ break;
+ case 15:
+ misc_priv_value = strtol(optarg, NULL, 0);
+ break;
+ case 17:
+ h264_entropy_mode = atoi(optarg) ? 1: 0;
+ break;
+ case 18:
+ if (strncmp(optarg, "BP", 2) == 0)
+ h264_profile = VAProfileH264Baseline;
+ else if (strncmp(optarg, "MP", 2) == 0)
+ h264_profile = VAProfileH264Main;
+ else if (strncmp(optarg, "HP", 2) == 0)
+ h264_profile = VAProfileH264High;
+ else
+ h264_profile = 0;
+ break;
case ':':
case '?':
print_help();
@@ -810,11 +865,24 @@ static int process_cmdline(int argc, char *argv[])
if (srcyuv_fp == NULL)
printf("Open source YUV file %s failed, use auto-generated YUV data\n", srcyuv_fn);
else {
- fseek(srcyuv_fp, 0L, SEEK_END);
- srcyuv_frames = ftell(srcyuv_fp) / (frame_width * frame_height * 1.5);
+ struct stat tmp;
+
+ fstat(fileno(srcyuv_fp), &tmp);
+ srcyuv_frames = tmp.st_size / (frame_width * frame_height * 1.5);
printf("Source YUV file %s with %llu frames\n", srcyuv_fn, srcyuv_frames);
+
+ if (frame_count == 0)
+ frame_count = srcyuv_frames;
}
}
+
+ /* open source file */
+ if (recyuv_fn) {
+ recyuv_fp = fopen(recyuv_fn,"w+");
+
+ if (recyuv_fp == NULL)
+ printf("Open reconstructed YUV file %s failed\n", recyuv_fn);
+ }
if (coded_fn == NULL) {
struct stat buf;
@@ -833,6 +901,15 @@ static int process_cmdline(int argc, char *argv[])
exit(1);
}
+ frame_width_mbaligned = (frame_width + 15) & (~15);
+ frame_height_mbaligned = (frame_height + 15) & (~15);
+ if (frame_width != frame_width_mbaligned ||
+ frame_height != frame_height_mbaligned) {
+ printf("Source frame is %dx%d and will code clip to %dx%d with crop\n",
+ frame_width, frame_height,
+ frame_width_mbaligned, frame_height_mbaligned
+ );
+ }
return 0;
}
@@ -853,6 +930,9 @@ static int init_va(void)
/* use the highest profile */
for (i = 0; i < sizeof(profile_list)/sizeof(profile_list[0]); i++) {
+ if ((h264_profile != ~0) && h264_profile != profile_list[i])
+ continue;
+
h264_profile = profile_list[i];
vaQueryConfigEntrypoints(va_dpy, h264_profile, entrypoints, &num_entrypoints);
for (slice_entrypoint = 0; slice_entrypoint < num_entrypoints; slice_entrypoint++) {
@@ -874,6 +954,7 @@ static int init_va(void)
printf("Use profile VAProfileH264Baseline\n");
ip_period = 1;
constraint_set_flag |= (1 << 0); /* Annex A.2.1 */
+ h264_entropy_mode = 0;
break;
case VAProfileH264ConstrainedBaseline:
printf("Use profile VAProfileH264ConstrainedBaseline\n");
@@ -919,7 +1000,7 @@ static int init_va(void)
if (attrib[VAConfigAttribRateControl].value != VA_ATTRIB_NOT_SUPPORTED) {
int tmp = attrib[VAConfigAttribRateControl].value;
- printf("Supported rate control mode (0x%x):", tmp);
+ printf("Support rate control mode (0x%x):", tmp);
if (tmp & VA_RC_NONE)
printf("NONE ");
@@ -997,7 +1078,8 @@ static int init_va(void)
if (attrib[VAConfigAttribEncMaxRefFrames].value != VA_ATTRIB_NOT_SUPPORTED) {
h264_maxref = attrib[VAConfigAttribEncMaxRefFrames].value;
- printf("Support %d reference frames\n", h264_maxref);
+ printf("Support %d RefPicList0 and %d RefPicList1\n",
+ h264_maxref & 0xffff, (h264_maxref >> 16) & 0xffff );
}
if (attrib[VAConfigAttribEncMaxSlices].value != VA_ATTRIB_NOT_SUPPORTED)
@@ -1034,7 +1116,7 @@ static int setup_encode()
/* create source surfaces */
va_status = vaCreateSurfaces(va_dpy,
- VA_RT_FORMAT_YUV420, frame_width, frame_height,
+ VA_RT_FORMAT_YUV420, frame_width_mbaligned, frame_height_mbaligned,
&src_surface[0], SURFACE_NUM,
NULL, 0);
CHECK_VASTATUS(va_status, "vaCreateSurfaces");
@@ -1042,7 +1124,7 @@ static int setup_encode()
/* create reference surfaces */
va_status = vaCreateSurfaces(
va_dpy,
- VA_RT_FORMAT_YUV420, frame_width, frame_height,
+ VA_RT_FORMAT_YUV420, frame_width_mbaligned, frame_height_mbaligned,
&ref_surface[0], SURFACE_NUM,
NULL, 0
);
@@ -1054,14 +1136,14 @@ static int setup_encode()
/* Create a context for this encode pipe */
va_status = vaCreateContext(va_dpy, config_id,
- frame_width, frame_height,
+ frame_width_mbaligned, frame_height_mbaligned,
VA_PROGRESSIVE,
tmp_surfaceid, 2 * SURFACE_NUM,
&context_id);
CHECK_VASTATUS(va_status, "vaCreateContext");
free(tmp_surfaceid);
- codedbuf_size = (frame_width * frame_height * 400) / (16*16);
+ codedbuf_size = (frame_width_mbaligned * frame_height_mbaligned * 400) / (16*16);
for (i = 0; i < SURFACE_NUM; i++) {
/* create coded buffer once for all
@@ -1114,7 +1196,7 @@ static void sort_one(VAPictureH264 ref[], int left, int right,
partition(ref, frame_idx, key, ascending);
} else {
key = ref[(left + right) / 2].TopFieldOrderCnt;
- partition(ref, TopFieldOrderCnt, key, ascending);
+ partition(ref, TopFieldOrderCnt, (signed int)key, ascending);
}
/* recursion */
@@ -1125,16 +1207,16 @@ static void sort_one(VAPictureH264 ref[], int left, int right,
sort_one(ref, i, right, ascending, frame_idx);
}
-static void sort_two(VAPictureH264 ref[], int left, int right, int key, int frame_idx,
- int divide_ascending, int list0_ascending, int list1_ascending)
+static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx,
+ int partition_ascending, int list0_ascending, int list1_ascending)
{
int i = left, j = right;
VAPictureH264 tmp;
if (frame_idx) {
- partition(ref, frame_idx, key, divide_ascending);
+ partition(ref, frame_idx, key, partition_ascending);
} else {
- partition(ref, TopFieldOrderCnt, key, divide_ascending);
+ partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending);
}
@@ -1191,14 +1273,14 @@ static int update_RefPicList(void)
static int render_sequence(void)
{
- VABufferID seq_param_buf, rc_param_buf, render_id[2];
+ VABufferID seq_param_buf, rc_param_buf, misc_param_tmpbuf, render_id[2];
VAStatus va_status;
- VAEncMiscParameterBuffer *misc_param;
+ VAEncMiscParameterBuffer *misc_param, *misc_param_tmp;
VAEncMiscParameterRateControl *misc_rate_ctrl;
seq_param.level_idc = 41 /*SH_LEVEL_3*/;
- seq_param.picture_width_in_mbs = frame_width / 16;
- seq_param.picture_height_in_mbs = frame_height / 16;
+ seq_param.picture_width_in_mbs = frame_width_mbaligned / 16;
+ seq_param.picture_height_in_mbs = frame_height_mbaligned / 16;
seq_param.bits_per_second = frame_bitrate;
seq_param.intra_period = intra_period;
@@ -1212,6 +1294,17 @@ static int render_sequence(void)
seq_param.seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4 = Log2MaxPicOrderCntLsb - 4;
seq_param.seq_fields.bits.log2_max_frame_num_minus4 = Log2MaxFrameNum - 4;;
seq_param.seq_fields.bits.frame_mbs_only_flag = 1;
+ seq_param.seq_fields.bits.chroma_format_idc = 1;
+ seq_param.seq_fields.bits.direct_8x8_inference_flag = 1;
+
+ 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;
+ }
va_status = vaCreateBuffer(va_dpy, context_id,
VAEncSequenceParameterBufferType,
@@ -1229,6 +1322,8 @@ static int render_sequence(void)
misc_rate_ctrl = (VAEncMiscParameterRateControl *)misc_param->data;
memset(misc_rate_ctrl, 0, sizeof(*misc_rate_ctrl));
misc_rate_ctrl->bits_per_second = frame_bitrate;
+ misc_rate_ctrl->target_percentage = 66;
+ misc_rate_ctrl->window_size = 1000;
misc_rate_ctrl->initial_qp = initial_qp;
misc_rate_ctrl->min_qp = minimal_qp;
misc_rate_ctrl->basic_unit_size = 0;
@@ -1240,10 +1335,24 @@ static int render_sequence(void)
va_status = vaRenderPicture(va_dpy,context_id, &render_id[0], 2);
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 0;
}
-static int calc_poc(unsigned int pic_order_cnt_lsb)
+static int calc_poc(int pic_order_cnt_lsb)
{
static int PicOrderCntMsb_ref = 0, pic_order_cnt_lsb_ref = 0;
int prevPicOrderCntMsb, prevPicOrderCntLsb;
@@ -1257,10 +1366,10 @@ static int calc_poc(unsigned int pic_order_cnt_lsb)
}
if ((pic_order_cnt_lsb < prevPicOrderCntLsb) &&
- ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2)))
+ ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (int)(MaxPicOrderCntLsb / 2)))
PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb;
else if ((pic_order_cnt_lsb > prevPicOrderCntLsb) &&
- ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2)))
+ ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (int)(MaxPicOrderCntLsb / 2)))
PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb;
else
PicOrderCntMsb = prevPicOrderCntMsb;
@@ -1307,7 +1416,7 @@ static int render_picture(void)
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.entropy_coding_mode_flag = 1;
+ pic_param.pic_fields.bits.entropy_coding_mode_flag = h264_entropy_mode;
pic_param.pic_fields.bits.deblocking_filter_control_present_flag = 1;
pic_param.frame_num = current_frame_num;
pic_param.coded_buf = coded_buf[current_slot];
@@ -1326,7 +1435,7 @@ static int render_picture(void)
static int render_packedsequence(void)
{
- VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0};
+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
VABufferID packedseq_para_bufid, packedseq_data_bufid, render_id[2];
unsigned int length_in_bits;
unsigned char *packedseq_buffer = NULL;
@@ -1365,7 +1474,7 @@ static int render_packedsequence(void)
static int render_packedpicture(void)
{
- VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0};
+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
VABufferID packedpic_para_bufid, packedpic_data_bufid, render_id[2];
unsigned int length_in_bits;
unsigned char *packedpic_buffer = NULL;
@@ -1404,7 +1513,7 @@ static void render_packedsei(void)
{
VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
VABufferID packed_sei_header_param_buf_id, packed_sei_buf_id, render_id[2];
- unsigned int length_in_bits, offset_in_bytes;
+ unsigned int length_in_bits /*offset_in_bytes*/;
unsigned char *packed_sei_buffer = NULL;
VAStatus va_status;
int init_cpb_size, target_bit_rate, i_initial_cpb_removal_delay_length, i_initial_cpb_removal_delay;
@@ -1431,7 +1540,7 @@ static void render_packedsei(void)
0,
&packed_sei_buffer);
- offset_in_bytes = 0;
+ //offset_in_bytes = 0;
packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
packed_header_param_buffer.bit_length = length_in_bits;
packed_header_param_buffer.has_emulation_bytes = 0;
@@ -1509,10 +1618,11 @@ static int render_slice(void)
/* one frame, one slice */
slice_param.macroblock_address = 0;
- slice_param.num_macroblocks = frame_width*frame_height/(16*16); /* Measured by MB */
+ slice_param.num_macroblocks = frame_width_mbaligned * frame_height_mbaligned/(16*16); /* Measured by MB */
slice_param.slice_type = (current_frame_type == FRAME_IDR)?2:current_frame_type;
- if (current_frame_type == FRAME_I || current_frame_type == FRAME_IDR) {
- ;
+ if (current_frame_type == FRAME_IDR) {
+ if (current_frame_encoding != 0)
+ ++slice_param.idr_pic_id;
} else if (current_frame_type == FRAME_P) {
int refpiclist0_max = h264_maxref & 0xffff;
memcpy(slice_param.RefPicList0, RefPicList0_P, refpiclist0_max*sizeof(VAPictureH264));
@@ -1538,9 +1648,10 @@ static int render_slice(void)
}
}
- slice_param.slice_alpha_c0_offset_div2 = 2;
- slice_param.slice_beta_offset_div2 = 2;
- slice_param.pic_order_cnt_lsb = current_frame_display % MaxPicOrderCntLsb;
+ slice_param.slice_alpha_c0_offset_div2 = 0;
+ slice_param.slice_beta_offset_div2 = 0;
+ slice_param.direct_spatial_mv_pred_flag = 1;
+ slice_param.pic_order_cnt_lsb = (current_frame_display - current_IDR_display) % MaxPicOrderCntLsb;
va_status = vaCreateBuffer(va_dpy,context_id,VAEncSliceParameterBufferType,
sizeof(slice_param),1,&slice_param,&slice_param_buf);
@@ -1548,7 +1659,7 @@ static int render_slice(void)
va_status = vaRenderPicture(va_dpy,context_id, &slice_param_buf, 1);
CHECK_VASTATUS(va_status,"vaRenderPicture");
-
+
return 0;
}
@@ -1566,115 +1677,122 @@ static int upload_source_YUV_once_for_all()
row_shift++;
if (row_shift==(2*box_width)) row_shift= 0;
}
- printf("Completed surface loading\n");
+ printf("Complete surface loading\n");
return 0;
}
-
static int load_surface(VASurfaceID surface_id, unsigned long long display_order)
{
- VAImage surface_image;
- unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL,*V_start=NULL, *uv_ptr;
- int Y_pitch=0, U_pitch=0, row, V_pitch, uv_size;
- VAStatus va_status;
-
+ unsigned char *srcyuv_ptr = NULL, *src_Y = NULL, *src_U = NULL, *src_V = NULL;
+ unsigned long long frame_start, mmap_start;
+ char *mmap_ptr = NULL;
+ int frame_size, mmap_size;
+
if (srcyuv_fp == NULL)
return 0;
- /* rewind the file pointer if encoding more than srcyuv_frames */
+ /* allow encoding more than srcyuv_frames */
display_order = display_order % srcyuv_frames;
+ frame_size = frame_width * frame_height * 3 / 2; /* for YUV420 */
+ frame_start = display_order * frame_size;
+
+ mmap_start = frame_start & (~0xfff);
+ mmap_size = (frame_size + (frame_start & 0xfff) + 0xfff) & (~0xfff);
+ mmap_ptr = mmap(0, mmap_size, PROT_READ, MAP_SHARED,
+ fileno(srcyuv_fp), mmap_start);
+ if (mmap_ptr == MAP_FAILED) {
+ printf("Failed to mmap YUV file (%s)\n", strerror(errno));
+ return 1;
+ }
+ srcyuv_ptr = (unsigned char *)mmap_ptr + (frame_start & 0xfff);
+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
+ src_Y = srcyuv_ptr;
+ src_U = src_Y + frame_width * frame_height;
+ src_V = NULL;
+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
+ srcyuv_fourcc == VA_FOURCC_YV12) {
+ src_Y = srcyuv_ptr;
+ if (srcyuv_fourcc == VA_FOURCC_IYUV) {
+ src_U = src_Y + frame_width * frame_height;
+ src_V = src_U + (frame_width/2) * (frame_height/2);
+ } else { /* YV12 */
+ src_V = src_Y + frame_width * frame_height;
+ src_U = src_V + (frame_width/2) * (frame_height/2);
+ }
+ } else {
+ printf("Unsupported source YUV format\n");
+ exit(1);
+ }
- fseek(srcyuv_fp, display_order * frame_width * frame_height * 1.5, SEEK_SET);
-
- va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
- CHECK_VASTATUS(va_status,"vaDeriveImage");
+ upload_surface_yuv(va_dpy, surface_id,
+ srcyuv_fourcc, frame_width, frame_height,
+ src_Y, src_U, src_V);
+ if (mmap_ptr)
+ munmap(mmap_ptr, mmap_size);
+
+ return 0;
+}
- vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
- assert(VA_STATUS_SUCCESS == va_status);
- Y_start = surface_p;
- Y_pitch = surface_image.pitches[0];
- switch (surface_image.format.fourcc) {
- case VA_FOURCC_NV12:
- U_start = (unsigned char *)surface_p + surface_image.offsets[1];
- V_start = U_start + 1;
- U_pitch = surface_image.pitches[1];
- V_pitch = surface_image.pitches[1];
- break;
- case VA_FOURCC_IYUV:
- U_start = (unsigned char *)surface_p + surface_image.offsets[1];
- V_start = (unsigned char *)surface_p + surface_image.offsets[2];
- U_pitch = surface_image.pitches[1];
- V_pitch = surface_image.pitches[2];
- break;
- case VA_FOURCC_YV12:
- U_start = (unsigned char *)surface_p + surface_image.offsets[2];
- V_start = (unsigned char *)surface_p + surface_image.offsets[1];
- U_pitch = surface_image.pitches[2];
- V_pitch = surface_image.pitches[1];
- break;
- case VA_FOURCC_YUY2:
- U_start = surface_p + 1;
- V_start = surface_p + 3;
- U_pitch = surface_image.pitches[0];
- V_pitch = surface_image.pitches[0];
- break;
- default:
- assert(0);
- }
+static int save_recyuv(VASurfaceID surface_id,
+ unsigned long long display_order,
+ unsigned long long encode_order)
+{
+ unsigned char *dst_Y = NULL, *dst_U = NULL, *dst_V = NULL;
+
+ if (recyuv_fp == NULL)
+ return 0;
- /* copy Y plane */
- for (row=0;row<frame_height;row++) {
- unsigned char *Y_row = Y_start + row * Y_pitch;
- (void)fread(Y_row, 1, surface_image.width, srcyuv_fp);
+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
+ int uv_size = 2 * (frame_width/2) * (frame_height/2);
+ dst_Y = malloc(2*uv_size);
+ dst_U = malloc(uv_size);
+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
+ srcyuv_fourcc == VA_FOURCC_YV12) {
+ int uv_size = (frame_width/2) * (frame_height/2);
+ dst_Y = malloc(4*uv_size);
+ dst_U = malloc(uv_size);
+ dst_V = malloc(uv_size);
+ } else {
+ printf("Unsupported source YUV format\n");
+ exit(1);
}
-
- /* copy UV data, reset file pointer,
- * surface_image.height may not be equal to source YUV height/frame_height
- */
- fseek(srcyuv_fp,
- display_order * frame_width * frame_height * 1.5 + frame_width * frame_height,
- SEEK_SET);
-
- uv_size = 2 * (frame_width/2) * (frame_height/2);
- uv_ptr = malloc(uv_size);
- fread(uv_ptr, uv_size, 1, srcyuv_fp);
-
- for (row =0; row < frame_height/2; row++) {
- unsigned char *U_row = U_start + row * U_pitch;
- unsigned char *u_ptr, *v_ptr;
- int j;
- switch (surface_image.format.fourcc) {
- case VA_FOURCC_NV12:
- if (srcyuv_fourcc == VA_FOURCC_NV12) {
- memcpy(U_row, uv_ptr + row * frame_width, frame_width);
- break;
- } else if (srcyuv_fourcc == VA_FOURCC_IYUV) {
- u_ptr = uv_ptr + row * (frame_width/2);
- v_ptr = uv_ptr + (frame_width/2) * (frame_height/2) + row * (frame_width/2);
- } else if (srcyuv_fourcc == VA_FOURCC_YV12) {
- v_ptr = uv_ptr + row * (frame_height/2);
- u_ptr = uv_ptr + (frame_width/2) * (frame_height/2) + row * (frame_width/2);
- }
- for(j = 0; j < frame_width/2; j++) {
- U_row[2*j] = u_ptr[j];
- U_row[2*j+1] = v_ptr[j];
- }
- break;
- case VA_FOURCC_IYUV:
- case VA_FOURCC_YV12:
- case VA_FOURCC_YUY2:
- default:
- printf("unsupported fourcc in load_surface\n");
- assert(0);
+
+ download_surface_yuv(va_dpy, surface_id,
+ srcyuv_fourcc, frame_width, frame_height,
+ dst_Y, dst_U, dst_V);
+ fseek(recyuv_fp, display_order * frame_width * frame_height * 1.5, SEEK_SET);
+
+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
+ int uv_size = 2 * (frame_width/2) * (frame_height/2);
+ fwrite(dst_Y, uv_size * 2, 1, recyuv_fp);
+ fwrite(dst_U, uv_size, 1, recyuv_fp);
+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
+ srcyuv_fourcc == VA_FOURCC_YV12) {
+ int uv_size = (frame_width/2) * (frame_height/2);
+ fwrite(dst_Y, uv_size * 4, 1, recyuv_fp);
+
+ if (srcyuv_fourcc == VA_FOURCC_IYUV) {
+ fwrite(dst_U, uv_size, 1, recyuv_fp);
+ fwrite(dst_V, uv_size, 1, recyuv_fp);
+ } else {
+ fwrite(dst_V, uv_size, 1, recyuv_fp);
+ fwrite(dst_U, uv_size, 1, recyuv_fp);
}
+ } else {
+ printf("Unsupported YUV format\n");
+ exit(1);
}
- free(uv_ptr);
- vaUnmapBuffer(va_dpy,surface_image.buf);
+ if (dst_Y)
+ free(dst_Y);
+ if (dst_U)
+ free(dst_U);
+ if (dst_V)
+ free(dst_V);
- vaDestroyImage(va_dpy,surface_image.image_id);
+ fflush(recyuv_fp);
return 0;
}
@@ -1712,21 +1830,15 @@ static int save_codeddata(unsigned long long display_order, unsigned long long e
break;
}
printf("%08lld", encode_order);
- /*
- if (current_frame_encoding % intra_count == 0)
- printf("(I)");
- else
- printf("(P)");
- */
printf("(%06d bytes coded)",coded_size);
- /* skipped frame ? */
- printf(" ");
+ fflush(coded_fp);
+
return 0;
}
-static struct storage_task_t * storage_task_dequque(void)
+static struct storage_task_t * storage_task_dequeue(void)
{
struct storage_task_t *header;
@@ -1782,8 +1894,9 @@ static void storage_task(unsigned long long display_order, unsigned long long en
tmp = GetTickCount();
save_codeddata(display_order, encode_order);
SavePictureTicks += GetTickCount() - tmp;
- /* tbd: save reconstructed frame */
-
+
+ save_recyuv(ref_surface[display_order % SURFACE_NUM], display_order, encode_order);
+
/* reload a new frame data */
tmp = GetTickCount();
if (srcyuv_fp != NULL)
@@ -1801,7 +1914,7 @@ static void * storage_task_thread(void *t)
while (1) {
struct storage_task_t *current;
- current = storage_task_dequque();
+ current = storage_task_dequeue();
if (current == NULL) {
pthread_mutex_lock(&encode_mutex);
pthread_cond_wait(&encode_cond, &encode_mutex);
@@ -1855,8 +1968,12 @@ static int encode_frames(void)
current_frame_num = 0;
current_IDR_display = current_frame_display;
}
+
/* check if the source frame is ready */
- while (srcsurface_status[current_slot] != SRC_SURFACE_IN_ENCODING);
+ while (srcsurface_status[current_slot] != SRC_SURFACE_IN_ENCODING) {
+ usleep(1);
+ }
+
tmp = GetTickCount();
va_status = vaBeginPicture(va_dpy, context_id, src_surface[current_slot]);
CHECK_VASTATUS(va_status,"vaBeginPicture");
@@ -1892,12 +2009,7 @@ static int encode_frames(void)
storage_task(current_frame_display, current_frame_encoding);
else /* queue the storage task queue */
storage_task_queue(current_frame_display, current_frame_encoding);
-
- /* how to process skipped frames
- surface_status = (VASurfaceStatus) 0;
- va_status = vaQuerySurfaceStatus(va_dpy, src_surface[i%SURFACE_NUM],&surface_status);
- frame_skipped = (surface_status & VASurfaceSkipped);
- */
+
update_ReferenceFrames();
}
@@ -1967,12 +2079,53 @@ static int print_input()
return 0;
}
+static int calc_PSNR(double *psnr)
+{
+ char *srcyuv_ptr = NULL, *recyuv_ptr = NULL, tmp;
+ unsigned long long min_size;
+ unsigned long long i, sse=0;
+ double ssemean;
+ int fourM = 0x400000; /* 4M */
+
+ min_size = MIN(srcyuv_frames, frame_count) * frame_width * frame_height * 1.5;
+ for (i=0; i<min_size; i++) {
+ unsigned long long j = i % fourM;
+
+ if ((i % fourM) == 0) {
+ if (srcyuv_ptr)
+ munmap(srcyuv_ptr, fourM);
+ if (recyuv_ptr)
+ munmap(recyuv_ptr, fourM);
+
+ srcyuv_ptr = mmap(0, fourM, PROT_READ, MAP_SHARED, fileno(srcyuv_fp), i);
+ recyuv_ptr = mmap(0, fourM, PROT_READ, MAP_SHARED, fileno(recyuv_fp), i);
+ if ((srcyuv_ptr == MAP_FAILED) || (recyuv_ptr == MAP_FAILED)) {
+ printf("Failed to mmap YUV files\n");
+ return 1;
+ }
+ }
+ tmp = srcyuv_ptr[j] - recyuv_ptr[j];
+ sse += tmp * tmp;
+ }
+ ssemean = (double)sse/(double)min_size;
+ *psnr = 20.0*log10(255) - 10.0*log10(ssemean);
+
+ if (srcyuv_ptr)
+ munmap(srcyuv_ptr, fourM);
+ if (recyuv_ptr)
+ munmap(recyuv_ptr, fourM);
+
+ return 0;
+}
static int print_performance(unsigned int PictureCount)
{
- unsigned int others = 0;
- double total_size = frame_width * frame_height * 1.5 * frame_count;
+ unsigned int psnr_ret = 1, others = 0;
+ double psnr = 0, total_size = frame_width * frame_height * 1.5 * frame_count;
+ if (calc_psnr && srcyuv_fp && recyuv_fp)
+ psnr_ret = calc_PSNR(&psnr);
+
others = TotalTicks - UploadPictureTicks - BeginPictureTicks
- RenderPictureTicks - EndPictureTicks - SyncPictureTicks - SavePictureTicks;
@@ -1982,6 +2135,9 @@ static int print_performance(unsigned int PictureCount)
(double) 1000*PictureCount / TotalTicks, PictureCount,
TotalTicks, ((double) TotalTicks) / (double) PictureCount);
printf("PERFORMANCE: Compression ratio : %d:1\n", (unsigned int)(total_size / frame_size));
+ if (psnr_ret == 0)
+ printf("PERFORMANCE: PSNR : %.2f (%lld frames calculated)\n",
+ psnr, MIN(frame_count, srcyuv_frames));
printf("PERFORMANCE: UploadPicture : %d ms (%.2f, %.2f%% percent)\n",
(int) UploadPictureTicks, ((double) UploadPictureTicks) / (double) PictureCount,
@@ -2006,8 +2162,8 @@ static int print_performance(unsigned int PictureCount)
others/(double) TotalTicks/0.01);
if (encode_syncmode == 0)
- printf("(Multithread enabled, the profiling is only for reference)\n");
-
+ printf("(Multithread enabled, the timing is only for reference)\n");
+
return 0;
}