hardware/intel/libva
Revision | 64f9de399187204d5c30cf205b4279ec5b002675 (tree) |
---|---|
Zeit | 2013-06-25 14:53:58 |
Autor | Austin Yuan <shengquan.yuan@inte...> |
Commiter | Xiang, Haihao |
h264encode: dump reconstructed frame and calc PSNR
Signed-off-by: Austin Yuan <shengquan.yuan@intel.com>
@@ -21,7 +21,7 @@ LOCAL_C_INCLUDES += \ | ||
21 | 21 | LOCAL_MODULE_TAGS := optional |
22 | 22 | LOCAL_MODULE := h264encode |
23 | 23 | |
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 | |
25 | 25 | |
26 | 26 | include $(BUILD_EXECUTABLE) |
27 | 27 |
@@ -33,7 +33,7 @@ h264encode_CFLAGS = -I$(top_srcdir)/test/common -g | ||
33 | 33 | h264encode_LDADD = \ |
34 | 34 | $(top_builddir)/va/libva.la \ |
35 | 35 | $(top_builddir)/test/common/libva-display.la \ |
36 | - -lpthread | |
36 | + -lpthread -lm | |
37 | 37 | |
38 | 38 | avcenc_SOURCES = avcenc.c |
39 | 39 | avcenc_CFLAGS = -I$(top_srcdir)/test/common -g |
@@ -30,9 +30,12 @@ | ||
30 | 30 | #include <sys/types.h> |
31 | 31 | #include <sys/stat.h> |
32 | 32 | #include <sys/time.h> |
33 | +#include <sys/mman.h> | |
33 | 34 | #include <fcntl.h> |
34 | 35 | #include <assert.h> |
35 | 36 | #include <pthread.h> |
37 | +#include <errno.h> | |
38 | +#include <math.h> | |
36 | 39 | #include <va/va.h> |
37 | 40 | #include <va/va_enc_h264.h> |
38 | 41 | #include "va_display.h" |
@@ -69,7 +72,6 @@ | ||
69 | 72 | |
70 | 73 | #define BITSTREAM_ALLOCATE_STEPPING 4096 |
71 | 74 | |
72 | - | |
73 | 75 | #define SURFACE_NUM 16 /* 16 surfaces for source YUV */ |
74 | 76 | #define SURFACE_NUM 16 /* 16 surfaces for reference */ |
75 | 77 | static VADisplay va_dpy; |
@@ -102,6 +104,7 @@ static char *coded_fn = NULL, *srcyuv_fn = NULL, *recyuv_fn = NULL; | ||
102 | 104 | static FILE *coded_fp = NULL, *srcyuv_fp = NULL, *recyuv_fp = NULL; |
103 | 105 | static unsigned long long srcyuv_frames = 0; |
104 | 106 | static int srcyuv_fourcc = VA_FOURCC_NV12; |
107 | +static int calc_psnr = 0; | |
105 | 108 | |
106 | 109 | static int frame_width = 176; |
107 | 110 | static int frame_height = 144; |
@@ -120,10 +123,13 @@ static int rc_mode = VA_RC_VBR; | ||
120 | 123 | static unsigned long long current_frame_encoding = 0; |
121 | 124 | static unsigned long long current_frame_display = 0; |
122 | 125 | static unsigned long long current_IDR_display = 0; |
123 | -static int current_frame_num = 0; | |
126 | +static unsigned int current_frame_num = 0; | |
124 | 127 | static int current_frame_type; |
125 | 128 | #define current_slot (current_frame_display % SURFACE_NUM) |
126 | 129 | |
130 | +#define MIN(a, b) ((a)>(b)?(b):(a)) | |
131 | +#define MAX(a, b) ((a)>(b)?(a):(b)) | |
132 | + | |
127 | 133 | /* thread to save coded data/upload source YUV */ |
128 | 134 | struct storage_task_t { |
129 | 135 | void *next; |
@@ -703,7 +709,9 @@ static int print_help(void) | ||
703 | 709 | printf(" --rcmode <NONE|CBR|VBR|VCM|CQP|VBR_CONTRAINED>\n"); |
704 | 710 | printf(" --syncmode: sequentially upload source, encoding, save result, no multi-thread\n"); |
705 | 711 | 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"); | |
707 | 715 | |
708 | 716 | return 0; |
709 | 717 | } |
@@ -712,6 +720,7 @@ static int process_cmdline(int argc, char *argv[]) | ||
712 | 720 | { |
713 | 721 | char c; |
714 | 722 | const struct option long_opts[] = { |
723 | + {"help", no_argument, NULL, 0 }, | |
715 | 724 | {"bitrate", required_argument, NULL, 1 }, |
716 | 725 | {"minqp", required_argument, NULL, 2 }, |
717 | 726 | {"initialqp", required_argument, NULL, 3 }, |
@@ -720,8 +729,10 @@ static int process_cmdline(int argc, char *argv[]) | ||
720 | 729 | {"ip_period", required_argument, NULL, 6 }, |
721 | 730 | {"rcmode", required_argument, NULL, 7 }, |
722 | 731 | {"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 }, | |
725 | 736 | {NULL, no_argument, NULL, 0 }}; |
726 | 737 | int long_index; |
727 | 738 |
@@ -742,6 +753,9 @@ static int process_cmdline(int argc, char *argv[]) | ||
742 | 753 | case 'o': |
743 | 754 | coded_fn = strdup(optarg); |
744 | 755 | break; |
756 | + case 0: | |
757 | + print_help(); | |
758 | + exit(0); | |
745 | 759 | case 1: |
746 | 760 | frame_bitrate = atoi(optarg); |
747 | 761 | break; |
@@ -771,15 +785,21 @@ static int process_cmdline(int argc, char *argv[]) | ||
771 | 785 | srcyuv_fn = strdup(optarg); |
772 | 786 | break; |
773 | 787 | case 10: |
788 | + recyuv_fn = strdup(optarg); | |
789 | + break; | |
790 | + case 11: | |
774 | 791 | srcyuv_fourcc = string_to_fourcc(optarg); |
775 | 792 | if (srcyuv_fourcc <= 0) { |
776 | 793 | print_help(); |
777 | 794 | exit(1); |
778 | 795 | } |
779 | 796 | break; |
780 | - case 11: | |
797 | + case 12: | |
781 | 798 | encode_syncmode = 1; |
782 | 799 | break; |
800 | + case 13: | |
801 | + calc_psnr = 1; | |
802 | + break; | |
783 | 803 | case ':': |
784 | 804 | case '?': |
785 | 805 | print_help(); |
@@ -815,6 +835,14 @@ static int process_cmdline(int argc, char *argv[]) | ||
815 | 835 | printf("Source YUV file %s with %llu frames\n", srcyuv_fn, srcyuv_frames); |
816 | 836 | } |
817 | 837 | } |
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 | + } | |
818 | 846 | |
819 | 847 | if (coded_fn == NULL) { |
820 | 848 | struct stat buf; |
@@ -919,7 +947,7 @@ static int init_va(void) | ||
919 | 947 | if (attrib[VAConfigAttribRateControl].value != VA_ATTRIB_NOT_SUPPORTED) { |
920 | 948 | int tmp = attrib[VAConfigAttribRateControl].value; |
921 | 949 | |
922 | - printf("Supported rate control mode (0x%x):", tmp); | |
950 | + printf("Supporte rate control mode (0x%x):", tmp); | |
923 | 951 | |
924 | 952 | if (tmp & VA_RC_NONE) |
925 | 953 | printf("NONE "); |
@@ -1114,7 +1142,7 @@ static void sort_one(VAPictureH264 ref[], int left, int right, | ||
1114 | 1142 | partition(ref, frame_idx, key, ascending); |
1115 | 1143 | } else { |
1116 | 1144 | key = ref[(left + right) / 2].TopFieldOrderCnt; |
1117 | - partition(ref, TopFieldOrderCnt, key, ascending); | |
1145 | + partition(ref, TopFieldOrderCnt, (signed int)key, ascending); | |
1118 | 1146 | } |
1119 | 1147 | |
1120 | 1148 | /* recursion */ |
@@ -1125,16 +1153,16 @@ static void sort_one(VAPictureH264 ref[], int left, int right, | ||
1125 | 1153 | sort_one(ref, i, right, ascending, frame_idx); |
1126 | 1154 | } |
1127 | 1155 | |
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) | |
1130 | 1158 | { |
1131 | 1159 | int i = left, j = right; |
1132 | 1160 | VAPictureH264 tmp; |
1133 | 1161 | |
1134 | 1162 | if (frame_idx) { |
1135 | - partition(ref, frame_idx, key, divide_ascending); | |
1163 | + partition(ref, frame_idx, key, partition_ascending); | |
1136 | 1164 | } else { |
1137 | - partition(ref, TopFieldOrderCnt, key, divide_ascending); | |
1165 | + partition(ref, TopFieldOrderCnt, (signed int)key, partition_ascending); | |
1138 | 1166 | } |
1139 | 1167 | |
1140 | 1168 |
@@ -1243,7 +1271,7 @@ static int render_sequence(void) | ||
1243 | 1271 | return 0; |
1244 | 1272 | } |
1245 | 1273 | |
1246 | -static int calc_poc(unsigned int pic_order_cnt_lsb) | |
1274 | +static int calc_poc(int pic_order_cnt_lsb) | |
1247 | 1275 | { |
1248 | 1276 | static int PicOrderCntMsb_ref = 0, pic_order_cnt_lsb_ref = 0; |
1249 | 1277 | int prevPicOrderCntMsb, prevPicOrderCntLsb; |
@@ -1257,10 +1285,10 @@ static int calc_poc(unsigned int pic_order_cnt_lsb) | ||
1257 | 1285 | } |
1258 | 1286 | |
1259 | 1287 | if ((pic_order_cnt_lsb < prevPicOrderCntLsb) && |
1260 | - ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (MaxPicOrderCntLsb / 2))) | |
1288 | + ((prevPicOrderCntLsb - pic_order_cnt_lsb) >= (int)(MaxPicOrderCntLsb / 2))) | |
1261 | 1289 | PicOrderCntMsb = prevPicOrderCntMsb + MaxPicOrderCntLsb; |
1262 | 1290 | else if ((pic_order_cnt_lsb > prevPicOrderCntLsb) && |
1263 | - ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (MaxPicOrderCntLsb / 2))) | |
1291 | + ((pic_order_cnt_lsb - prevPicOrderCntLsb) > (int)(MaxPicOrderCntLsb / 2))) | |
1264 | 1292 | PicOrderCntMsb = prevPicOrderCntMsb - MaxPicOrderCntLsb; |
1265 | 1293 | else |
1266 | 1294 | PicOrderCntMsb = prevPicOrderCntMsb; |
@@ -1326,7 +1354,7 @@ static int render_picture(void) | ||
1326 | 1354 | |
1327 | 1355 | static int render_packedsequence(void) |
1328 | 1356 | { |
1329 | - VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0}; | |
1357 | + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; | |
1330 | 1358 | VABufferID packedseq_para_bufid, packedseq_data_bufid, render_id[2]; |
1331 | 1359 | unsigned int length_in_bits; |
1332 | 1360 | unsigned char *packedseq_buffer = NULL; |
@@ -1365,7 +1393,7 @@ static int render_packedsequence(void) | ||
1365 | 1393 | |
1366 | 1394 | static int render_packedpicture(void) |
1367 | 1395 | { |
1368 | - VAEncPackedHeaderParameterBuffer packedheader_param_buffer={0}; | |
1396 | + VAEncPackedHeaderParameterBuffer packedheader_param_buffer; | |
1369 | 1397 | VABufferID packedpic_para_bufid, packedpic_data_bufid, render_id[2]; |
1370 | 1398 | unsigned int length_in_bits; |
1371 | 1399 | unsigned char *packedpic_buffer = NULL; |
@@ -1404,7 +1432,7 @@ static void render_packedsei(void) | ||
1404 | 1432 | { |
1405 | 1433 | VAEncPackedHeaderParameterBuffer packed_header_param_buffer; |
1406 | 1434 | 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*/; | |
1408 | 1436 | unsigned char *packed_sei_buffer = NULL; |
1409 | 1437 | VAStatus va_status; |
1410 | 1438 | 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) | ||
1431 | 1459 | 0, |
1432 | 1460 | &packed_sei_buffer); |
1433 | 1461 | |
1434 | - offset_in_bytes = 0; | |
1462 | + //offset_in_bytes = 0; | |
1435 | 1463 | packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI; |
1436 | 1464 | packed_header_param_buffer.bit_length = length_in_bits; |
1437 | 1465 | packed_header_param_buffer.has_emulation_bytes = 0; |
@@ -1571,110 +1599,130 @@ static int upload_source_YUV_once_for_all() | ||
1571 | 1599 | return 0; |
1572 | 1600 | } |
1573 | 1601 | |
1574 | - | |
1602 | +#define check_ret(ret) \ | |
1603 | +if (ret != 1) { \ | |
1604 | + printf("fread doesn't return enough data\n"); \ | |
1605 | + exit(1); \ | |
1606 | +} | |
1575 | 1607 | static int load_surface(VASurfaceID surface_id, unsigned long long display_order) |
1576 | 1608 | { |
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 | + | |
1582 | 1612 | if (srcyuv_fp == NULL) |
1583 | 1613 | return 0; |
1584 | 1614 | |
1585 | 1615 | /* rewind the file pointer if encoding more than srcyuv_frames */ |
1586 | 1616 | display_order = display_order % srcyuv_frames; |
1587 | - | |
1588 | 1617 | fseek(srcyuv_fp, display_order * frame_width * frame_height * 1.5, SEEK_SET); |
1589 | 1618 | |
1590 | - va_status = vaDeriveImage(va_dpy,surface_id, &surface_image); | |
1591 | - CHECK_VASTATUS(va_status,"vaDeriveImage"); | |
1592 | 1619 | |
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); | |
1595 | 1622 | |
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); | |
1625 | 1654 | } |
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 | + | |
1626 | 1669 | |
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); | |
1631 | 1692 | } |
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); | |
1671 | 1714 | } |
1715 | + } else { | |
1716 | + printf("Unsupported YUV format\n"); | |
1717 | + exit(1); | |
1672 | 1718 | } |
1673 | - free(uv_ptr); | |
1674 | 1719 | |
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); | |
1678 | 1726 | |
1679 | 1727 | return 0; |
1680 | 1728 | } |
@@ -1782,8 +1830,9 @@ static void storage_task(unsigned long long display_order, unsigned long long en | ||
1782 | 1830 | tmp = GetTickCount(); |
1783 | 1831 | save_codeddata(display_order, encode_order); |
1784 | 1832 | SavePictureTicks += GetTickCount() - tmp; |
1785 | - /* tbd: save reconstructed frame */ | |
1786 | - | |
1833 | + | |
1834 | + save_recyuv(ref_surface[display_order % SURFACE_NUM], display_order, encode_order); | |
1835 | + | |
1787 | 1836 | /* reload a new frame data */ |
1788 | 1837 | tmp = GetTickCount(); |
1789 | 1838 | if (srcyuv_fp != NULL) |
@@ -1967,12 +2016,50 @@ static int print_input() | ||
1967 | 2016 | return 0; |
1968 | 2017 | } |
1969 | 2018 | |
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 | +} | |
1970 | 2054 | |
1971 | 2055 | static int print_performance(unsigned int PictureCount) |
1972 | 2056 | { |
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; | |
1975 | 2059 | |
2060 | + if (calc_psnr && srcyuv_fp && recyuv_fp) | |
2061 | + psnr_ret = calc_PSNR(&psnr); | |
2062 | + | |
1976 | 2063 | others = TotalTicks - UploadPictureTicks - BeginPictureTicks |
1977 | 2064 | - RenderPictureTicks - EndPictureTicks - SyncPictureTicks - SavePictureTicks; |
1978 | 2065 |
@@ -1982,6 +2069,9 @@ static int print_performance(unsigned int PictureCount) | ||
1982 | 2069 | (double) 1000*PictureCount / TotalTicks, PictureCount, |
1983 | 2070 | TotalTicks, ((double) TotalTicks) / (double) PictureCount); |
1984 | 2071 | 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)); | |
1985 | 2075 | |
1986 | 2076 | printf("PERFORMANCE: UploadPicture : %d ms (%.2f, %.2f%% percent)\n", |
1987 | 2077 | (int) UploadPictureTicks, ((double) UploadPictureTicks) / (double) PictureCount, |
@@ -2006,8 +2096,8 @@ static int print_performance(unsigned int PictureCount) | ||
2006 | 2096 | others/(double) TotalTicks/0.01); |
2007 | 2097 | |
2008 | 2098 | 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 | + | |
2011 | 2101 | return 0; |
2012 | 2102 | } |
2013 | 2103 |
@@ -24,7 +24,7 @@ | ||
24 | 24 | #include "loadsurface_yuv.h" |
25 | 25 | |
26 | 26 | 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) | |
28 | 28 | { |
29 | 29 | int row=0, col=0; |
30 | 30 |
@@ -39,10 +39,10 @@ static int scale_2dimage(unsigned char *src_img, int src_imgw, int src_imgh, | ||
39 | 39 | |
40 | 40 | |
41 | 41 | 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) | |
46 | 46 | { |
47 | 47 | /* PIC YUV format */ |
48 | 48 | unsigned char *pic_y_old = yuvga_pic; |
@@ -155,7 +155,7 @@ static int yuvgen_planar(int width, int height, | ||
155 | 155 | |
156 | 156 | /* copy Y plane */ |
157 | 157 | int y_factor = 1; |
158 | - if (fourcc == VA_FOURCC_YUY2) y_factor = 2; | |
158 | + if (fourcc == VA_FOURCC_YUY2) y_factor = 2; | |
159 | 159 | for (row=0;row<height;row++) { |
160 | 160 | unsigned char *Y_row = Y_start + row * Y_pitch; |
161 | 161 | int jj, xpos, ypos; |
@@ -178,7 +178,7 @@ static int yuvgen_planar(int width, int height, | ||
178 | 178 | |
179 | 179 | if (fourcc == VA_FOURCC_YUY2) { |
180 | 180 | Y_row[jj*y_factor+1] = uv_value; // it is for UV |
181 | - } | |
181 | + } | |
182 | 182 | } |
183 | 183 | } |
184 | 184 |
@@ -196,11 +196,11 @@ static int yuvgen_planar(int width, int height, | ||
196 | 196 | switch (fourcc) { |
197 | 197 | case VA_FOURCC_NV12: |
198 | 198 | memset(U_row, uv_value, width); |
199 | - break; | |
199 | + break; | |
200 | 200 | case VA_FOURCC_YV12: |
201 | 201 | memset (U_row,uv_value,width/2); |
202 | 202 | memset (V_row,uv_value,width/2); |
203 | - break; | |
203 | + break; | |
204 | 204 | case VA_FOURCC_YUY2: |
205 | 205 | // see above. it is set with Y update. |
206 | 206 | break; |
@@ -286,3 +286,195 @@ static int upload_surface(VADisplay va_dpy, VASurfaceID surface_id, | ||
286 | 286 | |
287 | 287 | return 0; |
288 | 288 | } |
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 | +} |