• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Keine Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

hardware/intel/libva


Commit MetaInfo

Revision64f9de399187204d5c30cf205b4279ec5b002675 (tree)
Zeit2013-06-25 14:53:58
AutorAustin Yuan <shengquan.yuan@inte...>
CommiterXiang, Haihao

Log Message

h264encode: dump reconstructed frame and calc PSNR

Signed-off-by: Austin Yuan <shengquan.yuan@intel.com>

Ändern Zusammenfassung

Diff

--- a/test/encode/Android.mk
+++ b/test/encode/Android.mk
@@ -21,7 +21,7 @@ LOCAL_C_INCLUDES += \
2121 LOCAL_MODULE_TAGS := optional
2222 LOCAL_MODULE := h264encode
2323
24-LOCAL_SHARED_LIBRARIES := libva-android libva libdl libdrm libcutils libutils libgui
24+LOCAL_SHARED_LIBRARIES := libva-android libva libdl libdrm libcutils libutils libgui libm
2525
2626 include $(BUILD_EXECUTABLE)
2727
--- a/test/encode/Makefile.am
+++ b/test/encode/Makefile.am
@@ -33,7 +33,7 @@ h264encode_CFLAGS = -I$(top_srcdir)/test/common -g
3333 h264encode_LDADD = \
3434 $(top_builddir)/va/libva.la \
3535 $(top_builddir)/test/common/libva-display.la \
36- -lpthread
36+ -lpthread -lm
3737
3838 avcenc_SOURCES = avcenc.c
3939 avcenc_CFLAGS = -I$(top_srcdir)/test/common -g
--- a/test/encode/h264encode.c
+++ b/test/encode/h264encode.c
@@ -30,9 +30,12 @@
3030 #include <sys/types.h>
3131 #include <sys/stat.h>
3232 #include <sys/time.h>
33+#include <sys/mman.h>
3334 #include <fcntl.h>
3435 #include <assert.h>
3536 #include <pthread.h>
37+#include <errno.h>
38+#include <math.h>
3639 #include <va/va.h>
3740 #include <va/va_enc_h264.h>
3841 #include "va_display.h"
@@ -69,7 +72,6 @@
6972
7073 #define BITSTREAM_ALLOCATE_STEPPING 4096
7174
72-
7375 #define SURFACE_NUM 16 /* 16 surfaces for source YUV */
7476 #define SURFACE_NUM 16 /* 16 surfaces for reference */
7577 static VADisplay va_dpy;
@@ -102,6 +104,7 @@ static char *coded_fn = NULL, *srcyuv_fn = NULL, *recyuv_fn = NULL;
102104 static FILE *coded_fp = NULL, *srcyuv_fp = NULL, *recyuv_fp = NULL;
103105 static unsigned long long srcyuv_frames = 0;
104106 static int srcyuv_fourcc = VA_FOURCC_NV12;
107+static int calc_psnr = 0;
105108
106109 static int frame_width = 176;
107110 static int frame_height = 144;
@@ -120,10 +123,13 @@ static int rc_mode = VA_RC_VBR;
120123 static unsigned long long current_frame_encoding = 0;
121124 static unsigned long long current_frame_display = 0;
122125 static unsigned long long current_IDR_display = 0;
123-static int current_frame_num = 0;
126+static unsigned int current_frame_num = 0;
124127 static int current_frame_type;
125128 #define current_slot (current_frame_display % SURFACE_NUM)
126129
130+#define MIN(a, b) ((a)>(b)?(b):(a))
131+#define MAX(a, b) ((a)>(b)?(a):(b))
132+
127133 /* thread to save coded data/upload source YUV */
128134 struct storage_task_t {
129135 void *next;
@@ -703,7 +709,9 @@ static int print_help(void)
703709 printf(" --rcmode <NONE|CBR|VBR|VCM|CQP|VBR_CONTRAINED>\n");
704710 printf(" --syncmode: sequentially upload source, encoding, save result, no multi-thread\n");
705711 printf(" --srcyuv <filename> load YUV from a file\n");
706- printf(" --fourcc <NV12|IYUV|I420|YV12> source YUV fourcc\n");
712+ printf(" --fourcc <NV12|IYUV|YV12> source YUV fourcc\n");
713+ printf(" --recyuv <filename> save reconstructed YUV into a file\n");
714+ printf(" --enablePSNR calculate PSNR of recyuv vs. srcyuv\n");
707715
708716 return 0;
709717 }
@@ -712,6 +720,7 @@ static int process_cmdline(int argc, char *argv[])
712720 {
713721 char c;
714722 const struct option long_opts[] = {
723+ {"help", no_argument, NULL, 0 },
715724 {"bitrate", required_argument, NULL, 1 },
716725 {"minqp", required_argument, NULL, 2 },
717726 {"initialqp", required_argument, NULL, 3 },
@@ -720,8 +729,10 @@ static int process_cmdline(int argc, char *argv[])
720729 {"ip_period", required_argument, NULL, 6 },
721730 {"rcmode", required_argument, NULL, 7 },
722731 {"srcyuv", required_argument, NULL, 9 },
723- {"fourcc", required_argument, NULL, 10 },
724- {"syncmode", no_argument, NULL, 11 },
732+ {"recyuv", required_argument, NULL, 10 },
733+ {"fourcc", required_argument, NULL, 11 },
734+ {"syncmode", no_argument, NULL, 12 },
735+ {"enablePSNR", no_argument, NULL, 13 },
725736 {NULL, no_argument, NULL, 0 }};
726737 int long_index;
727738
@@ -742,6 +753,9 @@ static int process_cmdline(int argc, char *argv[])
742753 case 'o':
743754 coded_fn = strdup(optarg);
744755 break;
756+ case 0:
757+ print_help();
758+ exit(0);
745759 case 1:
746760 frame_bitrate = atoi(optarg);
747761 break;
@@ -771,15 +785,21 @@ static int process_cmdline(int argc, char *argv[])
771785 srcyuv_fn = strdup(optarg);
772786 break;
773787 case 10:
788+ recyuv_fn = strdup(optarg);
789+ break;
790+ case 11:
774791 srcyuv_fourcc = string_to_fourcc(optarg);
775792 if (srcyuv_fourcc <= 0) {
776793 print_help();
777794 exit(1);
778795 }
779796 break;
780- case 11:
797+ case 12:
781798 encode_syncmode = 1;
782799 break;
800+ case 13:
801+ calc_psnr = 1;
802+ break;
783803 case ':':
784804 case '?':
785805 print_help();
@@ -815,6 +835,14 @@ static int process_cmdline(int argc, char *argv[])
815835 printf("Source YUV file %s with %llu frames\n", srcyuv_fn, srcyuv_frames);
816836 }
817837 }
838+
839+ /* open source file */
840+ if (recyuv_fn) {
841+ recyuv_fp = fopen(recyuv_fn,"w+");
842+
843+ if (recyuv_fp == NULL)
844+ printf("Open reconstructed YUV file %s failed\n", recyuv_fn);
845+ }
818846
819847 if (coded_fn == NULL) {
820848 struct stat buf;
@@ -919,7 +947,7 @@ static int init_va(void)
919947 if (attrib[VAConfigAttribRateControl].value != VA_ATTRIB_NOT_SUPPORTED) {
920948 int tmp = attrib[VAConfigAttribRateControl].value;
921949
922- printf("Supported rate control mode (0x%x):", tmp);
950+ printf("Supporte rate control mode (0x%x):", tmp);
923951
924952 if (tmp & VA_RC_NONE)
925953 printf("NONE ");
@@ -1114,7 +1142,7 @@ static void sort_one(VAPictureH264 ref[], int left, int right,
11141142 partition(ref, frame_idx, key, ascending);
11151143 } else {
11161144 key = ref[(left + right) / 2].TopFieldOrderCnt;
1117- partition(ref, TopFieldOrderCnt, key, ascending);
1145+ partition(ref, TopFieldOrderCnt, (signed int)key, ascending);
11181146 }
11191147
11201148 /* recursion */
@@ -1125,16 +1153,16 @@ static void sort_one(VAPictureH264 ref[], int left, int right,
11251153 sort_one(ref, i, right, ascending, frame_idx);
11261154 }
11271155
1128-static void sort_two(VAPictureH264 ref[], int left, int right, int key, int frame_idx,
1129- int divide_ascending, int list0_ascending, int list1_ascending)
1156+static void sort_two(VAPictureH264 ref[], int left, int right, unsigned int key, unsigned int frame_idx,
1157+ int partition_ascending, int list0_ascending, int list1_ascending)
11301158 {
11311159 int i = left, j = right;
11321160 VAPictureH264 tmp;
11331161
11341162 if (frame_idx) {
1135- partition(ref, frame_idx, key, divide_ascending);
1163+ partition(ref, frame_idx, key, partition_ascending);
11361164 } else {
1137- partition(ref, TopFieldOrderCnt, key, divide_ascending);
1165+ partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending);
11381166 }
11391167
11401168
@@ -1243,7 +1271,7 @@ static int render_sequence(void)
12431271 return 0;
12441272 }
12451273
1246-static int calc_poc(unsigned int pic_order_cnt_lsb)
1274+static int calc_poc(int pic_order_cnt_lsb)
12471275 {
12481276 static int PicOrderCntMsb_ref = 0, pic_order_cnt_lsb_ref = 0;
12491277 int prevPicOrderCntMsb, prevPicOrderCntLsb;
@@ -1257,10 +1285,10 @@ static int calc_poc(unsigned int pic_order_cnt_lsb)
12571285 }
12581286
12591287 if ((pic_order_cnt_lsb < prevPicOrderCntLsb) &&
1260- ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2)))
1288+ ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (int)(MaxPicOrderCntLsb / 2)))
12611289 PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb;
12621290 else if ((pic_order_cnt_lsb > prevPicOrderCntLsb) &&
1263- ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2)))
1291+ ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (int)(MaxPicOrderCntLsb / 2)))
12641292 PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb;
12651293 else
12661294 PicOrderCntMsb = prevPicOrderCntMsb;
@@ -1326,7 +1354,7 @@ static int render_picture(void)
13261354
13271355 static int render_packedsequence(void)
13281356 {
1329- VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0};
1357+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
13301358 VABufferID packedseq_para_bufid, packedseq_data_bufid, render_id[2];
13311359 unsigned int length_in_bits;
13321360 unsigned char *packedseq_buffer = NULL;
@@ -1365,7 +1393,7 @@ static int render_packedsequence(void)
13651393
13661394 static int render_packedpicture(void)
13671395 {
1368- VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0};
1396+ VAEncPackedHeaderParameterBuffer packedheader_param_buffer;
13691397 VABufferID packedpic_para_bufid, packedpic_data_bufid, render_id[2];
13701398 unsigned int length_in_bits;
13711399 unsigned char *packedpic_buffer = NULL;
@@ -1404,7 +1432,7 @@ static void render_packedsei(void)
14041432 {
14051433 VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
14061434 VABufferID packed_sei_header_param_buf_id, packed_sei_buf_id, render_id[2];
1407- unsigned int length_in_bits, offset_in_bytes;
1435+ unsigned int length_in_bits /*offset_in_bytes*/;
14081436 unsigned char *packed_sei_buffer = NULL;
14091437 VAStatus va_status;
14101438 int init_cpb_size, target_bit_rate, i_initial_cpb_removal_delay_length, i_initial_cpb_removal_delay;
@@ -1431,7 +1459,7 @@ static void render_packedsei(void)
14311459 0,
14321460 &packed_sei_buffer);
14331461
1434- offset_in_bytes = 0;
1462+ //offset_in_bytes = 0;
14351463 packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
14361464 packed_header_param_buffer.bit_length = length_in_bits;
14371465 packed_header_param_buffer.has_emulation_bytes = 0;
@@ -1571,110 +1599,130 @@ static int upload_source_YUV_once_for_all()
15711599 return 0;
15721600 }
15731601
1574-
1602+#define check_ret(ret) \
1603+if (ret != 1) { \
1604+ printf("fread doesn't return enough data\n"); \
1605+ exit(1); \
1606+}
15751607 static int load_surface(VASurfaceID surface_id, unsigned long long display_order)
15761608 {
1577- VAImage surface_image;
1578- unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL,*V_start=NULL, *uv_ptr;
1579- int Y_pitch=0, U_pitch=0, row, V_pitch, uv_size;
1580- VAStatus va_status;
1581-
1609+ unsigned char *src_Y = NULL, *src_U = NULL, *src_V = NULL;
1610+ int ret = 0;
1611+
15821612 if (srcyuv_fp == NULL)
15831613 return 0;
15841614
15851615 /* rewind the file pointer if encoding more than srcyuv_frames */
15861616 display_order = display_order % srcyuv_frames;
1587-
15881617 fseek(srcyuv_fp, display_order * frame_width * frame_height * 1.5, SEEK_SET);
15891618
1590- va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
1591- CHECK_VASTATUS(va_status,"vaDeriveImage");
15921619
1593- vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
1594- assert(VA_STATUS_SUCCESS == va_status);
1620+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
1621+ int uv_size = 2 * (frame_width/2) * (frame_height/2);
15951622
1596- Y_start = surface_p;
1597- Y_pitch = surface_image.pitches[0];
1598- switch (surface_image.format.fourcc) {
1599- case VA_FOURCC_NV12:
1600- U_start = (unsigned char *)surface_p + surface_image.offsets[1];
1601- V_start = U_start + 1;
1602- U_pitch = surface_image.pitches[1];
1603- V_pitch = surface_image.pitches[1];
1604- break;
1605- case VA_FOURCC_IYUV:
1606- U_start = (unsigned char *)surface_p + surface_image.offsets[1];
1607- V_start = (unsigned char *)surface_p + surface_image.offsets[2];
1608- U_pitch = surface_image.pitches[1];
1609- V_pitch = surface_image.pitches[2];
1610- break;
1611- case VA_FOURCC_YV12:
1612- U_start = (unsigned char *)surface_p + surface_image.offsets[2];
1613- V_start = (unsigned char *)surface_p + surface_image.offsets[1];
1614- U_pitch = surface_image.pitches[2];
1615- V_pitch = surface_image.pitches[1];
1616- break;
1617- case VA_FOURCC_YUY2:
1618- U_start = surface_p + 1;
1619- V_start = surface_p + 3;
1620- U_pitch = surface_image.pitches[0];
1621- V_pitch = surface_image.pitches[0];
1622- break;
1623- default:
1624- assert(0);
1623+ src_Y = malloc(2 * uv_size);
1624+ src_U = malloc(uv_size);
1625+
1626+ ret = fread(src_Y, frame_width * frame_height, 1, srcyuv_fp);
1627+ check_ret(ret);
1628+ ret = fread(src_U, uv_size, 1, srcyuv_fp);
1629+ check_ret(ret);
1630+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
1631+ srcyuv_fourcc == VA_FOURCC_YV12) {
1632+ int uv_size = (frame_width/2) * (frame_height/2);
1633+
1634+ src_Y = malloc(4 * uv_size);
1635+ src_U = malloc(uv_size);
1636+ src_V = malloc(uv_size);
1637+
1638+ ret = fread(src_Y, frame_width * frame_height, 1, srcyuv_fp);
1639+ check_ret(ret);
1640+ if (srcyuv_fourcc == VA_FOURCC_IYUV) {
1641+ ret = fread(src_U, uv_size, 1, srcyuv_fp);
1642+ check_ret(ret);
1643+ ret = fread(src_V, uv_size, 1, srcyuv_fp);
1644+ check_ret(ret);
1645+ } else { /* YV12 */
1646+ ret = fread(src_V, uv_size, 1, srcyuv_fp);
1647+ check_ret(ret);
1648+ ret = fread(src_U, uv_size, 1, srcyuv_fp);
1649+ check_ret(ret);
1650+ }
1651+ } else {
1652+ printf("Unsupported source YUV format\n");
1653+ exit(1);
16251654 }
1655+
1656+ upload_surface_yuv(va_dpy, surface_id,
1657+ srcyuv_fourcc, frame_width, frame_height,
1658+ src_Y, src_U, src_V);
1659+ if (src_Y)
1660+ free(src_Y);
1661+ if (src_U)
1662+ free(src_U);
1663+ if (src_V)
1664+ free(src_V);
1665+
1666+ return 0;
1667+}
1668+
16261669
1627- /* copy Y plane */
1628- for (row=0;row<frame_height;row++) {
1629- unsigned char *Y_row = Y_start + row * Y_pitch;
1630- (void)fread(Y_row, 1, surface_image.width, srcyuv_fp);
1670+static int save_recyuv(VASurfaceID surface_id,
1671+ unsigned long long display_order,
1672+ unsigned long long encode_order)
1673+{
1674+ unsigned char *dst_Y = NULL, *dst_U = NULL, *dst_V = NULL;
1675+
1676+ if (recyuv_fp == NULL)
1677+ return 0;
1678+
1679+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
1680+ int uv_size = 2 * (frame_width/2) * (frame_height/2);
1681+ dst_Y = malloc(2*uv_size);
1682+ dst_U = malloc(uv_size);
1683+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
1684+ srcyuv_fourcc == VA_FOURCC_YV12) {
1685+ int uv_size = (frame_width/2) * (frame_height/2);
1686+ dst_Y = malloc(4*uv_size);
1687+ dst_U = malloc(uv_size);
1688+ dst_V = malloc(uv_size);
1689+ } else {
1690+ printf("Unsupported source YUV format\n");
1691+ exit(1);
16311692 }
1632-
1633- /* copy UV data, reset file pointer,
1634- * surface_image.height may not be equal to source YUV height/frame_height
1635- */
1636- fseek(srcyuv_fp,
1637- display_order * frame_width * frame_height * 1.5 + frame_width * frame_height,
1638- SEEK_SET);
1639-
1640- uv_size = 2 * (frame_width/2) * (frame_height/2);
1641- uv_ptr = malloc(uv_size);
1642- fread(uv_ptr, uv_size, 1, srcyuv_fp);
1643-
1644- for (row =0; row < frame_height/2; row++) {
1645- unsigned char *U_row = U_start + row * U_pitch;
1646- unsigned char *u_ptr, *v_ptr;
1647- int j;
1648- switch (surface_image.format.fourcc) {
1649- case VA_FOURCC_NV12:
1650- if (srcyuv_fourcc == VA_FOURCC_NV12) {
1651- memcpy(U_row, uv_ptr + row * frame_width, frame_width);
1652- break;
1653- } else if (srcyuv_fourcc == VA_FOURCC_IYUV) {
1654- u_ptr = uv_ptr + row * (frame_width/2);
1655- v_ptr = uv_ptr + (frame_width/2) * (frame_height/2) + row * (frame_width/2);
1656- } else if (srcyuv_fourcc == VA_FOURCC_YV12) {
1657- v_ptr = uv_ptr + row * (frame_height/2);
1658- u_ptr = uv_ptr + (frame_width/2) * (frame_height/2) + row * (frame_width/2);
1659- }
1660- for(j = 0; j < frame_width/2; j++) {
1661- U_row[2*j] = u_ptr[j];
1662- U_row[2*j+1] = v_ptr[j];
1663- }
1664- break;
1665- case VA_FOURCC_IYUV:
1666- case VA_FOURCC_YV12:
1667- case VA_FOURCC_YUY2:
1668- default:
1669- printf("unsupported fourcc in load_surface\n");
1670- assert(0);
1693+
1694+ download_surface_yuv(va_dpy, surface_id,
1695+ srcyuv_fourcc, frame_width, frame_height,
1696+ dst_Y, dst_U, dst_V);
1697+ fseek(recyuv_fp, display_order * frame_width * frame_height * 1.5, SEEK_SET);
1698+
1699+ if (srcyuv_fourcc == VA_FOURCC_NV12) {
1700+ int uv_size = 2 * (frame_width/2) * (frame_height/2);
1701+ fwrite(dst_Y, uv_size * 2, 1, recyuv_fp);
1702+ fwrite(dst_U, uv_size, 1, recyuv_fp);
1703+ } else if (srcyuv_fourcc == VA_FOURCC_IYUV ||
1704+ srcyuv_fourcc == VA_FOURCC_YV12) {
1705+ int uv_size = (frame_width/2) * (frame_height/2);
1706+ fwrite(dst_Y, uv_size * 4, 1, recyuv_fp);
1707+
1708+ if (srcyuv_fourcc == VA_FOURCC_IYUV) {
1709+ fwrite(dst_U, uv_size, 1, recyuv_fp);
1710+ fwrite(dst_V, uv_size, 1, recyuv_fp);
1711+ } else {
1712+ fwrite(dst_V, uv_size, 1, recyuv_fp);
1713+ fwrite(dst_U, uv_size, 1, recyuv_fp);
16711714 }
1715+ } else {
1716+ printf("Unsupported YUV format\n");
1717+ exit(1);
16721718 }
1673- free(uv_ptr);
16741719
1675- vaUnmapBuffer(va_dpy,surface_image.buf);
1676-
1677- vaDestroyImage(va_dpy,surface_image.image_id);
1720+ if (dst_Y)
1721+ free(dst_Y);
1722+ if (dst_U)
1723+ free(dst_U);
1724+ if (dst_V)
1725+ free(dst_V);
16781726
16791727 return 0;
16801728 }
@@ -1782,8 +1830,9 @@ static void storage_task(unsigned long long display_order, unsigned long long en
17821830 tmp = GetTickCount();
17831831 save_codeddata(display_order, encode_order);
17841832 SavePictureTicks += GetTickCount() - tmp;
1785- /* tbd: save reconstructed frame */
1786-
1833+
1834+ save_recyuv(ref_surface[display_order % SURFACE_NUM], display_order, encode_order);
1835+
17871836 /* reload a new frame data */
17881837 tmp = GetTickCount();
17891838 if (srcyuv_fp != NULL)
@@ -1967,12 +2016,50 @@ static int print_input()
19672016 return 0;
19682017 }
19692018
2019+static int calc_PSNR(double *psnr)
2020+{
2021+ unsigned long srcyuv_size, recyuv_size, min_size;
2022+ char *srcyuv_ptr, *recyuv_ptr;
2023+ unsigned long i, sse=0;
2024+ double ssemean;
2025+
2026+ fseek(srcyuv_fp, 0L, SEEK_END);
2027+ srcyuv_size = ftell(srcyuv_fp);
2028+ fseek(recyuv_fp, 0L, SEEK_END);
2029+ recyuv_size = ftell(recyuv_fp);
2030+
2031+ fseek(srcyuv_fp, 0L, SEEK_SET);
2032+ fseek(recyuv_fp, 0L, SEEK_SET);
2033+
2034+ min_size = MIN(srcyuv_size,recyuv_size);
2035+ srcyuv_ptr = mmap (0, min_size, PROT_READ, MAP_SHARED, fileno(srcyuv_fp), 0);
2036+ recyuv_ptr = mmap (0, min_size, PROT_READ, MAP_SHARED, fileno(recyuv_fp), 0);
2037+ if ((srcyuv_ptr == MAP_FAILED) || (recyuv_ptr == MAP_FAILED)) {
2038+ printf("Failed to mmap YUV files\n");
2039+ return 1;
2040+ }
2041+
2042+ for (i=0; i<min_size; i++) {
2043+ char tmp = srcyuv_ptr[i] - recyuv_ptr[i];
2044+ sse += tmp * tmp;
2045+ }
2046+ ssemean = (double)sse/(double)min_size;
2047+ *psnr = 20.0*log10(255) - 10.0*log10(ssemean);
2048+
2049+ munmap(srcyuv_ptr, min_size);
2050+ munmap(recyuv_ptr, min_size);
2051+
2052+ return 0;
2053+}
19702054
19712055 static int print_performance(unsigned int PictureCount)
19722056 {
1973- unsigned int others = 0;
1974- double total_size = frame_width * frame_height * 1.5 * frame_count;
2057+ unsigned int psnr_ret = 1, others = 0;
2058+ double psnr = 0, total_size = frame_width * frame_height * 1.5 * frame_count;
19752059
2060+ if (calc_psnr && srcyuv_fp && recyuv_fp)
2061+ psnr_ret = calc_PSNR(&psnr);
2062+
19762063 others = TotalTicks - UploadPictureTicks - BeginPictureTicks
19772064 - RenderPictureTicks - EndPictureTicks - SyncPictureTicks - SavePictureTicks;
19782065
@@ -1982,6 +2069,9 @@ static int print_performance(unsigned int PictureCount)
19822069 (double) 1000*PictureCount / TotalTicks, PictureCount,
19832070 TotalTicks, ((double) TotalTicks) / (double) PictureCount);
19842071 printf("PERFORMANCE: Compression ratio : %d:1\n", (unsigned int)(total_size / frame_size));
2072+ if (psnr_ret == 0)
2073+ printf("PERFORMANCE: PSNR : %.2f (%lld frames calculated)\n",
2074+ psnr, MIN(frame_count, srcyuv_frames));
19852075
19862076 printf("PERFORMANCE: UploadPicture : %d ms (%.2f, %.2f%% percent)\n",
19872077 (int) UploadPictureTicks, ((double) UploadPictureTicks) / (double) PictureCount,
@@ -2006,8 +2096,8 @@ static int print_performance(unsigned int PictureCount)
20062096 others/(double) TotalTicks/0.01);
20072097
20082098 if (encode_syncmode == 0)
2009- printf("(Multithread enabled, the profiling is only for reference)\n");
2010-
2099+ printf("(Multithread enabled, the timing is only for reference)\n");
2100+
20112101 return 0;
20122102 }
20132103
--- a/test/loadsurface.h
+++ b/test/loadsurface.h
@@ -24,7 +24,7 @@
2424 #include "loadsurface_yuv.h"
2525
2626 static int scale_2dimage(unsigned char *src_img, int src_imgw, int src_imgh,
27- unsigned char *dst_img, int dst_imgw, int dst_imgh)
27+ unsigned char *dst_img, int dst_imgw, int dst_imgh)
2828 {
2929 int row=0, col=0;
3030
@@ -39,10 +39,10 @@ static int scale_2dimage(unsigned char *src_img, int src_imgw, int src_imgh,
3939
4040
4141 static int YUV_blend_with_pic(int width, int height,
42- unsigned char *Y_start, int Y_pitch,
43- unsigned char *U_start, int U_pitch,
44- unsigned char *V_start, int V_pitch,
45- unsigned int fourcc, int fixed_alpha)
42+ unsigned char *Y_start, int Y_pitch,
43+ unsigned char *U_start, int U_pitch,
44+ unsigned char *V_start, int V_pitch,
45+ unsigned int fourcc, int fixed_alpha)
4646 {
4747 /* PIC YUV format */
4848 unsigned char *pic_y_old = yuvga_pic;
@@ -155,7 +155,7 @@ static int yuvgen_planar(int width, int height,
155155
156156 /* copy Y plane */
157157 int y_factor = 1;
158- if (fourcc == VA_FOURCC_YUY2) y_factor = 2;
158+ if (fourcc == VA_FOURCC_YUY2) y_factor = 2;
159159 for (row=0;row<height;row++) {
160160 unsigned char *Y_row = Y_start + row * Y_pitch;
161161 int jj, xpos, ypos;
@@ -178,7 +178,7 @@ static int yuvgen_planar(int width, int height,
178178
179179 if (fourcc == VA_FOURCC_YUY2) {
180180 Y_row[jj*y_factor+1] = uv_value; // it is for UV
181- }
181+ }
182182 }
183183 }
184184
@@ -196,11 +196,11 @@ static int yuvgen_planar(int width, int height,
196196 switch (fourcc) {
197197 case VA_FOURCC_NV12:
198198 memset(U_row, uv_value, width);
199- break;
199+ break;
200200 case VA_FOURCC_YV12:
201201 memset (U_row,uv_value,width/2);
202202 memset (V_row,uv_value,width/2);
203- break;
203+ break;
204204 case VA_FOURCC_YUY2:
205205 // see above. it is set with Y update.
206206 break;
@@ -286,3 +286,195 @@ static int upload_surface(VADisplay va_dpy, VASurfaceID surface_id,
286286
287287 return 0;
288288 }
289+
290+/*
291+ * Upload YUV data from memory into a surface
292+ * if src_fourcc == NV12, assume the buffer pointed by src_U
293+ * is UV interleaved (src_V is ignored)
294+ */
295+static int upload_surface_yuv(VADisplay va_dpy, VASurfaceID surface_id,
296+ int src_fourcc, int src_width, int src_height,
297+ unsigned char *src_Y, unsigned char *src_U, unsigned char *src_V)
298+{
299+ VAImage surface_image;
300+ unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL, *V_start=NULL;
301+ int Y_pitch=0, U_pitch=0, V_pitch=0, row;
302+ VAStatus va_status;
303+
304+ va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
305+ CHECK_VASTATUS(va_status,"vaDeriveImage");
306+
307+ vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
308+ assert(VA_STATUS_SUCCESS == va_status);
309+
310+ Y_start = surface_p;
311+ Y_pitch = surface_image.pitches[0];
312+ switch (surface_image.format.fourcc) {
313+ case VA_FOURCC_NV12:
314+ U_start = (unsigned char *)surface_p + surface_image.offsets[1];
315+ V_start = U_start + 1;
316+ U_pitch = surface_image.pitches[1];
317+ V_pitch = surface_image.pitches[1];
318+ break;
319+ case VA_FOURCC_IYUV:
320+ U_start = (unsigned char *)surface_p + surface_image.offsets[1];
321+ V_start = (unsigned char *)surface_p + surface_image.offsets[2];
322+ U_pitch = surface_image.pitches[1];
323+ V_pitch = surface_image.pitches[2];
324+ break;
325+ case VA_FOURCC_YV12:
326+ U_start = (unsigned char *)surface_p + surface_image.offsets[2];
327+ V_start = (unsigned char *)surface_p + surface_image.offsets[1];
328+ U_pitch = surface_image.pitches[2];
329+ V_pitch = surface_image.pitches[1];
330+ break;
331+ case VA_FOURCC_YUY2:
332+ U_start = surface_p + 1;
333+ V_start = surface_p + 3;
334+ U_pitch = surface_image.pitches[0];
335+ V_pitch = surface_image.pitches[0];
336+ break;
337+ default:
338+ assert(0);
339+ }
340+
341+ /* copy Y plane */
342+ for (row=0;row<src_height;row++) {
343+ unsigned char *Y_row = Y_start + row * Y_pitch;
344+ memcpy(Y_row, src_Y + row*src_width, src_width);
345+ }
346+
347+ for (row =0; row < src_height/2; row++) {
348+ unsigned char *U_row = U_start + row * U_pitch;
349+ unsigned char *u_ptr = NULL, *v_ptr=NULL;
350+ int j;
351+ switch (surface_image.format.fourcc) {
352+ case VA_FOURCC_NV12:
353+ if (src_fourcc == VA_FOURCC_NV12) {
354+ memcpy(U_row, src_U + row * src_width, src_width);
355+ break;
356+ } else if (src_fourcc == VA_FOURCC_IYUV) {
357+ u_ptr = src_U + row * (src_width/2);
358+ v_ptr = src_V + row * (src_width/2);
359+ } else if (src_fourcc == VA_FOURCC_YV12) {
360+ v_ptr = src_U + row * (src_width/2);
361+ u_ptr = src_V + row * (src_width/2);
362+ }
363+ for(j = 0; j < src_width/2; j++) {
364+ U_row[2*j] = u_ptr[j];
365+ U_row[2*j+1] = v_ptr[j];
366+ }
367+ break;
368+ case VA_FOURCC_IYUV:
369+ case VA_FOURCC_YV12:
370+ case VA_FOURCC_YUY2:
371+ default:
372+ printf("unsupported fourcc in load_surface_yuv\n");
373+ assert(0);
374+ }
375+ }
376+
377+ vaUnmapBuffer(va_dpy,surface_image.buf);
378+
379+ vaDestroyImage(va_dpy,surface_image.image_id);
380+
381+ return 0;
382+}
383+
384+/*
385+ * Download YUV data from a surface into memory
386+ * Some hardward doesn't have a aperture for linear access of
387+ * tiled surface, thus use vaGetImage to expect the implemnetion
388+ * to do tile to linear convert
389+ *
390+ * if dst_fourcc == NV12, assume the buffer pointed by dst_U
391+ * is UV interleaved (src_V is ignored)
392+ */
393+static int download_surface_yuv(VADisplay va_dpy, VASurfaceID surface_id,
394+ int dst_fourcc, int dst_width, int dst_height,
395+ unsigned char *dst_Y, unsigned char *dst_U, unsigned char *dst_V)
396+{
397+ VAImage surface_image;
398+ unsigned char *surface_p=NULL, *Y_start=NULL, *U_start=NULL,*V_start=NULL;
399+ int Y_pitch=0, U_pitch=0, V_pitch=0, row;
400+ VAStatus va_status;
401+
402+ va_status = vaDeriveImage(va_dpy,surface_id, &surface_image);
403+ CHECK_VASTATUS(va_status,"vaDeriveImage");
404+
405+ vaMapBuffer(va_dpy,surface_image.buf,(void **)&surface_p);
406+ assert(VA_STATUS_SUCCESS == va_status);
407+
408+ Y_start = surface_p;
409+ Y_pitch = surface_image.pitches[0];
410+ switch (surface_image.format.fourcc) {
411+ case VA_FOURCC_NV12:
412+ U_start = (unsigned char *)surface_p + surface_image.offsets[1];
413+ V_start = U_start + 1;
414+ U_pitch = surface_image.pitches[1];
415+ V_pitch = surface_image.pitches[1];
416+ break;
417+ case VA_FOURCC_IYUV:
418+ U_start = (unsigned char *)surface_p + surface_image.offsets[1];
419+ V_start = (unsigned char *)surface_p + surface_image.offsets[2];
420+ U_pitch = surface_image.pitches[1];
421+ V_pitch = surface_image.pitches[2];
422+ break;
423+ case VA_FOURCC_YV12:
424+ U_start = (unsigned char *)surface_p + surface_image.offsets[2];
425+ V_start = (unsigned char *)surface_p + surface_image.offsets[1];
426+ U_pitch = surface_image.pitches[2];
427+ V_pitch = surface_image.pitches[1];
428+ break;
429+ case VA_FOURCC_YUY2:
430+ U_start = surface_p + 1;
431+ V_start = surface_p + 3;
432+ U_pitch = surface_image.pitches[0];
433+ V_pitch = surface_image.pitches[0];
434+ break;
435+ default:
436+ assert(0);
437+ }
438+
439+ /* copy Y plane */
440+ for (row=0;row<dst_height;row++) {
441+ unsigned char *Y_row = Y_start + row * Y_pitch;
442+ memcpy(dst_Y + row*dst_width, Y_row, dst_width);
443+ }
444+
445+ for (row =0; row < dst_height/2; row++) {
446+ unsigned char *U_row = U_start + row * U_pitch;
447+ unsigned char *u_ptr = NULL, *v_ptr = NULL;
448+ int j;
449+ switch (surface_image.format.fourcc) {
450+ case VA_FOURCC_NV12:
451+ if (dst_fourcc == VA_FOURCC_NV12) {
452+ memcpy(dst_U + row * dst_width, U_row, dst_width);
453+ break;
454+ } else if (dst_fourcc == VA_FOURCC_IYUV) {
455+ u_ptr = dst_U + row * (dst_width/2);
456+ v_ptr = dst_V + row * (dst_width/2);
457+ } else if (dst_fourcc == VA_FOURCC_YV12) {
458+ v_ptr = dst_U + row * (dst_width/2);
459+ u_ptr = dst_V + row * (dst_width/2);
460+ }
461+ for(j = 0; j < dst_width/2; j++) {
462+ u_ptr[j] = U_row[2*j];
463+ v_ptr[j] = U_row[2*j+1];
464+ }
465+ break;
466+ case VA_FOURCC_IYUV:
467+ case VA_FOURCC_YV12:
468+ case VA_FOURCC_YUY2:
469+ default:
470+ printf("unsupported fourcc in load_surface_yuv\n");
471+ assert(0);
472+ }
473+ }
474+
475+ vaUnmapBuffer(va_dpy,surface_image.buf);
476+
477+ vaDestroyImage(va_dpy,surface_image.image_id);
478+
479+ return 0;
480+}