video-converter: Implement multi-threaded scaling/conversion

This adds a property to select the maximum number of threads to use for
conversion and scaling. During processing, each plane is split into
an equal number of consecutive lines that are then processed by each
thread.

During tests, this gave up to 1.8x speedup with 2 threads and up to 3.2x
speedup with 4 threads when converting e.g. 1080p to 4k in v210.

https://bugzilla.gnome.org/show_bug.cgi?id=778974
This commit is contained in:
Sebastian Dröge 2017-02-20 21:38:17 +02:00
parent d15ad75caf
commit 49ac382b47
6 changed files with 2337 additions and 541 deletions

File diff suppressed because it is too large Load diff

View file

@ -265,6 +265,14 @@ typedef enum {
*/
#define GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE "GstVideoConverter.primaries-mode"
/**
* GST_VIDEO_CONVERTER_OPT_THREADS:
*
* #G_TYPE_UINT, maximum number of threads to use. Default 1, 0 for the number
* of cores.
*/
#define GST_VIDEO_CONVERTER_OPT_THREADS "GstVideoConverter.threads"
typedef struct _GstVideoConverter GstVideoConverter;
GstVideoConverter * gst_video_converter_new (GstVideoInfo *in_info,

View file

@ -67,6 +67,7 @@ G_DEFINE_TYPE (GstVideoConvert, gst_video_convert, GST_TYPE_VIDEO_FILTER);
#define DEFAULT_PROP_MATRIX_MODE GST_VIDEO_MATRIX_MODE_FULL
#define DEFAULT_PROP_GAMMA_MODE GST_VIDEO_GAMMA_MODE_NONE
#define DEFAULT_PROP_PRIMARIES_MODE GST_VIDEO_PRIMARIES_MODE_NONE
#define DEFAULT_PROP_N_THREADS 1
enum
{
@ -79,7 +80,8 @@ enum
PROP_CHROMA_MODE,
PROP_MATRIX_MODE,
PROP_GAMMA_MODE,
PROP_PRIMARIES_MODE
PROP_PRIMARIES_MODE,
PROP_N_THREADS
};
#define CSP_VIDEO_CAPS GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \
@ -464,7 +466,9 @@ gst_video_convert_set_info (GstVideoFilter * filter,
GST_VIDEO_CONVERTER_OPT_GAMMA_MODE,
GST_TYPE_VIDEO_GAMMA_MODE, space->gamma_mode,
GST_VIDEO_CONVERTER_OPT_PRIMARIES_MODE,
GST_TYPE_VIDEO_PRIMARIES_MODE, space->primaries_mode, NULL));
GST_TYPE_VIDEO_PRIMARIES_MODE, space->primaries_mode,
GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT,
space->n_threads, NULL));
if (space->convert == NULL)
goto no_convert;
@ -576,6 +580,10 @@ gst_video_convert_class_init (GstVideoConvertClass * klass)
"Primaries Conversion Mode", gst_video_primaries_mode_get_type (),
DEFAULT_PROP_PRIMARIES_MODE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_N_THREADS,
g_param_spec_uint ("n-threads", "Threads",
"Maximum number of threads to use", 0, G_MAXUINT,
DEFAULT_PROP_N_THREADS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
@ -590,6 +598,7 @@ gst_video_convert_init (GstVideoConvert * space)
space->matrix_mode = DEFAULT_PROP_MATRIX_MODE;
space->gamma_mode = DEFAULT_PROP_GAMMA_MODE;
space->primaries_mode = DEFAULT_PROP_PRIMARIES_MODE;
space->n_threads = DEFAULT_PROP_N_THREADS;
}
void
@ -628,6 +637,9 @@ gst_video_convert_set_property (GObject * object, guint property_id,
case PROP_DITHER_QUANTIZATION:
csp->dither_quantization = g_value_get_uint (value);
break;
case PROP_N_THREADS:
csp->n_threads = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -670,6 +682,9 @@ gst_video_convert_get_property (GObject * object, guint property_id,
case PROP_DITHER_QUANTIZATION:
g_value_set_uint (value, csp->dither_quantization);
break;
case PROP_N_THREADS:
g_value_set_uint (value, csp->n_threads);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;

View file

@ -56,6 +56,7 @@ struct _GstVideoConvert {
GstVideoGammaMode gamma_mode;
GstVideoPrimariesMode primaries_mode;
gdouble alpha_value;
gint n_threads;
};
struct _GstVideoConvertClass

View file

@ -90,6 +90,7 @@ GST_DEBUG_CATEGORY_STATIC (CAT_PERFORMANCE);
#define DEFAULT_PROP_SUBMETHOD 1
#define DEFAULT_PROP_ENVELOPE 2.0
#define DEFAULT_PROP_GAMMA_DECODE FALSE
#define DEFAULT_PROP_N_THREADS 1
enum
{
@ -102,6 +103,7 @@ enum
PROP_SUBMETHOD,
PROP_ENVELOPE,
PROP_GAMMA_DECODE,
PROP_N_THREADS
};
#undef GST_VIDEO_SIZE_RANGE
@ -260,6 +262,11 @@ gst_video_scale_class_init (GstVideoScaleClass * klass)
"Decode gamma before scaling", DEFAULT_PROP_GAMMA_DECODE,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_N_THREADS,
g_param_spec_uint ("n-threads", "Threads",
"Maximum number of threads to use", 0, G_MAXUINT,
DEFAULT_PROP_N_THREADS,
G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
gst_element_class_set_static_metadata (element_class,
"Video scaler", "Filter/Converter/Video/Scaler",
@ -291,6 +298,7 @@ gst_video_scale_init (GstVideoScale * videoscale)
videoscale->dither = DEFAULT_PROP_DITHER;
videoscale->envelope = DEFAULT_PROP_ENVELOPE;
videoscale->gamma_decode = DEFAULT_PROP_GAMMA_DECODE;
videoscale->n_threads = DEFAULT_PROP_N_THREADS;
}
static void
@ -350,6 +358,11 @@ gst_video_scale_set_property (GObject * object, guint prop_id,
vscale->gamma_decode = g_value_get_boolean (value);
GST_OBJECT_UNLOCK (vscale);
break;
case PROP_N_THREADS:
GST_OBJECT_LOCK (vscale);
vscale->n_threads = g_value_get_uint (value);
GST_OBJECT_UNLOCK (vscale);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -403,6 +416,11 @@ gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value,
g_value_set_boolean (value, vscale->gamma_decode);
GST_OBJECT_UNLOCK (vscale);
break;
case PROP_N_THREADS:
GST_OBJECT_LOCK (vscale);
g_value_set_uint (value, vscale->n_threads);
GST_OBJECT_UNLOCK (vscale);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -606,7 +624,9 @@ gst_video_scale_set_info (GstVideoFilter * filter, GstCaps * in,
GST_VIDEO_MATRIX_MODE_NONE, GST_VIDEO_CONVERTER_OPT_DITHER_METHOD,
GST_TYPE_VIDEO_DITHER_METHOD, GST_VIDEO_DITHER_NONE,
GST_VIDEO_CONVERTER_OPT_CHROMA_MODE, GST_TYPE_VIDEO_CHROMA_MODE,
GST_VIDEO_CHROMA_MODE_NONE, NULL);
GST_VIDEO_CHROMA_MODE_NONE,
GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, videoscale->n_threads,
NULL);
if (videoscale->gamma_decode) {
gst_structure_set (options,

View file

@ -88,6 +88,7 @@ struct _GstVideoScale {
int submethod;
double envelope;
gboolean gamma_decode;
gint n_threads;
GstVideoConverter *convert;