提交 8d125dc0 编写于 作者: J jp9000

libobs: Add better default source color range handling

Fixes handling of the `obs_source_frame::full_range` member variable,
which is often set to false by default by many plugins even when using
RGB, which would cause RGB to be marked as "partial range".  This change
is crucial for when partial range RBG support is implemented.

Adds `obs_source_frame2` structure that replaces the `full_range` member
variable with a `range` variable, which uses the `video_range_type` enum
to allow handling default range values.  This member variable treats
VIDEO_RANGE_DEFAULT as full range if the format is RGB, and partial
range if the format is YUV.

Also adds `obs_source_output_video2` and `obs_source_preload_video2`
functions which use the `obs_source_frame2` structure instead of the
`obs_source_frame` structure.

When using the original `obs_source_frame`, `obs_source_output_video`,
and `obs_source_preload_video` functions, RGB will always be full range
by default for backward compatibility purposes.
上级 f109d1c2
......@@ -135,15 +135,23 @@ static inline const char *get_video_colorspace_name(enum video_colorspace cs)
return "601";
}
static inline const char *get_video_range_name(enum video_range_type range)
static inline enum video_range_type resolve_video_range(
enum video_format format, enum video_range_type range)
{
switch (range) {
case VIDEO_RANGE_FULL: return "Full";
case VIDEO_RANGE_PARTIAL:
case VIDEO_RANGE_DEFAULT:;
if (range == VIDEO_RANGE_DEFAULT) {
range = format_is_yuv(format)
? VIDEO_RANGE_PARTIAL
: VIDEO_RANGE_FULL;
}
return "Partial";
return range;
}
static inline const char *get_video_range_name(enum video_format format,
enum video_range_type range)
{
range = resolve_video_range(format, range);
return range == VIDEO_RANGE_FULL ? "Full" : "Partial";
}
enum video_scale_type {
......
......@@ -2436,7 +2436,7 @@ static inline struct obs_source_frame *cache_video(struct obs_source *source,
return new_frame;
}
void obs_source_output_video(obs_source_t *source,
static void obs_source_output_video_internal(obs_source_t *source,
const struct obs_source_frame *frame)
{
if (!obs_source_valid(source, "obs_source_output_video"))
......@@ -2464,6 +2464,56 @@ void obs_source_output_video(obs_source_t *source,
pthread_mutex_unlock(&source->async_mutex);
}
void obs_source_output_video(obs_source_t *source,
const struct obs_source_frame *frame)
{
if (!frame) {
obs_source_output_video_internal(source, NULL);
return;
}
struct obs_source_frame new_frame = *frame;
new_frame.full_range = format_is_yuv(frame->format)
? new_frame.full_range
: true;
obs_source_output_video_internal(source, &new_frame);
}
void obs_source_output_video2(obs_source_t *source,
const struct obs_source_frame2 *frame)
{
if (!frame) {
obs_source_output_video_internal(source, NULL);
return;
}
struct obs_source_frame new_frame;
enum video_range_type range = resolve_video_range(frame->format,
frame->range);
for (size_t i = 0; i < MAX_AV_PLANES; i++) {
new_frame.data[i] = frame->data[i];
new_frame.linesize[i] = frame->linesize[i];
}
new_frame.width = frame->width;
new_frame.height = frame->height;
new_frame.timestamp = frame->timestamp;
new_frame.format = frame->format;
new_frame.full_range = range == VIDEO_RANGE_FULL;
new_frame.flip = frame->flip;
memcpy(&new_frame.color_matrix, &frame->color_matrix,
sizeof(frame->color_matrix));
memcpy(&new_frame.color_range_min, &frame->color_range_min,
sizeof(frame->color_range_min));
memcpy(&new_frame.color_range_max, &frame->color_range_max,
sizeof(frame->color_range_max));
obs_source_output_video_internal(source, &new_frame);
}
static inline bool preload_frame_changed(obs_source_t *source,
const struct obs_source_frame *in)
{
......@@ -2475,7 +2525,7 @@ static inline bool preload_frame_changed(obs_source_t *source,
in->format != source->async_preload_frame->format;
}
void obs_source_preload_video(obs_source_t *source,
static void obs_source_preload_video_internal(obs_source_t *source,
const struct obs_source_frame *frame)
{
if (!obs_source_valid(source, "obs_source_preload_video"))
......@@ -2504,6 +2554,56 @@ void obs_source_preload_video(obs_source_t *source,
obs_leave_graphics();
}
void obs_source_preload_video(obs_source_t *source,
const struct obs_source_frame *frame)
{
if (!frame) {
obs_source_preload_video_internal(source, NULL);
return;
}
struct obs_source_frame new_frame = *frame;
new_frame.full_range = format_is_yuv(frame->format)
? new_frame.full_range
: true;
obs_source_preload_video_internal(source, &new_frame);
}
void obs_source_preload_video2(obs_source_t *source,
const struct obs_source_frame2 *frame)
{
if (!frame) {
obs_source_preload_video_internal(source, NULL);
return;
}
struct obs_source_frame new_frame;
enum video_range_type range = resolve_video_range(frame->format,
frame->range);
for (size_t i = 0; i < MAX_AV_PLANES; i++) {
new_frame.data[i] = frame->data[i];
new_frame.linesize[i] = frame->linesize[i];
}
new_frame.width = frame->width;
new_frame.height = frame->height;
new_frame.timestamp = frame->timestamp;
new_frame.format = frame->format;
new_frame.full_range = range == VIDEO_RANGE_FULL;
new_frame.flip = frame->flip;
memcpy(&new_frame.color_matrix, &frame->color_matrix,
sizeof(frame->color_matrix));
memcpy(&new_frame.color_range_min, &frame->color_range_min,
sizeof(frame->color_range_min));
memcpy(&new_frame.color_range_max, &frame->color_range_max,
sizeof(frame->color_range_max));
obs_source_preload_video_internal(source, &new_frame);
}
void obs_source_show_preloaded_video(obs_source_t *source)
{
uint64_t sys_ts;
......
......@@ -1129,7 +1129,8 @@ int obs_reset_video(struct obs_video_info *ovi)
bool yuv = format_is_yuv(ovi->output_format);
const char *yuv_format = get_video_colorspace_name(ovi->colorspace);
const char *yuv_range = get_video_range_name(ovi->range);
const char *yuv_range = get_video_range_name(ovi->output_format,
ovi->range);
blog(LOG_INFO, "---------------------------------");
blog(LOG_INFO, "video settings reset:\n"
......
......@@ -220,6 +220,10 @@ struct obs_source_audio {
*
* If a YUV format is specified, it will be automatically upsampled and
* converted to RGB via shader on the graphics processor.
*
* NOTE: Non-YUV formats will always be treated as full range with this
* structure! Use obs_source_frame2 along with obs_source_output_video2
* instead if partial range support is desired for non-YUV video formats.
*/
struct obs_source_frame {
uint8_t *data[MAX_AV_PLANES];
......@@ -240,6 +244,21 @@ struct obs_source_frame {
bool prev_frame;
};
struct obs_source_frame2 {
uint8_t *data[MAX_AV_PLANES];
uint32_t linesize[MAX_AV_PLANES];
uint32_t width;
uint32_t height;
uint64_t timestamp;
enum video_format format;
enum video_range_type range;
float color_matrix[16];
float color_range_min[3];
float color_range_max[3];
bool flip;
};
/** Access to the argc/argv used to start OBS. What you see is what you get. */
struct obs_cmdline_args {
int argc;
......@@ -1117,13 +1136,29 @@ EXPORT void obs_source_draw_set_color_matrix(
EXPORT void obs_source_draw(gs_texture_t *image, int x, int y,
uint32_t cx, uint32_t cy, bool flip);
/** Outputs asynchronous video data. Set to NULL to deactivate the texture */
/**
* Outputs asynchronous video data. Set to NULL to deactivate the texture
*
* NOTE: Non-YUV formats will always be treated as full range with this
* function! Use obs_source_output_video2 instead if partial range support is
* desired for non-YUV video formats.
*/
EXPORT void obs_source_output_video(obs_source_t *source,
const struct obs_source_frame *frame);
EXPORT void obs_source_output_video2(obs_source_t *source,
const struct obs_source_frame2 *frame);
/** Preloads asynchronous video data to allow instantaneous playback */
/**
* Preloads asynchronous video data to allow instantaneous playback
*
* NOTE: Non-YUV formats will always be treated as full range with this
* function! Use obs_source_preload_video2 instead if partial range support is
* desired for non-YUV video formats.
*/
EXPORT void obs_source_preload_video(obs_source_t *source,
const struct obs_source_frame *frame);
EXPORT void obs_source_preload_video2(obs_source_t *source,
const struct obs_source_frame2 *frame);
/** Shows any preloaded video data */
EXPORT void obs_source_show_preloaded_video(obs_source_t *source);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册