diff --git a/src/lib/clapper/clapper-cache-private.h b/src/lib/clapper/clapper-cache-private.h index 66c41ab4..a8af7324 100644 --- a/src/lib/clapper/clapper-cache-private.h +++ b/src/lib/clapper/clapper-cache-private.h @@ -27,6 +27,9 @@ G_BEGIN_DECLS G_GNUC_INTERNAL void clapper_cache_initialize (void); +G_GNUC_INTERNAL +gboolean clapper_cache_is_disabled (void); + G_GNUC_INTERNAL GMappedFile * clapper_cache_open (const gchar *filename, const gchar **data, GError **error); @@ -39,12 +42,18 @@ gint clapper_cache_read_int (const gchar **data); G_GNUC_INTERNAL guint clapper_cache_read_uint (const gchar **data); +G_GNUC_INTERNAL +gint64 clapper_cache_read_int64 (const gchar **data); + G_GNUC_INTERNAL gdouble clapper_cache_read_double (const gchar **data); G_GNUC_INTERNAL const gchar * clapper_cache_read_string (const gchar **data); +G_GNUC_INTERNAL +const guint8 * clapper_cache_read_data (const gchar **data, gsize *size); + G_GNUC_INTERNAL GType clapper_cache_read_enum (const gchar **data); @@ -69,12 +78,18 @@ void clapper_cache_store_int (GByteArray *bytes, gint val); G_GNUC_INTERNAL void clapper_cache_store_uint (GByteArray *bytes, guint val); +G_GNUC_INTERNAL +void clapper_cache_store_int64 (GByteArray *bytes, gint64 val); + G_GNUC_INTERNAL void clapper_cache_store_double (GByteArray *bytes, gdouble val); G_GNUC_INTERNAL void clapper_cache_store_string (GByteArray *bytes, const gchar *val); +G_GNUC_INTERNAL +void clapper_cache_store_data (GByteArray *bytes, const guint8 *val, gsize val_size); + G_GNUC_INTERNAL void clapper_cache_store_enum (GByteArray *bytes, GType enum_type); diff --git a/src/lib/clapper/clapper-cache.c b/src/lib/clapper/clapper-cache.c index efd21902..30774800 100644 --- a/src/lib/clapper/clapper-cache.c +++ b/src/lib/clapper/clapper-cache.c @@ -45,6 +45,12 @@ clapper_cache_initialize (void) } } +gboolean +clapper_cache_is_disabled (void) +{ + return cache_disabled; +} + GMappedFile * clapper_cache_open (const gchar *filename, const gchar **data, GError **error) { @@ -111,6 +117,15 @@ clapper_cache_read_uint (const gchar **data) return val; } +inline gint64 +clapper_cache_read_int64 (const gchar **data) +{ + gint64 val = *(const gint64 *) *data; + *data += sizeof (gint64); + + return val; +} + inline gdouble clapper_cache_read_double (const gchar **data) { @@ -134,6 +149,22 @@ clapper_cache_read_string (const gchar **data) return str; } +inline const guint8 * +clapper_cache_read_data (const gchar **data, gsize *size) +{ + const guint8 *val = NULL; + + *size = *(const gsize *) *data; + *data += sizeof (gsize); + + if (G_LIKELY (*size > 0)) { + val = (const guint8 *) *data; + *data += *size; + } + + return val; +} + inline GType clapper_cache_read_enum (const gchar **data) { @@ -332,6 +363,12 @@ clapper_cache_store_uint (GByteArray *bytes, guint val) g_byte_array_append (bytes, (const guint8 *) &val, sizeof (guint)); } +inline void +clapper_cache_store_int64 (GByteArray *bytes, gint64 val) +{ + g_byte_array_append (bytes, (const guint8 *) &val, sizeof (gint64)); +} + inline void clapper_cache_store_double (GByteArray *bytes, gdouble val) { @@ -349,6 +386,14 @@ clapper_cache_store_string (GByteArray *bytes, const gchar *val) g_byte_array_append (bytes, (const guint8 *) val, strlen (val) + 1); } +inline void +clapper_cache_store_data (GByteArray *bytes, const guint8 *val, gsize val_size) +{ + g_byte_array_append (bytes, (const guint8 *) &val_size, sizeof (gsize)); + if (G_LIKELY (val_size > 0)) + g_byte_array_append (bytes, val, val_size); +} + inline void clapper_cache_store_enum (GByteArray *bytes, GType enum_type) { diff --git a/src/lib/clapper/clapper-enhancer-proxy-private.h b/src/lib/clapper/clapper-enhancer-proxy-private.h index 144a9c2d..fb1ff659 100644 --- a/src/lib/clapper/clapper-enhancer-proxy-private.h +++ b/src/lib/clapper/clapper-enhancer-proxy-private.h @@ -21,6 +21,7 @@ #include #include +#include #include "clapper-enhancer-proxy.h" @@ -45,6 +46,9 @@ G_GNUC_INTERNAL GObject * clapper_enhancer_proxy_get_peas_info (ClapperEnhancerProxy *proxy); G_GNUC_INTERNAL -void clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *proxy, GObject *enhancer); +GstStructure * clapper_enhancer_proxy_make_current_config (ClapperEnhancerProxy *proxy); + +G_GNUC_INTERNAL +void clapper_enhancer_proxy_apply_config_to_enhancer (ClapperEnhancerProxy *proxy, const GstStructure *config, GObject *enhancer); G_END_DECLS diff --git a/src/lib/clapper/clapper-enhancer-proxy.c b/src/lib/clapper/clapper-enhancer-proxy.c index 8371cdd9..4c1ee7a7 100644 --- a/src/lib/clapper/clapper-enhancer-proxy.c +++ b/src/lib/clapper/clapper-enhancer-proxy.c @@ -507,15 +507,18 @@ _apply_config_cb (GQuark field_id, const GValue *value, GObject *enhancer) return TRUE; } -void -clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *self, GObject *enhancer) +/* + * clapper_enhancer_proxy_make_current_config: + * + * Returns: (transfer full) (nullable): Current merged global and local config as #GstStructure. + */ +GstStructure * +clapper_enhancer_proxy_make_current_config (ClapperEnhancerProxy *self) { GSettings *settings = clapper_enhancer_proxy_get_settings (self); GstStructure *merged_config = NULL; guint i; - GST_DEBUG_OBJECT (self, "Applying config to enhancer"); - /* Lock here to ensure consistent local config */ GST_OBJECT_LOCK (self); @@ -587,13 +590,14 @@ clapper_enhancer_proxy_apply_current_config_to_enhancer (ClapperEnhancerProxy *s g_clear_object (&settings); - /* Nothing if no configurable properties - * or all have default values */ - if (merged_config) { - gst_structure_foreach (merged_config, (GstStructureForeachFunc) _apply_config_cb, enhancer); - gst_structure_free (merged_config); - } + return merged_config; +} +void +clapper_enhancer_proxy_apply_config_to_enhancer (ClapperEnhancerProxy *self, const GstStructure *config, GObject *enhancer) +{ + GST_DEBUG_OBJECT (self, "Applying config to enhancer"); + gst_structure_foreach (config, (GstStructureForeachFunc) _apply_config_cb, enhancer); GST_DEBUG_OBJECT (self, "Enhancer config applied"); } diff --git a/src/lib/clapper/clapper-harvest-private.h b/src/lib/clapper/clapper-harvest-private.h index e363b69f..6146abb2 100644 --- a/src/lib/clapper/clapper-harvest-private.h +++ b/src/lib/clapper/clapper-harvest-private.h @@ -23,6 +23,7 @@ #include #include "clapper-harvest.h" +#include "clapper-enhancer-proxy.h" G_BEGIN_DECLS @@ -32,4 +33,10 @@ ClapperHarvest * clapper_harvest_new (void); G_GNUC_INTERNAL gboolean clapper_harvest_unpack (ClapperHarvest *harvest, GstBuffer **buffer, gsize *buf_size, GstCaps **caps, GstTagList **tags, GstToc **toc, GstStructure **headers); +G_GNUC_INTERNAL +gboolean clapper_harvest_fill_from_cache (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy, const GstStructure *config, GUri *uri); + +G_GNUC_INTERNAL +void clapper_harvest_export_to_cache (ClapperHarvest *harvest, ClapperEnhancerProxy *proxy, const GstStructure *config, GUri *uri); + G_END_DECLS diff --git a/src/lib/clapper/clapper-harvest.c b/src/lib/clapper/clapper-harvest.c index 4c0d603a..641fd32d 100644 --- a/src/lib/clapper/clapper-harvest.c +++ b/src/lib/clapper/clapper-harvest.c @@ -31,7 +31,11 @@ * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2867 */ +#include "config.h" + #include "clapper-harvest-private.h" +#include "clapper-cache-private.h" +#include "clapper-utils.h" #define GST_CAT_DEFAULT clapper_harvest_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -50,6 +54,8 @@ struct _ClapperHarvest guint16 n_chapters; guint16 n_tracks; + + gint64 exp_epoch; }; #define parent_class clapper_harvest_parent_class @@ -119,6 +125,302 @@ clapper_harvest_unpack (ClapperHarvest *self, return TRUE; } +/* Custom implementation due to the lack of TOC serialization in GStreamer */ +static void +_harvest_fill_toc_from_cache (ClapperHarvest *self, const gchar **data) +{ + guint i, n_entries; + + n_entries = clapper_cache_read_uint (data); + for (i = 0; i < n_entries; ++i) { + guint j, n_subentries; + + n_subentries = clapper_cache_read_uint (data); + for (j = 0; j < n_subentries; ++j) { + GstTocEntryType type; + const gchar *title; + gdouble start, end; + + type = (GstTocEntryType) clapper_cache_read_int (data); + title = clapper_cache_read_string (data); + start = clapper_cache_read_double (data); + end = clapper_cache_read_double (data); + + clapper_harvest_toc_add (self, type, title, start, end); + } + } +} + +static void +_harvest_store_toc_to_cache (ClapperHarvest *self, GByteArray *bytes) +{ + GList *list = NULL, *el; + guint n_entries = 0; + + if (self->toc) { + list = gst_toc_get_entries (self->toc); + n_entries = g_list_length (list); + } + clapper_cache_store_uint (bytes, n_entries); + + for (el = list; el; el = g_list_next (el)) { + const GstTocEntry *entry = (const GstTocEntry *) el->data; + GList *subentries, *sub_el; + guint n_subentries; + + subentries = gst_toc_entry_get_sub_entries (entry); + n_subentries = g_list_length (subentries); + + clapper_cache_store_uint (bytes, n_subentries); + + for (sub_el = subentries; sub_el; sub_el = g_list_next (sub_el)) { + const GstTocEntry *subentry = (const GstTocEntry *) sub_el->data; + GstTagList *tags; + gint64 start = 0, end = 0; + gdouble start_dbl, end_dbl; + const gchar *title = NULL; + + clapper_cache_store_int (bytes, (gint) gst_toc_entry_get_entry_type (subentry)); + + if ((tags = gst_toc_entry_get_tags (subentry))) + gst_tag_list_peek_string_index (tags, GST_TAG_TITLE, 0, &title); + + clapper_cache_store_string (bytes, title); + + gst_toc_entry_get_start_stop_times (subentry, &start, &end); + start_dbl = ((gdouble) start) / GST_SECOND; + end_dbl = (end >= 0) ? ((gdouble) end) / GST_SECOND : -1; + + clapper_cache_store_double (bytes, start_dbl); + clapper_cache_store_double (bytes, end_dbl); + } + } +} + +static inline gchar * +_build_cache_filename (ClapperEnhancerProxy *proxy, GUri *uri) +{ + gchar *uri_str = g_uri_to_string (uri); + gchar name[15]; + + g_snprintf (name, sizeof (name), "%u.bin", g_str_hash (uri_str)); + g_free (uri_str); + + return g_build_filename (g_get_user_cache_dir (), CLAPPER_API_NAME, + "enhancers", clapper_enhancer_proxy_get_module_name (proxy), + "harvests", name, NULL); +} + +/* NOTE: On failure, this function must not modify harvest! */ +gboolean +clapper_harvest_fill_from_cache (ClapperHarvest *self, ClapperEnhancerProxy *proxy, + const GstStructure *config, GUri *uri) +{ + GMappedFile *mapped_file; + GstStructure *config_cached = NULL; + GError *error = NULL; + gchar *filename; + const gchar *data, *read_str; + const guint8 *buf_data; + guint8 *buf_copy; + gsize buf_size; + gint64 epoch_cached, epoch_now = 0; + gdouble exp_seconds; + gboolean changed, read_ok = FALSE; + + filename = _build_cache_filename (proxy, uri); + GST_DEBUG_OBJECT (self, "Importing harvest from cache file: \"%s\"", filename); + mapped_file = clapper_cache_open (filename, &data, &error); + g_free (filename); + + if (!mapped_file) { + /* No error if cache disabled or version mismatch */ + if (error) { + if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) + GST_DEBUG_OBJECT (self, "No cached harvest found"); + else + GST_ERROR_OBJECT (self, "Could not use cached harvest, reason: %s", error->message); + + g_error_free (error); + } + + return FALSE; + } + + /* Plugin version check */ + if (g_strcmp0 (clapper_cache_read_string (&data), + clapper_enhancer_proxy_get_version (proxy)) != 0) + goto finish; // no error printing here + + if (G_LIKELY ((epoch_cached = clapper_cache_read_int64 (&data)) > 0)) { + GDateTime *date = g_date_time_new_now_utc (); + epoch_now = g_date_time_to_unix (date); + g_date_time_unref (date); + } + + /* Check if expired */ + if ((exp_seconds = (gdouble) (epoch_cached - epoch_now)) <= 0) { + GST_DEBUG_OBJECT (self, "Cached harvest expired"); // expiration is not an error + goto finish; + } + GST_DEBUG_OBJECT (self, "Cached harvest expiration in %" CLAPPER_TIME_FORMAT, + CLAPPER_TIME_ARGS (exp_seconds)); + + /* Read last used config to generate cache data */ + if ((read_str = clapper_cache_read_string (&data))) + config_cached = gst_structure_from_string (read_str, NULL); + + /* Compare used config when cache was generated to the current one */ + changed = (config_cached && config) + ? !gst_structure_is_equal (config_cached, config) + : (config_cached != config); + + gst_clear_structure (&config_cached); + + if (changed) { + GST_DEBUG_OBJECT (self, "Enhancer config differs from the last time"); + goto finish; + } + + /* Read media type */ + read_str = clapper_cache_read_string (&data); + if (G_UNLIKELY (read_str == NULL)) { + GST_ERROR_OBJECT (self, "Could not read media type from cache file"); + goto finish; + } + + /* Read buffer data */ + buf_data = clapper_cache_read_data (&data, &buf_size); + if (G_UNLIKELY (buf_data == NULL)) { + GST_ERROR_OBJECT (self, "Could not read buffer data from cache"); + goto finish; + } + + /* Fill harvest */ + buf_copy = g_memdup2 (buf_data, buf_size); + if (!clapper_harvest_fill (self, read_str, buf_copy, buf_size)) + goto finish; + + /* Read tags */ + read_str = clapper_cache_read_string (&data); + if (read_str && (self->tags = gst_tag_list_new_from_string (read_str))) { + GST_LOG_OBJECT (self, "Read %s", read_str); + gst_tag_list_set_scope (self->tags, GST_TAG_SCOPE_GLOBAL); + } + + /* Read TOC */ + _harvest_fill_toc_from_cache (self, &data); + + /* Read headers */ + read_str = clapper_cache_read_string (&data); + if (read_str && (self->headers = gst_structure_from_string (read_str, NULL))) + GST_LOG_OBJECT (self, "Read %s", read_str); + + read_ok = TRUE; + +finish: + g_mapped_file_unref (mapped_file); + + if (!read_ok) + return FALSE; + + GST_DEBUG_OBJECT (self, "Filled harvest from cache"); + return TRUE; +} + +void +clapper_harvest_export_to_cache (ClapperHarvest *self, ClapperEnhancerProxy *proxy, + const GstStructure *config, GUri *uri) +{ + GByteArray *bytes; + const GstStructure *caps_structure; + gchar *filename, *temp_str = NULL; + gboolean data_ok = TRUE; + + /* No caching if no expiration date set */ + if (self->exp_epoch <= 0) + return; + + /* Might happen if extractor extract function implementation + * returns %TRUE without filling harvest properly */ + if (G_UNLIKELY (self->caps == NULL || self->buffer == NULL)) + return; // no data to cache + + bytes = clapper_cache_create (); + + /* If cache disabled */ + if (G_UNLIKELY (bytes == NULL)) + return; + + filename = _build_cache_filename (proxy, uri); + GST_DEBUG_OBJECT (self, "Exporting harvest to cache file: \"%s\"", filename); + + /* Store enhancer version that generated harvest */ + clapper_cache_store_string (bytes, clapper_enhancer_proxy_get_version (proxy)); + + /* Store expiration date */ + clapper_cache_store_int64 (bytes, self->exp_epoch); + + /* Store config used to generate harvest */ + if (config) + temp_str = gst_structure_to_string (config); + clapper_cache_store_string (bytes, temp_str); // NULL when no config + g_clear_pointer (&temp_str, g_free); + + /* Store media type */ + caps_structure = gst_caps_get_structure (self->caps, 0); + if (G_LIKELY (caps_structure != NULL)) { + clapper_cache_store_string (bytes, gst_structure_get_name (caps_structure)); + } else { + GST_ERROR_OBJECT (self, "Cannot cache empty caps"); + data_ok = FALSE; + } + + if (G_LIKELY (data_ok)) { + GstMemory *mem; + GstMapInfo map_info; + + /* Store buffer data */ + mem = gst_buffer_peek_memory (self->buffer, 0); + if (G_LIKELY (gst_memory_map (mem, &map_info, GST_MAP_READ))) { + clapper_cache_store_data (bytes, map_info.data, map_info.size); + gst_memory_unmap (mem, &map_info); + } else { + GST_ERROR_OBJECT (self, "Could not map harvest buffer for reading"); + data_ok = FALSE; + } + } + + if (G_LIKELY (data_ok)) { + GError *error = NULL; + + /* Store tags */ + if (self->tags) + temp_str = gst_tag_list_to_string (self->tags); + clapper_cache_store_string (bytes, temp_str); + g_clear_pointer (&temp_str, g_free); + + /* Store TOC */ + _harvest_store_toc_to_cache (self, bytes); + + /* Store headers */ + if (self->headers) + temp_str = gst_structure_to_string (self->headers); + clapper_cache_store_string (bytes, temp_str); + g_clear_pointer (&temp_str, g_free); + + if (clapper_cache_write (filename, bytes, &error)) { + GST_DEBUG_OBJECT (self, "Successfully exported harvest to cache file"); + } else if (error) { + GST_ERROR_OBJECT (self, "Could not cache harvest, reason: %s", error->message); + g_error_free (error); + } + } + + g_free (filename); + g_byte_array_free (bytes, TRUE); +} + /** * clapper_harvest_fill: * @harvest: a #ClapperHarvest @@ -155,7 +457,7 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da return FALSE; } - if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_DEBUG) { + if (gst_debug_category_get_threshold (GST_CAT_DEFAULT) >= GST_LEVEL_LOG) { gboolean is_printable = (strcmp (media_type, "application/dash+xml") == 0) || (strcmp (media_type, "application/x-hls") == 0) || (strcmp (media_type, "text/uri-list") == 0); @@ -166,7 +468,7 @@ clapper_harvest_fill (ClapperHarvest *self, const gchar *media_type, gpointer da data_str = g_new0 (gchar, size + 1); memcpy (data_str, data, size); - GST_DEBUG_OBJECT (self, "Filled with data:\n%s", data_str); + GST_LOG_OBJECT (self, "Filled with data:\n%s", data_str); g_free (data_str); } @@ -328,7 +630,7 @@ clapper_harvest_toc_add (ClapperHarvest *self, GstTocEntryType type, g_snprintf (edition, sizeof (edition), "0%i", type); g_snprintf (id, sizeof (id), "%s.%" G_GUINT16_FORMAT, id_prefix, nth_entry); - GST_DEBUG_OBJECT (self, "Inserting TOC %s: \"%s\"" + GST_LOG_OBJECT (self, "Inserting TOC %s: \"%s\"" " (%" G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ")", id, title, start_time, end_time); @@ -380,7 +682,7 @@ clapper_harvest_headers_set (ClapperHarvest *self, const gchar *key, ...) while (key != NULL) { const gchar *val = va_arg (args, const gchar *); - GST_DEBUG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, val); + GST_LOG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, val); gst_structure_set (self->headers, key, G_TYPE_STRING, val, NULL); key = va_arg (args, const gchar *); } @@ -409,10 +711,70 @@ clapper_harvest_headers_set_value (ClapperHarvest *self, const gchar *key, const _ensure_headers (self); - GST_DEBUG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, g_value_get_string (value)); + GST_LOG_OBJECT (self, "Set header, \"%s\": \"%s\"", key, g_value_get_string (value)); gst_structure_set_value (self->headers, key, value); } +/** + * clapper_harvest_set_expiration_date_utc: + * @harvest: a #ClapperHarvest + * @date_utc: a #GDateTime in UTC time + * + * Set date in UTC time until harvested content is expected + * to stay alive. + * + * This is used for harvest caching, so next time user requests to + * play the same URI, recently harvested data can be reused without + * the need to run [vfunc@Clapper.Extractable.extract] again. + * + * Since: 0.10 + */ +void +clapper_harvest_set_expiration_date_utc (ClapperHarvest *self, GDateTime *date_utc) +{ + g_return_if_fail (CLAPPER_IS_HARVEST (self)); + g_return_if_fail (date_utc != NULL); + + self->exp_epoch = g_date_time_to_unix (date_utc); + GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); +} + +/** + * clapper_harvest_set_expiration_seconds: + * @harvest: a #ClapperHarvest + * @seconds: time in seconds until expiration + * + * Set amount of seconds for how long harvested content is + * expected to stay alive. + * + * Alternative function to [method@Clapper.Harvest.set_expiration_date_utc], + * but takes time as number in seconds from now. + * + * It is safe to pass zero or negative number to this function in + * case when calculating time manually and it already expired. + * + * Since: 0.10 + */ +void +clapper_harvest_set_expiration_seconds (ClapperHarvest *self, gdouble seconds) +{ + GDateTime *date, *date_epoch; + + g_return_if_fail (CLAPPER_IS_HARVEST (self)); + + GST_LOG_OBJECT (self, "Set expiration in %" CLAPPER_TIME_FORMAT, + CLAPPER_TIME_ARGS (seconds)); + + date = g_date_time_new_now_utc (); + date_epoch = g_date_time_add_seconds (date, seconds); + g_date_time_unref (date); + + self->exp_epoch = g_date_time_to_unix (date_epoch); + g_date_time_unref (date_epoch); + + GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); +} + static void clapper_harvest_init (ClapperHarvest *self) { diff --git a/src/lib/clapper/clapper-harvest.h b/src/lib/clapper/clapper-harvest.h index 54cd0ad3..aceb2dce 100644 --- a/src/lib/clapper/clapper-harvest.h +++ b/src/lib/clapper/clapper-harvest.h @@ -61,4 +61,10 @@ void clapper_harvest_headers_set (ClapperHarvest *harvest, const gchar *key, ... CLAPPER_API void clapper_harvest_headers_set_value (ClapperHarvest *harvest, const gchar *key, const GValue *value); +CLAPPER_API +void clapper_harvest_set_expiration_date_utc (ClapperHarvest *harvest, GDateTime *date_utc); + +CLAPPER_API +void clapper_harvest_set_expiration_seconds (ClapperHarvest *harvest, gdouble seconds); + G_END_DECLS diff --git a/src/lib/clapper/clapper-playbin-bus.c b/src/lib/clapper/clapper-playbin-bus.c index cc42992f..faa815cc 100644 --- a/src/lib/clapper/clapper-playbin-bus.c +++ b/src/lib/clapper/clapper-playbin-bus.c @@ -29,12 +29,7 @@ #include "clapper-timeline-private.h" #include "clapper-stream-private.h" #include "clapper-stream-list-private.h" - -#include "clapper-functionalities-availability.h" - -#if CLAPPER_WITH_ENHANCERS_LOADER -#include "gst/clapper-enhancer-src-private.h" -#endif +#include "gst/clapper-extractable-src-private.h" #define GST_CAT_DEFAULT clapper_playbin_bus_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -875,7 +870,6 @@ _handle_tag_msg (GstMessage *msg, ClapperPlayer *player) { GstObject *src = GST_MESSAGE_SRC (msg); GstTagList *tags = NULL; - gboolean from_enhancer_src; /* Tag messages should only be posted by sink elements */ if (G_UNLIKELY (!src)) @@ -886,14 +880,8 @@ _handle_tag_msg (GstMessage *msg, ClapperPlayer *player) GST_LOG_OBJECT (player, "Got tags from element: %s: %" GST_PTR_FORMAT, GST_OBJECT_NAME (src), tags); -#if CLAPPER_WITH_ENHANCERS_LOADER - from_enhancer_src = CLAPPER_IS_ENHANCER_SRC (src); -#else - from_enhancer_src = FALSE; -#endif - - /* ClapperEnhancerSrc determines tags before stream start */ - if (from_enhancer_src) { + /* ClapperExtractableSrc determines tags before stream start */ + if (CLAPPER_IS_EXTRACTABLE_SRC (src)) { if (player->pending_tags) { gst_tag_list_unref (player->pending_tags); } @@ -910,7 +898,7 @@ _handle_toc_msg (GstMessage *msg, ClapperPlayer *player) { GstObject *src = GST_MESSAGE_SRC (msg); GstToc *toc = NULL; - gboolean from_enhancer_src, updated = FALSE; + gboolean updated = FALSE; /* TOC messages should only be posted by sink elements */ if (G_UNLIKELY (!src)) @@ -923,14 +911,8 @@ _handle_toc_msg (GstMessage *msg, ClapperPlayer *player) " from element: %s, updated: %s", toc, GST_OBJECT_NAME (src), (updated) ? "yes" : "no"); -#if CLAPPER_WITH_ENHANCERS_LOADER - from_enhancer_src = CLAPPER_IS_ENHANCER_SRC (src); -#else - from_enhancer_src = FALSE; -#endif - - /* ClapperEnhancerSrc determines TOC before stream start */ - if (from_enhancer_src) { + /* ClapperExtractableSrc determines TOC before stream start */ + if (CLAPPER_IS_EXTRACTABLE_SRC (src)) { if (player->pending_toc) { gst_toc_unref (player->pending_toc); } diff --git a/src/lib/clapper/clapper-player.c b/src/lib/clapper/clapper-player.c index 6bad15f8..de1efcc0 100644 --- a/src/lib/clapper/clapper-player.c +++ b/src/lib/clapper/clapper-player.c @@ -816,7 +816,7 @@ _element_setup_cb (GstElement *playbin, GstElement *element, ClapperPlayer *self factory_name = g_intern_static_string (GST_OBJECT_NAME (factory)); GST_INFO_OBJECT (self, "Element setup: %s", factory_name); - if (factory_name == g_intern_static_string ("clapperenhancersrc")) { + if (factory_name == g_intern_static_string ("clapperextractablesrc")) { g_object_set (element, "enhancer-proxies", self->enhancer_proxies, NULL); diff --git a/src/lib/clapper/gst/clapper-enhancer-director.c b/src/lib/clapper/gst/clapper-enhancer-director.c index 2664faf9..d044ed13 100644 --- a/src/lib/clapper/gst/clapper-enhancer-director.c +++ b/src/lib/clapper/gst/clapper-enhancer-director.c @@ -17,12 +17,17 @@ * Boston, MA 02110-1301, USA. */ +#include "config.h" + #include #include "clapper-enhancer-director-private.h" +#include "../clapper-basic-functions.h" +#include "../clapper-cache-private.h" #include "../clapper-enhancer-proxy-private.h" #include "../clapper-extractable-private.h" #include "../clapper-harvest-private.h" +#include "../clapper-utils.h" #include "../../shared/clapper-shared-utils-private.h" #include "../clapper-functionalities-availability.h" @@ -31,6 +36,8 @@ #include "../clapper-enhancers-loader-private.h" #endif +#define CLEANUP_INTERVAL 10800 // once every 3 hours + #define GST_CAT_DEFAULT clapper_enhancer_director_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -57,7 +64,7 @@ clapper_enhancer_director_extract_in_thread (ClapperEnhancerDirectorData *data) ClapperEnhancerDirector *self = data->director; GList *el; ClapperHarvest *harvest = NULL; - gboolean success = FALSE, cached = FALSE; + gboolean success = FALSE; GST_DEBUG_OBJECT (self, "Extraction start"); @@ -65,22 +72,22 @@ clapper_enhancer_director_extract_in_thread (ClapperEnhancerDirectorData *data) if (g_cancellable_is_cancelled (data->cancellable)) return NULL; - /* TODO: Cache lookup */ - if (cached) { - // if ((success = fill harvest from cache)) - // return harvest; - } - GST_DEBUG_OBJECT (self, "Enhancer proxies for URI: %u", g_list_length (data->filtered_proxies)); for (el = data->filtered_proxies; el; el = g_list_next (el)) { ClapperEnhancerProxy *proxy = CLAPPER_ENHANCER_PROXY_CAST (el->data); ClapperExtractable *extractable = NULL; + GstStructure *config; - /* Check just before extract */ - if (g_cancellable_is_cancelled (data->cancellable)) + harvest = clapper_harvest_new (); // fresh harvest for each iteration + config = clapper_enhancer_proxy_make_current_config (proxy); + + if ((success = clapper_harvest_fill_from_cache (harvest, proxy, config, data->uri)) + || g_cancellable_is_cancelled (data->cancellable)) { // Check before extract + gst_clear_structure (&config); break; + } #if CLAPPER_WITH_ENHANCERS_LOADER extractable = CLAPPER_EXTRACTABLE_CAST ( @@ -88,32 +95,32 @@ clapper_enhancer_director_extract_in_thread (ClapperEnhancerDirectorData *data) #endif if (G_LIKELY (extractable != NULL)) { - clapper_enhancer_proxy_apply_current_config_to_enhancer (proxy, (GObject *) extractable); - - harvest = clapper_harvest_new (); // fresh harvest for each extractable + clapper_enhancer_proxy_apply_config_to_enhancer (proxy, config, (GObject *) extractable); success = clapper_extractable_extract (extractable, data->uri, harvest, data->cancellable, data->error); gst_object_unref (extractable); - /* We are done with extractable, but keep its harvest */ - if (success) - break; + /* We are done with extractable, but keep harvest and try to cache it */ + if (success) { + if (!g_cancellable_is_cancelled (data->cancellable)) + clapper_harvest_export_to_cache (harvest, proxy, config, data->uri); - /* Clear harvest and try again with next enhancer */ - g_clear_object (&harvest); + gst_clear_structure (&config); + break; + } } + + /* Cleanup to try again with next enhancer */ + g_clear_object (&harvest); + gst_clear_structure (&config); } - /* Cancelled during extract */ + /* Cancelled during extraction or exporting to cache */ if (g_cancellable_is_cancelled (data->cancellable)) success = FALSE; - if (success) { - if (!cached) { - /* TODO: Store in cache */ - } - } else { + if (!success) { gst_clear_object (&harvest); /* Ensure we have some error set on failure */ @@ -131,6 +138,171 @@ clapper_enhancer_director_extract_in_thread (ClapperEnhancerDirectorData *data) return harvest; } +static inline void +_harvest_delete_if_expired (ClapperEnhancerDirector *self, + ClapperEnhancerProxy *proxy, GFile *file, const gint64 epoch_now) +{ + GMappedFile *mapped_file; + const gchar *data; + gchar *filename; + GError *error = NULL; + gboolean delete = TRUE; + + filename = g_file_get_path (file); + + if ((mapped_file = clapper_cache_open (filename, &data, &error))) { + /* Do not delete if versions match and not expired */ + if (g_strcmp0 (clapper_cache_read_string (&data), + clapper_enhancer_proxy_get_version (proxy)) == 0 + && clapper_cache_read_int64 (&data) > epoch_now) { + delete = FALSE; + } + g_mapped_file_unref (mapped_file); + } else if (error) { + if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) + GST_DEBUG_OBJECT (self, "No cached harvest file found"); + else + GST_ERROR_OBJECT (self, "Could not read cached harvest file, reason: %s", error->message); + + g_clear_error (&error); + } + + if (delete) { + if (G_LIKELY (g_file_delete (file, NULL, &error))) { + GST_TRACE_OBJECT (self, "Deleted cached harvest: \"%s\"", filename); + } else { + GST_ERROR_OBJECT (self, "Could not delete harvest: \"%s\", reason: %s", + filename, GST_STR_NULL (error->message)); + g_error_free (error); + } + } + + g_free (filename); +} + +static inline void +_cache_proxy_harvests_cleanup (ClapperEnhancerDirector *self, + ClapperEnhancerProxy *proxy, const gint64 epoch_now) +{ + GFile *dir; + GFileEnumerator *dir_enum; + GError *error = NULL; + + dir = g_file_new_build_filename (g_get_user_cache_dir (), CLAPPER_API_NAME, + "enhancers", clapper_enhancer_proxy_get_module_name (proxy), + "harvests", NULL); + + if ((dir_enum = g_file_enumerate_children (dir, + G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_TYPE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error))) { + while (TRUE) { + GFileInfo *info = NULL; + GFile *child = NULL; + + if (!g_file_enumerator_iterate (dir_enum, &info, + &child, NULL, &error) || !info) + break; + + if (G_LIKELY (g_file_info_get_file_type (info) == G_FILE_TYPE_REGULAR + && g_str_has_suffix (g_file_info_get_name (info), ".bin"))) + _harvest_delete_if_expired (self, proxy, child, epoch_now); + } + + g_object_unref (dir_enum); + } + + if (error) { + if (error->domain != G_IO_ERROR || error->code != G_IO_ERROR_NOT_FOUND) { + gchar *path = g_file_get_path (dir); + + GST_ERROR_OBJECT (self, "Could not cleanup in dir: \"%s\", reason: %s", + path, GST_STR_NULL (error->message)); + g_free (path); + } + + g_error_free (error); + } + + g_object_unref (dir); +} + +static gboolean +_cache_cleanup_func (ClapperEnhancerDirector *self) +{ + GMappedFile *mapped_file; + GDateTime *date; + GError *error = NULL; + gchar *filename; + const gchar *data; + gint64 since_cleanup, epoch_now, epoch_last = 0; + + date = g_date_time_new_now_utc (); + epoch_now = g_date_time_to_unix (date); + g_date_time_unref (date); + + filename = g_build_filename (g_get_user_cache_dir (), CLAPPER_API_NAME, + "enhancers", "cleanup.bin", NULL); + + if ((mapped_file = clapper_cache_open (filename, &data, &error))) { + epoch_last = clapper_cache_read_int64 (&data); + g_mapped_file_unref (mapped_file); + } else if (error) { + if (error->domain == G_FILE_ERROR && error->code == G_FILE_ERROR_NOENT) + GST_DEBUG_OBJECT (self, "No cache cleanup file found"); + else + GST_ERROR_OBJECT (self, "Could not read cache cleanup file, reason: %s", error->message); + + g_clear_error (&error); + } + + since_cleanup = epoch_now - epoch_last; + + if (since_cleanup >= CLEANUP_INTERVAL) { + ClapperEnhancerProxyList *proxies; + guint i, n_proxies; + GByteArray *bytes; + + GST_TRACE_OBJECT (self, "Time for cache cleanup, last was %" + CLAPPER_TIME_FORMAT " ago", CLAPPER_TIME_ARGS (since_cleanup)); + + /* Start with writing to cache cleanup time, + * so other directors can find it earlier */ + if ((bytes = clapper_cache_create ())) { + clapper_cache_store_int64 (bytes, epoch_now); + + if (clapper_cache_write (filename, bytes, &error)) { + GST_TRACE_OBJECT (self, "Written data to cache cleanup file, cleanup time: %" + G_GINT64_FORMAT, epoch_now); + } else if (error) { + GST_ERROR_OBJECT (self, "Could not write cache cleanup data, reason: %s", error->message); + g_clear_error (&error); + } + + g_byte_array_free (bytes, TRUE); + } + + /* Now do cleanup */ + proxies = clapper_get_global_enhancer_proxies (); + n_proxies = clapper_enhancer_proxy_list_get_n_proxies (proxies); + + for (i = 0; i < n_proxies; ++i) { + ClapperEnhancerProxy *proxy = clapper_enhancer_proxy_list_peek_proxy (proxies, i); + + if (!clapper_enhancer_proxy_target_has_interface (proxy, CLAPPER_TYPE_EXTRACTABLE)) + continue; + + _cache_proxy_harvests_cleanup (self, proxy, epoch_now); + } + } else { + GST_TRACE_OBJECT (self, "No cache cleanup yet, last was %" + CLAPPER_TIME_FORMAT " ago", CLAPPER_TIME_ARGS (since_cleanup)); + } + + g_free (filename); + + return G_SOURCE_REMOVE; +} + /* * clapper_enhancer_director_new: * @@ -153,6 +325,8 @@ clapper_enhancer_director_extract (ClapperEnhancerDirector *self, GCancellable *cancellable, GError **error) { ClapperEnhancerDirectorData *data = g_new (ClapperEnhancerDirectorData, 1); + GMainContext *context; + ClapperHarvest *harvest; data->director = self; data->filtered_proxies = filtered_proxies; @@ -160,10 +334,18 @@ clapper_enhancer_director_extract (ClapperEnhancerDirector *self, data->cancellable = cancellable; data->error = error; - return CLAPPER_HARVEST_CAST (clapper_shared_utils_context_invoke_sync_full ( - clapper_threaded_object_get_context (CLAPPER_THREADED_OBJECT_CAST (self)), + context = clapper_threaded_object_get_context (CLAPPER_THREADED_OBJECT_CAST (self)); + + harvest = CLAPPER_HARVEST_CAST (clapper_shared_utils_context_invoke_sync_full (context, (GThreadFunc) clapper_enhancer_director_extract_in_thread, data, (GDestroyNotify) g_free)); + + /* Run cleanup async. Since context belongs to "self", do not ref it. + * This ensures clean shutdown with thread stop function called. */ + if (!g_cancellable_is_cancelled (cancellable) && !clapper_cache_is_disabled ()) + g_main_context_invoke (context, (GSourceFunc) _cache_cleanup_func, self); + + return harvest; } static void diff --git a/src/lib/clapper/gst/clapper-enhancer-src-private.h b/src/lib/clapper/gst/clapper-extractable-src-private.h similarity index 76% rename from src/lib/clapper/gst/clapper-enhancer-src-private.h rename to src/lib/clapper/gst/clapper-extractable-src-private.h index 4e313d74..908b591a 100644 --- a/src/lib/clapper/gst/clapper-enhancer-src-private.h +++ b/src/lib/clapper/gst/clapper-extractable-src-private.h @@ -26,12 +26,12 @@ G_BEGIN_DECLS -#define CLAPPER_TYPE_ENHANCER_SRC (clapper_enhancer_src_get_type()) -#define CLAPPER_ENHANCER_SRC_CAST(obj) ((ClapperEnhancerSrc *)(obj)) +#define CLAPPER_TYPE_EXTRACTABLE_SRC (clapper_extractable_src_get_type()) +#define CLAPPER_EXTRACTABLE_SRC_CAST(obj) ((ClapperExtractableSrc *)(obj)) G_GNUC_INTERNAL -G_DECLARE_FINAL_TYPE (ClapperEnhancerSrc, clapper_enhancer_src, CLAPPER, ENHANCER_SRC, GstPushSrc) +G_DECLARE_FINAL_TYPE (ClapperExtractableSrc, clapper_extractable_src, CLAPPER, EXTRACTABLE_SRC, GstPushSrc) -GST_ELEMENT_REGISTER_DECLARE (clapperenhancersrc) +GST_ELEMENT_REGISTER_DECLARE (clapperextractablesrc) G_END_DECLS diff --git a/src/lib/clapper/gst/clapper-enhancer-src.c b/src/lib/clapper/gst/clapper-extractable-src.c similarity index 77% rename from src/lib/clapper/gst/clapper-enhancer-src.c rename to src/lib/clapper/gst/clapper-extractable-src.c index 9297e622..d11cc8b3 100644 --- a/src/lib/clapper/gst/clapper-enhancer-src.c +++ b/src/lib/clapper/gst/clapper-extractable-src.c @@ -19,7 +19,7 @@ #include "config.h" -#include "clapper-enhancer-src-private.h" +#include "clapper-extractable-src-private.h" #include "clapper-enhancer-director-private.h" #include "../clapper-basic-functions.h" @@ -28,13 +28,13 @@ #include "../clapper-extractable.h" #include "../clapper-harvest-private.h" -#define GST_CAT_DEFAULT clapper_enhancer_src_debug +#define GST_CAT_DEFAULT clapper_extractable_src_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define CHECK_SCHEME_IS_HTTPS(scheme) (g_str_has_prefix (scheme, "http") \ && (scheme[4] == '\0' || (scheme[4] == 's' && scheme[5] == '\0'))) -struct _ClapperEnhancerSrc +struct _ClapperExtractableSrc { GstPushSrc parent; @@ -65,7 +65,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS_ANY); static GstURIType -clapper_enhancer_src_uri_handler_get_type (GType type) +clapper_extractable_src_uri_handler_get_type (GType type) { return GST_URI_SRC; } @@ -145,19 +145,19 @@ _host_fixup (const gchar *host) } /* - * _enhancer_check_for_uri: - * @self: a #ClapperEnhancerSrc + * _extractable_check_for_uri: + * @self: a #ClapperExtractableSrc * @uri: a #GUri * - * Check whether there is at least one enhancer for @uri in global list. + * Check whether there is at least one extractable enhancer for @uri in global list. * This is used to reject URI early, thus making playbin choose different * source element. It uses global list, since at this stage element is not * yet placed within pipeline, so it cannot get proxies from player. * - * Returns: whether at least one enhancer advertises support for given URI. + * Returns: whether at least one extractable enhancer advertises support for given URI. */ static gboolean -_enhancer_check_for_uri (ClapperEnhancerSrc *self, GUri *uri) +_extractable_check_for_uri (ClapperExtractableSrc *self, GUri *uri) { ClapperEnhancerProxyList *proxies = clapper_get_global_enhancer_proxies (); gboolean is_https; @@ -168,7 +168,7 @@ _enhancer_check_for_uri (ClapperEnhancerSrc *self, GUri *uri) if (host) host = _host_fixup (host); - GST_INFO_OBJECT (self, "Enhancer check, scheme: \"%s\", host: \"%s\"", + GST_INFO_OBJECT (self, "Extractable check, scheme: \"%s\", host: \"%s\"", scheme, GST_STR_NULL (host)); /* Whether "http(s)" scheme is used */ @@ -191,8 +191,8 @@ _enhancer_check_for_uri (ClapperEnhancerSrc *self, GUri *uri) } /* - * _filter_enhancers_for_uri: - * @self: a #ClapperEnhancerSrc + * _filter_extractables_for_uri: + * @self: a #ClapperExtractableSrc * @proxies: a #ClapperEnhancerProxyList * @uri: a #GUri * @@ -202,7 +202,7 @@ _enhancer_check_for_uri (ClapperEnhancerSrc *self, GUri *uri) * Returns: (transfer full): A sublist in the form of #GList with proxies. */ static GList * -_filter_enhancers_for_uri (ClapperEnhancerSrc *self, +_filter_extractables_for_uri (ClapperExtractableSrc *self, ClapperEnhancerProxyList *proxies, GUri *uri) { GList *sublist = NULL; @@ -214,7 +214,7 @@ _filter_enhancers_for_uri (ClapperEnhancerSrc *self, if (host) host = _host_fixup (host); - GST_INFO_OBJECT (self, "Enhancer filter, scheme: \"%s\", host: \"%s\"", + GST_INFO_OBJECT (self, "Extractable filter, scheme: \"%s\", host: \"%s\"", scheme, GST_STR_NULL (host)); /* Whether "http(s)" scheme is used */ @@ -239,7 +239,7 @@ _filter_enhancers_for_uri (ClapperEnhancerSrc *self, } static const gchar *const * -clapper_enhancer_src_uri_handler_get_protocols (GType type) +clapper_extractable_src_uri_handler_get_protocols (GType type) { static GOnce schemes_once = G_ONCE_INIT; @@ -248,9 +248,9 @@ clapper_enhancer_src_uri_handler_get_protocols (GType type) } static gchar * -clapper_enhancer_src_uri_handler_get_uri (GstURIHandler *handler) +clapper_extractable_src_uri_handler_get_uri (GstURIHandler *handler) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (handler); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (handler); gchar *uri; GST_OBJECT_LOCK (self); @@ -261,10 +261,10 @@ clapper_enhancer_src_uri_handler_get_uri (GstURIHandler *handler) } static gboolean -clapper_enhancer_src_uri_handler_set_uri (GstURIHandler *handler, +clapper_extractable_src_uri_handler_set_uri (GstURIHandler *handler, const gchar *uri, GError **error) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (handler); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (handler); GUri *guri; const gchar *const *protocols; gboolean supported = FALSE; @@ -300,7 +300,7 @@ clapper_enhancer_src_uri_handler_set_uri (GstURIHandler *handler, return FALSE; } - if (!_enhancer_check_for_uri (self, guri)) { + if (!_extractable_check_for_uri (self, guri)) { g_set_error (error, GST_URI_ERROR, GST_URI_ERROR_BAD_URI, "None of the available enhancers can handle this URI"); g_uri_unref (guri); @@ -324,22 +324,22 @@ clapper_enhancer_src_uri_handler_set_uri (GstURIHandler *handler, static void _uri_handler_iface_init (GstURIHandlerInterface *iface) { - iface->get_type = clapper_enhancer_src_uri_handler_get_type; - iface->get_protocols = clapper_enhancer_src_uri_handler_get_protocols; - iface->get_uri = clapper_enhancer_src_uri_handler_get_uri; - iface->set_uri = clapper_enhancer_src_uri_handler_set_uri; + iface->get_type = clapper_extractable_src_uri_handler_get_type; + iface->get_protocols = clapper_extractable_src_uri_handler_get_protocols; + iface->get_uri = clapper_extractable_src_uri_handler_get_uri; + iface->set_uri = clapper_extractable_src_uri_handler_set_uri; } -#define parent_class clapper_enhancer_src_parent_class -G_DEFINE_TYPE_WITH_CODE (ClapperEnhancerSrc, clapper_enhancer_src, GST_TYPE_PUSH_SRC, +#define parent_class clapper_extractable_src_parent_class +G_DEFINE_TYPE_WITH_CODE (ClapperExtractableSrc, clapper_extractable_src, GST_TYPE_PUSH_SRC, G_IMPLEMENT_INTERFACE (GST_TYPE_URI_HANDLER, _uri_handler_iface_init)); -GST_ELEMENT_REGISTER_DEFINE (clapperenhancersrc, "clapperenhancersrc", - 512, CLAPPER_TYPE_ENHANCER_SRC); +GST_ELEMENT_REGISTER_DEFINE (clapperextractablesrc, "clapperextractablesrc", + 512, CLAPPER_TYPE_EXTRACTABLE_SRC); static gboolean -clapper_enhancer_src_start (GstBaseSrc *base_src) +clapper_extractable_src_start (GstBaseSrc *base_src) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (base_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (base_src); gboolean can_start; GST_DEBUG_OBJECT (self, "Start"); @@ -358,9 +358,9 @@ clapper_enhancer_src_start (GstBaseSrc *base_src) } static gboolean -clapper_enhancer_src_stop (GstBaseSrc *base_src) +clapper_extractable_src_stop (GstBaseSrc *base_src) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (base_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (base_src); GST_DEBUG_OBJECT (self, "Stop"); @@ -370,9 +370,9 @@ clapper_enhancer_src_stop (GstBaseSrc *base_src) } static gboolean -clapper_enhancer_src_get_size (GstBaseSrc *base_src, guint64 *size) +clapper_extractable_src_get_size (GstBaseSrc *base_src, guint64 *size) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (base_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (base_src); if (self->buf_size > 0) { *size = self->buf_size; @@ -383,15 +383,15 @@ clapper_enhancer_src_get_size (GstBaseSrc *base_src, guint64 *size) } static gboolean -clapper_enhancer_src_is_seekable (GstBaseSrc *base_src) +clapper_extractable_src_is_seekable (GstBaseSrc *base_src) { return FALSE; } static gboolean -clapper_enhancer_src_unlock (GstBaseSrc *base_src) +clapper_extractable_src_unlock (GstBaseSrc *base_src) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (base_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (base_src); GST_LOG_OBJECT (self, "Cancel triggered"); g_cancellable_cancel (self->cancellable); @@ -400,9 +400,9 @@ clapper_enhancer_src_unlock (GstBaseSrc *base_src) } static gboolean -clapper_enhancer_src_unlock_stop (GstBaseSrc *base_src) +clapper_extractable_src_unlock_stop (GstBaseSrc *base_src) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (base_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (base_src); GST_LOG_OBJECT (self, "Resetting cancellable"); @@ -414,7 +414,7 @@ clapper_enhancer_src_unlock_stop (GstBaseSrc *base_src) /* Pushes tags, toc and request headers downstream (all transfer full) */ static void -_push_events (ClapperEnhancerSrc *self, GstTagList *tags, GstToc *toc, +_push_events (ClapperExtractableSrc *self, GstTagList *tags, GstToc *toc, GstStructure *headers, gboolean updated) { GstEvent *event; @@ -462,9 +462,9 @@ _push_events (ClapperEnhancerSrc *self, GstTagList *tags, GstToc *toc, } static GstFlowReturn -clapper_enhancer_src_create (GstPushSrc *push_src, GstBuffer **outbuf) +clapper_extractable_src_create (GstPushSrc *push_src, GstBuffer **outbuf) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (push_src); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (push_src); ClapperEnhancerProxyList *proxies; GList *filtered_proxies; GUri *guri; @@ -502,7 +502,7 @@ clapper_enhancer_src_create (GstPushSrc *push_src, GstBuffer **outbuf) GST_OBJECT_UNLOCK (self); - filtered_proxies = _filter_enhancers_for_uri (self, proxies, guri); + filtered_proxies = _filter_extractables_for_uri (self, proxies, guri); gst_object_unref (proxies); harvest = clapper_enhancer_director_extract (self->director, @@ -554,7 +554,7 @@ _handle_uri_query (GstQuery *query) } static gboolean -clapper_enhancer_src_query (GstBaseSrc *base_src, GstQuery *query) +clapper_extractable_src_query (GstBaseSrc *base_src, GstQuery *query) { gboolean ret = FALSE; @@ -573,7 +573,7 @@ clapper_enhancer_src_query (GstBaseSrc *base_src, GstQuery *query) } static void -clapper_enhancer_src_set_enhancer_proxies (ClapperEnhancerSrc *self, +clapper_extractable_src_set_enhancer_proxies (ClapperExtractableSrc *self, ClapperEnhancerProxyList *enhancer_proxies) { GST_OBJECT_LOCK (self); @@ -583,15 +583,15 @@ clapper_enhancer_src_set_enhancer_proxies (ClapperEnhancerSrc *self, } static void -clapper_enhancer_src_init (ClapperEnhancerSrc *self) +clapper_extractable_src_init (ClapperExtractableSrc *self) { self->cancellable = g_cancellable_new (); } static void -clapper_enhancer_src_dispose (GObject *object) +clapper_extractable_src_dispose (GObject *object) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (object); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (object); GST_OBJECT_LOCK (self); g_clear_object (&self->director); @@ -601,9 +601,9 @@ clapper_enhancer_src_dispose (GObject *object) } static void -clapper_enhancer_src_finalize (GObject *object) +clapper_extractable_src_finalize (GObject *object) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (object); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (object); GST_TRACE_OBJECT (self, "Finalize"); @@ -616,10 +616,10 @@ clapper_enhancer_src_finalize (GObject *object) } static void -clapper_enhancer_src_set_property (GObject *object, guint prop_id, +clapper_extractable_src_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (object); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (object); switch (prop_id) { case PROP_URI:{ @@ -632,7 +632,7 @@ clapper_enhancer_src_set_property (GObject *object, guint prop_id, break; } case PROP_ENHANCER_PROXIES: - clapper_enhancer_src_set_enhancer_proxies (self, g_value_get_object (value)); + clapper_extractable_src_set_enhancer_proxies (self, g_value_get_object (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -641,10 +641,10 @@ clapper_enhancer_src_set_property (GObject *object, guint prop_id, } static void -clapper_enhancer_src_get_property (GObject *object, guint prop_id, +clapper_extractable_src_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - ClapperEnhancerSrc *self = CLAPPER_ENHANCER_SRC_CAST (object); + ClapperExtractableSrc *self = CLAPPER_EXTRACTABLE_SRC_CAST (object); switch (prop_id) { case PROP_URI: @@ -657,30 +657,30 @@ clapper_enhancer_src_get_property (GObject *object, guint prop_id, } static void -clapper_enhancer_src_class_init (ClapperEnhancerSrcClass *klass) +clapper_extractable_src_class_init (ClapperExtractableSrcClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; GstElementClass *gstelement_class = (GstElementClass *) klass; GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; GstPushSrcClass *gstpushsrc_class = (GstPushSrcClass *) klass; - GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperenhancersrc", 0, - "Clapper Enhancer Source"); + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperextractablesrc", 0, + "Clapper Extractable Source"); - gobject_class->set_property = clapper_enhancer_src_set_property; - gobject_class->get_property = clapper_enhancer_src_get_property; - gobject_class->dispose = clapper_enhancer_src_dispose; - gobject_class->finalize = clapper_enhancer_src_finalize; + gobject_class->set_property = clapper_extractable_src_set_property; + gobject_class->get_property = clapper_extractable_src_get_property; + gobject_class->dispose = clapper_extractable_src_dispose; + gobject_class->finalize = clapper_extractable_src_finalize; - gstbasesrc_class->start = clapper_enhancer_src_start; - gstbasesrc_class->stop = clapper_enhancer_src_stop; - gstbasesrc_class->get_size = clapper_enhancer_src_get_size; - gstbasesrc_class->is_seekable = clapper_enhancer_src_is_seekable; - gstbasesrc_class->unlock = clapper_enhancer_src_unlock; - gstbasesrc_class->unlock_stop = clapper_enhancer_src_unlock_stop; - gstbasesrc_class->query = clapper_enhancer_src_query; + gstbasesrc_class->start = clapper_extractable_src_start; + gstbasesrc_class->stop = clapper_extractable_src_stop; + gstbasesrc_class->get_size = clapper_extractable_src_get_size; + gstbasesrc_class->is_seekable = clapper_extractable_src_is_seekable; + gstbasesrc_class->unlock = clapper_extractable_src_unlock; + gstbasesrc_class->unlock_stop = clapper_extractable_src_unlock_stop; + gstbasesrc_class->query = clapper_extractable_src_query; - gstpushsrc_class->create = clapper_enhancer_src_create; + gstpushsrc_class->create = clapper_extractable_src_create; param_specs[PROP_URI] = g_param_spec_string ("uri", "URI", "URI", NULL, @@ -694,7 +694,7 @@ clapper_enhancer_src_class_init (ClapperEnhancerSrcClass *klass) gst_element_class_add_static_pad_template (gstelement_class, &src_template); - gst_element_class_set_static_metadata (gstelement_class, "Clapper Enhancer Source", - "Source", "A source element that uses Clapper Enhancers to produce data", + gst_element_class_set_static_metadata (gstelement_class, "Clapper Extractable Source", + "Source", "A source element that uses Clapper extractable enhancers to produce data", "Rafał Dzięgiel "); } diff --git a/src/lib/clapper/gst/clapper-plugin.c b/src/lib/clapper/gst/clapper-plugin.c index 7a758722..2bb2a7d9 100644 --- a/src/lib/clapper/gst/clapper-plugin.c +++ b/src/lib/clapper/gst/clapper-plugin.c @@ -27,7 +27,7 @@ #include "../clapper-extractable.h" #include "clapper-plugin-private.h" -#include "clapper-enhancer-src-private.h" +#include "clapper-extractable-src-private.h" #include "clapper-uri-list-demux-private.h" /* @@ -67,7 +67,7 @@ clapper_gst_plugin_init (GstPlugin *plugin) /* Avoid registering an URI handler without schemes */ if (clapper_gst_plugin_has_enhancers (global_proxies, CLAPPER_TYPE_EXTRACTABLE)) - res |= GST_ELEMENT_REGISTER (clapperenhancersrc, plugin); + res |= GST_ELEMENT_REGISTER (clapperextractablesrc, plugin); res |= GST_ELEMENT_REGISTER (clapperurilistdemux, plugin); diff --git a/src/lib/clapper/gst/clapper-uri-list-demux.c b/src/lib/clapper/gst/clapper-uri-list-demux.c index 1c7e3ea5..64e00695 100644 --- a/src/lib/clapper/gst/clapper-uri-list-demux.c +++ b/src/lib/clapper/gst/clapper-uri-list-demux.c @@ -193,7 +193,7 @@ _feature_filter (GstPluginFeature *feature, const gchar *search_proto) feature_name = gst_plugin_feature_get_name (feature); /* Do not loop endlessly creating our own sources and demuxers */ - if (!feature_name || strcmp (feature_name, "clapperenhancersrc") == 0) + if (!feature_name || strcmp (feature_name, "clapperextractablesrc") == 0) return FALSE; protocols = gst_element_factory_get_uri_protocols (factory); diff --git a/src/lib/clapper/meson.build b/src/lib/clapper/meson.build index b48695b3..8e2d1afd 100644 --- a/src/lib/clapper/meson.build +++ b/src/lib/clapper/meson.build @@ -155,7 +155,7 @@ clapper_sources = [ 'clapper-utils.c', 'clapper-video-stream.c', 'gst/clapper-plugin.c', - 'gst/clapper-enhancer-src.c', + 'gst/clapper-extractable-src.c', 'gst/clapper-enhancer-director.c', 'gst/clapper-uri-list-demux.c', '../shared/clapper-shared-utils.c',