1 /*
2 * Copyright (c) 2009-2021, 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 scaling and several surface format conversion.
25 * Usage: ./vppscaling_csc process_scaling_csc.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 /* indicate the pipleine is scaling -> 3dlut, two seperate calls */
51 #define VA_SCALING_3DLUT 0
52 /* indicate the pipleine is 3dlut -> scaling, by default in one call */
53 #define VA_3DLUT_SCALING 1
54 #define VA_SCALING_ONLY 2
55
56 static VADisplay va_dpy = NULL;
57 static VAContextID context_id = 0;
58 static VAConfigID config_id = 0;
59 static VASurfaceID g_in_surface_id = VA_INVALID_ID;
60 static VASurfaceID g_out_surface_id = VA_INVALID_ID;
61 /* only for VA_SCALING_3DLUT scaled surface */
62 static VASurfaceID g_inter_surface_id = VA_INVALID_ID;
63 static VASurfaceID g_3dlut_surface_id = VA_INVALID_ID;
64
65 static FILE* g_config_file_fd = NULL;
66 static FILE* g_src_file_fd = NULL;
67 static FILE* g_dst_file_fd = NULL;
68
69 static char g_config_file_name[MAX_LEN];
70 static char g_src_file_name[MAX_LEN];
71 static char g_dst_file_name[MAX_LEN];
72
73 static uint32_t g_in_pic_width = 352;
74 static uint32_t g_in_pic_height = 288;
75 static uint32_t g_out_pic_width = 352;
76 static uint32_t g_out_pic_height = 288;
77
78 static uint32_t g_in_fourcc = VA_FOURCC('N', 'V', '1', '2');
79 static uint32_t g_in_format = VA_RT_FORMAT_YUV420;
80 static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2');
81 static uint32_t g_out_format = VA_RT_FORMAT_YUV420;
82 static uint32_t g_src_file_fourcc = VA_FOURCC('I', '4', '2', '0');
83 static uint32_t g_dst_file_fourcc = VA_FOURCC('N', 'V', '1', '2');
84
85 static uint32_t g_frame_count = 1;
86 static uint32_t g_pipeline_sequence = VA_3DLUT_SCALING;
87
88 static char g_3dlut_file_name[MAX_LEN];
89 static uint16_t g_3dlut_seg_size = 65;
90 static uint16_t g_3dlut_mul_size = 128;
91 static uint32_t g_3dlut_channel_mapping = 1;
92
93 #if VA_CHECK_VERSION(1, 12, 0)
94
95 static int8_t
read_value_string(FILE * fp,const char * field_name,char * value)96 read_value_string(FILE *fp, const char* field_name, char* value)
97 {
98 char strLine[MAX_LEN];
99 char* field = NULL;
100 char* str = NULL;
101 uint16_t i;
102
103 if (!fp || !field_name || !value) {
104 printf("Invalid fuction parameters\n");
105 return -1;
106 }
107
108 rewind(fp);
109
110 while (!feof(fp)) {
111 if (!fgets(strLine, MAX_LEN, fp))
112 continue;
113
114 for (i = 0; i < MAX_LEN && strLine[i]; i++)
115 if (strLine[i] != ' ') break;
116
117 if (i == MAX_LEN || strLine[i] == '#' || strLine[i] == '\n')
118 continue;
119
120 field = strtok(&strLine[i], ":");
121 if (strncmp(field, field_name, strlen(field_name)))
122 continue;
123
124 if (!(str = strtok(NULL, ":")))
125 continue;
126
127 /* skip blank space in string */
128 while (*str == ' ')
129 str++;
130
131 *(str + strlen(str) - 1) = '\0';
132 strcpy(value, str);
133
134 return 0;
135 }
136
137 return -1;
138 }
139
140 static int8_t
read_value_uint32(FILE * fp,const char * field_name,uint32_t * value)141 read_value_uint32(FILE* fp, const char* field_name, uint32_t* value)
142 {
143 char str[MAX_LEN];
144
145 if (read_value_string(fp, field_name, str)) {
146 printf("Failed to find integer field: %s", field_name);
147 return -1;
148 }
149
150 *value = (uint32_t)atoi(str);
151 return 0;
152 }
153
154 static int8_t
read_value_uint16(FILE * fp,const char * field_name,uint16_t * value)155 read_value_uint16(FILE* fp, const char* field_name, uint16_t* value)
156 {
157 char str[MAX_LEN];
158
159 if (read_value_string(fp, field_name, str)) {
160 printf("Failed to find integer field: %s", field_name);
161 return -1;
162 }
163
164 *value = (uint16_t)atoi(str);
165 return 0;
166 }
167
168 /* Load yuv frame to NV12/YV12/I420 surface*/
169 static VAStatus
upload_yuv_frame_to_yuv_surface(FILE * fp,VASurfaceID surface_id)170 upload_yuv_frame_to_yuv_surface(FILE *fp,
171 VASurfaceID surface_id)
172 {
173 VAStatus va_status;
174 VAImage surface_image;
175 unsigned char *y_src = NULL;
176 unsigned char *u_src = NULL;
177 unsigned char *v_src = NULL;
178 unsigned char *y_dst = NULL;
179 unsigned char *u_dst = NULL;
180 unsigned char *v_dst = NULL;
181 void *surface_p = NULL;
182 uint32_t frame_size, row, col;
183 size_t n_items;
184 unsigned char * newImageBuffer = NULL;
185 va_status = vaSyncSurface(va_dpy, surface_id);
186 CHECK_VASTATUS(va_status, "vaSyncSurface");
187
188 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
189 CHECK_VASTATUS(va_status, "vaDeriveImage");
190
191 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
192 CHECK_VASTATUS(va_status, "vaMapBuffer");
193
194 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
195 surface_image.format.fourcc == VA_FOURCC_I420 ||
196 surface_image.format.fourcc == VA_FOURCC_NV12) {
197
198 frame_size = surface_image.width * surface_image.height * 3 / 2;
199 newImageBuffer = (unsigned char*)malloc(frame_size);
200 assert(newImageBuffer);
201
202 do {
203 n_items = fread(newImageBuffer, frame_size, 1, fp);
204 } while (n_items != 1);
205
206 y_src = newImageBuffer;
207 if (g_src_file_fourcc == VA_FOURCC_I420) {
208 u_src = newImageBuffer + surface_image.width * surface_image.height;
209 v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4;
210 } else if (g_src_file_fourcc == VA_FOURCC_YV12) {
211 v_src = newImageBuffer + surface_image.width * surface_image.height;
212 u_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 4;
213 } else if (g_src_file_fourcc == VA_FOURCC_NV12) {
214 u_src = newImageBuffer + surface_image.width * surface_image.height;
215 v_src = u_src;
216 } else {
217 printf("Not supported YUV fourcc for input file !!!\n");
218 free(newImageBuffer);
219 return VA_STATUS_ERROR_INVALID_SURFACE;
220 }
221
222 y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
223
224 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
225 v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
226 u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
227 } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
228 u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
229 v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
230 } else {
231 u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
232 v_dst = u_dst;
233 }
234
235 /* Y plane, directly copy */
236 for (row = 0; row < surface_image.height; row++) {
237 memcpy(y_dst, y_src, surface_image.width);
238 y_dst += surface_image.pitches[0];
239 y_src += surface_image.width;
240 }
241
242 /* UV plane */
243 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
244 surface_image.format.fourcc == VA_FOURCC_I420) {
245 for (row = 0; row < surface_image.height / 2; row ++) {
246 if (g_src_file_fourcc == VA_FOURCC_I420 ||
247 g_src_file_fourcc == VA_FOURCC_YV12) {
248 memcpy(v_dst, v_src, surface_image.width / 2);
249 memcpy(u_dst, u_src, surface_image.width / 2);
250
251 v_src += surface_image.width / 2;
252 u_src += surface_image.width / 2;
253 } else {
254 for (col = 0; col < surface_image.width / 2; col++) {
255 u_dst[col] = u_src[col * 2];
256 v_dst[col] = u_src[col * 2 + 1];
257 }
258
259 u_src += surface_image.width;
260 v_src = u_src;
261 }
262
263 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
264 v_dst += surface_image.pitches[1];
265 u_dst += surface_image.pitches[2];
266 } else {
267 v_dst += surface_image.pitches[2];
268 u_dst += surface_image.pitches[1];
269 }
270 }
271 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
272 for (row = 0; row < surface_image.height / 2; row++) {
273 if (g_src_file_fourcc == VA_FOURCC_I420 ||
274 g_src_file_fourcc == VA_FOURCC_YV12) {
275 for (col = 0; col < surface_image.width / 2; col++) {
276 u_dst[col * 2] = u_src[col];
277 u_dst[col * 2 + 1] = v_src[col];
278 }
279
280 u_src += (surface_image.width / 2);
281 v_src += (surface_image.width / 2);
282 } else {
283 memcpy(u_dst, u_src, surface_image.width);
284 u_src += surface_image.width;
285 v_src = u_src;
286 }
287
288 u_dst += surface_image.pitches[1];
289 }
290 }
291 } else if ((surface_image.format.fourcc == VA_FOURCC_YUY2 &&
292 g_src_file_fourcc == VA_FOURCC_YUY2) ||
293 (surface_image.format.fourcc == VA_FOURCC_UYVY &&
294 g_src_file_fourcc == VA_FOURCC_UYVY)) {
295 frame_size = surface_image.width * surface_image.height * 2;
296 newImageBuffer = (unsigned char*)malloc(frame_size);
297 assert(newImageBuffer);
298
299 do {
300 n_items = fread(newImageBuffer, frame_size, 1, fp);
301 } while (n_items != 1);
302
303 y_src = newImageBuffer;
304 y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
305
306 /* plane 0, directly copy */
307 for (row = 0; row < surface_image.height; row++) {
308 memcpy(y_dst, y_src, surface_image.width * 2);
309 y_src += surface_image.width * 2;
310 y_dst += surface_image.pitches[0];
311 }
312 } else if ((surface_image.format.fourcc == VA_FOURCC_P010 &&
313 g_src_file_fourcc == VA_FOURCC_P010) ||
314 (surface_image.format.fourcc == VA_FOURCC_I010 &&
315 g_src_file_fourcc == VA_FOURCC_I010)) {
316 frame_size = surface_image.width * surface_image.height * 3;
317 newImageBuffer = (unsigned char*)malloc(frame_size);
318 assert(newImageBuffer);
319
320 do {
321 n_items = fread(newImageBuffer, frame_size, 1, fp);
322 } while (n_items != 1);
323
324 y_src = newImageBuffer;
325 y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
326
327 /* plane 0, directly copy */
328 for (row = 0; row < surface_image.height; row++) {
329 memcpy(y_dst, y_src, surface_image.width * 2);
330 y_src += surface_image.width * 2;
331 y_dst += surface_image.pitches[0];
332 }
333
334 /* UV plane */
335 if (surface_image.format.fourcc == VA_FOURCC_I010) {
336 assert(g_src_file_fourcc == VA_FOURCC_I010);
337
338 u_src = newImageBuffer + surface_image.width * surface_image.height * 2;
339 v_src = newImageBuffer + surface_image.width * surface_image.height * 5 / 2;
340
341 u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
342 v_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
343
344 for (row = 0; row < surface_image.height / 2; row++) {
345 memcpy(u_dst, u_src, surface_image.width);
346 memcpy(v_dst, v_src, surface_image.width);
347
348 u_src += surface_image.width;
349 v_src += surface_image.width;
350
351 u_dst += surface_image.pitches[1];
352 v_dst += surface_image.pitches[2];
353 }
354 } else if (surface_image.format.fourcc == VA_FOURCC_P010) {
355 assert(g_src_file_fourcc == VA_FOURCC_P010);
356
357 u_src = newImageBuffer + surface_image.width * surface_image.height * 2;
358 v_src = u_src;
359
360 u_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
361 v_dst = u_dst;
362
363 for (row = 0; row < surface_image.height / 2; row++) {
364 memcpy(u_dst, u_src, surface_image.width * 2);
365
366 u_src += surface_image.width * 2;
367 v_src = u_src;
368
369 u_dst += surface_image.pitches[1];
370 v_dst = u_dst;
371 }
372 }
373 } else if ((surface_image.format.fourcc == VA_FOURCC_RGBA &&
374 g_src_file_fourcc == VA_FOURCC_RGBA) ||
375 (surface_image.format.fourcc == VA_FOURCC_RGBX &&
376 g_src_file_fourcc == VA_FOURCC_RGBX) ||
377 (surface_image.format.fourcc == VA_FOURCC_BGRA &&
378 g_src_file_fourcc == VA_FOURCC_BGRA) ||
379 (surface_image.format.fourcc == VA_FOURCC_BGRX &&
380 g_src_file_fourcc == VA_FOURCC_BGRX)) {
381 frame_size = surface_image.width * surface_image.height * 4;
382 newImageBuffer = (unsigned char*)malloc(frame_size);
383 assert(newImageBuffer);
384
385 do {
386 n_items = fread(newImageBuffer, frame_size, 1, fp);
387 } while (n_items != 1);
388
389 y_src = newImageBuffer;
390 y_dst = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
391
392 /* plane 0, directly copy */
393 for (row = 0; row < surface_image.height; row++) {
394 memcpy(y_dst, y_src, surface_image.width * 4);
395 y_src += surface_image.width * 4;
396 y_dst += surface_image.pitches[0];
397 }
398 } else {
399 printf("Not supported YUV surface fourcc !!! \n");
400 return VA_STATUS_ERROR_INVALID_SURFACE;
401 }
402
403 if (newImageBuffer) {
404 free(newImageBuffer);
405 newImageBuffer = NULL;
406 }
407
408 vaUnmapBuffer(va_dpy, surface_image.buf);
409 vaDestroyImage(va_dpy, surface_image.image_id);
410
411 return VA_STATUS_SUCCESS;
412 }
413
414 /* Store NV12/YV12/I420 surface to yv12 file */
415 static VAStatus
store_yuv_surface_to_yv12_file(FILE * fp,VASurfaceID surface_id)416 store_yuv_surface_to_yv12_file(FILE *fp,
417 VASurfaceID surface_id)
418 {
419 VAStatus va_status;
420 VAImage surface_image;
421 void *surface_p = NULL;
422 unsigned char *y_src = NULL;
423 unsigned char *u_src = NULL;
424 unsigned char *v_src = NULL;
425 unsigned char *y_dst = NULL;
426 unsigned char *u_dst = NULL;
427 unsigned char *v_dst = NULL;
428 uint32_t row, col;
429 int32_t n_items;
430 unsigned char * newImageBuffer = NULL;
431 va_status = vaSyncSurface(va_dpy, surface_id);
432 CHECK_VASTATUS(va_status, "vaSyncSurface");
433
434 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
435 CHECK_VASTATUS(va_status, "vaDeriveImage");
436
437 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
438 CHECK_VASTATUS(va_status, "vaMapBuffer");
439
440 /* store the surface to one YV12 file or one bmp file*/
441 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
442 surface_image.format.fourcc == VA_FOURCC_I420 ||
443 surface_image.format.fourcc == VA_FOURCC_NV12) {
444
445 uint32_t y_size = surface_image.width * surface_image.height;
446 uint32_t u_size = y_size / 4;
447
448 newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
449 assert(newImageBuffer);
450
451 /* stored as YV12 format */
452 y_dst = newImageBuffer;
453 v_dst = newImageBuffer + y_size;
454 u_dst = newImageBuffer + y_size + u_size;
455
456 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
457 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
458 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
459 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
460 } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
461 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
462 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
463 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
464 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
465 v_src = u_src;
466 }
467
468 /* Y plane copy */
469 for (row = 0; row < surface_image.height; row++) {
470 memcpy(y_dst, y_src, surface_image.width);
471 y_src += surface_image.pitches[0];
472 y_dst += surface_image.width;
473 }
474
475 /* UV plane copy */
476 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
477 surface_image.format.fourcc == VA_FOURCC_I420) {
478 for (row = 0; row < surface_image.height / 2; row ++) {
479 memcpy(v_dst, v_src, surface_image.width / 2);
480 memcpy(u_dst, u_src, surface_image.width / 2);
481
482 v_dst += surface_image.width / 2;
483 u_dst += surface_image.width / 2;
484
485 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
486 v_src += surface_image.pitches[1];
487 u_src += surface_image.pitches[2];
488 } else {
489 v_src += surface_image.pitches[2];
490 u_src += surface_image.pitches[1];
491 }
492 }
493 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
494 for (row = 0; row < surface_image.height / 2; row++) {
495 for (col = 0; col < surface_image.width / 2; col++) {
496 u_dst[col] = u_src[col * 2];
497 v_dst[col] = u_src[col * 2 + 1];
498 }
499
500 u_src += surface_image.pitches[1];
501 u_dst += (surface_image.width / 2);
502 v_dst += (surface_image.width / 2);
503 }
504 }
505
506 /* write frame to file */
507 do {
508 n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
509 } while (n_items != 1);
510
511 } else {
512 printf("Not supported YUV surface fourcc !!! \n");
513 return VA_STATUS_ERROR_INVALID_SURFACE;
514 }
515
516 if (newImageBuffer) {
517 free(newImageBuffer);
518 newImageBuffer = NULL;
519 }
520
521 vaUnmapBuffer(va_dpy, surface_image.buf);
522 vaDestroyImage(va_dpy, surface_image.image_id);
523
524 return VA_STATUS_SUCCESS;
525 }
526
527 static VAStatus
store_yuv_surface_to_i420_file(FILE * fp,VASurfaceID surface_id)528 store_yuv_surface_to_i420_file(FILE *fp,
529 VASurfaceID surface_id)
530 {
531 VAStatus va_status;
532 VAImage surface_image;
533 void *surface_p = NULL;
534 unsigned char *y_src = NULL;
535 unsigned char *u_src = NULL;
536 unsigned char *v_src = NULL;
537 unsigned char *y_dst = NULL;
538 unsigned char *u_dst = NULL;
539 unsigned char *v_dst = NULL;
540 uint32_t row, col;
541 int32_t n_items;
542 unsigned char * newImageBuffer = NULL;
543 va_status = vaSyncSurface(va_dpy, surface_id);
544 CHECK_VASTATUS(va_status, "vaSyncSurface");
545
546 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
547 CHECK_VASTATUS(va_status, "vaDeriveImage");
548
549 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
550 CHECK_VASTATUS(va_status, "vaMapBuffer");
551
552 /* store the surface to one i420 file */
553 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
554 surface_image.format.fourcc == VA_FOURCC_I420 ||
555 surface_image.format.fourcc == VA_FOURCC_NV12) {
556
557 uint32_t y_size = surface_image.width * surface_image.height;
558 uint32_t u_size = y_size / 4;
559
560 newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
561 assert(newImageBuffer);
562
563 /* stored as YV12 format */
564 y_dst = newImageBuffer;
565 u_dst = newImageBuffer + y_size;
566 v_dst = newImageBuffer + y_size + u_size;
567
568 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
569 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
570 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
571 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
572 } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
573 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
574 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
575 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
576 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
577 v_src = u_src;
578 }
579
580 /* Y plane copy */
581 for (row = 0; row < surface_image.height; row++) {
582 memcpy(y_dst, y_src, surface_image.width);
583 y_src += surface_image.pitches[0];
584 y_dst += surface_image.width;
585 }
586
587 /* UV plane copy */
588 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
589 surface_image.format.fourcc == VA_FOURCC_I420) {
590 for (row = 0; row < surface_image.height / 2; row ++) {
591 memcpy(v_dst, v_src, surface_image.width / 2);
592 memcpy(u_dst, u_src, surface_image.width / 2);
593
594 v_dst += surface_image.width / 2;
595 u_dst += surface_image.width / 2;
596
597 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
598 v_src += surface_image.pitches[1];
599 u_src += surface_image.pitches[2];
600 } else {
601 v_src += surface_image.pitches[2];
602 u_src += surface_image.pitches[1];
603 }
604 }
605 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
606 for (row = 0; row < surface_image.height / 2; row++) {
607 for (col = 0; col < surface_image.width / 2; col++) {
608 u_dst[col] = u_src[col * 2];
609 v_dst[col] = u_src[col * 2 + 1];
610 }
611
612 u_src += surface_image.pitches[1];
613 u_dst += (surface_image.width / 2);
614 v_dst += (surface_image.width / 2);
615 }
616 }
617
618 /* write frame to file */
619 do {
620 n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
621 } while (n_items != 1);
622
623 } else {
624 printf("Not supported YUV surface fourcc !!! \n");
625 return VA_STATUS_ERROR_INVALID_SURFACE;
626 }
627
628 if (newImageBuffer) {
629 free(newImageBuffer);
630 newImageBuffer = NULL;
631 }
632
633 vaUnmapBuffer(va_dpy, surface_image.buf);
634 vaDestroyImage(va_dpy, surface_image.image_id);
635
636 return VA_STATUS_SUCCESS;
637 }
638
639 static VAStatus
store_yuv_surface_to_nv12_file(FILE * fp,VASurfaceID surface_id)640 store_yuv_surface_to_nv12_file(FILE *fp,
641 VASurfaceID surface_id)
642 {
643 VAStatus va_status;
644 VAImage surface_image;
645 void *surface_p = NULL;
646 unsigned char *y_src = NULL;
647 unsigned char *u_src = NULL;
648 unsigned char *v_src = NULL;
649 unsigned char *y_dst = NULL;
650 unsigned char *u_dst = NULL;
651 unsigned char *v_dst = NULL;
652 uint32_t row, col;
653 int32_t n_items;
654 unsigned char * newImageBuffer = NULL;
655 va_status = vaSyncSurface(va_dpy, surface_id);
656 CHECK_VASTATUS(va_status, "vaSyncSurface");
657
658 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
659 CHECK_VASTATUS(va_status, "vaDeriveImage");
660
661 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
662 CHECK_VASTATUS(va_status, "vaMapBuffer");
663
664 /* store the surface to one nv12 file */
665 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
666 surface_image.format.fourcc == VA_FOURCC_I420 ||
667 surface_image.format.fourcc == VA_FOURCC_NV12) {
668
669 uint32_t y_size = surface_image.width * surface_image.height;
670
671 newImageBuffer = (unsigned char*)malloc(y_size * 3 / 2);
672 assert(newImageBuffer);
673
674 /* stored as YV12 format */
675 y_dst = newImageBuffer;
676 u_dst = v_dst = newImageBuffer + y_size;
677
678 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
679
680 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
681 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
682 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
683 } else if (surface_image.format.fourcc == VA_FOURCC_I420) {
684 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
685 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
686 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
687 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
688 v_src = u_src;
689 }
690
691 /* Y plane copy */
692 for (row = 0; row < surface_image.height; row++) {
693 memcpy(y_dst, y_src, surface_image.width);
694 y_src += surface_image.pitches[0];
695 y_dst += surface_image.width;
696 }
697
698 /* UV plane copy */
699 if (surface_image.format.fourcc == VA_FOURCC_YV12 ||
700 surface_image.format.fourcc == VA_FOURCC_I420) {
701 for (row = 0; row < surface_image.height / 2; row ++) {
702 for (col = 0; col < surface_image.width / 2; col++) {
703 u_dst[col * 2] = u_src[col];
704 u_dst[col * 2 + 1] = v_src[col];
705 }
706
707 u_dst += surface_image.width;
708
709 if (surface_image.format.fourcc == VA_FOURCC_YV12) {
710 v_src += surface_image.pitches[1];
711 u_src += surface_image.pitches[2];
712 } else {
713 v_src += surface_image.pitches[2];
714 u_src += surface_image.pitches[1];
715 }
716 }
717 } else if (surface_image.format.fourcc == VA_FOURCC_NV12) {
718 for (row = 0; row < surface_image.height / 2; row++) {
719 memcpy(u_dst, u_src, surface_image.width);
720 u_dst += surface_image.width;
721 u_src += surface_image.pitches[1];
722 }
723 }
724
725 /* write frame to file */
726 do {
727 n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
728 } while (n_items != 1);
729
730 } else {
731 printf("Not supported YUV surface fourcc !!! \n");
732 return VA_STATUS_ERROR_INVALID_SURFACE;
733 }
734
735 if (newImageBuffer) {
736 free(newImageBuffer);
737 newImageBuffer = NULL;
738 }
739
740 vaUnmapBuffer(va_dpy, surface_image.buf);
741 vaDestroyImage(va_dpy, surface_image.image_id);
742
743 return VA_STATUS_SUCCESS;
744 }
745
746 static VAStatus
store_packed_yuv_surface_to_packed_file(FILE * fp,VASurfaceID surface_id)747 store_packed_yuv_surface_to_packed_file(FILE *fp,
748 VASurfaceID surface_id)
749 {
750 VAStatus va_status;
751 VAImage surface_image;
752 void *surface_p = NULL;
753 unsigned char *y_src = NULL;
754 unsigned char *y_dst = NULL;
755 uint32_t row;
756 int32_t n_items;
757 unsigned char * newImageBuffer = NULL;
758 va_status = vaSyncSurface(va_dpy, surface_id);
759 CHECK_VASTATUS(va_status, "vaSyncSurface");
760
761 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
762 CHECK_VASTATUS(va_status, "vaDeriveImage");
763
764 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
765 CHECK_VASTATUS(va_status, "vaMapBuffer");
766
767 /* store the surface to one YUY2 or UYVY file */
768 if (surface_image.format.fourcc == VA_FOURCC_YUY2 ||
769 surface_image.format.fourcc == VA_FOURCC_UYVY) {
770 uint32_t frame_size = surface_image.width * surface_image.height * 2;
771
772 newImageBuffer = (unsigned char*)malloc(frame_size);
773 assert(newImageBuffer);
774 memset(newImageBuffer, 0, frame_size);
775
776 /* stored as YUY2 or UYVY format */
777 y_dst = newImageBuffer;
778
779 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
780
781 /* Plane 0 copy */
782 for (row = 0; row < surface_image.height; row++) {
783 memcpy(y_dst, y_src, surface_image.width * 2);
784 y_src += surface_image.pitches[0];
785 y_dst += surface_image.width * 2;
786 }
787
788 /* write frame to file */
789 do {
790 n_items = fwrite(newImageBuffer, frame_size, 1, fp);
791 } while (n_items != 1);
792
793 } else {
794 printf("Not supported YUV surface fourcc !!! \n");
795 return VA_STATUS_ERROR_INVALID_SURFACE;
796 }
797
798 if (newImageBuffer) {
799 free(newImageBuffer);
800 newImageBuffer = NULL;
801 }
802
803 vaUnmapBuffer(va_dpy, surface_image.buf);
804 vaDestroyImage(va_dpy, surface_image.image_id);
805
806 return VA_STATUS_SUCCESS;
807 }
808
809 static VAStatus
store_yuv_surface_to_10bit_file(FILE * fp,VASurfaceID surface_id)810 store_yuv_surface_to_10bit_file(FILE *fp, VASurfaceID surface_id)
811 {
812 VAStatus va_status;
813 VAImage surface_image;
814 void *surface_p = NULL;
815 unsigned char *y_src = NULL;
816 unsigned char *u_src = NULL;
817 unsigned char *v_src = NULL;
818 unsigned char *y_dst = NULL;
819 unsigned char *u_dst = NULL;
820 unsigned char *v_dst = NULL;
821 uint32_t row;
822 int32_t n_items;
823 unsigned char * newImageBuffer = NULL;
824 va_status = vaSyncSurface(va_dpy, surface_id);
825 CHECK_VASTATUS(va_status, "vaSyncSurface");
826
827 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
828 CHECK_VASTATUS(va_status, "vaDeriveImage");
829
830 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
831 CHECK_VASTATUS(va_status, "vaMapBuffer");
832
833 /* store the surface to one 10bit file */
834 uint32_t y_size = surface_image.width * surface_image.height * 2;
835 uint32_t u_size = y_size / 4;
836
837 newImageBuffer = (unsigned char*)malloc(y_size * 3);
838 assert(newImageBuffer);
839 y_dst = newImageBuffer;
840
841 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
842
843 /* Y plane copy */
844 for (row = 0; row < surface_image.height; row++) {
845 memcpy(y_dst, y_src, surface_image.width * 2);
846 y_src += surface_image.pitches[0];
847 y_dst += surface_image.width * 2;
848 }
849
850 if (surface_image.format.fourcc == VA_FOURCC_I010) {
851 u_dst = newImageBuffer + y_size;
852 v_dst = newImageBuffer + y_size + u_size;
853
854 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
855 v_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[2]);
856
857 for (row = 0; row < surface_image.height / 2; row++) {
858 memcpy(u_dst, u_src, surface_image.width);
859 memcpy(v_dst, v_src, surface_image.width);
860
861 u_dst += surface_image.width;
862 v_dst += surface_image.width;
863
864 u_src += surface_image.pitches[1];
865 v_src += surface_image.pitches[2];
866 }
867 } else if (surface_image.format.fourcc == VA_FOURCC_P010) {
868 u_dst = newImageBuffer + y_size;
869 v_dst = u_dst;
870
871 u_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[1]);
872 v_src = u_src;
873
874 for (row = 0; row < surface_image.height / 2; row++) {
875 memcpy(u_dst, u_src, surface_image.width * 2);
876 u_dst += surface_image.width * 2;
877 u_src += surface_image.pitches[1];
878 }
879 } else {
880 printf("Not supported YUV surface fourcc !!! \n");
881 free(newImageBuffer);
882 return VA_STATUS_ERROR_INVALID_SURFACE;
883 }
884
885 /* write frame to file */
886 do {
887 n_items = fwrite(newImageBuffer, y_size * 3 / 2, 1, fp);
888 } while (n_items != 1);
889
890 if (newImageBuffer) {
891 free(newImageBuffer);
892 newImageBuffer = NULL;
893 }
894
895 vaUnmapBuffer(va_dpy, surface_image.buf);
896 vaDestroyImage(va_dpy, surface_image.image_id);
897
898 return VA_STATUS_SUCCESS;
899 }
900
901 static VAStatus
store_rgb_surface_to_rgb_file(FILE * fp,VASurfaceID surface_id)902 store_rgb_surface_to_rgb_file(FILE *fp, VASurfaceID surface_id)
903 {
904 VAStatus va_status;
905 VAImage surface_image;
906 void *surface_p = NULL;
907 unsigned char *y_src = NULL;
908 unsigned char *y_dst = NULL;
909 uint32_t frame_size, row;
910 int32_t n_items;
911 unsigned char * newImageBuffer = NULL;
912 va_status = vaSyncSurface(va_dpy, surface_id);
913 CHECK_VASTATUS(va_status, "vaSyncSurface");
914
915 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
916 CHECK_VASTATUS(va_status, "vaDeriveImage");
917
918 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
919 CHECK_VASTATUS(va_status, "vaMapBuffer");
920
921 frame_size = surface_image.width * surface_image.height * 4;
922 newImageBuffer = (unsigned char*)malloc(frame_size);
923 assert(newImageBuffer);
924 y_dst = newImageBuffer;
925
926 y_src = (unsigned char *)((unsigned char*)surface_p + surface_image.offsets[0]);
927
928 for (row = 0; row < surface_image.height; row++) {
929 memcpy(y_dst, y_src, surface_image.width * 4);
930 y_src += surface_image.pitches[0];
931 y_dst += surface_image.width * 4;
932 }
933
934 /* write frame to file */
935 do {
936 n_items = fwrite(newImageBuffer, frame_size, 1, fp);
937 } while (n_items != 1);
938
939 if (newImageBuffer) {
940 free(newImageBuffer);
941 newImageBuffer = NULL;
942 }
943
944 vaUnmapBuffer(va_dpy, surface_image.buf);
945 vaDestroyImage(va_dpy, surface_image.image_id);
946
947 return VA_STATUS_SUCCESS;
948 }
949
950 static VAStatus
store_yuv_surface_to_file(FILE * fp,VASurfaceID surface_id)951 store_yuv_surface_to_file(FILE *fp,
952 VASurfaceID surface_id)
953 {
954 if (g_out_fourcc == VA_FOURCC_YV12 ||
955 g_out_fourcc == VA_FOURCC_I420 ||
956 g_out_fourcc == VA_FOURCC_NV12) {
957 if (g_dst_file_fourcc == VA_FOURCC_YV12)
958 return store_yuv_surface_to_yv12_file(fp, surface_id);
959 else if (g_dst_file_fourcc == VA_FOURCC_I420)
960 return store_yuv_surface_to_i420_file(fp, surface_id);
961 else if (g_dst_file_fourcc == VA_FOURCC_NV12)
962 return store_yuv_surface_to_nv12_file(fp, surface_id);
963 else {
964 printf("Not supported YUV fourcc for output !!!\n");
965 return VA_STATUS_ERROR_INVALID_SURFACE;
966 }
967 } else if ((g_out_fourcc == VA_FOURCC_YUY2 &&
968 g_dst_file_fourcc == VA_FOURCC_YUY2) ||
969 (g_out_fourcc == VA_FOURCC_UYVY &&
970 g_dst_file_fourcc == VA_FOURCC_UYVY)) {
971 return store_packed_yuv_surface_to_packed_file(fp, surface_id);
972 } else if ((g_out_fourcc == VA_FOURCC_I010 &&
973 g_dst_file_fourcc == VA_FOURCC_I010) ||
974 (g_out_fourcc == VA_FOURCC_P010 &&
975 g_dst_file_fourcc == VA_FOURCC_P010)) {
976 return store_yuv_surface_to_10bit_file(fp, surface_id);
977 } else if ((g_out_fourcc == VA_FOURCC_RGBA &&
978 g_dst_file_fourcc == VA_FOURCC_RGBA) ||
979 (g_out_fourcc == VA_FOURCC_RGBX &&
980 g_dst_file_fourcc == VA_FOURCC_RGBX) ||
981 (g_out_fourcc == VA_FOURCC_RGBA &&
982 g_dst_file_fourcc == VA_FOURCC_BGRA) ||
983 (g_out_fourcc == VA_FOURCC_BGRX &&
984 g_dst_file_fourcc == VA_FOURCC_BGRX)) {
985 return store_rgb_surface_to_rgb_file(fp, surface_id);
986 } else {
987 printf("Not supported YUV fourcc for output !!!\n");
988 return VA_STATUS_ERROR_INVALID_SURFACE;
989 }
990 }
991
992 static VAStatus
upload_data_to_3dlut(FILE * fp,VASurfaceID & surface_id)993 upload_data_to_3dlut(FILE *fp,
994 VASurfaceID &surface_id)
995 {
996 VAStatus va_status;
997 VAImage surface_image;
998 void *surface_p = NULL;
999 uint32_t frame_size, lut3d_size;
1000 unsigned char * newImageBuffer = NULL;
1001 va_status = vaSyncSurface(va_dpy, surface_id);
1002 CHECK_VASTATUS(va_status, "vaSyncSurface");
1003
1004 va_status = vaDeriveImage(va_dpy, surface_id, &surface_image);
1005 CHECK_VASTATUS(va_status, "vaDeriveImage");
1006
1007 va_status = vaMapBuffer(va_dpy, surface_image.buf, &surface_p);
1008 CHECK_VASTATUS(va_status, "vaMapBuffer");
1009
1010 if (surface_image.format.fourcc == VA_FOURCC_RGBA && fp) {
1011 /* 3DLUT surface is allocated to 32 bit RGB */
1012 frame_size = surface_image.width * surface_image.height * 4;
1013 newImageBuffer = (unsigned char*)malloc(frame_size);
1014 assert(newImageBuffer);
1015
1016 fseek(fp, 0L, SEEK_END);
1017 lut3d_size = ftell(fp);
1018 rewind(fp);
1019
1020 uint32_t real_size = (frame_size > lut3d_size) ? lut3d_size : frame_size;
1021
1022 if (fread(newImageBuffer, real_size, 1, fp) != 0) {
1023 memcpy(surface_p, newImageBuffer, real_size);
1024 printf("upload_data_to_3dlut: 3DLUT surface width %d, height %d, pitch %d, frame size %d, 3dlut file size: %d\n", surface_image.width, surface_image.height, surface_image.pitches[0], frame_size, lut3d_size);
1025 }
1026 }
1027
1028 if (newImageBuffer) {
1029 free(newImageBuffer);
1030 newImageBuffer = NULL;
1031 }
1032
1033 vaUnmapBuffer(va_dpy, surface_image.buf);
1034 vaDestroyImage(va_dpy, surface_image.image_id);
1035
1036 return VA_STATUS_SUCCESS;
1037 }
1038
1039 static VAStatus
create_surface(VASurfaceID * p_surface_id,uint32_t width,uint32_t height,uint32_t fourCC,uint32_t format)1040 create_surface(VASurfaceID * p_surface_id,
1041 uint32_t width, uint32_t height,
1042 uint32_t fourCC, uint32_t format)
1043 {
1044 VAStatus va_status;
1045 VASurfaceAttrib surface_attrib;
1046 surface_attrib.type = VASurfaceAttribPixelFormat;
1047 surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
1048 surface_attrib.value.type = VAGenericValueTypeInteger;
1049 surface_attrib.value.value.i = fourCC;
1050
1051 va_status = vaCreateSurfaces(va_dpy,
1052 format,
1053 width,
1054 height,
1055 p_surface_id,
1056 1,
1057 &surface_attrib,
1058 1);
1059 return va_status;
1060 }
1061
1062 static VAStatus
lut3D_filter_init(VABufferID & filter_param_buf_id)1063 lut3D_filter_init(VABufferID &filter_param_buf_id)
1064 {
1065 VAStatus va_status;
1066 VAProcFilterParameterBuffer3DLUT lut3d_param;
1067 VABufferID lut3d_param_buf_id;
1068 uint32_t num_caps = 10;
1069 bool bSupported = false;
1070
1071 VAProcFilterCap3DLUT caps[num_caps];
1072 memset(&caps, 0, sizeof(VAProcFilterCap3DLUT)*num_caps);
1073 va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
1074 VAProcFilter3DLUT,
1075 (void *)caps, &num_caps);
1076 CHECK_VASTATUS(va_status, "vaQueryVideoProcFilterCaps");
1077 printf("vaQueryVideoProcFilterCaps num_caps %d\n", num_caps);
1078
1079 /* check if the input parameters are supported */
1080 for (uint32_t index = 0; index < num_caps; index++) {
1081 // check lut_size and lut_stride
1082 if ((caps[index].lut_size = g_3dlut_seg_size) &&
1083 (caps[index].lut_stride[0] == g_3dlut_seg_size) &&
1084 (caps[index].lut_stride[1] == g_3dlut_seg_size) &&
1085 (caps[index].lut_stride[2] == g_3dlut_mul_size)) {
1086 bSupported = true;
1087 }
1088 }
1089
1090 if (bSupported) {
1091 lut3d_param.type = VAProcFilter3DLUT;
1092 lut3d_param.lut_surface = g_3dlut_surface_id;
1093 lut3d_param.lut_size = g_3dlut_seg_size;
1094 lut3d_param.lut_stride[0] = g_3dlut_seg_size;
1095 lut3d_param.lut_stride[1] = g_3dlut_seg_size;
1096 lut3d_param.lut_stride[2] = g_3dlut_mul_size;
1097 lut3d_param.bit_depth = 16;
1098 lut3d_param.num_channel = 4;
1099 lut3d_param.channel_mapping = g_3dlut_channel_mapping;
1100
1101 /* create 3dlut fitler buffer */
1102 va_status = vaCreateBuffer(va_dpy, context_id,
1103 VAProcFilterParameterBufferType, sizeof(lut3d_param), 1,
1104 &lut3d_param, &lut3d_param_buf_id);
1105
1106 filter_param_buf_id = lut3d_param_buf_id;
1107 }
1108
1109 return va_status;
1110 }
1111
1112 static VAStatus
video_frame_process_3dlut(VASurfaceID in_surface_id,VASurfaceID out_surface_id)1113 video_frame_process_3dlut(VASurfaceID in_surface_id,
1114 VASurfaceID out_surface_id)
1115 {
1116 VAStatus va_status;
1117 VAProcPipelineParameterBuffer pipeline_param;
1118 VARectangle surface_region, output_region;
1119 VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1120 VABufferID filter_param_buf_id = VA_INVALID_ID;
1121
1122 /*Create 3DLUT Filter*/
1123 lut3D_filter_init(filter_param_buf_id);
1124
1125 /* Fill pipeline buffer */
1126 surface_region.x = 0;
1127 surface_region.y = 0;
1128 surface_region.width = g_in_pic_width;
1129 surface_region.height = g_in_pic_height;
1130 output_region.x = 0;
1131 output_region.y = 0;
1132 output_region.width = g_out_pic_width;
1133 output_region.height = g_out_pic_height;
1134
1135 memset(&pipeline_param, 0, sizeof(pipeline_param));
1136 pipeline_param.surface = in_surface_id;
1137 pipeline_param.surface_region = &surface_region;
1138 pipeline_param.output_region = &output_region;
1139 pipeline_param.filter_flags = 0;
1140 pipeline_param.filters = &filter_param_buf_id;
1141 pipeline_param.num_filters = 1;
1142 /* input is bt2020 */
1143 pipeline_param.surface_color_standard = VAProcColorStandardBT2020;
1144 pipeline_param.output_color_standard = VAProcColorStandardBT709;
1145
1146 va_status = vaCreateBuffer(va_dpy,
1147 context_id,
1148 VAProcPipelineParameterBufferType,
1149 sizeof(pipeline_param),
1150 1,
1151 &pipeline_param,
1152 &pipeline_param_buf_id);
1153 CHECK_VASTATUS(va_status, "vaCreateBuffer");
1154
1155 va_status = vaBeginPicture(va_dpy,
1156 context_id,
1157 out_surface_id);
1158 CHECK_VASTATUS(va_status, "vaBeginPicture");
1159
1160 va_status = vaRenderPicture(va_dpy,
1161 context_id,
1162 &pipeline_param_buf_id,
1163 1);
1164 CHECK_VASTATUS(va_status, "vaRenderPicture");
1165
1166 va_status = vaEndPicture(va_dpy, context_id);
1167 CHECK_VASTATUS(va_status, "vaEndPicture");
1168
1169 if (pipeline_param_buf_id != VA_INVALID_ID) {
1170 vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
1171 }
1172
1173 if (filter_param_buf_id != VA_INVALID_ID) {
1174 vaDestroyBuffer(va_dpy, filter_param_buf_id);
1175 }
1176
1177 return va_status;
1178 }
1179
1180 static VAStatus
video_frame_process_scaling(VASurfaceID in_surface_id,VASurfaceID out_surface_id)1181 video_frame_process_scaling(VASurfaceID in_surface_id,
1182 VASurfaceID out_surface_id)
1183 {
1184 VAStatus va_status;
1185 VAProcPipelineParameterBuffer pipeline_param;
1186 VARectangle surface_region, output_region;
1187 VABufferID pipeline_param_buf_id = VA_INVALID_ID;
1188
1189 /* Fill pipeline buffer */
1190 surface_region.x = 0;
1191 surface_region.y = 0;
1192 surface_region.width = g_in_pic_width;
1193 surface_region.height = g_in_pic_height;
1194 output_region.x = 0;
1195 output_region.y = 0;
1196 output_region.width = g_out_pic_width;
1197 output_region.height = g_out_pic_height;
1198
1199 memset(&pipeline_param, 0, sizeof(pipeline_param));
1200 pipeline_param.surface = in_surface_id;
1201 pipeline_param.surface_region = &surface_region;
1202 pipeline_param.output_region = &output_region;
1203 /* Default is going to SFC */
1204 // pipeline_param.filter_flags = 0;
1205 // pipeline_param.filters = &filter_param_buf_id;
1206 pipeline_param.num_filters = 0;
1207 /* input is bt2020 */
1208 // pipeline_param.surface_color_standard = VAProcColorStandardBT2020;
1209 // pipeline_param.output_color_standard = VAProcColorStandardBT709;
1210
1211 va_status = vaCreateBuffer(va_dpy,
1212 context_id,
1213 VAProcPipelineParameterBufferType,
1214 sizeof(pipeline_param),
1215 1,
1216 &pipeline_param,
1217 &pipeline_param_buf_id);
1218 CHECK_VASTATUS(va_status, "vaCreateBuffer");
1219
1220 va_status = vaBeginPicture(va_dpy,
1221 context_id,
1222 out_surface_id);
1223 CHECK_VASTATUS(va_status, "vaBeginPicture");
1224
1225 va_status = vaRenderPicture(va_dpy,
1226 context_id,
1227 &pipeline_param_buf_id,
1228 1);
1229 CHECK_VASTATUS(va_status, "vaRenderPicture");
1230
1231 va_status = vaEndPicture(va_dpy, context_id);
1232 CHECK_VASTATUS(va_status, "vaEndPicture");
1233
1234 if (pipeline_param_buf_id != VA_INVALID_ID) {
1235 vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
1236 }
1237
1238 return va_status;
1239 }
1240
1241 static VAStatus
vpp_context_create()1242 vpp_context_create()
1243 {
1244 VAStatus va_status = VA_STATUS_SUCCESS;
1245 int32_t j;
1246
1247 /* VA driver initialization */
1248 va_dpy = va_open_display();
1249 int32_t major_ver, minor_ver;
1250 va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
1251 assert(va_status == VA_STATUS_SUCCESS);
1252
1253 /* Check whether VPP is supported by driver */
1254 VAEntrypoint entrypoints[5];
1255 int32_t num_entrypoints;
1256 num_entrypoints = vaMaxNumEntrypoints(va_dpy);
1257 va_status = vaQueryConfigEntrypoints(va_dpy,
1258 VAProfileNone,
1259 entrypoints,
1260 &num_entrypoints);
1261 CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
1262
1263 for (j = 0; j < num_entrypoints; j++) {
1264 if (entrypoints[j] == VAEntrypointVideoProc)
1265 break;
1266 }
1267
1268 if (j == num_entrypoints) {
1269 printf("VPP is not supported by driver\n");
1270 assert(0);
1271 }
1272
1273 /* Render target surface format check */
1274 VAConfigAttrib attrib;
1275 attrib.type = VAConfigAttribRTFormat;
1276 va_status = vaGetConfigAttributes(va_dpy,
1277 VAProfileNone,
1278 VAEntrypointVideoProc,
1279 &attrib,
1280 1);
1281 CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
1282 if (!(attrib.value & g_out_format)) {
1283 printf("RT format %d is not supported by VPP !\n", g_out_format);
1284 assert(0);
1285 }
1286
1287 /* Create surface/config/context for VPP pipeline */
1288 va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height,
1289 g_in_fourcc, g_in_format);
1290 CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
1291
1292 if (g_pipeline_sequence == VA_SCALING_3DLUT) {
1293 /* Create intermediate surface for scaling + 3DLUT */
1294 va_status = create_surface(&g_inter_surface_id, g_out_pic_width, g_out_pic_height,
1295 g_in_fourcc, g_in_format);
1296 CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
1297 }
1298
1299 va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height,
1300 g_out_fourcc, g_out_format);
1301 CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
1302
1303 if (g_pipeline_sequence != VA_SCALING_ONLY) {
1304 uint32_t lut3d_size = g_3dlut_seg_size * g_3dlut_seg_size * g_3dlut_mul_size * (16 / 8) * 4;
1305 printf("3dlut file name: %s, 3dlut size: %d\n", g_3dlut_file_name, lut3d_size);
1306 /* create 3dlut surface and fill it with the data in 3dlut file */
1307 va_status = create_surface(&g_3dlut_surface_id, g_3dlut_seg_size * g_3dlut_mul_size, g_3dlut_seg_size * 2,
1308 VA_FOURCC_RGBA, VA_RT_FORMAT_RGB32);
1309 CHECK_VASTATUS(va_status, "vaCreateSurfaces for 3dlut.");
1310 /* fill 3dlut with the 3dlut file data */
1311 FILE *lut3d_file = NULL;
1312 lut3d_file = fopen(g_3dlut_file_name, "rb");
1313 upload_data_to_3dlut(lut3d_file, g_3dlut_surface_id);
1314 if (lut3d_file) {
1315 fclose(lut3d_file);
1316 lut3d_file = NULL;
1317 }
1318 }
1319
1320 va_status = vaCreateConfig(va_dpy,
1321 VAProfileNone,
1322 VAEntrypointVideoProc,
1323 &attrib,
1324 1,
1325 &config_id);
1326 CHECK_VASTATUS(va_status, "vaCreateConfig");
1327
1328 va_status = vaCreateContext(va_dpy,
1329 config_id,
1330 g_out_pic_width,
1331 g_out_pic_height,
1332 VA_PROGRESSIVE,
1333 &g_out_surface_id,
1334 1,
1335 &context_id);
1336 CHECK_VASTATUS(va_status, "vaCreateContext");
1337 return va_status;
1338 }
1339
1340 static void
vpp_context_destroy()1341 vpp_context_destroy()
1342 {
1343 /* Release resource */
1344 printf("vaDestroySurfaces input and output surface!\n");
1345 vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
1346 vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
1347 if (g_pipeline_sequence == VA_SCALING_3DLUT) {
1348 printf("vaDestroySurfaces intermediate surface for Scaling->3DLUT!\n");
1349 vaDestroySurfaces(va_dpy, &g_inter_surface_id, 1);
1350 }
1351 if (g_pipeline_sequence != VA_SCALING_ONLY) {
1352 printf("vaDestroySurfaces 3dlut surface for Scaling!\n");
1353 vaDestroySurfaces(va_dpy, &g_3dlut_surface_id, 1);
1354 }
1355 printf("vaDestroyContext!\n");
1356 vaDestroyContext(va_dpy, context_id);
1357 printf("vaDestroyConfig!\n");
1358 vaDestroyConfig(va_dpy, config_id);
1359
1360 printf("vaTerminate!\n");
1361 vaTerminate(va_dpy);
1362 printf("va_close_display!\n");
1363 va_close_display(va_dpy);
1364 }
1365
1366 static int8_t
parse_fourcc_and_format(char * str,uint32_t * fourcc,uint32_t * format)1367 parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
1368 {
1369 uint32_t tfourcc = VA_FOURCC('N', 'V', '1', '2');
1370 uint32_t tformat = VA_RT_FORMAT_YUV420;
1371
1372 if (!strcmp(str, "YV12")) {
1373 tfourcc = VA_FOURCC('Y', 'V', '1', '2');
1374 } else if (!strcmp(str, "I420")) {
1375 tfourcc = VA_FOURCC('I', '4', '2', '0');
1376 } else if (!strcmp(str, "NV12")) {
1377 tfourcc = VA_FOURCC('N', 'V', '1', '2');
1378 } else if (!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) {
1379 tfourcc = VA_FOURCC('Y', 'U', 'Y', '2');
1380 } else if (!strcmp(str, "UYVY")) {
1381 tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y');
1382 } else if (!strcmp(str, "P010")) {
1383 tfourcc = VA_FOURCC('P', '0', '1', '0');
1384 } else if (!strcmp(str, "I010")) {
1385 tfourcc = VA_FOURCC('I', '0', '1', '0');
1386 } else if (!strcmp(str, "RGBA")) {
1387 tfourcc = VA_FOURCC_RGBA;
1388 } else if (!strcmp(str, "RGBX")) {
1389 tfourcc = VA_FOURCC_RGBX;
1390 } else if (!strcmp(str, "BGRA")) {
1391 tfourcc = VA_FOURCC_BGRA;
1392 } else if (!strcmp(str, "BGRX")) {
1393 tfourcc = VA_FOURCC_BGRX;
1394 } else {
1395 printf("Not supported format: %s! Currently only support following format: %s\n",
1396 str, "YV12, I420, NV12, YUY2(YUYV), UYVY, P010, I010, RGBA, RGBX, BGRA or BGRX");
1397 assert(0);
1398 }
1399
1400 if (fourcc)
1401 *fourcc = tfourcc;
1402
1403 if (format)
1404 *format = tformat;
1405
1406 return 0;
1407 }
1408
1409 static int8_t
parse_basic_parameters()1410 parse_basic_parameters()
1411 {
1412 char str[MAX_LEN];
1413
1414 /* Read src frame file information */
1415 read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name);
1416 read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width);
1417 read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height);
1418 read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
1419 parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format);
1420
1421 /* Read dst frame file information */
1422 read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name);
1423 read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width);
1424 read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT", &g_out_pic_height);
1425 read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
1426 parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format);
1427
1428 read_value_string(g_config_file_fd, "SRC_FILE_FORMAT", str);
1429 parse_fourcc_and_format(str, &g_src_file_fourcc, NULL);
1430
1431 read_value_string(g_config_file_fd, "DST_FILE_FORMAT", str);
1432 parse_fourcc_and_format(str, &g_dst_file_fourcc, NULL);
1433
1434 read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
1435
1436 read_value_uint32(g_config_file_fd, "3DLUT_SCALING", &g_pipeline_sequence);
1437
1438 if (read_value_string(g_config_file_fd, "3DLUT_FILE_NAME", g_3dlut_file_name)) {
1439 printf("Read 3DLUT file failed, exit.");
1440 }
1441
1442 if (read_value_uint16(g_config_file_fd, "3DLUT_SEG_SIZE", &g_3dlut_seg_size)) {
1443 printf("Read segment_size failed, exit.");
1444 }
1445
1446 if (read_value_uint16(g_config_file_fd, "3DLUT_MUL_SIZE", &g_3dlut_mul_size)) {
1447 printf("Read multiple_size failed, exit.");
1448 }
1449
1450 if (read_value_uint32(g_config_file_fd, "3DLUT_CHANNEL_MAPPING", &g_3dlut_channel_mapping)) {
1451 printf("Read channel_mapping failed, exit.");
1452 }
1453
1454 if (g_in_pic_width != g_out_pic_width ||
1455 g_in_pic_height != g_out_pic_height)
1456 printf("Scaling will be done : from %4d x %4d to %4d x %4d \n",
1457 g_in_pic_width, g_in_pic_height,
1458 g_out_pic_width, g_out_pic_height);
1459
1460 if (g_in_fourcc != g_out_fourcc)
1461 printf("Format conversion will be done: from %d to %d \n",
1462 g_in_fourcc, g_out_fourcc);
1463
1464 return 0;
1465 }
1466
1467 static void
print_help()1468 print_help()
1469 {
1470 printf("The app is used to test the scaling and csc feature.\n");
1471 printf("Cmd Usage: ./vpp3dlut process_3dlut.cfg\n");
1472 printf("The configure file process_scaling_csc.cfg is used to configure the para.\n");
1473 printf("You can refer process_scaling_csc.cfg.template for each para meaning and create the configure file.\n");
1474 }
1475
main(int32_t argc,char * argv[])1476 int32_t main(int32_t argc, char *argv[])
1477 {
1478 VAStatus va_status;
1479 uint32_t i;
1480
1481 if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
1482 print_help();
1483 return -1;
1484 }
1485
1486 /* Parse the configure file for video process*/
1487 strncpy(g_config_file_name, argv[1], MAX_LEN);
1488 g_config_file_name[MAX_LEN - 1] = '\0';
1489
1490 if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))) {
1491 printf("Open configure file %s failed!\n", g_config_file_name);
1492 assert(0);
1493 }
1494
1495 /* Parse basic parameters */
1496 if (parse_basic_parameters()) {
1497 printf("Parse parameters in configure file error\n");
1498 assert(0);
1499 }
1500
1501 va_status = vpp_context_create();
1502 if (va_status != VA_STATUS_SUCCESS) {
1503 printf("vpp context create failed \n");
1504 assert(0);
1505 }
1506
1507 /* Video frame fetch, process and store */
1508 if (NULL == (g_src_file_fd = fopen(g_src_file_name, "r"))) {
1509 printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1510 g_src_file_name, g_config_file_name);
1511 assert(0);
1512 }
1513
1514 if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))) {
1515 printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
1516 g_dst_file_name, g_config_file_name);
1517 assert(0);
1518 }
1519
1520 for (i = 0; i < g_frame_count; i ++) {
1521 upload_yuv_frame_to_yuv_surface(g_src_file_fd, g_in_surface_id);
1522 if (g_pipeline_sequence == VA_3DLUT_SCALING) {
1523 printf("process frame #%d in VA_3DLUT_SCALING\n", i);
1524 video_frame_process_3dlut(g_in_surface_id, g_out_surface_id);
1525 } else if (g_pipeline_sequence == VA_SCALING_3DLUT) {
1526 printf("process frame #%d in VA_SCALING_3DLUT\n", i);
1527 video_frame_process_scaling(g_in_surface_id, g_inter_surface_id);
1528 video_frame_process_3dlut(g_inter_surface_id, g_out_surface_id);
1529 } else if (g_pipeline_sequence == VA_SCALING_ONLY) {
1530 printf("process frame #%d in VA_SCALING_ONLY\n", i);
1531 video_frame_process_scaling(g_in_surface_id, g_out_surface_id);
1532 } else {
1533 printf("Unknown pipeline sequence, default is 3DLUT->scaling!\n");
1534 }
1535 store_yuv_surface_to_file(g_dst_file_fd, g_out_surface_id);
1536 }
1537
1538 if (g_src_file_fd)
1539 fclose(g_src_file_fd);
1540
1541 if (g_dst_file_fd)
1542 fclose(g_dst_file_fd);
1543
1544 if (g_config_file_fd)
1545 fclose(g_config_file_fd);
1546
1547 vpp_context_destroy();
1548
1549 return 0;
1550 }
1551
1552 #endif
1553