Enable threading in ffmpeg decoders that support it.
authorJan Schmidt <thaytan@noraisin.net>
Tue, 21 Jun 2011 04:33:29 +0000 (14:33 +1000)
committerJan Schmidt <thaytan@noraisin.net>
Tue, 21 Jun 2011 04:33:29 +0000 (14:33 +1000)
Add a max-threads property, which defaults to '0 = auto'
Add a utility function taken from libschroedinger which sets
the ffmpeg worker thread count to match the computer processor
count by default.

ext/ffmpeg/gstffmpegdec.c
ext/ffmpeg/gstffmpegutils.c
ext/ffmpeg/gstffmpegutils.h

index 8fab659..ef76928 100644 (file)
@@ -121,6 +121,7 @@ struct _GstFFMpegDec
   gboolean do_padding;
   gboolean debug_mv;
   gboolean crop;
+  int max_threads;
 
   /* QoS stuff *//* with LOCK */
   gdouble proportion;
@@ -194,6 +195,7 @@ gst_ts_info_get (GstFFMpegDec * dec, gint idx)
 #define DEFAULT_DO_PADDING             TRUE
 #define DEFAULT_DEBUG_MV               FALSE
 #define DEFAULT_CROP                   TRUE
+#define DEFAULT_MAX_THREADS            0
 
 enum
 {
@@ -204,6 +206,7 @@ enum
   PROP_DO_PADDING,
   PROP_DEBUG_MV,
   PROP_CROP,
+  PROP_MAX_THREADS,
   PROP_LAST
 };
 
@@ -358,6 +361,8 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass * klass)
   gobject_class->get_property = gst_ffmpegdec_get_property;
 
   if (klass->in_plugin->type == AVMEDIA_TYPE_VIDEO) {
+    int caps;
+
     g_object_class_install_property (gobject_class, PROP_SKIPFRAME,
         g_param_spec_enum ("skip-frame", "Skip frames",
             "Which types of frames to skip during decoding",
@@ -385,6 +390,15 @@ gst_ffmpegdec_class_init (GstFFMpegDecClass * klass)
             "Crop images to the display region",
             DEFAULT_CROP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 #endif
+
+    caps = klass->in_plugin->capabilities;
+    if (caps & (CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS)) {
+      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, DEFAULT_MAX_THREADS,
+              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+    }
   }
 
   gstelement_class->change_state = gst_ffmpegdec_change_state;
@@ -428,6 +442,7 @@ gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec)
   ffmpegdec->do_padding = DEFAULT_DO_PADDING;
   ffmpegdec->debug_mv = DEFAULT_DEBUG_MV;
   ffmpegdec->crop = DEFAULT_CROP;
+  ffmpegdec->max_threads = DEFAULT_MAX_THREADS;
 
   ffmpegdec->format.video.par_n = -1;
   ffmpegdec->format.video.fps_n = -1;
@@ -849,6 +864,11 @@ gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
    * supports it) */
   ffmpegdec->context->debug_mv = ffmpegdec->debug_mv;
 
+  if (ffmpegdec->max_threads == 0)
+    ffmpegdec->context->thread_count = gst_ffmpeg_auto_max_threads ();
+  else
+    ffmpegdec->context->thread_count = ffmpegdec->max_threads;
+
   /* open codec - we don't select an output pix_fmt yet,
    * simply because we don't know! We only get it
    * during playback... */
@@ -2794,6 +2814,9 @@ gst_ffmpegdec_set_property (GObject * object,
     case PROP_CROP:
       ffmpegdec->crop = g_value_get_boolean (value);
       break;
+    case PROP_MAX_THREADS:
+      ffmpegdec->max_threads = g_value_get_int (value);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -2825,6 +2848,9 @@ gst_ffmpegdec_get_property (GObject * object,
     case PROP_CROP:
       g_value_set_boolean (value, ffmpegdec->crop);
       break;
+    case PROP_MAX_THREADS:
+      g_value_set_int (value, ffmpegdec->max_threads);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
index 89a564e..d039914 100644 (file)
 #include "config.h"
 #endif
 #include "gstffmpegutils.h"
+#include <unistd.h>
+#ifdef __APPLE__
+#include <sys/sysctl.h>
+#endif
 
 G_CONST_RETURN gchar *
 gst_ffmpeg_get_codecid_longname (enum CodecID codec_id)
@@ -443,3 +447,37 @@ new_aligned_buffer (gint size, GstCaps * caps)
 
   return buf;
 }
+
+int
+gst_ffmpeg_auto_max_threads (void)
+{
+  static gsize n_threads = 0;
+  if (g_once_init_enter (&n_threads)) {
+    int n = 1;
+#if defined(_WIN32)
+    {
+      const char *s = getenv ("NUMBER_OF_PROCESSORS");
+      if (s) {
+        n = atoi (s);
+      }
+    }
+#elif defined(__APPLE__)
+    {
+      int mib[] = { CTL_HW, HW_NCPU };
+      size_t dataSize = sizeof (int);
+
+      if (sysctl (mib, 2, &n_threads, &dataSize, NULL, 0)) {
+        n = 1;
+      }
+    }
+#else
+    n = sysconf (_SC_NPROCESSORS_CONF);
+#endif
+    if (n < 1)
+      n = 1;
+
+    g_once_init_leave (&n_threads, n);
+  }
+
+  return (int) (n_threads);
+}
index a75ed01..4b713de 100644 (file)
@@ -80,6 +80,8 @@ gst_ffmpeg_time_gst_to_ff (guint64 time, AVRational base)
 void 
 gst_ffmpeg_init_pix_fmt_info(void);
 
+int
+gst_ffmpeg_auto_max_threads(void);
 
 G_CONST_RETURN gchar *
 gst_ffmpeg_get_codecid_longname (enum CodecID codec_id);