obs-studio/plugins/obs-ffmpeg/closest-pixel-format.h
jp9000 d3f92ca5d6 obs-ffmpeg: Make FFmpeg a usable output
This makes FFmpeg usable as an output, and removes or changes most of
the code that was originally intended for testing purposes.

Changes the settings for the FFmpeg output to the following:
* url:             Sets the output URL or file path
* video_bitrate:   Sets the video bitrate
* audio_bitrate:   Sets the audio bitrate
* video_encoder:   Sets the video encoder (by name, blank for default)
* audio_encoder:   Sets the audio encoder (by name, blank for default)
* video_settings:  Sets custom video encoder FFmpeg settings
* audio_settings:  Sets custom audio encoder FFmpeg settings
* scale_width:     Image scale width (0 if none)
* scale_height:    Image scale height (0 if none)

The reason why scale_width and scale_height are provided is because it
may internally convert formats, and it may be a bit more optimal to use
that scaler instead of the pre-output scaler just in case it already has
to convert formats internally anyway (though you can do it either way
you wish).

Video format handling has also changed; it will now attempt to use the
closest format to the current format if available for a given video
codec.
2015-02-04 16:51:54 -08:00

116 lines
2.4 KiB
C

#pragma once
static const enum AVPixelFormat i420_formats[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_YUV422P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat nv12_formats[] = {
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat yuy2_formats[] = {
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat uyvy_formats[] = {
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat rgba_formats[] = {
AV_PIX_FMT_RGBA,
AV_PIX_FMT_BGRA,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_NONE
};
static const enum AVPixelFormat bgra_formats[] = {
AV_PIX_FMT_BGRA,
AV_PIX_FMT_RGBA,
AV_PIX_FMT_YUYV422,
AV_PIX_FMT_UYVY422,
AV_PIX_FMT_NV12,
AV_PIX_FMT_NV21,
AV_PIX_FMT_NONE
};
static enum AVPixelFormat get_best_format(
const enum AVPixelFormat *best,
const enum AVPixelFormat *formats)
{
while (*best != AV_PIX_FMT_NONE) {
enum AVPixelFormat best_format = *best;
const enum AVPixelFormat *cur_formats = formats;
while (*cur_formats != AV_PIX_FMT_NONE) {
enum AVPixelFormat avail_format = *cur_formats;
if (best_format == avail_format)
return best_format;
cur_formats++;
}
best++;
}
return AV_PIX_FMT_NONE;
}
static inline enum AVPixelFormat get_closest_format(
enum AVPixelFormat format,
const enum AVPixelFormat *formats)
{
enum AVPixelFormat best_format = AV_PIX_FMT_NONE;
if (!formats || formats[0] == AV_PIX_FMT_NONE)
return format;
switch ((int)format) {
case AV_PIX_FMT_YUV420P:
best_format = get_best_format(i420_formats, formats);
break;
case AV_PIX_FMT_NV12:
best_format = get_best_format(nv12_formats, formats);
break;
case AV_PIX_FMT_YUYV422:
best_format = get_best_format(yuy2_formats, formats);
break;
case AV_PIX_FMT_UYVY422:
best_format = get_best_format(uyvy_formats, formats);
break;
case AV_PIX_FMT_RGBA:
best_format = get_best_format(rgba_formats, formats);
break;
case AV_PIX_FMT_BGRA:
best_format = get_best_format(bgra_formats, formats);
break;
}
return (best_format == AV_PIX_FMT_NONE) ? formats[0] : best_format;
}