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 denoise feature.
25  * Usage: ./vppdenoise process_denoise.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
denoise_filter_init(VABufferID * filter_param_buf_id)1009 denoise_filter_init(VABufferID *filter_param_buf_id)
1010 {
1011     VAStatus va_status = VA_STATUS_SUCCESS;
1012     VAProcFilterParameterBuffer denoise_param;
1013     VABufferID denoise_param_buf_id;
1014     float intensity;
1015 
1016     VAProcFilterCap denoise_caps;
1017     uint32_t num_denoise_caps = 1;
1018     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
1019                                            VAProcFilterNoiseReduction,
1020                                            &denoise_caps, &num_denoise_caps);
1021     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilterCaps");
1022 
1023     if (read_value_float(g_config_file_fd, "DENOISE_INTENSITY", &intensity)) {
1024         printf("Read denoise intensity failed, use default value");
1025         intensity = denoise_caps.range.default_value;
1026     }
1027     intensity = adjust_to_range(&denoise_caps.range, intensity);
1028 
1029     denoise_param.type  = VAProcFilterNoiseReduction;
1030     denoise_param.value = intensity;
1031 
1032     printf("Denoise intensity: %f\n", intensity);
1033 
1034     va_status = vaCreateBuffer(va_dpy, context_id,
1035                                VAProcFilterParameterBufferType, sizeof(denoise_param), 1,
1036                                &denoise_param, &denoise_param_buf_id);
1037     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1038 
1039     *filter_param_buf_id = denoise_param_buf_id;
1040 
1041     return va_status;
1042 }
1043 static VAStatus
video_frame_process(VASurfaceID in_surface_id,VASurfaceID out_surface_id)1044 video_frame_process(VASurfaceID in_surface_id,
1045                     VASurfaceID out_surface_id)
1046 {
1047     VAStatus va_status;
1048     VAProcPipelineParameterBuffer pipeline_param;
1049     VARectangle surface_region, output_region;
1050     VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1051     VABufferID filter_param_buf_id = VA_INVALID_ID;
1052     denoise_filter_init(&filter_param_buf_id);
1053     /* Fill pipeline buffer */
1054     surface_region.x = 0;
1055     surface_region.y = 0;
1056     surface_region.width = g_in_pic_width;
1057     surface_region.height = g_in_pic_height;
1058     output_region.x = 0;
1059     output_region.y = 0;
1060     output_region.width = g_out_pic_width;
1061     output_region.height = g_out_pic_height;
1062 
1063     memset(&pipeline_param, 0, sizeof(pipeline_param));
1064     pipeline_param.surface = in_surface_id;
1065     pipeline_param.surface_region = &surface_region;
1066     pipeline_param.output_region = &output_region;
1067     pipeline_param.filter_flags = 0;
1068     pipeline_param.filters      = &filter_param_buf_id;
1069     pipeline_param.num_filters  = 1;
1070 
1071     va_status = vaCreateBuffer(va_dpy,
1072                                context_id,
1073                                VAProcPipelineParameterBufferType,
1074                                sizeof(pipeline_param),
1075                                1,
1076                                &pipeline_param,
1077                                &pipeline_param_buf_id);
1078     CHECK_VASTATUS(va_status, "vaCreateBuffer");
1079 
1080     va_status = vaBeginPicture(va_dpy,
1081                                context_id,
1082                                out_surface_id);
1083     CHECK_VASTATUS(va_status, "vaBeginPicture");
1084 
1085     va_status = vaRenderPicture(va_dpy,
1086                                 context_id,
1087                                 &pipeline_param_buf_id,
1088                                 1);
1089     CHECK_VASTATUS(va_status, "vaRenderPicture");
1090 
1091     va_status = vaEndPicture(va_dpy, context_id);
1092     CHECK_VASTATUS(va_status, "vaEndPicture");
1093 
1094     if (filter_param_buf_id != VA_INVALID_ID)
1095         vaDestroyBuffer(va_dpy, filter_param_buf_id);
1096 
1097     if (pipeline_param_buf_id != VA_INVALID_ID)
1098         vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
1099 
1100     return va_status;
1101 }
1102 
1103 static VAStatus
vpp_context_create()1104 vpp_context_create()
1105 {
1106     VAStatus va_status = VA_STATUS_SUCCESS;
1107     uint32_t i;
1108     int32_t j;
1109 
1110     /* VA driver initialization */
1111     va_dpy = va_open_display();
1112     int32_t major_ver, minor_ver;
1113     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
1114     assert(va_status == VA_STATUS_SUCCESS);
1115 
1116     /* Check whether VPP is supported by driver */
1117     VAEntrypoint entrypoints[5];
1118     int32_t num_entrypoints;
1119     num_entrypoints = vaMaxNumEntrypoints(va_dpy);
1120     va_status = vaQueryConfigEntrypoints(va_dpy,
1121                                          VAProfileNone,
1122                                          entrypoints,
1123                                          &num_entrypoints);
1124     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
1125 
1126     for (j = 0; j < num_entrypoints; j++) {
1127         if (entrypoints[j] == VAEntrypointVideoProc)
1128             break;
1129     }
1130 
1131     if (j == num_entrypoints) {
1132         printf("VPP is not supported by driver\n");
1133         assert(0);
1134     }
1135 
1136     /* Render target surface format check */
1137     VAConfigAttrib attrib;
1138     attrib.type = VAConfigAttribRTFormat;
1139     va_status = vaGetConfigAttributes(va_dpy,
1140                                       VAProfileNone,
1141                                       VAEntrypointVideoProc,
1142                                       &attrib,
1143                                       1);
1144     CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
1145     if (!(attrib.value & g_out_format)) {
1146         printf("RT format %d is not supported by VPP !\n", g_out_format);
1147         assert(0);
1148     }
1149 
1150     /* Create surface/config/context for VPP pipeline */
1151     va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height,
1152                                g_in_fourcc, g_in_format);
1153     CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
1154 
1155     va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height,
1156                                g_out_fourcc, g_out_format);
1157     CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
1158 
1159     va_status = vaCreateConfig(va_dpy,
1160                                VAProfileNone,
1161                                VAEntrypointVideoProc,
1162                                &attrib,
1163                                1,
1164                                &config_id);
1165     CHECK_VASTATUS(va_status, "vaCreateConfig");
1166 
1167     va_status = vaCreateContext(va_dpy,
1168                                 config_id,
1169                                 g_out_pic_width,
1170                                 g_out_pic_height,
1171                                 VA_PROGRESSIVE,
1172                                 &g_out_surface_id,
1173                                 1,
1174                                 &context_id);
1175     CHECK_VASTATUS(va_status, "vaCreateContext");
1176 
1177     uint32_t supported_filter_num = VAProcFilterCount;
1178     VAProcFilterType supported_filter_types[VAProcFilterCount];
1179 
1180     va_status = vaQueryVideoProcFilters(va_dpy,
1181                                         context_id,
1182                                         supported_filter_types,
1183                                         &supported_filter_num);
1184 
1185     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilters");
1186 
1187     for (i = 0; i < supported_filter_num; i++) {
1188         if (supported_filter_types[i] == VAProcFilterNoiseReduction)
1189             break;
1190     }
1191 
1192     if (i == supported_filter_num) {
1193         printf("VPP filter type VAProcFilterNoiseReduction is not supported by driver !\n");
1194         assert(0);
1195     }
1196     return va_status;
1197 }
1198 
1199 static void
vpp_context_destroy()1200 vpp_context_destroy()
1201 {
1202     /* Release resource */
1203     vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
1204     vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
1205     vaDestroyContext(va_dpy, context_id);
1206     vaDestroyConfig(va_dpy, config_id);
1207 
1208     vaTerminate(va_dpy);
1209     va_close_display(va_dpy);
1210 }
1211 
1212 static int8_t
parse_fourcc_and_format(char * str,uint32_t * fourcc,uint32_t * format)1213 parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
1214 {
1215     uint32_t tfourcc = VA_FOURCC('N', 'V', '1', '2');
1216     uint32_t tformat = VA_RT_FORMAT_YUV420;
1217 
1218     if (!strcmp(str, "YV12")) {
1219         tfourcc = VA_FOURCC('Y', 'V', '1', '2');
1220     } else if (!strcmp(str, "I420")) {
1221         tfourcc = VA_FOURCC('I', '4', '2', '0');
1222     } else if (!strcmp(str, "NV12")) {
1223         tfourcc = VA_FOURCC('N', 'V', '1', '2');
1224     } else if (!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) {
1225         tfourcc = VA_FOURCC('Y', 'U', 'Y', '2');
1226     } else if (!strcmp(str, "UYVY")) {
1227         tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y');
1228     } else if (!strcmp(str, "P010")) {
1229         tfourcc = VA_FOURCC('P', '0', '1', '0');
1230     } else if (!strcmp(str, "I010")) {
1231         tfourcc = VA_FOURCC('I', '0', '1', '0');
1232     } else if (!strcmp(str, "RGBA")) {
1233         tfourcc = VA_FOURCC_RGBA;
1234     } else if (!strcmp(str, "RGBX")) {
1235         tfourcc = VA_FOURCC_RGBX;
1236     } else if (!strcmp(str, "BGRA")) {
1237         tfourcc = VA_FOURCC_BGRA;
1238     } else if (!strcmp(str, "BGRX")) {
1239         tfourcc = VA_FOURCC_BGRX;
1240     } else {
1241         printf("Not supported format: %s! Currently only support following format: %s\n",
1242                str, "YV12, I420, NV12, YUY2(YUYV), UYVY, P010, I010, RGBA, RGBX, BGRA or BGRX");
1243         assert(0);
1244     }
1245 
1246     if (fourcc)
1247         *fourcc = tfourcc;
1248 
1249     if (format)
1250         *format = tformat;
1251 
1252     return 0;
1253 }
1254 
1255 static int8_t
parse_basic_parameters()1256 parse_basic_parameters()
1257 {
1258     char str[MAX_LEN];
1259 
1260     /* Read src frame file information */
1261     read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name);
1262     read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width);
1263     read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height);
1264     read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
1265     parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format);
1266 
1267     /* Read dst frame file information */
1268     read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name);
1269     read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width);
1270     read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT", &g_out_pic_height);
1271     read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
1272     parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format);
1273 
1274     read_value_string(g_config_file_fd, "SRC_FILE_FORMAT", str);
1275     parse_fourcc_and_format(str, &g_src_file_fourcc, NULL);
1276 
1277     read_value_string(g_config_file_fd, "DST_FILE_FORMAT", str);
1278     parse_fourcc_and_format(str, &g_dst_file_fourcc, NULL);
1279 
1280     read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
1281 
1282     if (g_in_pic_width != g_out_pic_width ||
1283         g_in_pic_height != g_out_pic_height)
1284         printf("Scaling will be done : from %4d x %4d to %4d x %4d \n",
1285                g_in_pic_width, g_in_pic_height,
1286                g_out_pic_width, g_out_pic_height);
1287 
1288     if (g_in_fourcc != g_out_fourcc)
1289         printf("Format conversion will be done: from %d to %d \n",
1290                g_in_fourcc, g_out_fourcc);
1291 
1292     return 0;
1293 }
1294 
1295 static void
print_help()1296 print_help()
1297 {
1298     printf("The app is used to test the denoise feature.\n");
1299     printf("Cmd Usage: ./vppdenoise process_denoise.cfg\n");
1300     printf("The configure file process_denoise.cfg is used to configure the para.\n");
1301     printf("You can refer process_denoise.cfg.template for each para meaning and create the configure file.\n");
1302 }
main(int32_t argc,char * argv[])1303 int32_t main(int32_t argc, char *argv[])
1304 {
1305     VAStatus va_status;
1306     uint32_t i;
1307 
1308     if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1309         print_help();
1310         return -1;
1311     }
1312 
1313     /* Parse the configure file for video process*/
1314     strncpy(g_config_file_name, argv[1], MAX_LEN);
1315     g_config_file_name[MAX_LEN - 1] = '\0';
1316 
1317     if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))) {
1318         printf("Open configure file %s failed!\n", g_config_file_name);
1319         assert(0);
1320     }
1321 
1322     /* Parse basic parameters */
1323     if (parse_basic_parameters()) {
1324         printf("Parse parameters in configure file error\n");
1325         assert(0);
1326     }
1327 
1328     va_status = vpp_context_create();
1329     if (va_status != VA_STATUS_SUCCESS) {
1330         printf("vpp context create failed \n");
1331         assert(0);
1332     }
1333 
1334     /* Video frame fetch, process and store */
1335     if (NULL == (g_src_file_fd = fopen(g_src_file_name, "r"))) {
1336         printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1337                g_src_file_name, g_config_file_name);
1338         assert(0);
1339     }
1340 
1341     if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))) {
1342         printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1343                g_dst_file_name, g_config_file_name);
1344         assert(0);
1345     }
1346 
1347     printf("\nStart to process, ...\n");
1348     struct timespec Pre_time;
1349     struct timespec Cur_time;
1350     unsigned int duration = 0;
1351     clock_gettime(CLOCK_MONOTONIC, &Pre_time);
1352 
1353     for (i = 0; i < g_frame_count; i ++) {
1354         upload_yuv_frame_to_yuv_surface(g_src_file_fd, g_in_surface_id);
1355         video_frame_process(g_in_surface_id, g_out_surface_id);
1356         store_yuv_surface_to_file(g_dst_file_fd, g_out_surface_id);
1357     }
1358 
1359     clock_gettime(CLOCK_MONOTONIC, &Cur_time);
1360     duration = (Cur_time.tv_sec - Pre_time.tv_sec) * 1000;
1361     if (Cur_time.tv_nsec > Pre_time.tv_nsec) {
1362         duration += (Cur_time.tv_nsec - Pre_time.tv_nsec) / 1000000;
1363     } else {
1364         duration += (Cur_time.tv_nsec + 1000000000 - Pre_time.tv_nsec) / 1000000 - 1000;
1365     }
1366     printf("Finish processing, performance: \n");
1367     printf("%d frames processed in: %d ms, ave time = %d ms\n", g_frame_count, duration, duration / g_frame_count);
1368 
1369     if (g_src_file_fd)
1370         fclose(g_src_file_fd);
1371 
1372     if (g_dst_file_fd)
1373         fclose(g_dst_file_fd);
1374 
1375     if (g_config_file_fd)
1376         fclose(g_config_file_fd);
1377 
1378     vpp_context_destroy();
1379 
1380     return 0;
1381 }
1382 
1383