Merge pull request #553 from Rafostar/harvest-caching

clapper: Implement harvest caching
This commit is contained in:
Rafał Dzięgiel
2025-05-21 19:49:26 +02:00
committed by GitHub
15 changed files with 753 additions and 146 deletions

View File

@@ -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);

View File

@@ -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)
{

View File

@@ -21,6 +21,7 @@
#include <glib.h>
#include <glib-object.h>
#include <gst/gst.h>
#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

View File

@@ -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");
}

View File

@@ -23,6 +23,7 @@
#include <gst/tag/tag.h>
#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

View File

@@ -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)
{

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -17,12 +17,17 @@
* Boston, MA 02110-1301, USA.
*/
#include "config.h"
#include <gst/gst.h>
#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

View File

@@ -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

View File

@@ -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 <rafostar.github@gmail.com>");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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',