obs-ffmpeg: Add max luminance metadata for PQ

Necessary for video player to remap display ranges.
This commit is contained in:
jpark37 2022-04-10 23:00:29 -07:00 committed by Jim
parent d2fb302e5c
commit 0d72c314d4
4 changed files with 39 additions and 2 deletions

View File

@ -30,6 +30,7 @@
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/channel_layout.h>
#include <libavutil/mastering_display_metadata.h>
#define ANSI_COLOR_RED "\x1b[0;91m"
#define ANSI_COLOR_MAGENTA "\x1b[0;95m"
@ -93,6 +94,7 @@ struct main_params {
int color_trc;
int colorspace;
int color_range;
int max_luminance;
char *acodec;
char *muxer_settings;
};
@ -320,6 +322,9 @@ static bool init_params(int *argc, char ***argv, struct main_params *params,
if (!get_opt_int(argc, argv, &params->color_range,
"video color range"))
return false;
if (!get_opt_int(argc, argv, &params->max_luminance,
"video max luminance"))
return false;
if (!get_opt_int(argc, argv, &params->fps_num, "video fps num"))
return false;
if (!get_opt_int(argc, argv, &params->fps_den, "video fps den"))
@ -415,6 +420,18 @@ static void create_video_stream(struct ffmpeg_mux *ffm)
#endif
ffm->video_stream->avg_frame_rate = av_inv_q(context->time_base);
if (ffm->params.max_luminance > 0) {
AVMasteringDisplayMetadata *const mastering =
av_mastering_display_metadata_alloc();
mastering->max_luminance =
av_make_q(ffm->params.max_luminance, 1);
mastering->has_luminance = 1;
av_stream_add_side_data(ffm->video_stream,
AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
(uint8_t *)mastering,
sizeof(*mastering));
}
if (ffm->output->oformat->flags & AVFMT_GLOBALHEADER)
context->flags |= CODEC_FLAG_GLOBAL_H;

View File

@ -162,11 +162,17 @@ static void add_video_encoder_params(struct ffmpeg_muxer *stream,
? AVCOL_RANGE_JPEG
: AVCOL_RANGE_MPEG;
dstr_catf(cmd, "%s %d %d %d %d %d %d %d %d %d ",
const int max_luminance =
(trc == AVCOL_TRC_SMPTE2084)
? (int)obs_get_video_hdr_nominal_peak_level()
: 0;
dstr_catf(cmd, "%s %d %d %d %d %d %d %d %d %d %d ",
obs_encoder_get_codec(vencoder), bitrate,
obs_output_get_width(stream->output),
obs_output_get_height(stream->output), (int)pri, (int)trc,
(int)spc, (int)range, (int)info->fps_num, (int)info->fps_den);
(int)spc, (int)range, max_luminance, (int)info->fps_num,
(int)info->fps_den);
}
static void add_audio_encoder_params(struct dstr *cmd, obs_encoder_t *aencoder)

View File

@ -26,6 +26,7 @@
#include "obs-ffmpeg-formats.h"
#include "obs-ffmpeg-compat.h"
#include <libavutil/channel_layout.h>
#include <libavutil/mastering_display_metadata.h>
struct ffmpeg_output {
obs_output_t *output;
@ -222,6 +223,18 @@ static bool create_video_stream(struct ffmpeg_data *data)
data->config.video_encoder))
return false;
if (data->config.color_trc == AVCOL_TRC_SMPTE2084) {
AVMasteringDisplayMetadata *const mastering =
av_mastering_display_metadata_alloc();
mastering->max_luminance = av_make_q(
(int)obs_get_video_hdr_nominal_peak_level(), 1);
mastering->has_luminance = 1;
av_stream_add_side_data(data->video,
AV_PKT_DATA_MASTERING_DISPLAY_METADATA,
(uint8_t *)mastering,
sizeof(*mastering));
}
closest_format = data->config.format;
if (data->vcodec->pix_fmts) {
closest_format = avcodec_find_best_pix_fmt_of_list(

View File

@ -27,6 +27,7 @@ struct ffmpeg_cfg {
enum AVColorPrimaries color_primaries;
enum AVColorTransferCharacteristic color_trc;
enum AVColorSpace colorspace;
int max_luminance;
int scale_width;
int scale_height;
int width;