• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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