1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18 #include <string.h>
19
23
28
31
33
37
41
44
47
51
53 {
57
60 }
61
64 if (
ctx->src_display) {
69 }
70
72 const int luma_den = 10000;
73 ctx->in_metadata.max_display_mastering_luminance =
75 ctx->in_metadata.min_display_mastering_luminance =
77 ctx->in_metadata.max_display_mastering_luminance);
78
80 "Mastering Display Metadata(in luminance):\n");
82 "min_luminance=%u, max_luminance=%u\n",
83 ctx->in_metadata.min_display_mastering_luminance,
84 ctx->in_metadata.max_display_mastering_luminance);
85 }
86
89 const int mapping[3] = {1, 2, 0}; //green, blue, red
90 const int chroma_den = 50000;
91
92 for (
i = 0;
i < 3;
i++) {
93 const int j = mapping[
i];
94 ctx->in_metadata.display_primaries_x[
i] =
97 chroma_den);
98 ctx->in_metadata.display_primaries_y[
i] =
101 chroma_den);
102 }
103
104 ctx->in_metadata.white_point_x =
106 chroma_den);
107 ctx->in_metadata.white_point_y =
109 chroma_den);
110
112 "Mastering Display Metadata(in primaries):\n");
114 "G(%u,%u) B(%u,%u) R(%u,%u) WP(%u,%u)\n",
115 ctx->in_metadata.display_primaries_x[0],
116 ctx->in_metadata.display_primaries_y[0],
117 ctx->in_metadata.display_primaries_x[1],
118 ctx->in_metadata.display_primaries_y[1],
119 ctx->in_metadata.display_primaries_x[2],
120 ctx->in_metadata.display_primaries_y[2],
121 ctx->in_metadata.white_point_x,
122 ctx->in_metadata.white_point_y);
123 }
124 } else {
127 }
128
131 if (
ctx->src_light) {
136 }
137
138 ctx->in_metadata.max_content_light_level = light_meta->
MaxCLL;
139 ctx->in_metadata.max_pic_average_light_level = light_meta->
MaxFALL;
140
142 "Mastering Content Light Level (in):\n");
144 "MaxCLL(%u) MaxFALL(%u)\n",
145 ctx->in_metadata.max_content_light_level,
146 ctx->in_metadata.max_pic_average_light_level);
147 } else {
149 }
150 return 0;
151 }
152
154 {
161 const int mapping[3] = {1, 2, 0}; //green, blue, red
162 const int chroma_den = 50000;
163 const int luma_den = 10000;
164
168 if (!metadata)
170
172
174 const int j = mapping[
i];
177
180 }
181
184
188
191
195
197 "Mastering display colour volume(out):\n");
199 "G(%u,%u) B(%u,%u) R(%u,%u) WP(%u,%u)\n",
200 ctx->out_metadata.display_primaries_x[0],
201 ctx->out_metadata.display_primaries_y[0],
202 ctx->out_metadata.display_primaries_x[1],
203 ctx->out_metadata.display_primaries_y[1],
204 ctx->out_metadata.display_primaries_x[2],
205 ctx->out_metadata.display_primaries_y[2],
206 ctx->out_metadata.white_point_x,
207 ctx->out_metadata.white_point_y);
209 "max_display_mastering_luminance=%u, min_display_mastering_luminance=%u\n",
210 ctx->out_metadata.max_display_mastering_luminance,
211 ctx->out_metadata.min_display_mastering_luminance);
212
216 if (!metadata_lt)
218
220
221 hdr_meta_lt->
MaxCLL =
FFMIN(
ctx->out_metadata.max_content_light_level, 65535);
222 hdr_meta_lt->
MaxFALL =
FFMIN(
ctx->out_metadata.max_pic_average_light_level, 65535);
223
225 "Content light level information(out):\n");
227 "MaxCLL(%u) MaxFALL(%u)\n",
228 ctx->out_metadata.max_content_light_level,
229 ctx->out_metadata.max_pic_average_light_level);
230
231 return 0;
232 }
233
235 {
238 VAStatus vas;
239 VAProcFilterParameterBufferHDRToneMapping *hdrtm_param;
240
242 (void**)&hdrtm_param);
243 if (vas != VA_STATUS_SUCCESS) {
245 "buffer (%d): %d (%s).\n",
248 }
249
250 memcpy(hdrtm_param->data.metadata, &
ctx->in_metadata,
sizeof(VAHdrMetaDataHDR10));
251
253 if (vas != VA_STATUS_SUCCESS) {
255 "%d (%s).\n", vas, vaErrorStr(vas));
257 }
258
259 return 0;
260 }
261
263 {
266 VAStatus vas;
267 VAProcFilterParameterBufferHDRToneMapping hdrtm_param;
268 VAProcFilterCapHighDynamicRange hdr_cap[VAProcHighDynamicRangeMetadataTypeCount];
269 int num_query_caps;
271
272 memset(&hdrtm_param, 0, sizeof(hdrtm_param));
273 memset(&
ctx->in_metadata, 0,
sizeof(
ctx->in_metadata));
274
275 num_query_caps = VAProcHighDynamicRangeMetadataTypeCount;
276 vas = vaQueryVideoProcFilterCaps(vpp_ctx->
hwctx->
display,
278 VAProcFilterHighDynamicRangeToneMapping,
279 &hdr_cap, &num_query_caps);
280 if (vas != VA_STATUS_SUCCESS) {
282 "context: %d (%s).\n", vas, vaErrorStr(vas));
284 }
285
286 for (
i = 0;
i < num_query_caps;
i++) {
287 if (hdr_cap[
i].metadata_type != VAProcHighDynamicRangeMetadataNone)
288 break;
289 }
290
291 if (
i >= num_query_caps) {
294 }
295
296 if (
ctx->mastering_display) {
297 for (
i = 0;
i < num_query_caps;
i++) {
298 if (VA_TONE_MAPPING_HDR_TO_HDR & hdr_cap[
i].caps_flag)
299 break;
300 }
301 if (
i >= num_query_caps) {
303 "VAAPI driver doesn't support HDR to HDR\n");
305 }
306 } else {
307 for (
i = 0;
i < num_query_caps;
i++) {
308 if (VA_TONE_MAPPING_HDR_TO_SDR & hdr_cap[
i].caps_flag)
309 break;
310 }
311 if (
i >= num_query_caps) {
313 "VAAPI driver doesn't support HDR to SDR\n");
315 }
316 }
317
318 hdrtm_param.type = VAProcFilterHighDynamicRangeToneMapping;
319 hdrtm_param.data.metadata_type = VAProcHighDynamicRangeMetadataHDR10;
320 hdrtm_param.data.metadata = &
ctx->in_metadata;
321 hdrtm_param.data.metadata_size = sizeof(VAHdrMetaDataHDR10);
322
324 VAProcFilterParameterBufferType,
325 &hdrtm_param, sizeof(hdrtm_param), 1);
326 }
327
329 {
335 VASurfaceID input_surface, output_surface;
336
337 VAProcPipelineParameterBuffer params;
338 int err;
339
340 VAHdrMetaData out_hdr_metadata;
341
345
349 }
350
352 if (err < 0)
354
356 if (err < 0)
358
359 input_surface = (VASurfaceID)(uintptr_t)input_frame->
data[3];
361 input_surface);
362
368 }
369
370 output_surface = (VASurfaceID)(uintptr_t)
output_frame->data[3];
372 output_surface);
373 memset(¶ms, 0, sizeof(params));
374
376 if (err < 0)
378
381
382 if (!
ctx->mastering_display) {
383 /* Use BT709 by default for HDR to SDR output frame */
387 }
388
391
394
397
398 if (
ctx->mastering_display) {
400 if (err < 0)
402 }
403
406 if (err < 0)
408
409 if (
ctx->mastering_display) {
410 out_hdr_metadata.metadata_type = VAProcHighDynamicRangeMetadataHDR10;
411 out_hdr_metadata.metadata = &
ctx->out_metadata;
412 out_hdr_metadata.metadata_size = sizeof(VAHdrMetaDataHDR10);
413 params.output_hdr_metadata = &out_hdr_metadata;
414 }
415
419 }
420
422 if (err < 0)
424
426
430
432
436 return err;
437 }
438
440 {
443
447
448 if (
ctx->output_format_string) {
450 } else {
451 if (
ctx->mastering_display) {
453 av_log(avctx,
AV_LOG_VERBOSE,
"Output format not set, use default format P010 for HDR to HDR tone mapping.\n");
454 } else {
456 av_log(avctx,
AV_LOG_VERBOSE,
"Output format not set, use default format NV12 for HDR to SDR tone mapping.\n");
457 }
458 }
459
460 #define STRING_OPTION(var_name, func_name, default_value) do { \
461 if (ctx->var_name ## _string) { \
462 int var = av_ ## func_name ## _from_name(ctx->var_name ## _string); \
463 if (var < 0) { \
464 av_log(avctx, AV_LOG_ERROR, "Invalid %s.\n", #var_name); \
465 return AVERROR(EINVAL); \
466 } \
467 ctx->var_name = var; \
468 } else { \
469 ctx->var_name = default_value; \
470 } \
471 } while (0)
472
476
477 if (
ctx->mastering_display) {
478 if (10 != sscanf(
ctx->mastering_display,
479 "%hu %hu|%hu %hu|%hu %hu|%hu %hu|%u %u",
480 &
ctx->out_metadata.display_primaries_x[0],
481 &
ctx->out_metadata.display_primaries_y[0],
482 &
ctx->out_metadata.display_primaries_x[1],
483 &
ctx->out_metadata.display_primaries_y[1],
484 &
ctx->out_metadata.display_primaries_x[2],
485 &
ctx->out_metadata.display_primaries_y[2],
486 &
ctx->out_metadata.white_point_x,
487 &
ctx->out_metadata.white_point_y,
488 &
ctx->out_metadata.min_display_mastering_luminance,
489 &
ctx->out_metadata.max_display_mastering_luminance)) {
491 "Option mastering-display input invalid\n");
493 }
494
495 if (!
ctx->content_light) {
496 ctx->out_metadata.max_content_light_level = 0;
497 ctx->out_metadata.max_pic_average_light_level = 0;
498 }
else if (2 != sscanf(
ctx->content_light,
499 "%hu %hu",
500 &
ctx->out_metadata.max_content_light_level,
501 &
ctx->out_metadata.max_pic_average_light_level)) {
503 "Option content-light input invalid\n");
505 }
506 }
507
508 return 0;
509 }
510
511 #define OFFSET(x) offsetof(HDRVAAPIContext, x)
512 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
515 { "matrix", "Output color matrix coefficient set",
517 { .str =
NULL }, .flags =
FLAGS, .unit =
"matrix" },
518 { "m", "Output color matrix coefficient set",
520 { .str =
NULL }, .flags =
FLAGS, .unit =
"matrix" },
521 { "primaries", "Output color primaries set",
523 { .str =
NULL }, .flags =
FLAGS, .unit =
"primaries" },
524 { "p", "Output color primaries set",
526 { .str =
NULL }, .flags =
FLAGS, .unit =
"primaries" },
527 { "transfer", "Output color transfer characteristics set",
529 { .str =
NULL }, .flags =
FLAGS, .unit =
"transfer" },
530 { "t", "Output color transfer characteristics set",
532 { .str =
NULL }, .flags =
FLAGS, .unit =
"transfer" },
533 { "display", "set mastering display colour volume",
536 { "light", "set content light level information",
540 };
541
542
544
546 {
551 },
552 };
553
555 {
559 },
560 };
561
563 .
name =
"tonemap_vaapi",
571 .priv_class = &tonemap_vaapi_class,
573 };