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