1 /*
2 * Copyright (c) 2009-2018, Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included
12 * in all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
21 */
22 /*
23  * Video process test case based on LibVA.
24  * This test covers sharpness feature.
25  * Usage: ./vppsharpness process_sharpness.cfg
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <time.h>
33 #include <assert.h>
34 #include <va/va.h>
35 #include <va/va_vpp.h>
36 #include "va_display.h"
37 
38 #ifndef VA_FOURCC_I420
39 #define VA_FOURCC_I420 0x30323449
40 #endif
41 
42 #define MAX_LEN   1024
43 
44 #define CHECK_VASTATUS(va_status,func)                                      \
45   if (va_status != VA_STATUS_SUCCESS) {                                     \
46       fprintf(stderr,"%s:%s (%d) failed,exit\n", __func__, func, __LINE__); \
47       exit(1);                                                              \
48   }
49 
50 static VADisplay va_dpy = NULL;
51 static VAContextID context_id = 0;
52 static VAConfigID  config_id = 0;
53 static VASurfaceID g_in_surface_id = VA_INVALID_ID;
54 static VASurfaceID g_out_surface_id = VA_INVALID_ID;
55 
56 static FILE* g_config_file_fd = NULL;
57 static FILE* g_src_file_fd = NULL;
58 static FILE* g_dst_file_fd = NULL;
59 
60 static char g_config_file_name[MAX_LEN];
61 static char g_src_file_name[MAX_LEN];
62 static char g_dst_file_name[MAX_LEN];
63 
64 static uint32_t g_in_pic_width = 352;
65 static uint32_t g_in_pic_height = 288;
66 static uint32_t g_out_pic_width = 352;
67 static uint32_t g_out_pic_height = 288;
68 
69 static uint32_t g_in_fourcc  = VA_FOURCC('N', 'V', '1', '2');
70 static uint32_t g_in_format  = VA_RT_FORMAT_YUV420;
71 static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2');
72 static uint32_t g_out_format = VA_RT_FORMAT_YUV420;
73 static uint32_t g_src_file_fourcc = VA_FOURCC('I', '4', '2', '0');
74 static uint32_t g_dst_file_fourcc = VA_FOURCC('Y', 'V', '1', '2');
75 
76 static uint32_t g_frame_count = 0;
77 
78 static int8_t
read_value_string(FILE * fp,const char * field_name,char * value)79 read_value_string(FILE *fp, const char* field_name, char* value)
80 {
81     char strLine[MAX_LEN];
82     char* field = NULL;
83     char* str = NULL;
84     uint16_t i;
85 
86     if (!fp || !field_name || !value)  {
87         printf("Invalid fuction parameters\n");
88         return -1;
89     }
90 
91     rewind(fp);
92 
93     while (!feof(fp)) {
94         if (!fgets(strLine, MAX_LEN, fp))
95             continue;
96 
97         for (i = 0; i < MAX_LEN && strLine[i]; i++)
98             if (strLine[i] != ' ') break;
99 
100         if (i == MAX_LEN || strLine[i] == '#' || strLine[i] == '\n')
101             continue;
102 
103         field = strtok(&strLine[i], ":");
104         if (strncmp(field, field_name, strlen(field_name)))
105             continue;
106 
107         if (!(str = strtok(NULL, ":")))
108             continue;
109 
110         /* skip blank space in string */
111         while (*str == ' ')
112             str++;
113 
114         *(str + strlen(str) - 1) = '\0';
115         strcpy(value, str);
116 
117         return 0;
118     }
119 
120     return -1;
121 }
122 
123 static int8_t
read_value_uint32(FILE * fp,const char * field_name,uint32_t * value)124 read_value_uint32(FILE* fp, const char* field_name, uint32_t* value)
125 {
126     char str[MAX_LEN];
127 
128     if (read_value_string(fp, field_name, str)) {
129         printf("Failed to find integer field: %s", field_name);
130         return -1;
131     }
132 
133     *value = (uint32_t)atoi(str);
134     return 0;
135 }
136 static int8_t
read_value_float(FILE * fp,const char * field_name,float * value)137 read_value_float(FILE *fp, const char* field_name, float* value)
138 {
139     char str[MAX_LEN];
140     if (read_value_string(fp, field_name, str)) {
141         printf("Failed to find float field: %s \n", field_name);
142         return -1;
143     }
144 
145     *value = atof(str);
146     return 0;
147 }
148 
149 static float
adjust_to_range(VAProcFilterValueRange * range,float value)150 adjust_to_range(VAProcFilterValueRange *range, float value)
151 {
152     if (value < range->min_value || value > range->max_value) {
153         printf("Value: %f exceed range: (%f ~ %f), force to use default: %f \n",
154                value, range->min_value, range->max_value, range->default_value);
155         return range->default_value;
156     }
157 
158     return value;
159 }
160 
161 static VAStatus
create_surface(VASurfaceID * p_surface_id,uint32_t width,uint32_t height,uint32_t fourCC,uint32_t format)162 create_surface(VASurfaceID * p_surface_id,
163                uint32_t width, uint32_t height,
164                uint32_t fourCC, uint32_t format)
165 {
166     VAStatus va_status;
167     VASurfaceAttrib    surface_attrib;
168     surface_attrib.type =  VASurfaceAttribPixelFormat;
169     surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
170     surface_attrib.value.type = VAGenericValueTypeInteger;
171     surface_attrib.value.value.i = fourCC;
172 
173     va_status = vaCreateSurfaces(va_dpy,
174                                  format,
175                                  width,
176                                  height,
177                                  p_surface_id,
178                                  1,
179                                  &surface_attrib,
180                                  1);
181     return va_status;
182 }
183 
184 /* Load yuv frame to NV12/YV12/I420 surface*/
185 static VAStatus
upload_yuv_frame_to_yuv_surface(FILE * fp,VASurfaceID surface_id)186 upload_yuv_frame_to_yuv_surface(FILE *fp,
187                                 VASurfaceID surface_id)
188 {
189     VAStatus va_status;
190     VAImage surface_image;
191     unsigned char *y_src = NULL;
192     unsigned char *u_src = NULL;
193     unsigned char *v_src = NULL;
194     unsigned char *y_dst = NULL;
195     unsigned char *u_dst = NULL;
196     unsigned char *v_dst = NULL;
197     void *surface_p = NULL;
198     uint32_t frame_size, row, col;
199     size_t n_items;
200     unsigned char * newImageBuffer = NULL;
201     va_status = vaSyncSurface(va_dpy, surface_id);
202     CHECK_VASTATUS(va_status, "vaSyncSurface");
203 
204     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
205     CHECK_VASTATUS(va_status, "vaDeriveImage");
206 
207     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
208     CHECK_VASTATUS(va_status, "vaMapBuffer");
209 
210     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
211         surface_image.format.fourcc == VA_FOURCC_I420 ||
212         surface_image.format.fourcc == VA_FOURCC_NV12) {
213 
214         frame_size = surface_image.width * surface_image.height * 3 / 2;
215         newImageBuffer = (unsigned char*)malloc(frame_size);
216         assert(newImageBuffer);
217 
218         do {
219             n_items = fread(newImageBuffer, frame_size, 1, fp);
220         } while (n_items != 1);
221 
222         y_src = newImageBuffer;
223         if (g_src_file_fourcc == VA_FOURCC_I420) {
224             u_src = newImageBuffer + surface_image.width * surface_image.height;
225             v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4;
226         } else if (g_src_file_fourcc == VA_FOURCC_YV12) {
227             v_src = newImageBuffer + surface_image.width * surface_image.height;
228             u_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4;
229         } else if (g_src_file_fourcc == VA_FOURCC_NV12) {
230             u_src = newImageBuffer + surface_image.width * surface_image.height;
231             v_src = u_src;
232         } else {
233             printf("Not supported YUV fourcc for input file !!!\n");
234             free(newImageBuffer);
235             return VA_STATUS_ERROR_INVALID_SURFACE;
236         }
237 
238         y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
239 
240         if (surface_image.format.fourcc == VA_FOURCC_YV12) {
241             v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
242             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
243         } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
244             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
245             v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
246         } else {
247             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
248             v_dst = u_dst;
249         }
250 
251         /* Y plane, directly copy */
252         for (row = 0; row < surface_image.height; row++) {
253             memcpy(y_dst, y_src, surface_image.width);
254             y_dst += surface_image.pitches[0];
255             y_src += surface_image.width;
256         }
257 
258         /* UV plane */
259         if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
260             surface_image.format.fourcc == VA_FOURCC_I420) {
261             for (row = 0; row < surface_image.height / 2; row ++) {
262                 if (g_src_file_fourcc == VA_FOURCC_I420 ||
263                     g_src_file_fourcc == VA_FOURCC_YV12) {
264                     memcpy(v_dst, v_src, surface_image.width / 2);
265                     memcpy(u_dst, u_src, surface_image.width / 2);
266 
267                     v_src += surface_image.width / 2;
268                     u_src += surface_image.width / 2;
269                 } else {
270                     for (col = 0; col < surface_image.width / 2; col++) {
271                         u_dst[col] = u_src[col * 2];
272                         v_dst[col] = u_src[col * 2 + 1];
273                     }
274 
275                     u_src += surface_image.width;
276                     v_src = u_src;
277                 }
278 
279                 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
280                     v_dst += surface_image.pitches[1];
281                     u_dst += surface_image.pitches[2];
282                 } else {
283                     v_dst += surface_image.pitches[2];
284                     u_dst += surface_image.pitches[1];
285                 }
286             }
287         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
288             for (row = 0; row < surface_image.height / 2; row++) {
289                 if (g_src_file_fourcc == VA_FOURCC_I420 ||
290                     g_src_file_fourcc == VA_FOURCC_YV12) {
291                     for (col = 0; col < surface_image.width / 2; col++) {
292                         u_dst[col * 2] = u_src[col];
293                         u_dst[col * 2 + 1] = v_src[col];
294                     }
295 
296                     u_src += (surface_image.width / 2);
297                     v_src += (surface_image.width / 2);
298                 } else {
299                     memcpy(u_dst, u_src, surface_image.width);
300                     u_src += surface_image.width;
301                     v_src = u_src;
302                 }
303 
304                 u_dst += surface_image.pitches[1];
305             }
306         }
307     } else if ((surface_image.format.fourcc == VA_FOURCC_YUY2 &&
308                 g_src_file_fourcc == VA_FOURCC_YUY2) ||
309                (surface_image.format.fourcc == VA_FOURCC_UYVY &&
310                 g_src_file_fourcc == VA_FOURCC_UYVY)) {
311         frame_size = surface_image.width * surface_image.height * 2;
312         newImageBuffer = (unsigned char*)malloc(frame_size);
313         assert(newImageBuffer);
314 
315         do {
316             n_items = fread(newImageBuffer, frame_size, 1, fp);
317         } while (n_items != 1);
318 
319         y_src = newImageBuffer;
320         y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
321 
322         /* plane 0, directly copy */
323         for (row = 0; row < surface_image.height; row++) {
324             memcpy(y_dst, y_src, surface_image.width * 2);
325             y_src += surface_image.width * 2;
326             y_dst += surface_image.pitches[0];
327         }
328     } else if ((surface_image.format.fourcc == VA_FOURCC_P010 &&
329                 g_src_file_fourcc == VA_FOURCC_P010) ||
330                (surface_image.format.fourcc == VA_FOURCC_I010 &&
331                 g_src_file_fourcc == VA_FOURCC_I010)) {
332         frame_size = surface_image.width * surface_image.height * 3;
333         newImageBuffer = (unsigned char*)malloc(frame_size);
334         assert(newImageBuffer);
335 
336         do {
337             n_items = fread(newImageBuffer, frame_size, 1, fp);
338         } while (n_items != 1);
339 
340         y_src = newImageBuffer;
341         y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
342 
343         /* plane 0, directly copy */
344         for (row = 0; row < surface_image.height; row++) {
345             memcpy(y_dst, y_src, surface_image.width * 2);
346             y_src += surface_image.width * 2;
347             y_dst += surface_image.pitches[0];
348         }
349 
350         /* UV plane */
351         if (surface_image.format.fourcc == VA_FOURCC_I010) {
352             assert(g_src_file_fourcc == VA_FOURCC_I010);
353 
354             u_src = newImageBuffer + surface_image.width * surface_image.height * 2;
355             v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 2;
356 
357             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
358             v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
359 
360             for (row = 0; row < surface_image.height / 2; row++) {
361                 memcpy(u_dst, u_src, surface_image.width);
362                 memcpy(v_dst, v_src, surface_image.width);
363 
364                 u_src += surface_image.width;
365                 v_src += surface_image.width;
366 
367                 u_dst += surface_image.pitches[1];
368                 v_dst += surface_image.pitches[2];
369             }
370         } else if (surface_image.format.fourcc == VA_FOURCC_P010) {
371             assert(g_src_file_fourcc == VA_FOURCC_P010);
372 
373             u_src = newImageBuffer + surface_image.width * surface_image.height * 2;
374             v_src = u_src;
375 
376             u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
377             v_dst = u_dst;
378 
379             for (row = 0; row < surface_image.height / 2; row++) {
380                 memcpy(u_dst, u_src, surface_image.width * 2);
381 
382                 u_src += surface_image.width * 2;
383                 v_src = u_src;
384 
385                 u_dst += surface_image.pitches[1];
386                 v_dst = u_dst;
387             }
388         }
389     }  else if ((surface_image.format.fourcc == VA_FOURCC_RGBA &&
390                  g_src_file_fourcc == VA_FOURCC_RGBA) ||
391                 (surface_image.format.fourcc == VA_FOURCC_RGBX &&
392                  g_src_file_fourcc == VA_FOURCC_RGBX) ||
393                 (surface_image.format.fourcc == VA_FOURCC_BGRA &&
394                  g_src_file_fourcc == VA_FOURCC_BGRA) ||
395                 (surface_image.format.fourcc == VA_FOURCC_BGRX &&
396                  g_src_file_fourcc == VA_FOURCC_BGRX)) {
397         frame_size = surface_image.width * surface_image.height * 4;
398         newImageBuffer = (unsigned char*)malloc(frame_size);
399         assert(newImageBuffer);
400 
401         do {
402             n_items = fread(newImageBuffer, frame_size, 1, fp);
403         } while (n_items != 1);
404 
405         y_src = newImageBuffer;
406         y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
407 
408         /* plane 0, directly copy */
409         for (row = 0; row < surface_image.height; row++) {
410             memcpy(y_dst, y_src, surface_image.width * 4);
411             y_src += surface_image.width * 4;
412             y_dst += surface_image.pitches[0];
413         }
414     } else {
415         printf("Not supported YUV surface fourcc !!! \n");
416         return VA_STATUS_ERROR_INVALID_SURFACE;
417     }
418 
419     if (newImageBuffer) {
420         free(newImageBuffer);
421         newImageBuffer = NULL;
422     }
423 
424     vaUnmapBuffer(va_dpy, surface_image.buf);
425     vaDestroyImage(va_dpy, surface_image.image_id);
426 
427     return VA_STATUS_SUCCESS;
428 }
429 
430 /* Store NV12/YV12/I420 surface to yv12 file */
431 static VAStatus
store_yuv_surface_to_yv12_file(FILE * fp,VASurfaceID surface_id)432 store_yuv_surface_to_yv12_file(FILE *fp,
433                                VASurfaceID surface_id)
434 {
435     VAStatus va_status;
436     VAImage surface_image;
437     void *surface_p = NULL;
438     unsigned char *y_src = NULL;
439     unsigned char *u_src = NULL;
440     unsigned char *v_src = NULL;
441     unsigned char *y_dst = NULL;
442     unsigned char *u_dst = NULL;
443     unsigned char *v_dst = NULL;
444     uint32_t row, col;
445     int32_t n_items;
446     unsigned char * newImageBuffer = NULL;
447     va_status = vaSyncSurface(va_dpy, surface_id);
448     CHECK_VASTATUS(va_status, "vaSyncSurface");
449 
450     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
451     CHECK_VASTATUS(va_status, "vaDeriveImage");
452 
453     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
454     CHECK_VASTATUS(va_status, "vaMapBuffer");
455 
456     /* store the surface to one YV12 file or one bmp file*/
457     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
458         surface_image.format.fourcc == VA_FOURCC_I420 ||
459         surface_image.format.fourcc == VA_FOURCC_NV12) {
460 
461         uint32_t y_size = surface_image.width * surface_image.height;
462         uint32_t u_size = y_size / 4;
463 
464         newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
465         assert(newImageBuffer);
466 
467         /* stored as YV12 format */
468         y_dst = newImageBuffer;
469         v_dst = newImageBuffer + y_size;
470         u_dst = newImageBuffer + y_size + u_size;
471 
472         y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
473         if (surface_image.format.fourcc == VA_FOURCC_YV12) {
474             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
475             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
476         } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
477             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
478             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
479         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
480             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
481             v_src = u_src;
482         }
483 
484         /* Y plane copy */
485         for (row = 0; row < surface_image.height; row++) {
486             memcpy(y_dst, y_src, surface_image.width);
487             y_src += surface_image.pitches[0];
488             y_dst += surface_image.width;
489         }
490 
491         /* UV plane copy */
492         if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
493             surface_image.format.fourcc == VA_FOURCC_I420) {
494             for (row = 0; row < surface_image.height / 2; row ++) {
495                 memcpy(v_dst, v_src, surface_image.width / 2);
496                 memcpy(u_dst, u_src, surface_image.width / 2);
497 
498                 v_dst += surface_image.width / 2;
499                 u_dst += surface_image.width / 2;
500 
501                 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
502                     v_src += surface_image.pitches[1];
503                     u_src += surface_image.pitches[2];
504                 } else {
505                     v_src += surface_image.pitches[2];
506                     u_src += surface_image.pitches[1];
507                 }
508             }
509         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
510             for (row = 0; row < surface_image.height / 2; row++) {
511                 for (col = 0; col < surface_image.width / 2; col++) {
512                     u_dst[col] = u_src[col * 2];
513                     v_dst[col] = u_src[col * 2 + 1];
514                 }
515 
516                 u_src += surface_image.pitches[1];
517                 u_dst += (surface_image.width / 2);
518                 v_dst += (surface_image.width / 2);
519             }
520         }
521 
522         /* write frame to file */
523         do {
524             n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
525         } while (n_items != 1);
526 
527     } else {
528         printf("Not supported YUV surface fourcc !!! \n");
529         return VA_STATUS_ERROR_INVALID_SURFACE;
530     }
531 
532     if (newImageBuffer) {
533         free(newImageBuffer);
534         newImageBuffer = NULL;
535     }
536 
537     vaUnmapBuffer(va_dpy, surface_image.buf);
538     vaDestroyImage(va_dpy, surface_image.image_id);
539 
540     return VA_STATUS_SUCCESS;
541 }
542 
543 static VAStatus
store_yuv_surface_to_i420_file(FILE * fp,VASurfaceID surface_id)544 store_yuv_surface_to_i420_file(FILE *fp,
545                                VASurfaceID surface_id)
546 {
547     VAStatus va_status;
548     VAImage surface_image;
549     void *surface_p = NULL;
550     unsigned char *y_src = NULL;
551     unsigned char *u_src = NULL;
552     unsigned char *v_src = NULL;
553     unsigned char *y_dst = NULL;
554     unsigned char *u_dst = NULL;
555     unsigned char *v_dst = NULL;
556     uint32_t row, col;
557     int32_t n_items;
558     unsigned char * newImageBuffer = NULL;
559     va_status = vaSyncSurface(va_dpy, surface_id);
560     CHECK_VASTATUS(va_status, "vaSyncSurface");
561 
562     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
563     CHECK_VASTATUS(va_status, "vaDeriveImage");
564 
565     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
566     CHECK_VASTATUS(va_status, "vaMapBuffer");
567 
568     /* store the surface to one i420 file */
569     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
570         surface_image.format.fourcc == VA_FOURCC_I420 ||
571         surface_image.format.fourcc == VA_FOURCC_NV12) {
572 
573         uint32_t y_size = surface_image.width * surface_image.height;
574         uint32_t u_size = y_size / 4;
575 
576         newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
577         assert(newImageBuffer);
578 
579         /* stored as YV12 format */
580         y_dst = newImageBuffer;
581         u_dst = newImageBuffer + y_size;
582         v_dst = newImageBuffer + y_size + u_size;
583 
584         y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
585         if (surface_image.format.fourcc == VA_FOURCC_YV12) {
586             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
587             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
588         } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
589             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
590             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
591         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
592             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
593             v_src = u_src;
594         }
595 
596         /* Y plane copy */
597         for (row = 0; row < surface_image.height; row++) {
598             memcpy(y_dst, y_src, surface_image.width);
599             y_src += surface_image.pitches[0];
600             y_dst += surface_image.width;
601         }
602 
603         /* UV plane copy */
604         if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
605             surface_image.format.fourcc == VA_FOURCC_I420) {
606             for (row = 0; row < surface_image.height / 2; row ++) {
607                 memcpy(v_dst, v_src, surface_image.width / 2);
608                 memcpy(u_dst, u_src, surface_image.width / 2);
609 
610                 v_dst += surface_image.width / 2;
611                 u_dst += surface_image.width / 2;
612 
613                 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
614                     v_src += surface_image.pitches[1];
615                     u_src += surface_image.pitches[2];
616                 } else {
617                     v_src += surface_image.pitches[2];
618                     u_src += surface_image.pitches[1];
619                 }
620             }
621         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
622             for (row = 0; row < surface_image.height / 2; row++) {
623                 for (col = 0; col < surface_image.width / 2; col++) {
624                     u_dst[col] = u_src[col * 2];
625                     v_dst[col] = u_src[col * 2 + 1];
626                 }
627 
628                 u_src += surface_image.pitches[1];
629                 u_dst += (surface_image.width / 2);
630                 v_dst += (surface_image.width / 2);
631             }
632         }
633 
634         /* write frame to file */
635         do {
636             n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
637         } while (n_items != 1);
638 
639     } else {
640         printf("Not supported YUV surface fourcc !!! \n");
641         return VA_STATUS_ERROR_INVALID_SURFACE;
642     }
643 
644     if (newImageBuffer) {
645         free(newImageBuffer);
646         newImageBuffer = NULL;
647     }
648 
649     vaUnmapBuffer(va_dpy, surface_image.buf);
650     vaDestroyImage(va_dpy, surface_image.image_id);
651 
652     return VA_STATUS_SUCCESS;
653 }
654 
655 static VAStatus
store_yuv_surface_to_nv12_file(FILE * fp,VASurfaceID surface_id)656 store_yuv_surface_to_nv12_file(FILE *fp,
657                                VASurfaceID surface_id)
658 {
659     VAStatus va_status;
660     VAImage surface_image;
661     void *surface_p = NULL;
662     unsigned char *y_src = NULL;
663     unsigned char *u_src = NULL;
664     unsigned char *v_src = NULL;
665     unsigned char *y_dst = NULL;
666     unsigned char *u_dst = NULL;
667     unsigned char *v_dst = NULL;
668     uint32_t row, col;
669     int32_t n_items;
670     unsigned char * newImageBuffer = NULL;
671     va_status = vaSyncSurface(va_dpy, surface_id);
672     CHECK_VASTATUS(va_status, "vaSyncSurface");
673 
674     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
675     CHECK_VASTATUS(va_status, "vaDeriveImage");
676 
677     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
678     CHECK_VASTATUS(va_status, "vaMapBuffer");
679 
680     /* store the surface to one nv12 file */
681     if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
682         surface_image.format.fourcc == VA_FOURCC_I420 ||
683         surface_image.format.fourcc == VA_FOURCC_NV12) {
684 
685         uint32_t y_size = surface_image.width * surface_image.height;
686 
687         newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
688         assert(newImageBuffer);
689 
690         /* stored as YV12 format */
691         y_dst = newImageBuffer;
692         u_dst = v_dst = newImageBuffer + y_size;
693 
694         y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
695 
696         if (surface_image.format.fourcc == VA_FOURCC_YV12) {
697             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
698             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
699         } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
700             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
701             v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
702         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
703             u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
704             v_src = u_src;
705         }
706 
707         /* Y plane copy */
708         for (row = 0; row < surface_image.height; row++) {
709             memcpy(y_dst, y_src, surface_image.width);
710             y_src += surface_image.pitches[0];
711             y_dst += surface_image.width;
712         }
713 
714         /* UV plane copy */
715         if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
716             surface_image.format.fourcc == VA_FOURCC_I420) {
717             for (row = 0; row < surface_image.height / 2; row ++) {
718                 for (col = 0; col < surface_image.width / 2; col++) {
719                     u_dst[col * 2] = u_src[col];
720                     u_dst[col * 2 + 1] = v_src[col];
721                 }
722 
723                 u_dst += surface_image.width;
724 
725                 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
726                     v_src += surface_image.pitches[1];
727                     u_src += surface_image.pitches[2];
728                 } else {
729                     v_src += surface_image.pitches[2];
730                     u_src += surface_image.pitches[1];
731                 }
732             }
733         } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
734             for (row = 0; row < surface_image.height / 2; row++) {
735                 memcpy(u_dst, u_src, surface_image.width);
736                 u_dst += surface_image.width;
737                 u_src += surface_image.pitches[1];
738             }
739         }
740 
741         /* write frame to file */
742         do {
743             n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
744         } while (n_items != 1);
745 
746     } else {
747         printf("Not supported YUV surface fourcc !!! \n");
748         return VA_STATUS_ERROR_INVALID_SURFACE;
749     }
750 
751     if (newImageBuffer) {
752         free(newImageBuffer);
753         newImageBuffer = NULL;
754     }
755 
756     vaUnmapBuffer(va_dpy, surface_image.buf);
757     vaDestroyImage(va_dpy, surface_image.image_id);
758 
759     return VA_STATUS_SUCCESS;
760 }
761 
762 static VAStatus
store_packed_yuv_surface_to_packed_file(FILE * fp,VASurfaceID surface_id)763 store_packed_yuv_surface_to_packed_file(FILE *fp,
764                                         VASurfaceID surface_id)
765 {
766     VAStatus va_status;
767     VAImage surface_image;
768     void *surface_p = NULL;
769     unsigned char *y_src = NULL;
770     unsigned char *y_dst = NULL;
771     uint32_t row;
772     int32_t n_items;
773     unsigned char * newImageBuffer = NULL;
774     va_status = vaSyncSurface(va_dpy, surface_id);
775     CHECK_VASTATUS(va_status, "vaSyncSurface");
776 
777     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
778     CHECK_VASTATUS(va_status, "vaDeriveImage");
779 
780     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
781     CHECK_VASTATUS(va_status, "vaMapBuffer");
782 
783     /* store the surface to one YUY2 or UYVY file */
784     if (surface_image.format.fourcc == VA_FOURCC_YUY2 ||
785         surface_image.format.fourcc == VA_FOURCC_UYVY) {
786         uint32_t frame_size = surface_image.width * surface_image.height * 2;
787 
788         newImageBuffer = (unsigned char*)malloc(frame_size);
789         assert(newImageBuffer);
790         memset(newImageBuffer, 0, frame_size);
791 
792         /* stored as YUY2 or UYVY format */
793         y_dst = newImageBuffer;
794 
795         y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
796 
797         /* Plane 0 copy */
798         for (row = 0; row < surface_image.height; row++) {
799             memcpy(y_dst, y_src, surface_image.width * 2);
800             y_src += surface_image.pitches[0];
801             y_dst += surface_image.width * 2;
802         }
803 
804         /* write frame to file */
805         do {
806             n_items = fwrite(newImageBuffer, frame_size, 1, fp);
807         } while (n_items != 1);
808 
809     } else {
810         printf("Not supported YUV surface fourcc !!! \n");
811         return VA_STATUS_ERROR_INVALID_SURFACE;
812     }
813 
814     if (newImageBuffer) {
815         free(newImageBuffer);
816         newImageBuffer = NULL;
817     }
818 
819     vaUnmapBuffer(va_dpy, surface_image.buf);
820     vaDestroyImage(va_dpy, surface_image.image_id);
821 
822     return VA_STATUS_SUCCESS;
823 }
824 
825 static VAStatus
store_yuv_surface_to_10bit_file(FILE * fp,VASurfaceID surface_id)826 store_yuv_surface_to_10bit_file(FILE *fp, VASurfaceID surface_id)
827 {
828     VAStatus va_status;
829     VAImage surface_image;
830     void *surface_p = NULL;
831     unsigned char *y_src = NULL;
832     unsigned char *u_src = NULL;
833     unsigned char *v_src = NULL;
834     unsigned char *y_dst = NULL;
835     unsigned char *u_dst = NULL;
836     unsigned char *v_dst = NULL;
837     uint32_t row;
838     int32_t n_items;
839     unsigned char * newImageBuffer = NULL;
840     va_status = vaSyncSurface(va_dpy, surface_id);
841     CHECK_VASTATUS(va_status, "vaSyncSurface");
842 
843     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
844     CHECK_VASTATUS(va_status, "vaDeriveImage");
845 
846     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
847     CHECK_VASTATUS(va_status, "vaMapBuffer");
848 
849     /* store the surface to one 10bit file */
850     uint32_t y_size = surface_image.width * surface_image.height * 2;
851     uint32_t u_size = y_size / 4;
852 
853     newImageBuffer = (unsigned char*)malloc(y_size * 3);
854     assert(newImageBuffer);
855     y_dst = newImageBuffer;
856 
857     y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
858 
859     /* Y plane copy */
860     for (row = 0; row < surface_image.height; row++) {
861         memcpy(y_dst, y_src, surface_image.width * 2);
862         y_src += surface_image.pitches[0];
863         y_dst += surface_image.width * 2;
864     }
865 
866     if (surface_image.format.fourcc == VA_FOURCC_I010) {
867         u_dst = newImageBuffer + y_size;
868         v_dst = newImageBuffer + y_size + u_size;
869 
870         u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
871         v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
872 
873         for (row = 0; row < surface_image.height / 2; row++) {
874             memcpy(u_dst, u_src, surface_image.width);
875             memcpy(v_dst, v_src, surface_image.width);
876 
877             u_dst += surface_image.width;
878             v_dst += surface_image.width;
879 
880             u_src += surface_image.pitches[1];
881             v_src += surface_image.pitches[2];
882         }
883     } else if (surface_image.format.fourcc == VA_FOURCC_P010) {
884         u_dst = newImageBuffer + y_size;
885         v_dst = u_dst;
886 
887         u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
888         v_src = u_src;
889 
890         for (row = 0; row < surface_image.height / 2; row++) {
891             memcpy(u_dst, u_src, surface_image.width * 2);
892             u_dst += surface_image.width * 2;
893             u_src += surface_image.pitches[1];
894         }
895     } else {
896         printf("Not supported YUV surface fourcc !!! \n");
897         free(newImageBuffer);
898         return VA_STATUS_ERROR_INVALID_SURFACE;
899     }
900 
901     /* write frame to file */
902     do {
903         n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
904     } while (n_items != 1);
905 
906     if (newImageBuffer) {
907         free(newImageBuffer);
908         newImageBuffer = NULL;
909     }
910 
911     vaUnmapBuffer(va_dpy, surface_image.buf);
912     vaDestroyImage(va_dpy, surface_image.image_id);
913 
914     return VA_STATUS_SUCCESS;
915 }
916 
917 static VAStatus
store_rgb_surface_to_rgb_file(FILE * fp,VASurfaceID surface_id)918 store_rgb_surface_to_rgb_file(FILE *fp, VASurfaceID surface_id)
919 {
920     VAStatus va_status;
921     VAImage surface_image;
922     void *surface_p = NULL;
923     unsigned char *y_src = NULL;
924     unsigned char *y_dst = NULL;
925     uint32_t frame_size, row;
926     int32_t n_items;
927     unsigned char * newImageBuffer = NULL;
928     va_status = vaSyncSurface(va_dpy, surface_id);
929     CHECK_VASTATUS(va_status, "vaSyncSurface");
930 
931     va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
932     CHECK_VASTATUS(va_status, "vaDeriveImage");
933 
934     va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
935     CHECK_VASTATUS(va_status, "vaMapBuffer");
936 
937     frame_size = surface_image.width * surface_image.height * 4;
938     newImageBuffer = (unsigned char*)malloc(frame_size);
939     assert(newImageBuffer);
940     y_dst = newImageBuffer;
941 
942     y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
943 
944     for (row = 0; row < surface_image.height; row++) {
945         memcpy(y_dst, y_src, surface_image.width * 4);
946         y_src += surface_image.pitches[0];
947         y_dst += surface_image.width * 4;
948     }
949 
950     /* write frame to file */
951     do {
952         n_items = fwrite(newImageBuffer, frame_size, 1, fp);
953     } while (n_items != 1);
954 
955     if (newImageBuffer) {
956         free(newImageBuffer);
957         newImageBuffer = NULL;
958     }
959 
960     vaUnmapBuffer(va_dpy, surface_image.buf);
961     vaDestroyImage(va_dpy, surface_image.image_id);
962 
963     return VA_STATUS_SUCCESS;
964 }
965 
966 static VAStatus
store_yuv_surface_to_file(FILE * fp,VASurfaceID surface_id)967 store_yuv_surface_to_file(FILE *fp,
968                           VASurfaceID surface_id)
969 {
970     if (g_out_fourcc == VA_FOURCC_YV12 ||
971         g_out_fourcc == VA_FOURCC_I420 ||
972         g_out_fourcc == VA_FOURCC_NV12) {
973         if (g_dst_file_fourcc == VA_FOURCC_YV12)
974             return store_yuv_surface_to_yv12_file(fp, surface_id);
975         else if (g_dst_file_fourcc == VA_FOURCC_I420)
976             return store_yuv_surface_to_i420_file(fp, surface_id);
977         else if (g_dst_file_fourcc == VA_FOURCC_NV12)
978             return store_yuv_surface_to_nv12_file(fp, surface_id);
979         else {
980             printf("Not supported YUV fourcc for output !!!\n");
981             return VA_STATUS_ERROR_INVALID_SURFACE;
982         }
983     } else if ((g_out_fourcc == VA_FOURCC_YUY2 &&
984                 g_dst_file_fourcc == VA_FOURCC_YUY2) ||
985                (g_out_fourcc == VA_FOURCC_UYVY &&
986                 g_dst_file_fourcc == VA_FOURCC_UYVY)) {
987         return store_packed_yuv_surface_to_packed_file(fp, surface_id);
988     } else if ((g_out_fourcc == VA_FOURCC_I010 &&
989                 g_dst_file_fourcc == VA_FOURCC_I010) ||
990                (g_out_fourcc == VA_FOURCC_P010 &&
991                 g_dst_file_fourcc == VA_FOURCC_P010)) {
992         return store_yuv_surface_to_10bit_file(fp, surface_id);
993     } else if ((g_out_fourcc == VA_FOURCC_RGBA &&
994                 g_dst_file_fourcc == VA_FOURCC_RGBA) ||
995                (g_out_fourcc == VA_FOURCC_RGBX &&
996                 g_dst_file_fourcc == VA_FOURCC_RGBX) ||
997                (g_out_fourcc == VA_FOURCC_RGBA &&
998                 g_dst_file_fourcc == VA_FOURCC_BGRA) ||
999                (g_out_fourcc == VA_FOURCC_BGRX &&
1000                 g_dst_file_fourcc == VA_FOURCC_BGRX)) {
1001         return store_rgb_surface_to_rgb_file(fp, surface_id);
1002     } else {
1003         printf("Not supported YUV fourcc for output !!!\n");
1004         return VA_STATUS_ERROR_INVALID_SURFACE;
1005     }
1006 }
1007 
1008 static VAStatus
sharpening_filter_init(VABufferID * filter_param_buf_id)1009 sharpening_filter_init(VABufferID *filter_param_buf_id)
1010 {
1011     VAStatus va_status;
1012     VAProcFilterParameterBuffer sharpening_param;
1013     VABufferID sharpening_param_buf_id;
1014     float intensity;
1015 
1016     VAProcFilterCap sharpening_caps;
1017     uint32_t num_sharpening_caps = 1;
1018     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
1019                                            VAProcFilterSharpening,
1020                                            &sharpening_caps, &num_sharpening_caps);
1021     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilterCaps");
1022 
1023     if (read_value_float(g_config_file_fd, "SHARPENING_INTENSITY", &intensity)) {
1024         printf("Read sharpening intensity failed, use default value.");
1025         intensity = sharpening_caps.range.default_value;
1026     }
1027 
1028     intensity = adjust_to_range(&sharpening_caps.range, intensity);
1029     printf("Sharpening intensity: %f\n", intensity);
1030     sharpening_param.value = intensity;
1031 
1032     sharpening_param.type  = VAProcFilterSharpening;
1033 
1034     /* create sharpening fitler buffer */
1035     va_status = vaCreateBuffer(va_dpy, context_id,
1036                                VAProcFilterParameterBufferType, sizeof(sharpening_param), 1,
1037                                &sharpening_param, &sharpening_param_buf_id);
1038 
1039     *filter_param_buf_id = sharpening_param_buf_id;
1040 
1041     return va_status;
1042 }
1043 
1044 static VAStatus
video_frame_process(VASurfaceID in_surface_id,VASurfaceID out_surface_id)1045 video_frame_process(VASurfaceID in_surface_id,
1046                     VASurfaceID out_surface_id)
1047 {
1048     VAStatus va_status;
1049     VAProcPipelineParameterBuffer pipeline_param;
1050     VARectangle surface_region, output_region;
1051     VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1052     VABufferID filter_param_buf_id = VA_INVALID_ID;
1053     sharpening_filter_init(&filter_param_buf_id);
1054     /* Fill pipeline buffer */
1055     surface_region.x = 0;
1056     surface_region.y = 0;
1057     surface_region.width = g_in_pic_width;
1058     surface_region.height = g_in_pic_height;
1059     output_region.x = 0;
1060     output_region.y = 0;
1061     output_region.width = g_out_pic_width;
1062     output_region.height = g_out_pic_height;
1063 
1064     memset(&pipeline_param, 0, sizeof(pipeline_param));
1065     pipeline_param.surface = in_surface_id;
1066     pipeline_param.surface_region = &surface_region;
1067     pipeline_param.output_region = &output_region;
1068     pipeline_param.filter_flags = 0;
1069     pipeline_param.filters      = &filter_param_buf_id;
1070     pipeline_param.num_filters  = 1;
1071 
1072     va_status = vaCreateBuffer(va_dpy,
1073                                context_id,
1074                                VAProcPipelineParameterBufferType,
1075                                sizeof(pipeline_param),
1076                                1,
1077                                &pipeline_param,
1078                                &pipeline_param_buf_id);
1079     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1080 
1081     va_status = vaBeginPicture(va_dpy,
1082                                context_id,
1083                                out_surface_id);
1084     CHECK_VASTATUS(va_status, "vaBeginPicture");
1085 
1086     va_status = vaRenderPicture(va_dpy,
1087                                 context_id,
1088                                 &pipeline_param_buf_id,
1089                                 1);
1090     CHECK_VASTATUS(va_status, "vaRenderPicture");
1091 
1092     va_status = vaEndPicture(va_dpy, context_id);
1093     CHECK_VASTATUS(va_status, "vaEndPicture");
1094 
1095     if (filter_param_buf_id != VA_INVALID_ID)
1096         vaDestroyBuffer(va_dpy, filter_param_buf_id);
1097 
1098     if (pipeline_param_buf_id != VA_INVALID_ID)
1099         vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
1100 
1101     return va_status;
1102 }
1103 
1104 static VAStatus
vpp_context_create()1105 vpp_context_create()
1106 {
1107     VAStatus va_status = VA_STATUS_SUCCESS;
1108     uint32_t i;
1109     int32_t j;
1110 
1111     /* VA driver initialization */
1112     va_dpy = va_open_display();
1113     int32_t major_ver, minor_ver;
1114     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
1115     assert(va_status == VA_STATUS_SUCCESS);
1116 
1117     /* Check whether VPP is supported by driver */
1118     VAEntrypoint entrypoints[5];
1119     int32_t num_entrypoints;
1120     num_entrypoints = vaMaxNumEntrypoints(va_dpy);
1121     va_status = vaQueryConfigEntrypoints(va_dpy,
1122                                          VAProfileNone,
1123                                          entrypoints,
1124                                          &num_entrypoints);
1125     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
1126 
1127     for (j = 0; j < num_entrypoints; j++) {
1128         if (entrypoints[j] == VAEntrypointVideoProc)
1129             break;
1130     }
1131 
1132     if (j == num_entrypoints) {
1133         printf("VPP is not supported by driver\n");
1134         assert(0);
1135     }
1136 
1137     /* Render target surface format check */
1138     VAConfigAttrib attrib;
1139     attrib.type = VAConfigAttribRTFormat;
1140     va_status = vaGetConfigAttributes(va_dpy,
1141                                       VAProfileNone,
1142                                       VAEntrypointVideoProc,
1143                                       &attrib,
1144                                       1);
1145     CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
1146     if (!(attrib.value & g_out_format)) {
1147         printf("RT format %d is not supported by VPP !\n", g_out_format);
1148         assert(0);
1149     }
1150 
1151     /* Create surface/config/context for VPP pipeline */
1152     va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height,
1153                                g_in_fourcc, g_in_format);
1154     CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
1155 
1156     va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height,
1157                                g_out_fourcc, g_out_format);
1158     CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
1159 
1160     va_status = vaCreateConfig(va_dpy,
1161                                VAProfileNone,
1162                                VAEntrypointVideoProc,
1163                                &attrib,
1164                                1,
1165                                &config_id);
1166     CHECK_VASTATUS(va_status, "vaCreateConfig");
1167 
1168     va_status = vaCreateContext(va_dpy,
1169                                 config_id,
1170                                 g_out_pic_width,
1171                                 g_out_pic_height,
1172                                 VA_PROGRESSIVE,
1173                                 &g_out_surface_id,
1174                                 1,
1175                                 &context_id);
1176     CHECK_VASTATUS(va_status, "vaCreateContext");
1177 
1178     uint32_t supported_filter_num = VAProcFilterCount;
1179     VAProcFilterType supported_filter_types[VAProcFilterCount];
1180 
1181     va_status = vaQueryVideoProcFilters(va_dpy,
1182                                         context_id,
1183                                         supported_filter_types,
1184                                         &supported_filter_num);
1185 
1186     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilters");
1187 
1188     for (i = 0; i < supported_filter_num; i++) {
1189         if (supported_filter_types[i] == VAProcFilterSharpening)
1190             break;
1191     }
1192 
1193     if (i == supported_filter_num) {
1194         printf("VPP filter type VAProcFilterSharpening is not supported by driver !\n");
1195         assert(0);
1196     }
1197     return va_status;
1198 }
1199 
1200 static void
vpp_context_destroy()1201 vpp_context_destroy()
1202 {
1203     /* Release resource */
1204     vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
1205     vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
1206     vaDestroyContext(va_dpy, context_id);
1207     vaDestroyConfig(va_dpy, config_id);
1208 
1209     vaTerminate(va_dpy);
1210     va_close_display(va_dpy);
1211 }
1212 
1213 static int8_t
parse_fourcc_and_format(char * str,uint32_t * fourcc,uint32_t * format)1214 parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
1215 {
1216     uint32_t tfourcc = VA_FOURCC('N', 'V', '1', '2');
1217     uint32_t tformat = VA_RT_FORMAT_YUV420;
1218 
1219     if (!strcmp(str, "YV12")) {
1220         tfourcc = VA_FOURCC('Y', 'V', '1', '2');
1221     } else if (!strcmp(str, "I420")) {
1222         tfourcc = VA_FOURCC('I', '4', '2', '0');
1223     } else if (!strcmp(str, "NV12")) {
1224         tfourcc = VA_FOURCC('N', 'V', '1', '2');
1225     } else if (!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) {
1226         tfourcc = VA_FOURCC('Y', 'U', 'Y', '2');
1227     } else if (!strcmp(str, "UYVY")) {
1228         tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y');
1229     } else if (!strcmp(str, "P010")) {
1230         tfourcc = VA_FOURCC('P', '0', '1', '0');
1231     } else if (!strcmp(str, "I010")) {
1232         tfourcc = VA_FOURCC('I', '0', '1', '0');
1233     } else if (!strcmp(str, "RGBA")) {
1234         tfourcc = VA_FOURCC_RGBA;
1235     } else if (!strcmp(str, "RGBX")) {
1236         tfourcc = VA_FOURCC_RGBX;
1237     } else if (!strcmp(str, "BGRA")) {
1238         tfourcc = VA_FOURCC_BGRA;
1239     } else if (!strcmp(str, "BGRX")) {
1240         tfourcc = VA_FOURCC_BGRX;
1241     } else {
1242         printf("Not supported format: %s! Currently only support following format: %s\n",
1243                str, "YV12, I420, NV12, YUY2(YUYV), UYVY, P010, I010, RGBA, RGBX, BGRA or BGRX");
1244         assert(0);
1245     }
1246 
1247     if (fourcc)
1248         *fourcc = tfourcc;
1249 
1250     if (format)
1251         *format = tformat;
1252 
1253     return 0;
1254 }
1255 
1256 static int8_t
parse_basic_parameters()1257 parse_basic_parameters()
1258 {
1259     char str[MAX_LEN];
1260 
1261     /* Read src frame file information */
1262     read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name);
1263     read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width);
1264     read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height);
1265     read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
1266     parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format);
1267 
1268     /* Read dst frame file information */
1269     read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name);
1270     read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width);
1271     read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT", &g_out_pic_height);
1272     read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
1273     parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format);
1274 
1275     read_value_string(g_config_file_fd, "SRC_FILE_FORMAT", str);
1276     parse_fourcc_and_format(str, &g_src_file_fourcc, NULL);
1277 
1278     read_value_string(g_config_file_fd, "DST_FILE_FORMAT", str);
1279     parse_fourcc_and_format(str, &g_dst_file_fourcc, NULL);
1280 
1281     read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
1282 
1283     if (g_in_pic_width != g_out_pic_width ||
1284         g_in_pic_height != g_out_pic_height)
1285         printf("Scaling will be done : from %4d x %4d to %4d x %4d \n",
1286                g_in_pic_width, g_in_pic_height,
1287                g_out_pic_width, g_out_pic_height);
1288 
1289     if (g_in_fourcc != g_out_fourcc)
1290         printf("Format conversion will be done: from %d to %d \n",
1291                g_in_fourcc, g_out_fourcc);
1292 
1293     return 0;
1294 }
1295 
1296 static void
print_help()1297 print_help()
1298 {
1299     printf("The app is used to test the sharpness feature.\n");
1300     printf("Cmd Usage: ./vppsharpness process_sharpness.cfg\n");
1301     printf("The configure file process_sharpness is used to configure the para.\n");
1302     printf("You can refer process_sharpness.cfg.template for each para meaning and create the configure file.\n");
1303 }
main(int32_t argc,char * argv[])1304 int32_t main(int32_t argc, char *argv[])
1305 {
1306     VAStatus va_status;
1307     uint32_t i;
1308 
1309     if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1310         print_help();
1311         return -1;
1312     }
1313 
1314     /* Parse the configure file for video process*/
1315     strncpy(g_config_file_name, argv[1], MAX_LEN);
1316     g_config_file_name[MAX_LEN - 1] = '\0';
1317 
1318     if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))) {
1319         printf("Open configure file %s failed!\n", g_config_file_name);
1320         assert(0);
1321     }
1322 
1323     /* Parse basic parameters */
1324     if (parse_basic_parameters()) {
1325         printf("Parse parameters in configure file error\n");
1326         assert(0);
1327     }
1328 
1329     va_status = vpp_context_create();
1330     if (va_status != VA_STATUS_SUCCESS) {
1331         printf("vpp context create failed \n");
1332         assert(0);
1333     }
1334 
1335     /* Video frame fetch, process and store */
1336     if (NULL == (g_src_file_fd = fopen(g_src_file_name, "r"))) {
1337         printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1338                g_src_file_name, g_config_file_name);
1339         assert(0);
1340     }
1341 
1342     if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))) {
1343         printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1344                g_dst_file_name, g_config_file_name);
1345         assert(0);
1346     }
1347 
1348     printf("\nStart to process, ...\n");
1349     struct timespec Pre_time;
1350     struct timespec Cur_time;
1351     unsigned int duration = 0;
1352     clock_gettime(CLOCK_MONOTONIC, &Pre_time);
1353 
1354     for (i = 0; i < g_frame_count; i ++) {
1355         upload_yuv_frame_to_yuv_surface(g_src_file_fd, g_in_surface_id);
1356         video_frame_process(g_in_surface_id, g_out_surface_id);
1357         store_yuv_surface_to_file(g_dst_file_fd, g_out_surface_id);
1358     }
1359 
1360     clock_gettime(CLOCK_MONOTONIC, &Cur_time);
1361     duration = (Cur_time.tv_sec - Pre_time.tv_sec) * 1000;
1362     if (Cur_time.tv_nsec > Pre_time.tv_nsec) {
1363         duration += (Cur_time.tv_nsec - Pre_time.tv_nsec) / 1000000;
1364     } else {
1365         duration += (Cur_time.tv_nsec + 1000000000 - Pre_time.tv_nsec) / 1000000 - 1000;
1366     }
1367 
1368     printf("Finish processing, performance: \n");
1369     printf("%d frames processed in: %d ms, ave time = %d ms\n", g_frame_count, duration, duration / g_frame_count);
1370 
1371     if (g_src_file_fd)
1372         fclose(g_src_file_fd);
1373 
1374     if (g_dst_file_fd)
1375         fclose(g_dst_file_fd);
1376 
1377     if (g_config_file_fd)
1378         fclose(g_config_file_fd);
1379 
1380     vpp_context_destroy();
1381 
1382     return 0;
1383 }
1384