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