Add API functions for output/encoder scaling

API functions added:
-----------------------------------------------
obs_output_set_preferred_size
obs_output_get_width
obs_output_get_height
obs_encoder_set_scaled_size
obs_encoder_get_width
obs_encoder_get_height

These functions allow for easier means of setting a custom resolution on
an output or encoder.

If an output uses an encoder and you set the preferred width/height
using the output, then the output will attempt to set the scaled
width/height for the encoder it's currently using.

Outputs and encoders now should use these functions to determine the
width/height of the raw frame data instead of using the video-io
functions.
This commit is contained in:
jp9000 2014-08-10 16:50:44 -07:00
parent f36f82b036
commit a0f679bc40
4 changed files with 189 additions and 4 deletions

View File

@ -130,6 +130,16 @@ static inline struct video_scale_info *get_video_info(
return NULL;
}
static inline bool has_scaling(struct obs_encoder *encoder)
{
uint32_t video_width = video_output_get_width(encoder->media);
uint32_t video_height = video_output_get_height(encoder->media);
return encoder->scaled_width && encoder->scaled_height &&
(video_width != encoder->scaled_width ||
video_height != encoder->scaled_height);
}
static void add_connection(struct obs_encoder *encoder)
{
struct audio_convert_info audio_info = {0};
@ -140,11 +150,23 @@ static void add_connection(struct obs_encoder *encoder)
audio_output_connect(encoder->media, &audio_info, receive_audio,
encoder);
} else {
struct video_scale_info *info = NULL;
struct video_scale_info *info =
get_video_info(encoder, &video_info);
if (!info && has_scaling(encoder)) {
info = &video_info;
info->format = video_output_get_format(encoder->media);
info->colorspace = VIDEO_CS_DEFAULT;
info->range = VIDEO_RANGE_DEFAULT;
}
if (info && (!info->width || !info->height)) {
info->width = obs_encoder_get_width(encoder);
info->height = obs_encoder_get_height(encoder);
}
info = get_video_info(encoder, &video_info);
video_output_connect(encoder->media, info, receive_video,
encoder);
encoder);
}
encoder->active = true;
@ -410,6 +432,45 @@ const char *obs_encoder_get_codec(obs_encoder_t encoder)
return encoder ? encoder->info.codec : NULL;
}
void obs_encoder_set_scaled_size(obs_encoder_t encoder, uint32_t width,
uint32_t height)
{
if (!encoder || encoder->info.type != OBS_ENCODER_VIDEO)
return;
if (encoder->active) {
blog(LOG_WARNING, "encoder '%s': Cannot set the scaled "
"resolution while the encoder is active",
obs_encoder_get_name(encoder));
return;
}
encoder->scaled_width = width;
encoder->scaled_height = height;
}
uint32_t obs_encoder_get_width(obs_encoder_t encoder)
{
if (!encoder || !encoder->media ||
encoder->info.type != OBS_ENCODER_VIDEO)
return 0;
return encoder->scaled_width != 0 ?
encoder->scaled_width :
video_output_get_width(encoder->media);
}
uint32_t obs_encoder_get_height(obs_encoder_t encoder)
{
if (!encoder || !encoder->media ||
encoder->info.type != OBS_ENCODER_VIDEO)
return 0;
return encoder->scaled_width != 0 ?
encoder->scaled_height :
video_output_get_height(encoder->media);
}
void obs_encoder_set_video(obs_encoder_t encoder, video_t video)
{
const struct video_output_info *voi;

View File

@ -419,6 +419,9 @@ struct obs_output {
obs_encoder_t audio_encoder;
obs_service_t service;
uint32_t scaled_width;
uint32_t scaled_height;
bool video_conversion_set;
bool audio_conversion_set;
struct video_scale_info video_conversion;
@ -452,6 +455,9 @@ struct obs_encoder {
size_t framesize;
size_t framesize_bytes;
uint32_t scaled_width;
uint32_t scaled_height;
bool active;
uint32_t timebase_num;

View File

@ -296,6 +296,11 @@ void obs_output_set_video_encoder(obs_output_t output, obs_encoder_t encoder)
obs_encoder_remove_output(encoder, output);
obs_encoder_add_output(encoder, output);
output->video_encoder = encoder;
/* set the preferred resolution on the encoder */
if (output->scaled_width && output->scaled_height)
obs_encoder_set_scaled_size(output->video_encoder,
output->scaled_width, output->scaled_height);
}
void obs_output_set_audio_encoder(obs_output_t output, obs_encoder_t encoder)
@ -365,6 +370,55 @@ int obs_output_get_total_frames(obs_output_t output)
return output ? output->total_frames : 0;
}
void obs_output_set_preferred_size(obs_output_t output, uint32_t width,
uint32_t height)
{
if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
return;
if (output->active) {
blog(LOG_WARNING, "output '%s': Cannot set the preferred "
"resolution while the output is active",
obs_output_get_name(output));
return;
}
output->scaled_width = width;
output->scaled_height = height;
if (output->info.flags & OBS_OUTPUT_ENCODED) {
if (output->video_encoder)
obs_encoder_set_scaled_size(output->video_encoder,
width, height);
}
}
uint32_t obs_output_get_width(obs_output_t output)
{
if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
return 0;
if (output->info.flags & OBS_OUTPUT_ENCODED)
return obs_encoder_get_width(output->video_encoder);
else
return output->scaled_width != 0 ?
output->scaled_width :
video_output_get_width(output->video);
}
uint32_t obs_output_get_height(obs_output_t output)
{
if (!output || (output->info.flags & OBS_OUTPUT_VIDEO) == 0)
return 0;
if (output->info.flags & OBS_OUTPUT_ENCODED)
return obs_encoder_get_height(output->video_encoder);
else
return output->scaled_height != 0 ?
output->scaled_height :
video_output_get_height(output->video);
}
void obs_output_set_video_conversion(obs_output_t output,
const struct video_scale_info *conversion)
{
@ -412,10 +466,43 @@ static bool can_begin_data_capture(struct obs_output *output, bool encoded,
return true;
}
static inline bool has_scaling(struct obs_output *output)
{
uint32_t video_width = video_output_get_width(output->video);
uint32_t video_height = video_output_get_height(output->video);
return output->scaled_width && output->scaled_height &&
(video_width != output->scaled_width ||
video_height != output->scaled_height);
}
static inline struct video_scale_info *get_video_conversion(
struct obs_output *output)
{
return output->video_conversion_set ? &output->video_conversion : NULL;
if (output->video_conversion_set) {
if (!output->video_conversion.width)
output->video_conversion.width =
obs_output_get_width(output);
if (!output->video_conversion.height)
output->video_conversion.height =
obs_output_get_height(output);
return &output->video_conversion;
} else if (has_scaling(output)) {
const struct video_output_info *info =
video_output_get_info(output->video);
output->video_conversion.format = info->format;
output->video_conversion.colorspace = VIDEO_CS_DEFAULT;
output->video_conversion.range = VIDEO_RANGE_DEFAULT;
output->video_conversion.width = output->scaled_width;
output->video_conversion.height = output->scaled_height;
return &output->video_conversion;
}
return NULL;
}
static inline struct audio_convert_info *get_audio_conversion(

View File

@ -953,6 +953,23 @@ EXPORT uint64_t obs_output_get_total_bytes(obs_output_t output);
EXPORT int obs_output_get_frames_dropped(obs_output_t output);
EXPORT int obs_output_get_total_frames(obs_output_t output);
/**
* Sets the preferred scaled resolution for this output. Set width and height
* to 0 to disable scaling.
*
* If this output uses an encoder, it will call obs_encoder_set_scaled_size on
* the encoder before the stream is started. If the encoder is already active,
* then this function will trigger a warning and do nothing.
*/
EXPORT void obs_output_set_preferred_size(obs_output_t output, uint32_t width,
uint32_t height);
/** For video outputs, returns the width of the encoded image */
EXPORT uint32_t obs_output_get_width(obs_output_t output);
/** For video outputs, returns the height of the encoded image */
EXPORT uint32_t obs_output_get_height(obs_output_t output);
/* ------------------------------------------------------------------------- */
/* Functions used by outputs */
@ -1032,6 +1049,20 @@ EXPORT const char *obs_encoder_get_name(obs_encoder_t encoder);
/** Returns the codec of the encoder */
EXPORT const char *obs_encoder_get_codec(obs_encoder_t encoder);
/**
* Sets the scaled resolution for a video encoder. Set width and height to 0
* to disable scaling. If the encoder is active, this function will trigger
* a warning, and do nothing.
*/
EXPORT void obs_encoder_set_scaled_size(obs_encoder_t encoder, uint32_t width,
uint32_t height);
/** For video encoders, returns the width of the encoded image */
EXPORT uint32_t obs_encoder_get_width(obs_encoder_t encoder);
/** For video encoders, returns the height of the encoded image */
EXPORT uint32_t obs_encoder_get_height(obs_encoder_t encoder);
/** Gets the default settings for an encoder type */
EXPORT obs_data_t obs_encoder_defaults(const char *id);