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