From b30d53d8ce5c8b0c97eae69de49a57fa1703085d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sun, 18 May 2025 14:21:19 +0200 Subject: [PATCH 1/4] clapper: Add ability to set harvest expiration date --- src/lib/clapper/clapper-harvest.c | 61 +++++++++++++++++++++++++++++++ src/lib/clapper/clapper-harvest.h | 6 +++ 2 files changed, 67 insertions(+) diff --git a/src/lib/clapper/clapper-harvest.c b/src/lib/clapper/clapper-harvest.c index 4c0d603a..0dc70e81 100644 --- a/src/lib/clapper/clapper-harvest.c +++ b/src/lib/clapper/clapper-harvest.c @@ -50,6 +50,8 @@ struct _ClapperHarvest guint16 n_chapters; guint16 n_tracks; + + gint64 exp_epoch; }; #define parent_class clapper_harvest_parent_class @@ -413,6 +415,65 @@ clapper_harvest_headers_set_value (ClapperHarvest *self, const gchar *key, const 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_DEBUG_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_DEBUG_OBJECT (self, "Set expiration seconds: %.3lfs", 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_DEBUG_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 From 6ddb53252ad513d94e77b5c8f9d8bc01c5a4d30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sun, 18 May 2025 20:24:08 +0200 Subject: [PATCH 2/4] clapper: Implement harvest caching Using recently added local cache functionality, store harvests that have expiration date. With this, next time the same URI is selected for playback we can read it from cache, skipping loading of any enhancer plugins and doing network requests. This also works nicely with Clapper discoverer feature. Making queued items be fetched and cached ahead of playback. --- src/lib/clapper/clapper-cache-private.h | 12 + src/lib/clapper/clapper-cache.c | 39 +++ .../clapper/clapper-enhancer-proxy-private.h | 6 +- src/lib/clapper/clapper-enhancer-proxy.c | 24 +- src/lib/clapper/clapper-harvest-private.h | 7 + src/lib/clapper/clapper-harvest.c | 317 +++++++++++++++++- .../clapper/gst/clapper-enhancer-director.c | 46 +-- 7 files changed, 409 insertions(+), 42 deletions(-) diff --git a/src/lib/clapper/clapper-cache-private.h b/src/lib/clapper/clapper-cache-private.h index 66c41ab4..6ace1a96 100644 --- a/src/lib/clapper/clapper-cache-private.h +++ b/src/lib/clapper/clapper-cache-private.h @@ -39,12 +39,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 +75,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..2028c366 100644 --- a/src/lib/clapper/clapper-cache.c +++ b/src/lib/clapper/clapper-cache.c @@ -111,6 +111,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 +143,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 +357,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 +380,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 0dc70e81..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); @@ -121,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 @@ -157,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); @@ -168,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); } @@ -330,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); @@ -382,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 *); } @@ -411,7 +711,7 @@ 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); } @@ -436,7 +736,7 @@ clapper_harvest_set_expiration_date_utc (ClapperHarvest *self, GDateTime *date_u g_return_if_fail (date_utc != NULL); self->exp_epoch = g_date_time_to_unix (date_utc); - GST_DEBUG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); + GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); } /** @@ -462,7 +762,8 @@ clapper_harvest_set_expiration_seconds (ClapperHarvest *self, gdouble seconds) g_return_if_fail (CLAPPER_IS_HARVEST (self)); - GST_DEBUG_OBJECT (self, "Set expiration seconds: %.3lfs", seconds); + 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); @@ -471,7 +772,7 @@ clapper_harvest_set_expiration_seconds (ClapperHarvest *self, gdouble seconds) self->exp_epoch = g_date_time_to_unix (date_epoch); g_date_time_unref (date_epoch); - GST_DEBUG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); + GST_LOG_OBJECT (self, "Expiration epoch: %" G_GINT64_FORMAT, self->exp_epoch); } static void diff --git a/src/lib/clapper/gst/clapper-enhancer-director.c b/src/lib/clapper/gst/clapper-enhancer-director.c index 2664faf9..dc68b67a 100644 --- a/src/lib/clapper/gst/clapper-enhancer-director.c +++ b/src/lib/clapper/gst/clapper-enhancer-director.c @@ -57,7 +57,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 +65,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 +88,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 */ From ca15f4760a6a459ea03dd5c1141dfa6c52a074b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Wed, 21 May 2025 14:15:34 +0200 Subject: [PATCH 3/4] clapper: Cleanup cached harvests periodically --- src/lib/clapper/clapper-cache-private.h | 3 + src/lib/clapper/clapper-cache.c | 6 + .../clapper/gst/clapper-enhancer-director.c | 186 +++++++++++++++++- ...te.h => clapper-extractable-src-private.h} | 0 ...hancer-src.c => clapper-extractable-src.c} | 0 5 files changed, 193 insertions(+), 2 deletions(-) rename src/lib/clapper/gst/{clapper-enhancer-src-private.h => clapper-extractable-src-private.h} (100%) rename src/lib/clapper/gst/{clapper-enhancer-src.c => clapper-extractable-src.c} (100%) diff --git a/src/lib/clapper/clapper-cache-private.h b/src/lib/clapper/clapper-cache-private.h index 6ace1a96..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); diff --git a/src/lib/clapper/clapper-cache.c b/src/lib/clapper/clapper-cache.c index 2028c366..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) { diff --git a/src/lib/clapper/gst/clapper-enhancer-director.c b/src/lib/clapper/gst/clapper-enhancer-director.c index dc68b67a..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); @@ -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 100% rename from src/lib/clapper/gst/clapper-enhancer-src-private.h rename to src/lib/clapper/gst/clapper-extractable-src-private.h diff --git a/src/lib/clapper/gst/clapper-enhancer-src.c b/src/lib/clapper/gst/clapper-extractable-src.c similarity index 100% rename from src/lib/clapper/gst/clapper-enhancer-src.c rename to src/lib/clapper/gst/clapper-extractable-src.c From 9fd87dbbb9c5e10f40de0cde2cc9f430dc6804c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Wed, 21 May 2025 17:41:46 +0200 Subject: [PATCH 4/4] clapper: Rename enhancersrc -> extractablesrc Since this element only uses enhancers of "extractable" type --- src/lib/clapper/clapper-playbin-bus.c | 30 +--- src/lib/clapper/clapper-player.c | 2 +- .../gst/clapper-extractable-src-private.h | 8 +- src/lib/clapper/gst/clapper-extractable-src.c | 144 +++++++++--------- src/lib/clapper/gst/clapper-plugin.c | 4 +- src/lib/clapper/gst/clapper-uri-list-demux.c | 2 +- src/lib/clapper/meson.build | 2 +- 7 files changed, 87 insertions(+), 105 deletions(-) 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 c84a10fd..7eda6a39 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-extractable-src-private.h b/src/lib/clapper/gst/clapper-extractable-src-private.h index 4e313d74..908b591a 100644 --- a/src/lib/clapper/gst/clapper-extractable-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-extractable-src.c b/src/lib/clapper/gst/clapper-extractable-src.c index 9297e622..d11cc8b3 100644 --- a/src/lib/clapper/gst/clapper-extractable-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',