• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (c) 2009-2022, 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 high dynamic range tone mapping feature.
25  * Usage: ./vpphdr_tm process_hdr_tm.cfg
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <time.h>
33 #include <assert.h>
34 #include <va/va.h>
35 #include <va/va_vpp.h>
36 #include "va_display.h"
37 
38 #ifndef VA_FOURCC_I420
39 #define VA_FOURCC_I420 0x30323449
40 #endif
41 
42 #define MAX_LEN   1024
43 
44 #define CHECK_VASTATUS(va_status,func)                                      \
45   if (va_status != VA_STATUS_SUCCESS) {                                     \
46       printf("%s:%s (%d) failed,exit\n", __func__, func, __LINE__);         \
47       exit(1);                                                              \
48   }
49 
50 static VADisplay va_dpy = NULL;
51 static VAContextID context_id = 0;
52 static VAConfigID  config_id = 0;
53 static VASurfaceID g_in_surface_id = VA_INVALID_ID;
54 static VASurfaceID g_out_surface_id = VA_INVALID_ID;
55 
56 static FILE* g_config_file_fd = NULL;
57 static FILE* g_src_file_fd = NULL;
58 static FILE* g_dst_file_fd = NULL;
59 
60 static char g_config_file_name[MAX_LEN];
61 static char g_src_file_name[MAX_LEN];
62 static char g_dst_file_name[MAX_LEN];
63 
64 static uint32_t g_in_pic_width = 1920;
65 static uint32_t g_in_pic_height = 1080;
66 static uint32_t g_out_pic_width = 1920;
67 static uint32_t g_out_pic_height = 1080;
68 
69 static uint32_t g_in_fourcc  = VA_FOURCC('N', 'V', '1', '2');
70 static uint32_t g_in_format  = VA_FOURCC_P010;
71 static uint32_t g_out_fourcc = VA_FOURCC('N', 'V', '1', '2');
72 static uint32_t g_out_format = VA_RT_FORMAT_YUV420;
73 static uint32_t g_src_file_fourcc = VA_FOURCC('I', '4', '2', '0');
74 static uint32_t g_dst_file_fourcc = VA_FOURCC('Y', 'V', '1', '2');
75 
76 static uint32_t g_frame_count = 1;
77 // The maximum display luminace is 1000 nits by default.
78 static uint32_t g_in_max_display_luminance = 10000000;
79 static uint32_t g_in_min_display_luminance = 100;
80 static uint32_t g_in_max_content_luminance = 4000;
81 static uint32_t g_in_pic_average_luminance = 1000;
82 // The maximum display luminace is 1000 nits by default.
83 static uint32_t g_out_max_display_luminance = 10000000;
84 static uint32_t g_out_min_display_luminance = 100;
85 static uint32_t g_out_max_content_luminance = 4000;
86 static uint32_t g_out_pic_average_luminance = 1000;
87 
88 static uint32_t g_in_colour_primaries = 9;
89 static uint32_t g_in_transfer_characteristic = 16;
90 
91 static uint32_t g_out_colour_primaries = 9;
92 static uint32_t g_out_transfer_characteristic = 16;
93 
94 static uint32_t g_tm_type = 1;
95 
96 static int8_t
read_value_string(FILE * fp,const char * field_name,char * value)97 read_value_string(FILE *fp, const char* field_name, char* value)
98 {
99     char strLine[MAX_LEN];
100     char* field = NULL;
101     char* str = NULL;
102     uint16_t i;
103 
104     if (!fp || !field_name || !value)  {
105         printf("Invalid fuction parameters\n");
106         return -1;
107     }
108 
109     rewind(fp);
110 
111     while (!feof(fp)) {
112         if (!fgets(strLine, MAX_LEN, fp))
113             continue;
114 
115         for (i = 0; i < MAX_LEN && strLine[i]; i++)
116             if (strLine[i] != ' ') break;
117 
118         if (i == MAX_LEN || strLine[i] == '#' || strLine[i] == '\n')
119             continue;
120 
121         field = strtok(&strLine[i], ":");
122         if (strncmp(field, field_name, strlen(field_name)))
123             continue;
124 
125         if (!(str = strtok(NULL, ":")))
126             continue;
127 
128         /* skip blank space in string */
129         while (*str == ' ')
130             str++;
131 
132         *(str + strlen(str) - 1) = '\0';
133         strcpy(value, str);
134 
135         return 0;
136     }
137     return -1;
138 }
139 
140 static int8_t
read_value_uint32(FILE * fp,const char * field_name,uint32_t * value)141 read_value_uint32(FILE* fp, const char* field_name, uint32_t* value)
142 {
143     char str[MAX_LEN];
144 
145     if (read_value_string(fp, field_name, str)) {
146         printf("Failed to find integer field: %s", field_name);
147         return -1;
148     }
149 
150     *value = (uint32_t)atoi(str);
151 
152     return 0;
153 }
154 
155 static VAStatus
create_surface(VASurfaceID * p_surface_id,uint32_t width,uint32_t height,uint32_t fourCC,uint32_t format)156 create_surface(VASurfaceID * p_surface_id,
157                uint32_t width, uint32_t height,
158                uint32_t fourCC, uint32_t format)
159 {
160     VAStatus va_status;
161     VASurfaceAttrib    surface_attrib;
162     surface_attrib.type =  VASurfaceAttribPixelFormat;
163     surface_attrib.flags = VA_SURFACE_ATTRIB_SETTABLE;
164     surface_attrib.value.type = VAGenericValueTypeInteger;
165     surface_attrib.value.value.i = fourCC;
166 
167     va_status = vaCreateSurfaces(va_dpy,
168                                  format,
169                                  width,
170                                  height,
171                                  p_surface_id,
172                                  1,
173                                  &surface_attrib,
174                                  1);
175 
176     printf("create_surface: p_surface_id %d, width %d, height %d, fourCC 0x%x, format 0x%x\n",
177            *p_surface_id, width, height, fourCC, format);
178 
179     return va_status;
180 }
181 
182 static VAStatus
hdrtm_filter_init(VABufferID * filter_param_buf_id,uint32_t tm_type)183 hdrtm_filter_init(VABufferID *filter_param_buf_id, uint32_t tm_type)
184 {
185     VAStatus va_status = VA_STATUS_SUCCESS;
186     VAProcFilterParameterBufferHDRToneMapping hdrtm_param;
187 
188     VAHdrMetaDataHDR10 in_hdr10_metadata = {};
189 
190     // The input is HDR content
191     in_hdr10_metadata.max_display_mastering_luminance = g_in_max_display_luminance;
192     in_hdr10_metadata.min_display_mastering_luminance = g_in_min_display_luminance;
193     in_hdr10_metadata.max_content_light_level         = g_in_max_content_luminance;
194     in_hdr10_metadata.max_pic_average_light_level     = g_in_pic_average_luminance;
195     in_hdr10_metadata.display_primaries_x[0] = 8500;
196     in_hdr10_metadata.display_primaries_y[0] = 39850;
197     in_hdr10_metadata.display_primaries_x[1] = 35400;
198     in_hdr10_metadata.display_primaries_y[1] = 14600;
199     in_hdr10_metadata.display_primaries_x[2] = 6550;
200     in_hdr10_metadata.display_primaries_y[2] = 2300;
201     in_hdr10_metadata.white_point_x = 15635;
202     in_hdr10_metadata.white_point_y = 16450;
203 
204     hdrtm_param.type = VAProcFilterHighDynamicRangeToneMapping;
205     hdrtm_param.data.metadata_type = VAProcHighDynamicRangeMetadataHDR10;
206     hdrtm_param.data.metadata = &in_hdr10_metadata;
207     hdrtm_param.data.metadata_size = sizeof(VAHdrMetaDataHDR10);
208 
209     va_status = vaCreateBuffer(va_dpy, context_id, VAProcFilterParameterBufferType, sizeof(hdrtm_param), 1, (void *)&hdrtm_param, filter_param_buf_id);
210 
211     return va_status;
212 }
213 
214 static VAStatus
hdrtm_metadata_init(VAHdrMetaData & out_metadata,uint32_t tm_type,VAHdrMetaDataHDR10 & out_hdr10_metadata)215 hdrtm_metadata_init(VAHdrMetaData &out_metadata, uint32_t tm_type, VAHdrMetaDataHDR10 &out_hdr10_metadata)
216 {
217     VAStatus va_status = VA_STATUS_SUCCESS;
218 
219 
220     out_hdr10_metadata.max_display_mastering_luminance = g_out_max_display_luminance;
221     out_hdr10_metadata.min_display_mastering_luminance = g_out_min_display_luminance;
222     out_hdr10_metadata.max_content_light_level         = g_out_max_content_luminance;
223     out_hdr10_metadata.max_pic_average_light_level     = g_out_pic_average_luminance;
224     printf("hdrtm_metadata_init g_out_max_display_luminance %d, g_out_min_display_luminance %d\n", g_out_max_display_luminance, g_out_min_display_luminance);
225     printf("hdrtm_metadata_init g_out_max_content_luminance %d, g_out_pic_average_luminance %d\n", g_out_max_content_luminance, g_out_pic_average_luminance);
226 
227     // HDR display or SDR display
228     switch (tm_type) {
229     case VA_TONE_MAPPING_HDR_TO_HDR:
230         out_hdr10_metadata.display_primaries_x[0] = 8500;
231         out_hdr10_metadata.display_primaries_y[0] = 39850;
232         out_hdr10_metadata.display_primaries_x[1] = 35400;
233         out_hdr10_metadata.display_primaries_y[1] = 14600;
234         out_hdr10_metadata.display_primaries_x[2] = 6550;
235         out_hdr10_metadata.display_primaries_y[2] = 2300;
236         out_hdr10_metadata.white_point_x = 15635;
237         out_hdr10_metadata.white_point_y = 16450;
238         break;
239     case VA_TONE_MAPPING_HDR_TO_SDR:
240         out_hdr10_metadata.display_primaries_x[0] = 15000;
241         out_hdr10_metadata.display_primaries_y[0] = 30000;
242         out_hdr10_metadata.display_primaries_x[1] = 32000;
243         out_hdr10_metadata.display_primaries_y[1] = 16500;
244         out_hdr10_metadata.display_primaries_x[2] = 7500;
245         out_hdr10_metadata.display_primaries_y[2] = 3000;
246         out_hdr10_metadata.white_point_x = 15635;
247         out_hdr10_metadata.white_point_y = 16450;
248         break;
249     default:
250         break;
251     }
252 
253     out_metadata.metadata_type = VAProcHighDynamicRangeMetadataHDR10;
254     out_metadata.metadata = &out_hdr10_metadata;
255     out_metadata.metadata_size = sizeof(VAHdrMetaDataHDR10);
256 
257     return va_status;
258 }
259 
260 static VAStatus
video_frame_process(VASurfaceID in_surface_id,VASurfaceID out_surface_id)261 video_frame_process(VASurfaceID in_surface_id,
262                     VASurfaceID out_surface_id)
263 {
264     VAStatus va_status;
265     VAProcPipelineParameterBuffer pipeline_param = {};
266     VARectangle surface_region = {}, output_region = {};
267     VABufferID pipeline_param_buf_id = VA_INVALID_ID;
268     VABufferID filter_param_buf_id = VA_INVALID_ID;
269     VAHdrMetaData out_metadata = {};
270 
271     /*Query Filter's Caps: The return value will be HDR10 and H2S, H2H, H2E. */
272     VAProcFilterCapHighDynamicRange hdrtm_caps[VAProcHighDynamicRangeMetadataTypeCount];
273     uint32_t num_hdrtm_caps = VAProcHighDynamicRangeMetadataTypeCount;
274     memset(&hdrtm_caps, 0, sizeof(VAProcFilterCapHighDynamicRange)*num_hdrtm_caps);
275     va_status = vaQueryVideoProcFilterCaps(va_dpy, context_id,
276                                            VAProcFilterHighDynamicRangeToneMapping,
277                                            (void *)hdrtm_caps, &num_hdrtm_caps);
278     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilterCaps");
279     printf("vaQueryVideoProcFilterCaps num_hdrtm_caps %d\n", num_hdrtm_caps);
280     for (int i = 0; i < num_hdrtm_caps; ++i)    {
281         printf("vaQueryVideoProcFilterCaps hdrtm_caps[%d]: metadata type %d, flag %d\n", i, hdrtm_caps[i].metadata_type, hdrtm_caps[i].caps_flag);
282     }
283 
284     hdrtm_filter_init(&filter_param_buf_id, g_tm_type);
285     VAHdrMetaDataHDR10 out_hdr10_metadata = {};
286     hdrtm_metadata_init(out_metadata, g_tm_type, out_hdr10_metadata);
287 
288     /* Fill pipeline buffer */
289     surface_region.x = 0;
290     surface_region.y = 0;
291     surface_region.width = g_in_pic_width;
292     surface_region.height = g_in_pic_height;
293     output_region.x = 0;
294     output_region.y = 0;
295     output_region.width = g_out_pic_width;
296     output_region.height = g_out_pic_height;
297 
298     memset(&pipeline_param, 0, sizeof(pipeline_param));
299     pipeline_param.surface = in_surface_id;
300     pipeline_param.surface_region = &surface_region;
301     pipeline_param.output_region = &output_region;
302     pipeline_param.filter_flags = 0;
303     pipeline_param.filters      = &filter_param_buf_id;
304     pipeline_param.num_filters  = 1;
305     pipeline_param.surface_color_standard = VAProcColorStandardExplicit;
306     pipeline_param.input_color_properties.colour_primaries = g_in_colour_primaries;
307     pipeline_param.input_color_properties.transfer_characteristics = g_in_transfer_characteristic;
308     pipeline_param.output_color_standard = VAProcColorStandardExplicit;
309     pipeline_param.output_color_properties.colour_primaries = g_out_colour_primaries;
310     pipeline_param.output_color_properties.transfer_characteristics = g_out_transfer_characteristic;
311     pipeline_param.output_hdr_metadata = &out_metadata;
312 
313     va_status = vaCreateBuffer(va_dpy,
314                                context_id,
315                                VAProcPipelineParameterBufferType,
316                                sizeof(pipeline_param),
317                                1,
318                                &pipeline_param,
319                                &pipeline_param_buf_id);
320     CHECK_VASTATUS(va_status, "vaCreateBuffer");
321 
322     va_status = vaBeginPicture(va_dpy,
323                                context_id,
324                                out_surface_id);
325     CHECK_VASTATUS(va_status, "vaBeginPicture");
326 
327     va_status = vaRenderPicture(va_dpy,
328                                 context_id,
329                                 &pipeline_param_buf_id,
330                                 1);
331     CHECK_VASTATUS(va_status, "vaRenderPicture");
332 
333     va_status = vaEndPicture(va_dpy, context_id);
334     CHECK_VASTATUS(va_status, "vaEndPicture");
335 
336     if (filter_param_buf_id != VA_INVALID_ID)
337         vaDestroyBuffer(va_dpy, filter_param_buf_id);
338 
339     if (pipeline_param_buf_id != VA_INVALID_ID)
340         vaDestroyBuffer(va_dpy, pipeline_param_buf_id);
341 
342     return va_status;
343 }
344 
345 static VAStatus
vpp_context_create()346 vpp_context_create()
347 {
348     VAStatus va_status = VA_STATUS_SUCCESS;
349     uint32_t i;
350     int32_t j;
351 
352     /* VA driver initialization */
353     va_dpy = va_open_display();
354     int32_t major_ver, minor_ver;
355     va_status = vaInitialize(va_dpy, &major_ver, &minor_ver);
356     assert(va_status == VA_STATUS_SUCCESS);
357 
358     /* Check whether VPP is supported by driver */
359     VAEntrypoint entrypoints[5];
360     int32_t num_entrypoints;
361     num_entrypoints = vaMaxNumEntrypoints(va_dpy);
362     va_status = vaQueryConfigEntrypoints(va_dpy,
363                                          VAProfileNone,
364                                          entrypoints,
365                                          &num_entrypoints);
366     CHECK_VASTATUS(va_status, "vaQueryConfigEntrypoints");
367 
368     for (j = 0; j < num_entrypoints; j++) {
369         if (entrypoints[j] == VAEntrypointVideoProc)
370             break;
371     }
372 
373     if (j == num_entrypoints) {
374         printf("VPP is not supported by driver\n");
375         assert(0);
376     }
377 
378     /* Render target surface format check */
379     VAConfigAttrib attrib;
380     attrib.type = VAConfigAttribRTFormat;
381     va_status = vaGetConfigAttributes(va_dpy,
382                                       VAProfileNone,
383                                       VAEntrypointVideoProc,
384                                       &attrib,
385                                       1);
386     CHECK_VASTATUS(va_status, "vaGetConfigAttributes");
387     if (!(attrib.value & g_out_format)) {
388         printf("RT format %d is not supported by VPP !\n", g_out_format);
389         //assert(0);
390     }
391 
392     /* Create surface/config/context for VPP pipeline */
393     va_status = create_surface(&g_in_surface_id, g_in_pic_width, g_in_pic_height,
394                                g_in_fourcc, g_in_format);
395     CHECK_VASTATUS(va_status, "vaCreateSurfaces for input");
396 
397     va_status = create_surface(&g_out_surface_id, g_out_pic_width, g_out_pic_height,
398                                g_out_fourcc, g_out_format);
399     CHECK_VASTATUS(va_status, "vaCreateSurfaces for output");
400 
401     va_status = vaCreateConfig(va_dpy,
402                                VAProfileNone,
403                                VAEntrypointVideoProc,
404                                &attrib,
405                                1,
406                                &config_id);
407     CHECK_VASTATUS(va_status, "vaCreateConfig");
408 
409     va_status = vaCreateContext(va_dpy,
410                                 config_id,
411                                 g_out_pic_width,
412                                 g_out_pic_height,
413                                 VA_PROGRESSIVE,
414                                 &g_out_surface_id,
415                                 1,
416                                 &context_id);
417     CHECK_VASTATUS(va_status, "vaCreateContext");
418 
419     uint32_t supported_filter_num = VAProcFilterCount;
420     VAProcFilterType supported_filter_types[VAProcFilterCount];
421 
422     va_status = vaQueryVideoProcFilters(va_dpy,
423                                         context_id,
424                                         supported_filter_types,
425                                         &supported_filter_num);
426 
427     CHECK_VASTATUS(va_status, "vaQueryVideoProcFilters");
428 
429     for (i = 0; i < supported_filter_num; i++) {
430         if (supported_filter_types[i] == VAProcFilterHighDynamicRangeToneMapping)
431             break;
432     }
433 
434     if (i == supported_filter_num) {
435         printf("VPP filter type VAProcFilterHighDynamicRangeToneMapping is not supported by driver !\n");
436     }
437     return va_status;
438 }
439 
440 static void
vpp_context_destroy()441 vpp_context_destroy()
442 {
443     /* Release resource */
444     vaDestroySurfaces(va_dpy, &g_in_surface_id, 1);
445     vaDestroySurfaces(va_dpy, &g_out_surface_id, 1);
446     vaDestroyContext(va_dpy, context_id);
447     vaDestroyConfig(va_dpy, config_id);
448 
449     vaTerminate(va_dpy);
450     va_close_display(va_dpy);
451 }
452 
453 static int8_t
parse_fourcc_and_format(char * str,uint32_t * fourcc,uint32_t * format)454 parse_fourcc_and_format(char *str, uint32_t *fourcc, uint32_t *format)
455 {
456     uint32_t tfourcc = VA_FOURCC('N', 'V', '1', '2');
457     uint32_t tformat = VA_RT_FORMAT_YUV420;
458 
459     if (!strcmp(str, "YV12")) {
460         tfourcc = VA_FOURCC('Y', 'V', '1', '2');
461     } else if (!strcmp(str, "I420")) {
462         tfourcc = VA_FOURCC('I', '4', '2', '0');
463     } else if (!strcmp(str, "NV12")) {
464         tfourcc = VA_FOURCC('N', 'V', '1', '2');
465     } else if (!strcmp(str, "YUY2") || !strcmp(str, "YUYV")) {
466         tfourcc = VA_FOURCC('Y', 'U', 'Y', '2');
467     } else if (!strcmp(str, "UYVY")) {
468         tfourcc = VA_FOURCC('U', 'Y', 'V', 'Y');
469     } else if (!strcmp(str, "P010")) {
470         tfourcc = VA_FOURCC('P', '0', '1', '0');
471     } else if (!strcmp(str, "I010")) {
472         tfourcc = VA_FOURCC('I', '0', '1', '0');
473     } else if (!strcmp(str, "RGBA")) {
474         tformat = VA_RT_FORMAT_RGB32;
475         tfourcc = VA_FOURCC_RGBA;
476         printf("parse_fourcc_and_format: RGBA format 0x%8x, fourcc 0x%8x\n", tformat, tfourcc);
477     } else if (!strcmp(str, "RGBX")) {
478         tfourcc = VA_FOURCC_RGBX;
479     } else if (!strcmp(str, "BGRA")) {
480         tfourcc = VA_FOURCC_BGRA;
481     } else if (!strcmp(str, "BGRX")) {
482         tfourcc = VA_FOURCC_BGRX;
483     } else if (!strcmp(str, "P010")) {
484         tfourcc = VA_FOURCC_P010;
485         printf("parse_fourcc_and_format: P010\n");
486     } else if (!strcmp(str, "A2RGB10")) {  //A2R10G10B10
487         tfourcc = VA_FOURCC_A2R10G10B10;
488         printf("parse_fourcc_and_format: ARGB10 format 0x%8x, fourcc 0x%8x\n", tformat, tfourcc);
489     } else {
490         printf("Not supported format: %s! Currently only support following format: %s\n",
491                str, "YV12, I420, NV12, YUY2(YUYV), UYVY, I010, RGBA, RGBX, BGRA or BGRX");
492         assert(0);
493     }
494 
495     printf("parse_fourcc_and_format: format 0x%x, fourcc 0x%x\n", tformat, tfourcc);
496 
497     if (fourcc)
498         *fourcc = tfourcc;
499 
500     if (format)
501         *format = tformat;
502 
503     return 0;
504 }
505 
read_frame_to_surface(FILE * fp,VASurfaceID surface_id)506 bool read_frame_to_surface(FILE *fp, VASurfaceID surface_id)
507 {
508     VAStatus va_status;
509     VAImage  va_image;
510 
511     int i = 0;
512 
513     int frame_size = 0, y_size = 0;
514 
515     unsigned char *y_src = NULL, *u_src = NULL;
516     unsigned char *y_dst = NULL, *u_dst = NULL;
517 
518     int bytes_per_pixel = 2;
519     size_t n_items;
520     void *out_buf = NULL;
521     unsigned char *src_buffer = NULL;
522 
523     if (fp == NULL)
524         return false;
525 
526     // This function blocks until all pending operations on the surface have been completed.
527     va_status = vaSyncSurface(va_dpy, surface_id);
528     CHECK_VASTATUS(va_status, "vaSyncSurface");
529 
530     va_status = vaDeriveImage(va_dpy, surface_id, &va_image);
531     CHECK_VASTATUS(va_status, "vaDeriveImage");
532 
533     va_status = vaMapBuffer(va_dpy, va_image.buf, &out_buf);
534     CHECK_VASTATUS(va_status, "vaMapBuffer");
535 
536     printf("read_frame_to_surface: va_image.width %d, va_image.height %d, va_image.pitches[0]: %d, va_image.pitches[1] %d, va_image.pitches[2] %d\n",
537            va_image.width, va_image.height, va_image.pitches[0], va_image.pitches[1], va_image.pitches[1]);
538 
539     switch (va_image.format.fourcc) {
540     case VA_FOURCC_P010:
541         frame_size = va_image.width * va_image.height * bytes_per_pixel * 3 / 2;
542         y_size = va_image.width * va_image.height * bytes_per_pixel;
543 
544         src_buffer = (unsigned char*)malloc(frame_size);
545         assert(src_buffer);
546         n_items = fread(src_buffer, 1, frame_size, fp);
547         if (n_items != frame_size) {
548             printf("read file failed on VA_FOURCC_P010\n");
549         }
550         y_src = src_buffer;
551         u_src = src_buffer + y_size; // UV offset for P010
552 
553         y_dst = (unsigned char*)out_buf + va_image.offsets[0]; // Y plane
554         u_dst = (unsigned char*)out_buf + va_image.offsets[1]; // U offset for P010
555 
556         for (i = 0; i < va_image.height; i++) {
557             memcpy(y_dst, y_src, va_image.width * 2);
558             y_dst += va_image.pitches[0];
559             y_src += va_image.width * 2;
560         }
561         for (i = 0; i < va_image.height >> 1; i++)  {
562             memcpy(u_dst, u_src, va_image.width * 2);
563             u_dst += va_image.pitches[1];
564             u_src += va_image.width * 2;
565         }
566         printf("read_frame_to_surface: P010 \n");
567         break;
568 
569     case VA_RT_FORMAT_RGB32_10BPP:
570     case VA_FOURCC_RGBA:
571     case VA_FOURCC_A2R10G10B10:
572     case VA_FOURCC_A2B10G10R10:
573         frame_size = va_image.width * va_image.height * 4;
574         src_buffer = (unsigned char*)malloc(frame_size);
575         assert(src_buffer);
576         n_items = fread(src_buffer, 1, frame_size, fp);
577         if (n_items != frame_size) {
578             printf("read file failed on VA_RT_FORMAT_RGB32_10BPP or VA_FOURCC_RGBA \n");
579         }
580         y_src = src_buffer;
581         y_dst = (unsigned char*)out_buf + va_image.offsets[0];
582 
583         for (i = 0; i < va_image.height; i++)  {
584             memcpy(y_dst, y_src, va_image.width * 4);
585             y_dst += va_image.pitches[0];
586             y_src += va_image.width * 4;
587         }
588         printf("read_frame_to_surface: RGBA or A2RGB10 \n");
589         break;
590 
591     default: // should not come here
592         printf("VA_STATUS_ERROR_INVALID_IMAGE_FORMAT \n");
593         va_status = VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
594         break;
595     }
596 
597     vaUnmapBuffer(va_dpy, va_image.buf);
598     vaDestroyImage(va_dpy, va_image.image_id);
599     if (src_buffer) {
600         free(src_buffer);
601         src_buffer = NULL;
602     }
603 
604     if (va_status != VA_STATUS_SUCCESS)
605         return false;
606     else
607         return true;
608 }
609 
write_surface_to_frame(FILE * fp,VASurfaceID surface_id)610 bool write_surface_to_frame(FILE *fp, VASurfaceID surface_id)
611 {
612     VAStatus va_status;
613     VAImage  va_image;
614 
615     int i = 0;
616 
617     int frame_size = 0, y_size = 0;
618 
619     unsigned char *y_src = NULL, *u_src = NULL;
620     unsigned char *y_dst = NULL, *u_dst = NULL;
621 
622     int bytes_per_pixel = 2;
623 
624     void *in_buf = NULL;
625     unsigned char *dst_buffer = NULL;
626 
627     if (fp == NULL)
628         return false;
629 
630     // This function blocks until all pending operations on the surface have been completed.
631     va_status = vaSyncSurface(va_dpy, surface_id);
632     CHECK_VASTATUS(va_status, "vaSyncSurface");
633 
634     va_status = vaDeriveImage(va_dpy, surface_id, &va_image);
635     CHECK_VASTATUS(va_status, "vaDeriveImage");
636 
637     va_status = vaMapBuffer(va_dpy, va_image.buf, &in_buf);
638     CHECK_VASTATUS(va_status, "vaMapBuffer");
639 
640     printf("write_surface_to_frame: va_image.width %d, va_image.height %d, va_image.pitches[0]: %d, va_image.pitches[1] %d, va_image.pitches[2] %d\n",
641            va_image.width, va_image.height, va_image.pitches[0], va_image.pitches[1], va_image.pitches[1]);
642 
643 
644     switch (va_image.format.fourcc) {
645     case VA_FOURCC_P010:
646     case VA_FOURCC_NV12:
647         bytes_per_pixel = (va_image.format.fourcc == VA_FOURCC_P010) ? 2 : 1;
648         frame_size = va_image.width * va_image.height * bytes_per_pixel * 3 / 2;
649         dst_buffer = (unsigned char*)malloc(frame_size);
650         assert(dst_buffer);
651         y_size = va_image.width * va_image.height * bytes_per_pixel;
652         y_dst = dst_buffer;
653         u_dst = dst_buffer + y_size; // UV offset for P010
654         y_src = (unsigned char*)in_buf + va_image.offsets[0];
655         u_src = (unsigned char*)in_buf + va_image.offsets[1]; // U offset for P010
656         for (i = 0; i < va_image.height; i++)  {
657             memcpy(y_dst, y_src, static_cast<size_t>(va_image.width * bytes_per_pixel));
658             y_dst += va_image.width * bytes_per_pixel;
659             y_src += va_image.pitches[0];
660         }
661         for (i = 0; i < va_image.height >> 1; i++)  {
662             memcpy(u_dst, u_src, static_cast<size_t>(va_image.width * bytes_per_pixel));
663             u_dst += va_image.width * bytes_per_pixel;
664             u_src += va_image.pitches[1];
665         }
666         printf("read_frame_to_surface: P010 \n");
667         break;
668 
669     case VA_FOURCC_RGBA:
670     case VA_FOURCC_ABGR:
671     case VA_FOURCC_A2B10G10R10:
672     case VA_FOURCC_A2R10G10B10:
673         frame_size = va_image.width * va_image.height * 4;
674         dst_buffer = (unsigned char*)malloc(frame_size);
675         assert(dst_buffer);
676         y_dst = dst_buffer;
677         y_src = (unsigned char*)in_buf + va_image.offsets[0];
678 
679         for (i = 0; i < va_image.height; i++) {
680             memcpy(y_dst, y_src, va_image.width * 4);
681             y_dst += va_image.pitches[0];
682             y_src += va_image.width * 4;
683         }
684         printf("read_frame_to_surface: RGBA and A2R10G10B10 \n");
685         break;
686 
687     default: // should not come here
688         printf("VA_STATUS_ERROR_INVALID_IMAGE_FORMAT %x\n", va_image.format.fourcc);
689         va_status = VA_STATUS_ERROR_INVALID_IMAGE_FORMAT;
690         break;
691     }
692     assert(dst_buffer);
693     fwrite(dst_buffer, 1, frame_size, fp);
694 
695     if (dst_buffer)  {
696         free(dst_buffer);
697         dst_buffer = NULL;
698     }
699 
700     vaUnmapBuffer(va_dpy, va_image.buf);
701     vaDestroyImage(va_dpy, va_image.image_id);
702     if (va_status != VA_STATUS_SUCCESS)
703         return false;
704     else
705         return true;
706 }
707 
708 static int8_t
parse_basic_parameters()709 parse_basic_parameters()
710 {
711     char str[MAX_LEN];
712 
713     /* Read src frame file information */
714     read_value_string(g_config_file_fd, "SRC_FILE_NAME", g_src_file_name);
715     read_value_uint32(g_config_file_fd, "SRC_FRAME_WIDTH", &g_in_pic_width);
716     read_value_uint32(g_config_file_fd, "SRC_FRAME_HEIGHT", &g_in_pic_height);
717     read_value_string(g_config_file_fd, "SRC_FRAME_FORMAT", str);
718     parse_fourcc_and_format(str, &g_in_fourcc, &g_in_format);
719 
720     printf("Input file: %s, width: %d, height: %d, fourcc 0x%x, format 0x%x\n", g_src_file_name, g_in_pic_width, g_in_pic_height, g_in_fourcc, g_in_format);
721 
722     /* Read dst frame file information */
723     read_value_string(g_config_file_fd, "DST_FILE_NAME", g_dst_file_name);
724     read_value_uint32(g_config_file_fd, "DST_FRAME_WIDTH", &g_out_pic_width);
725     read_value_uint32(g_config_file_fd, "DST_FRAME_HEIGHT", &g_out_pic_height);
726     read_value_string(g_config_file_fd, "DST_FRAME_FORMAT", str);
727     parse_fourcc_and_format(str, &g_out_fourcc, &g_out_format);
728 
729     printf("Output file: %s, width: %d, height: %d, fourcc 0x%x, format 0x%x\n", g_dst_file_name, g_out_pic_width, g_out_pic_height, g_out_fourcc, g_out_format);
730 
731     read_value_string(g_config_file_fd, "SRC_FILE_FORMAT", str);
732     parse_fourcc_and_format(str, &g_src_file_fourcc, NULL);
733 
734     read_value_string(g_config_file_fd, "DST_FILE_FORMAT", str);
735     parse_fourcc_and_format(str, &g_dst_file_fourcc, NULL);
736 
737     read_value_uint32(g_config_file_fd, "FRAME_SUM", &g_frame_count);
738 
739     read_value_uint32(g_config_file_fd, "SRC_MAX_DISPLAY_MASTERING_LUMINANCE", &g_in_max_display_luminance);
740     read_value_uint32(g_config_file_fd, "SRC_MIN_DISPLAY_MASTERING_LUMINANCE", &g_in_min_display_luminance);
741     read_value_uint32(g_config_file_fd, "SRC_MAX_CONTENT_LIGHT_LEVEL",         &g_in_max_content_luminance);
742     read_value_uint32(g_config_file_fd, "SRC_MAX_PICTURE_AVERAGE_LIGHT_LEVEL", &g_in_pic_average_luminance);
743 
744     read_value_uint32(g_config_file_fd, "DST_MAX_DISPLAY_MASTERING_LUMINANCE", &g_out_max_display_luminance);
745     read_value_uint32(g_config_file_fd, "DST_MIN_DISPLAY_MASTERING_LUMINANCE", &g_out_min_display_luminance);
746     read_value_uint32(g_config_file_fd, "DST_MAX_CONTENT_LIGHT_LEVEL",         &g_out_max_content_luminance);
747     read_value_uint32(g_config_file_fd, "DST_MAX_PICTURE_AVERAGE_LIGHT_LEVEL", &g_out_pic_average_luminance);
748 
749     read_value_uint32(g_config_file_fd, "SRC_FRAME_COLOUR_PRIMARIES",         &g_in_colour_primaries);
750     read_value_uint32(g_config_file_fd, "SRC_FRAME_TRANSFER_CHARACTERISTICS", &g_in_transfer_characteristic);
751     read_value_uint32(g_config_file_fd, "DST_FRAME_COLOUR_PRIMARIES",         &g_out_colour_primaries);
752     read_value_uint32(g_config_file_fd, "DST_FRAME_TRANSFER_CHARACTERISTICS", &g_out_transfer_characteristic);
753 
754     read_value_uint32(g_config_file_fd, "TM_TYPE", &g_tm_type);
755 
756     return 0;
757 }
758 
759 static void
print_help()760 print_help()
761 {
762     printf("The app is used to test the hdr tm feature.\n");
763     printf("Cmd Usage: ./process_hdr_tm.cfg process_hdr_tm.cfg.cfg\n");
764     printf("The configure file process_hdr_tm.cfg is used to configure the para.\n");
765     printf("You can refer process_hdr_tm.cfg.template for each para meaning and create the configure file.\n");
766 }
767 
main(int32_t argc,char * argv[])768 int32_t main(int32_t argc, char *argv[])
769 {
770     VAStatus va_status;
771     uint32_t i;
772 
773     if (argc != 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
774         print_help();
775         return -1;
776     }
777 
778     /* Parse the configure file for video process*/
779     strncpy(g_config_file_name, argv[1], MAX_LEN);
780     g_config_file_name[MAX_LEN - 1] = '\0';
781 
782     if (NULL == (g_config_file_fd = fopen(g_config_file_name, "r"))) {
783         printf("Open configure file %s failed!\n", g_config_file_name);
784         assert(0);
785     }
786 
787     /* Parse basic parameters */
788     if (parse_basic_parameters()) {
789         printf("Parse parameters in configure file error\n");
790         assert(0);
791     }
792 
793     va_status = vpp_context_create();
794     if (va_status != VA_STATUS_SUCCESS) {
795         printf("vpp context create failed \n");
796         assert(0);
797     }
798 
799     /* Video frame fetch, process and store */
800     if (NULL == (g_src_file_fd = fopen(g_src_file_name, "r"))) {
801         printf("Open SRC_FILE_NAME: %s failed, please specify it in config file: %s !\n",
802                g_src_file_name, g_config_file_name);
803         assert(0);
804     }
805 
806     if (NULL == (g_dst_file_fd = fopen(g_dst_file_name, "w"))) {
807         printf("Open DST_FILE_NAME: %s failed, please specify it in config file: %s !\n",
808                g_dst_file_name, g_config_file_name);
809         assert(0);
810     }
811 
812     printf("\nStart to process, ...\n");
813     struct timespec Pre_time;
814     struct timespec Cur_time;
815     unsigned int duration = 0;
816     clock_gettime(CLOCK_MONOTONIC, &Pre_time);
817 
818     for (i = 0; i < g_frame_count; i ++) {
819         read_frame_to_surface(g_src_file_fd, g_in_surface_id);
820         video_frame_process(g_in_surface_id, g_out_surface_id);
821         write_surface_to_frame(g_dst_file_fd, g_out_surface_id);
822     }
823 
824     clock_gettime(CLOCK_MONOTONIC, &Cur_time);
825     duration = (Cur_time.tv_sec - Pre_time.tv_sec) * 1000;
826     if (Cur_time.tv_nsec > Pre_time.tv_nsec) {
827         duration += (Cur_time.tv_nsec - Pre_time.tv_nsec) / 1000000;
828     } else {
829         duration += (Cur_time.tv_nsec + 1000000000 - Pre_time.tv_nsec) / 1000000 - 1000;
830     }
831     printf("Finish processing, performance: \n");
832     printf("%d frames processed in: %d ms, ave time = %d ms\n", g_frame_count, duration, duration / g_frame_count);
833 
834     if (g_src_file_fd) {
835         fclose(g_src_file_fd);
836         g_src_file_fd = NULL;
837     }
838 
839     if (g_dst_file_fd) {
840         fclose(g_dst_file_fd);
841         g_dst_file_fd = NULL;
842     }
843 
844     if (g_config_file_fd) {
845         fclose(g_config_file_fd);
846         g_config_file_fd = NULL;
847     }
848 
849     vpp_context_destroy();
850 
851     return 0;
852 }
853