From 2c1244331f9a782bd1e406819fff814b4eb4abeb Mon Sep 17 00:00:00 2001 From: Aaron Boxer Date: Sun, 28 Jul 2019 19:08:24 -0400 Subject: openjpegdec: enable multi-threaded decode --- ext/openjpeg/gstopenjpegdec.c | 73 +++++++++++++++++++++++++++++++++++++++++++ ext/openjpeg/gstopenjpegdec.h | 2 ++ 2 files changed, 75 insertions(+) (limited to 'ext/openjpeg') diff --git a/ext/openjpeg/gstopenjpegdec.c b/ext/openjpeg/gstopenjpegdec.c index 706a08a32..20dfeab96 100644 --- a/ext/openjpeg/gstopenjpegdec.c +++ b/ext/openjpeg/gstopenjpegdec.c @@ -32,6 +32,15 @@ GST_DEBUG_CATEGORY_STATIC (gst_openjpeg_dec_debug); #define GST_CAT_DEFAULT gst_openjpeg_dec_debug +enum +{ + PROP_0, + PROP_MAX_THREADS, + PROP_LAST +}; + +#define GST_OPENJPEG_DEC_DEFAULT_MAX_THREADS 0 + static gboolean gst_openjpeg_dec_start (GstVideoDecoder * decoder); static gboolean gst_openjpeg_dec_stop (GstVideoDecoder * decoder); static gboolean gst_openjpeg_dec_set_format (GstVideoDecoder * decoder, @@ -40,6 +49,11 @@ static GstFlowReturn gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, GstVideoCodecFrame * frame); static gboolean gst_openjpeg_dec_decide_allocation (GstVideoDecoder * decoder, GstQuery * query); +static void gst_openjpeg_dec_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_openjpeg_dec_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + #if G_BYTE_ORDER == G_LITTLE_ENDIAN #define GRAY16 "GRAY16_LE" @@ -75,6 +89,7 @@ gst_openjpeg_dec_class_init (GstOpenJPEGDecClass * klass) { GstElementClass *element_class; GstVideoDecoderClass *video_decoder_class; + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); element_class = (GstElementClass *) klass; video_decoder_class = (GstVideoDecoderClass *) klass; @@ -97,6 +112,21 @@ gst_openjpeg_dec_class_init (GstOpenJPEGDecClass * klass) video_decoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_openjpeg_dec_handle_frame); video_decoder_class->decide_allocation = gst_openjpeg_dec_decide_allocation; + gobject_class->set_property = gst_openjpeg_dec_set_property; + gobject_class->get_property = gst_openjpeg_dec_get_property; + + /** + * GstOpenJPEGDec:max-threads: + * + * Maximum number of worker threads to spawn. (0 = auto) + * + * Since: 1.18 + */ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_THREADS, + g_param_spec_int ("max-threads", "Maximum decode threads", + "Maximum number of worker threads to spawn. (0 = auto)", + 0, G_MAXINT, GST_OPENJPEG_DEC_DEFAULT_MAX_THREADS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); GST_DEBUG_CATEGORY_INIT (gst_openjpeg_dec_debug, "openjpegdec", 0, "OpenJPEG Decoder"); @@ -114,6 +144,8 @@ gst_openjpeg_dec_init (GstOpenJPEGDec * self) GST_PAD_SET_ACCEPT_TEMPLATE (GST_VIDEO_DECODER_SINK_PAD (self)); opj_set_default_decoder_parameters (&self->params); self->sampling = GST_JPEG2000_SAMPLING_NONE; + self->max_threads = GST_OPENJPEG_DEC_DEFAULT_MAX_THREADS; + self->num_procs = g_get_num_processors (); } static gboolean @@ -148,6 +180,39 @@ gst_openjpeg_dec_stop (GstVideoDecoder * video_decoder) return TRUE; } + +static void +gst_openjpeg_dec_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstOpenJPEGDec *dec = (GstOpenJPEGDec *) object; + + switch (prop_id) { + case PROP_MAX_THREADS: + g_atomic_int_set (&dec->max_threads, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_openjpeg_dec_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstOpenJPEGDec *dec = (GstOpenJPEGDec *) object; + + switch (prop_id) { + case PROP_MAX_THREADS: + g_value_set_int (value, g_atomic_int_get (&dec->max_threads)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static gboolean gst_openjpeg_dec_set_format (GstVideoDecoder * decoder, GstVideoCodecState * state) @@ -1055,6 +1120,7 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, opj_image_t *image; GstVideoFrame vframe; opj_dparameters_t params; + gint max_threads; GST_DEBUG_OBJECT (self, "Handling frame"); @@ -1087,6 +1153,13 @@ gst_openjpeg_dec_handle_frame (GstVideoDecoder * decoder, if (!opj_setup_decoder (dec, ¶ms)) goto open_error; + max_threads = g_atomic_int_get (&self->max_threads); + if (max_threads == 0) + max_threads = self->num_procs; + if (!opj_codec_set_threads (dec, max_threads)) + GST_WARNING_OBJECT (self, "Failed to set %d number of threads", + max_threads); + if (!gst_buffer_map (frame->input_buffer, &map, GST_MAP_READ)) goto map_read_error; diff --git a/ext/openjpeg/gstopenjpegdec.h b/ext/openjpeg/gstopenjpegdec.h index 4b4c6cfd0..edb061775 100644 --- a/ext/openjpeg/gstopenjpegdec.h +++ b/ext/openjpeg/gstopenjpegdec.h @@ -57,6 +57,8 @@ struct _GstOpenJPEGDec OPJ_COLOR_SPACE color_space; GstJPEG2000Sampling sampling; gint ncomps; + gint max_threads; /* atomic */ + gint num_procs; void (*fill_frame) (GstVideoFrame *frame, opj_image_t * image); -- cgit v1.2.1