mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
transcoder: Port to a GstBus API instead
Following the move made by GstPlayer in: https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/35 Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1840>
This commit is contained in:
parent
7cf6e4d8f2
commit
984f0c2d2f
7 changed files with 735 additions and 512 deletions
30
gst-libs/gst/transcoder/gsttranscoder-message-private.h
Normal file
30
gst-libs/gst/transcoder/gsttranscoder-message-private.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2020 Stephan Hesse <stephan@emliri.com>
|
||||
* Copyright (C) 2020 Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define GST_TRANSCODER_MESSAGE_DATA "gst-transcoder-message-data"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_TYPE "transcoder-message-type"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_POSITION "position"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_DURATION "duration"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_ERROR "error"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_WARNING "warning"
|
||||
#define GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS "issue-details"
|
342
gst-libs/gst/transcoder/gsttranscoder-signal-adapter.c
Normal file
342
gst-libs/gst/transcoder/gsttranscoder-signal-adapter.c
Normal file
|
@ -0,0 +1,342 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2019-2020 Stephan Hesse <stephan@emliri.com>
|
||||
* Copyright (C) 2020 Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gsttranscoder.h"
|
||||
#include "gsttranscoder-signal-adapter.h"
|
||||
|
||||
#include "gsttranscoder-message-private.h"
|
||||
|
||||
#include <gst/gst.h>
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_transcoder_signal_adapter_debug);
|
||||
#define GST_CAT_DEFAULT gst_transcoder_signal_adapter_debug
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_POSITION_UPDATED,
|
||||
SIGNAL_DURATION_CHANGED,
|
||||
SIGNAL_DONE,
|
||||
SIGNAL_ERROR,
|
||||
SIGNAL_WARNING,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_TRANSCODER,
|
||||
PROP_LAST
|
||||
};
|
||||
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
struct _GstTranscoderSignalAdapter
|
||||
{
|
||||
GObject parent;
|
||||
GstBus *bus;
|
||||
GSource *source;
|
||||
|
||||
GstTranscoder *transcoder;
|
||||
};
|
||||
|
||||
struct _GstTranscoderSignalAdapterClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
#define _do_init \
|
||||
GST_DEBUG_CATEGORY_INIT (gst_transcoder_signal_adapter_debug, "gst-transcoder-signaladapter", \
|
||||
0, "GstTranscoder signal adapter")
|
||||
|
||||
#define parent_class gst_transcoder_signal_adapter_parent_class
|
||||
G_DEFINE_TYPE_WITH_CODE (GstTranscoderSignalAdapter,
|
||||
gst_transcoder_signal_adapter, G_TYPE_OBJECT, _do_init);
|
||||
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_adapter_emit (GstTranscoderSignalAdapter * self,
|
||||
const GstStructure * message_data)
|
||||
{
|
||||
GstTranscoderMessage transcoder_message_type;
|
||||
g_return_if_fail (g_str_equal (gst_structure_get_name (message_data),
|
||||
GST_TRANSCODER_MESSAGE_DATA));
|
||||
|
||||
GST_LOG ("Emitting message %" GST_PTR_FORMAT, message_data);
|
||||
gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_TYPE,
|
||||
GST_TYPE_TRANSCODER_MESSAGE, &transcoder_message_type, NULL);
|
||||
|
||||
switch (transcoder_message_type) {
|
||||
case GST_TRANSCODER_MESSAGE_POSITION_UPDATED:{
|
||||
GstClockTime pos = GST_CLOCK_TIME_NONE;
|
||||
gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_POSITION,
|
||||
GST_TYPE_CLOCK_TIME, &pos, NULL);
|
||||
g_signal_emit (self, signals[SIGNAL_POSITION_UPDATED], 0, pos);
|
||||
break;
|
||||
}
|
||||
case GST_TRANSCODER_MESSAGE_DURATION_CHANGED:{
|
||||
GstClockTime duration = GST_CLOCK_TIME_NONE;
|
||||
gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_DURATION,
|
||||
GST_TYPE_CLOCK_TIME, &duration, NULL);
|
||||
g_signal_emit (self, signals[SIGNAL_DURATION_CHANGED], 0, duration);
|
||||
break;
|
||||
}
|
||||
case GST_TRANSCODER_MESSAGE_DONE:
|
||||
g_signal_emit (self, signals[SIGNAL_DONE], 0);
|
||||
break;
|
||||
case GST_TRANSCODER_MESSAGE_ERROR:{
|
||||
GError *error = NULL;
|
||||
GstStructure *details;
|
||||
|
||||
gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_ERROR,
|
||||
G_TYPE_ERROR, &error, GST_TYPE_STRUCTURE, &details, NULL);
|
||||
g_signal_emit (self, signals[SIGNAL_ERROR], 0, error, details);
|
||||
g_error_free (error);
|
||||
if (details)
|
||||
gst_structure_free (details);
|
||||
break;
|
||||
}
|
||||
case GST_TRANSCODER_MESSAGE_WARNING:{
|
||||
GstStructure *details;
|
||||
GError *error = NULL;
|
||||
|
||||
gst_structure_get (message_data, GST_TRANSCODER_MESSAGE_DATA_WARNING,
|
||||
G_TYPE_ERROR, &error, GST_TYPE_STRUCTURE, &details, NULL);
|
||||
g_signal_emit (self, signals[SIGNAL_WARNING], 0, error, details);
|
||||
g_error_free (error);
|
||||
if (details)
|
||||
gst_structure_free (details);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* callback for the bus-message in-sync handling
|
||||
*/
|
||||
static GstBusSyncReply
|
||||
gst_transcoder_signal_adapter_bus_sync_handler
|
||||
(GstBus * bus, GstMessage * message, gpointer user_data)
|
||||
{
|
||||
GstTranscoderSignalAdapter *self = GST_TRANSCODER_SIGNAL_ADAPTER (user_data);
|
||||
const GstStructure *message_data = gst_message_get_structure (message);
|
||||
gst_transcoder_signal_adapter_emit (self, message_data);
|
||||
gst_message_unref (message);
|
||||
return GST_BUS_DROP;
|
||||
}
|
||||
|
||||
/*
|
||||
* callback for the bus-watch
|
||||
* pre: there is a message on the bus
|
||||
*/
|
||||
static gboolean
|
||||
gst_transcoder_signal_adapter_on_message (GstBus * bus,
|
||||
GstMessage * message, gpointer user_data)
|
||||
{
|
||||
GstTranscoderSignalAdapter *self = GST_TRANSCODER_SIGNAL_ADAPTER (user_data);
|
||||
const GstStructure *message_data = gst_message_get_structure (message);
|
||||
gst_transcoder_signal_adapter_emit (self, message_data);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_signal_adapter_new:
|
||||
* @transcoder: (transfer none): #GstTranscoder instance to emit signals for.
|
||||
* @context: (nullable): A #GMainContext on which the main-loop will process
|
||||
* transcoder bus messages on. Can be NULL (thread-default
|
||||
* context will be used then).
|
||||
*
|
||||
* A bus-watching #GSource will be created and attached to the context. The
|
||||
* attached callback will emit the corresponding signal for the message
|
||||
* received. Matching signals for transcoder messages from the bus will be
|
||||
* emitted by it on the created adapter object.
|
||||
*
|
||||
* Returns: (transfer full)(nullable): A new #GstTranscoderSignalAdapter to
|
||||
* connect signal handlers to.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstTranscoderSignalAdapter *
|
||||
gst_transcoder_signal_adapter_new (GstTranscoder * transcoder,
|
||||
GMainContext * context)
|
||||
{
|
||||
GstTranscoderSignalAdapter *self = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TRANSCODER (transcoder), NULL);
|
||||
|
||||
if (!context) {
|
||||
context = g_main_context_get_thread_default ();
|
||||
}
|
||||
|
||||
self = g_object_new (GST_TYPE_TRANSCODER_SIGNAL_ADAPTER, NULL);
|
||||
self->bus = gst_transcoder_get_message_bus (transcoder);
|
||||
self->source = gst_bus_create_watch (self->bus);
|
||||
|
||||
if (!self->source) {
|
||||
GST_ERROR_OBJECT (transcoder, "Could not create watch.");
|
||||
|
||||
gst_object_unref (self);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g_source_attach (self->source, context);
|
||||
g_source_set_callback (self->source,
|
||||
(GSourceFunc) gst_transcoder_signal_adapter_on_message, self, NULL);
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_signal_adapter_new_sync_emit:
|
||||
* @transcoder: (transfer none): #GstTranscoder instance to emit signals
|
||||
* synchronously for.
|
||||
*
|
||||
* Returns: (transfer full): A new #GstTranscoderSignalAdapter to connect signal
|
||||
* handlers to.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstTranscoderSignalAdapter *
|
||||
gst_transcoder_signal_adapter_new_sync_emit (GstTranscoder * transcoder)
|
||||
{
|
||||
GstBus *bus = NULL;
|
||||
GstTranscoderSignalAdapter *self = NULL;
|
||||
|
||||
g_return_val_if_fail (GST_IS_TRANSCODER (transcoder), NULL);
|
||||
|
||||
bus = gst_transcoder_get_message_bus (transcoder);
|
||||
|
||||
self = g_object_new (GST_TYPE_TRANSCODER_SIGNAL_ADAPTER, NULL);
|
||||
self->bus = bus;
|
||||
gst_bus_set_sync_handler (self->bus,
|
||||
gst_transcoder_signal_adapter_bus_sync_handler, self, NULL);
|
||||
return self;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_adapter_init (GstTranscoderSignalAdapter * self)
|
||||
{
|
||||
self->source = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_adapter_dispose (GObject * object)
|
||||
{
|
||||
GstTranscoderSignalAdapter *self = GST_TRANSCODER_SIGNAL_ADAPTER (object);
|
||||
|
||||
if (self->source) {
|
||||
g_source_destroy (self->source);
|
||||
g_source_unref (self->source);
|
||||
self->source = NULL;
|
||||
}
|
||||
|
||||
gst_clear_object (&self->bus);
|
||||
gst_clear_object (&self->transcoder);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_adapter_get_property (GObject * object, guint prop_id,
|
||||
GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTranscoderSignalAdapter *self = GST_TRANSCODER_SIGNAL_ADAPTER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_TRANSCODER:
|
||||
g_value_set_object (value, self->transcoder);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_adapter_class_init (GstTranscoderSignalAdapterClass *
|
||||
klass)
|
||||
{
|
||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
|
||||
gobject_class->dispose = gst_transcoder_signal_adapter_dispose;
|
||||
gobject_class->get_property = gst_transcoder_signal_adapter_get_property;
|
||||
|
||||
signals[SIGNAL_POSITION_UPDATED] =
|
||||
g_signal_new ("position-updated", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_CLOCK_TIME);
|
||||
|
||||
signals[SIGNAL_DURATION_CHANGED] =
|
||||
g_signal_new ("duration-changed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_CLOCK_TIME);
|
||||
|
||||
signals[SIGNAL_DONE] =
|
||||
g_signal_new ("done", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 0, G_TYPE_INVALID);
|
||||
|
||||
signals[SIGNAL_ERROR] =
|
||||
g_signal_new ("error", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 2, G_TYPE_ERROR, GST_TYPE_STRUCTURE);
|
||||
|
||||
signals[SIGNAL_WARNING] =
|
||||
g_signal_new ("warning", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 2, G_TYPE_ERROR, GST_TYPE_STRUCTURE);
|
||||
|
||||
/**
|
||||
* GstTranscoderSignalAdapter:transcoder:
|
||||
*
|
||||
* The #GstTranscoder tracked by the adapter.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
param_specs[PROP_TRANSCODER] =
|
||||
g_param_spec_object ("transcoder", "Transcoder",
|
||||
"The GstTranscoder @self is tracking", GST_TYPE_TRANSCODER,
|
||||
G_PARAM_READABLE);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_transcoder_signal_adapter_get_transcoder:
|
||||
* @self: The #GstTranscoderSignalAdapter
|
||||
*
|
||||
* Returns: (transfer full): The #GstTranscoder @self is tracking
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstTranscoder *
|
||||
gst_transcoder_signal_adapter_get_transcoder (GstTranscoderSignalAdapter * self)
|
||||
{
|
||||
return gst_object_ref (self->transcoder);
|
||||
}
|
61
gst-libs/gst/transcoder/gsttranscoder-signal-adapter.h
Normal file
61
gst-libs/gst/transcoder/gsttranscoder-signal-adapter.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/* GStreamer
|
||||
*
|
||||
* Copyright (C) 2019-2020 Stephan Hesse <stephan@emliri.com>
|
||||
* Copyright (C) 2020 Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <gst/gst.h>
|
||||
#include <gst/transcoder/gsttranscoder.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
* GstTranscoderSignalAdapter:
|
||||
*
|
||||
* Transforms #GstTranscoder bus messages to signals from the adapter object.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
|
||||
/**
|
||||
* GST_TYPE_TRANSCODER_SIGNAL_ADAPTER:
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
#define GST_TYPE_TRANSCODER_SIGNAL_ADAPTER (gst_transcoder_signal_adapter_get_type ())
|
||||
GST_TRANSCODER_API
|
||||
|
||||
/**
|
||||
* GstTranscoderSignalAdapterClass:
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
G_DECLARE_FINAL_TYPE(GstTranscoderSignalAdapter, gst_transcoder_signal_adapter, GST, TRANSCODER_SIGNAL_ADAPTER, GObject)
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new_sync_emit (GstTranscoder * transcoder);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GstTranscoderSignalAdapter * gst_transcoder_signal_adapter_new (GstTranscoder * transcoder, GMainContext * context);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GstTranscoder * gst_transcoder_signal_adapter_get_transcoder (GstTranscoderSignalAdapter * self);
|
||||
|
||||
|
||||
G_END_DECLS
|
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
|
||||
#include "gsttranscoder.h"
|
||||
#include "gsttranscoder-message-private.h"
|
||||
|
||||
GST_DEBUG_CATEGORY_STATIC (gst_transcoder_debug);
|
||||
#define GST_CAT_DEFAULT gst_transcoder_debug
|
||||
|
@ -52,7 +53,6 @@ gst_transcoder_error_quark (void)
|
|||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_SIGNAL_DISPATCHER,
|
||||
PROP_SRC_URI,
|
||||
PROP_DEST_URI,
|
||||
PROP_PROFILE,
|
||||
|
@ -64,22 +64,10 @@ enum
|
|||
PROP_LAST
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SIGNAL_POSITION_UPDATED,
|
||||
SIGNAL_DURATION_CHANGED,
|
||||
SIGNAL_DONE,
|
||||
SIGNAL_ERROR,
|
||||
SIGNAL_WARNING,
|
||||
SIGNAL_LAST
|
||||
};
|
||||
|
||||
struct _GstTranscoder
|
||||
{
|
||||
GstObject parent;
|
||||
|
||||
GstTranscoderSignalDispatcher *signal_dispatcher;
|
||||
|
||||
GstEncodingProfile *profile;
|
||||
gchar *source_uri;
|
||||
gchar *dest_uri;
|
||||
|
@ -99,6 +87,8 @@ struct _GstTranscoder
|
|||
gint wanted_cpu_usage;
|
||||
|
||||
GstClockTime last_duration;
|
||||
|
||||
GstBus *api_bus;
|
||||
};
|
||||
|
||||
struct _GstTranscoderClass
|
||||
|
@ -106,15 +96,9 @@ struct _GstTranscoderClass
|
|||
GstObjectClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_dispatcher_dispatch (GstTranscoderSignalDispatcher * self,
|
||||
GstTranscoder * transcoder, void (*emitter) (gpointer data), gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
#define parent_class gst_transcoder_parent_class
|
||||
G_DEFINE_TYPE (GstTranscoder, gst_transcoder, GST_TYPE_OBJECT);
|
||||
|
||||
static guint signals[SIGNAL_LAST] = { 0, };
|
||||
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||||
|
||||
static void gst_transcoder_dispose (GObject * object);
|
||||
|
@ -162,6 +146,7 @@ gst_transcoder_init (GstTranscoder * self)
|
|||
|
||||
self->context = g_main_context_new ();
|
||||
self->loop = g_main_loop_new (self->context, FALSE);
|
||||
self->api_bus = gst_bus_new ();
|
||||
self->wanted_cpu_usage = 100;
|
||||
|
||||
self->position_update_interval_ms = DEFAULT_POSITION_UPDATE_INTERVAL_MS;
|
||||
|
@ -180,12 +165,6 @@ gst_transcoder_class_init (GstTranscoderClass * klass)
|
|||
gobject_class->finalize = gst_transcoder_finalize;
|
||||
gobject_class->constructed = gst_transcoder_constructed;
|
||||
|
||||
param_specs[PROP_SIGNAL_DISPATCHER] =
|
||||
g_param_spec_object ("signal-dispatcher",
|
||||
"Signal Dispatcher", "Dispatcher for the signals to e.g. event loops",
|
||||
GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER,
|
||||
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
param_specs[PROP_SRC_URI] =
|
||||
g_param_spec_string ("src-uri", "URI", "Source URI", DEFAULT_URI,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
@ -232,31 +211,6 @@ gst_transcoder_class_init (GstTranscoderClass * klass)
|
|||
DEFAULT_AVOID_REENCODING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class, PROP_LAST, param_specs);
|
||||
|
||||
signals[SIGNAL_POSITION_UPDATED] =
|
||||
g_signal_new ("position-updated", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_CLOCK_TIME);
|
||||
|
||||
signals[SIGNAL_DURATION_CHANGED] =
|
||||
g_signal_new ("duration-changed", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 1, GST_TYPE_CLOCK_TIME);
|
||||
|
||||
signals[SIGNAL_DONE] =
|
||||
g_signal_new ("done", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 0, G_TYPE_INVALID);
|
||||
|
||||
signals[SIGNAL_ERROR] =
|
||||
g_signal_new ("error", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 2, G_TYPE_ERROR, GST_TYPE_STRUCTURE);
|
||||
|
||||
signals[SIGNAL_WARNING] =
|
||||
g_signal_new ("warning", G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS, 0, NULL,
|
||||
NULL, NULL, G_TYPE_NONE, 2, G_TYPE_ERROR, GST_TYPE_STRUCTURE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -292,8 +246,6 @@ gst_transcoder_finalize (GObject * object)
|
|||
|
||||
g_free (self->source_uri);
|
||||
g_free (self->dest_uri);
|
||||
if (self->signal_dispatcher)
|
||||
g_object_unref (self->signal_dispatcher);
|
||||
g_cond_clear (&self->cond);
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
|
@ -329,9 +281,6 @@ gst_transcoder_set_property (GObject * object, guint prop_id,
|
|||
GstTranscoder *self = GST_TRANSCODER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_SIGNAL_DISPATCHER:
|
||||
self->signal_dispatcher = g_value_dup_object (value);
|
||||
break;
|
||||
case PROP_SRC_URI:{
|
||||
GST_OBJECT_LOCK (self);
|
||||
g_free (self->source_uri);
|
||||
|
@ -441,6 +390,34 @@ gst_transcoder_get_property (GObject * object, guint prop_id,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Works same as gst_structure_set to set field/type/value triplets on message data
|
||||
*/
|
||||
static void
|
||||
api_bus_post_message (GstTranscoder * self, GstTranscoderMessage message_type,
|
||||
const gchar * firstfield, ...)
|
||||
{
|
||||
GstStructure *message_data = NULL;
|
||||
GstMessage *msg = NULL;
|
||||
va_list varargs;
|
||||
|
||||
GST_INFO ("Posting API-bus message-type: %s",
|
||||
gst_transcoder_message_get_name (message_type));
|
||||
message_data = gst_structure_new (GST_TRANSCODER_MESSAGE_DATA,
|
||||
GST_TRANSCODER_MESSAGE_DATA_TYPE, GST_TYPE_TRANSCODER_MESSAGE,
|
||||
message_type, NULL);
|
||||
|
||||
va_start (varargs, firstfield);
|
||||
gst_structure_set_valist (message_data, firstfield, varargs);
|
||||
va_end (varargs);
|
||||
|
||||
msg = gst_message_new_custom (GST_MESSAGE_APPLICATION,
|
||||
GST_OBJECT (self), message_data);
|
||||
GST_DEBUG ("Created message with payload: [ %" GST_PTR_FORMAT " ]",
|
||||
message_data);
|
||||
gst_bus_post (self->api_bus, msg);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
main_loop_running_cb (gpointer user_data)
|
||||
{
|
||||
|
@ -455,32 +432,6 @@ main_loop_running_cb (gpointer user_data)
|
|||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstTranscoder *transcoder;
|
||||
GstClockTime position;
|
||||
} PositionUpdatedSignalData;
|
||||
|
||||
static void
|
||||
position_updated_dispatch (gpointer user_data)
|
||||
{
|
||||
PositionUpdatedSignalData *data = user_data;
|
||||
|
||||
if (data->transcoder->target_state >= GST_STATE_PAUSED) {
|
||||
g_signal_emit (data->transcoder, signals[SIGNAL_POSITION_UPDATED], 0,
|
||||
data->position);
|
||||
g_object_notify_by_pspec (G_OBJECT (data->transcoder),
|
||||
param_specs[PROP_POSITION]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
position_updated_signal_data_free (PositionUpdatedSignalData * data)
|
||||
{
|
||||
g_object_unref (data->transcoder);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
tick_cb (gpointer user_data)
|
||||
{
|
||||
|
@ -498,16 +449,9 @@ tick_cb (gpointer user_data)
|
|||
|
||||
GST_LOG_OBJECT (self, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS (position));
|
||||
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_POSITION_UPDATED], 0, NULL, NULL, NULL) != 0) {
|
||||
PositionUpdatedSignalData *data = g_new0 (PositionUpdatedSignalData, 1);
|
||||
|
||||
data->transcoder = g_object_ref (self);
|
||||
data->position = position;
|
||||
gst_transcoder_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
position_updated_dispatch, data,
|
||||
(GDestroyNotify) position_updated_signal_data_free);
|
||||
}
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_POSITION_UPDATED,
|
||||
GST_TRANSCODER_MESSAGE_DATA_POSITION, GST_TYPE_CLOCK_TIME, position,
|
||||
NULL);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
@ -537,58 +481,6 @@ remove_tick_source (GstTranscoder * self)
|
|||
self->tick_source = NULL;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstTranscoder *transcoder;
|
||||
GError *err;
|
||||
GstStructure *details;
|
||||
} IssueSignalData;
|
||||
|
||||
static void
|
||||
error_dispatch (gpointer user_data)
|
||||
{
|
||||
IssueSignalData *data = user_data;
|
||||
|
||||
g_signal_emit (data->transcoder, signals[SIGNAL_ERROR], 0, data->err,
|
||||
data->details);
|
||||
}
|
||||
|
||||
static void
|
||||
free_issue_signal_data (IssueSignalData * data)
|
||||
{
|
||||
g_object_unref (data->transcoder);
|
||||
if (data->details)
|
||||
gst_structure_free (data->details);
|
||||
g_clear_error (&data->err);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_error (GstTranscoder * self, GError * err, const GstStructure * details)
|
||||
{
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_ERROR], 0, NULL, NULL, NULL) != 0) {
|
||||
IssueSignalData *data = g_new0 (IssueSignalData, 1);
|
||||
|
||||
data->transcoder = g_object_ref (self);
|
||||
data->err = g_error_copy (err);
|
||||
if (details)
|
||||
data->details = gst_structure_copy (details);
|
||||
gst_transcoder_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
error_dispatch, data, (GDestroyNotify) free_issue_signal_data);
|
||||
}
|
||||
|
||||
g_error_free (err);
|
||||
|
||||
remove_tick_source (self);
|
||||
|
||||
self->target_state = GST_STATE_NULL;
|
||||
self->current_state = GST_STATE_NULL;
|
||||
self->is_live = FALSE;
|
||||
self->is_eos = FALSE;
|
||||
gst_element_set_state (self->transcodebin, GST_STATE_NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
dump_dot_file (GstTranscoder * self, const gchar * name)
|
||||
{
|
||||
|
@ -602,33 +494,6 @@ dump_dot_file (GstTranscoder * self, const gchar * name)
|
|||
g_free (full_name);
|
||||
}
|
||||
|
||||
static void
|
||||
warning_dispatch (gpointer user_data)
|
||||
{
|
||||
IssueSignalData *data = user_data;
|
||||
|
||||
g_signal_emit (data->transcoder, signals[SIGNAL_WARNING], 0, data->err,
|
||||
data->details);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_warning (GstTranscoder * self, GError * err, const GstStructure * details)
|
||||
{
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_WARNING], 0, NULL, NULL, NULL) != 0) {
|
||||
IssueSignalData *data = g_new0 (IssueSignalData, 1);
|
||||
|
||||
data->transcoder = g_object_ref (self);
|
||||
data->err = g_error_copy (err);
|
||||
if (details)
|
||||
data->details = gst_structure_copy (details);
|
||||
gst_transcoder_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
warning_dispatch, data, (GDestroyNotify) free_issue_signal_data);
|
||||
}
|
||||
|
||||
g_error_free (err);
|
||||
}
|
||||
|
||||
static void
|
||||
error_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
|
||||
{
|
||||
|
@ -654,7 +519,11 @@ error_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
|
|||
"msg-source-element-name", G_TYPE_STRING, "name",
|
||||
"msg-source-type", G_TYPE_GTYPE, G_OBJECT_TYPE (msg->src),
|
||||
"msg-error", G_TYPE_STRING, message, NULL);
|
||||
emit_error (self, g_error_copy (err), details);
|
||||
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR, err,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS, GST_TYPE_STRUCTURE, details,
|
||||
NULL);
|
||||
|
||||
gst_structure_free (details);
|
||||
g_clear_error (&err);
|
||||
|
@ -695,8 +564,13 @@ warning_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
|
|||
transcoder_err =
|
||||
g_error_new_literal (GST_TRANSCODER_ERROR, GST_TRANSCODER_ERROR_FAILED,
|
||||
full_message);
|
||||
emit_warning (self, transcoder_err, details);
|
||||
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_WARNING,
|
||||
GST_TRANSCODER_MESSAGE_DATA_WARNING, G_TYPE_ERROR, transcoder_err,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS, GST_TYPE_STRUCTURE, details,
|
||||
NULL);
|
||||
|
||||
g_clear_error (&transcoder_err);
|
||||
g_clear_error (&err);
|
||||
g_free (debug);
|
||||
g_free (name);
|
||||
|
@ -704,12 +578,6 @@ warning_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg, gpointer user_data)
|
|||
g_free (message);
|
||||
}
|
||||
|
||||
static void
|
||||
eos_dispatch (gpointer user_data)
|
||||
{
|
||||
g_signal_emit (user_data, signals[SIGNAL_DONE], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
|
||||
gpointer user_data)
|
||||
|
@ -723,11 +591,7 @@ eos_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
|
|||
tick_cb (self);
|
||||
remove_tick_source (self);
|
||||
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_DONE], 0, NULL, NULL, NULL) != 0) {
|
||||
gst_transcoder_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
eos_dispatch, g_object_ref (self), (GDestroyNotify) g_object_unref);
|
||||
}
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_DONE, NULL, NULL);
|
||||
self->is_eos = TRUE;
|
||||
}
|
||||
|
||||
|
@ -744,54 +608,13 @@ clock_lost_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
|
|||
if (state_ret != GST_STATE_CHANGE_FAILURE)
|
||||
state_ret = gst_element_set_state (self->transcodebin, GST_STATE_PLAYING);
|
||||
|
||||
if (state_ret == GST_STATE_CHANGE_FAILURE)
|
||||
emit_error (self, g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "Failed to handle clock loss"),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GstTranscoder *transcoder;
|
||||
GstClockTime duration;
|
||||
} DurationChangedSignalData;
|
||||
|
||||
static void
|
||||
duration_changed_dispatch (gpointer user_data)
|
||||
{
|
||||
DurationChangedSignalData *data = user_data;
|
||||
|
||||
if (data->transcoder->target_state >= GST_STATE_PAUSED) {
|
||||
g_signal_emit (data->transcoder, signals[SIGNAL_DURATION_CHANGED], 0,
|
||||
data->duration);
|
||||
g_object_notify_by_pspec (G_OBJECT (data->transcoder),
|
||||
param_specs[PROP_DURATION]);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
duration_changed_signal_data_free (DurationChangedSignalData * data)
|
||||
{
|
||||
g_object_unref (data->transcoder);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_duration_changed (GstTranscoder * self, GstClockTime duration)
|
||||
{
|
||||
GST_DEBUG_OBJECT (self, "Duration changed %" GST_TIME_FORMAT,
|
||||
GST_TIME_ARGS (duration));
|
||||
|
||||
if (g_signal_handler_find (self, G_SIGNAL_MATCH_ID,
|
||||
signals[SIGNAL_DURATION_CHANGED], 0, NULL, NULL, NULL) != 0) {
|
||||
DurationChangedSignalData *data = g_new0 (DurationChangedSignalData, 1);
|
||||
|
||||
data->transcoder = g_object_ref (self);
|
||||
data->duration = duration;
|
||||
gst_transcoder_signal_dispatcher_dispatch (self->signal_dispatcher, self,
|
||||
duration_changed_dispatch, data,
|
||||
(GDestroyNotify) duration_changed_signal_data_free);
|
||||
if (state_ret == GST_STATE_CHANGE_FAILURE) {
|
||||
GError *err = g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "Failed to handle clock loss");
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR, err, NULL);
|
||||
g_error_free (err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -836,7 +659,9 @@ duration_changed_cb (G_GNUC_UNUSED GstBus * bus, G_GNUC_UNUSED GstMessage * msg,
|
|||
|
||||
if (gst_element_query_duration (self->transcodebin, GST_FORMAT_TIME,
|
||||
&duration)) {
|
||||
emit_duration_changed (self, duration);
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_DURATION_CHANGED,
|
||||
GST_TRANSCODER_MESSAGE_DATA_DURATION, GST_TYPE_CLOCK_TIME,
|
||||
duration, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -866,11 +691,16 @@ request_state_cb (G_GNUC_UNUSED GstBus * bus, GstMessage * msg,
|
|||
|
||||
self->target_state = state;
|
||||
state_ret = gst_element_set_state (self->transcodebin, state);
|
||||
if (state_ret == GST_STATE_CHANGE_FAILURE)
|
||||
emit_error (self, g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED,
|
||||
"Failed to change to requested state %s",
|
||||
gst_element_state_get_name (state)), NULL);
|
||||
if (state_ret == GST_STATE_CHANGE_FAILURE) {
|
||||
GError *err = g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED,
|
||||
"Failed to change to requested state %s",
|
||||
gst_element_state_get_name (state));
|
||||
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR, err, NULL);
|
||||
g_error_free (err);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1030,7 +860,7 @@ gst_transcoder_new (const gchar * source_uri,
|
|||
|
||||
profile = create_encoding_profile (encoding_profile);
|
||||
|
||||
return gst_transcoder_new_full (source_uri, dest_uri, profile, NULL);
|
||||
return gst_transcoder_new_full (source_uri, dest_uri, profile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1040,15 +870,12 @@ gst_transcoder_new (const gchar * source_uri,
|
|||
* @profile: The #GstEncodingProfile defining the output format
|
||||
* have a look at the #GstEncodingProfile documentation to find more
|
||||
* about the serialization format.
|
||||
* @signal_dispatcher: The #GstTranscoderSignalDispatcher to be used
|
||||
* to dispatch the various signals.
|
||||
*
|
||||
* Returns: a new #GstTranscoder instance
|
||||
*/
|
||||
GstTranscoder *
|
||||
gst_transcoder_new_full (const gchar * source_uri,
|
||||
const gchar * dest_uri, GstEncodingProfile * profile,
|
||||
GstTranscoderSignalDispatcher * signal_dispatcher)
|
||||
const gchar * dest_uri, GstEncodingProfile * profile)
|
||||
{
|
||||
static GOnce once = G_ONCE_INIT;
|
||||
|
||||
|
@ -1058,8 +885,7 @@ gst_transcoder_new_full (const gchar * source_uri,
|
|||
g_return_val_if_fail (dest_uri, NULL);
|
||||
|
||||
return g_object_new (GST_TYPE_TRANSCODER, "src-uri", source_uri,
|
||||
"dest-uri", dest_uri, "profile", profile,
|
||||
"signal-dispatcher", signal_dispatcher, NULL);
|
||||
"dest-uri", dest_uri, "profile", profile, NULL);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -1069,8 +895,7 @@ typedef struct
|
|||
} RunSyncData;
|
||||
|
||||
static void
|
||||
_error_cb (GstTranscoder * self, GError * error, GstStructure * details,
|
||||
RunSyncData * data)
|
||||
_error_cb (RunSyncData * data, GError * error, GstStructure * details)
|
||||
{
|
||||
if (data->error == NULL)
|
||||
g_propagate_error (&data->error, error);
|
||||
|
@ -1082,7 +907,7 @@ _error_cb (GstTranscoder * self, GError * error, GstStructure * details,
|
|||
}
|
||||
|
||||
static void
|
||||
_done_cb (GstTranscoder * self, RunSyncData * data)
|
||||
_done_cb (RunSyncData * data)
|
||||
{
|
||||
if (data->loop) {
|
||||
g_main_loop_quit (data->loop);
|
||||
|
@ -1103,17 +928,20 @@ gboolean
|
|||
gst_transcoder_run (GstTranscoder * self, GError ** error)
|
||||
{
|
||||
RunSyncData data = { 0, };
|
||||
GstTranscoderSignalAdapter *signal_adapter =
|
||||
gst_transcoder_signal_adapter_new (self, NULL);
|
||||
|
||||
data.loop = g_main_loop_new (NULL, FALSE);
|
||||
g_signal_connect (self, "error", G_CALLBACK (_error_cb), &data);
|
||||
g_signal_connect (self, "done", G_CALLBACK (_done_cb), &data);
|
||||
g_signal_connect_swapped (signal_adapter, "error", G_CALLBACK (_error_cb),
|
||||
&data);
|
||||
g_signal_connect_swapped (signal_adapter, "done", G_CALLBACK (_done_cb),
|
||||
&data);
|
||||
gst_transcoder_run_async (self);
|
||||
|
||||
if (!data.error)
|
||||
g_main_loop_run (data.loop);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self, _error_cb, &data);
|
||||
g_signal_handlers_disconnect_by_func (self, _done_cb, &data);
|
||||
g_object_unref (signal_adapter);
|
||||
|
||||
if (data.error) {
|
||||
if (error)
|
||||
|
@ -1143,8 +971,12 @@ gst_transcoder_run_async (GstTranscoder * self)
|
|||
GST_DEBUG_OBJECT (self, "Play");
|
||||
|
||||
if (!self->profile) {
|
||||
emit_error (self, g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "No \"profile\" provided"), NULL);
|
||||
GError *err = g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "No \"profile\" provided");
|
||||
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR, err, NULL);
|
||||
g_error_free (err);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -1153,8 +985,12 @@ gst_transcoder_run_async (GstTranscoder * self)
|
|||
state_ret = gst_element_set_state (self->transcodebin, GST_STATE_PLAYING);
|
||||
|
||||
if (state_ret == GST_STATE_CHANGE_FAILURE) {
|
||||
emit_error (self, g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "Could not start transcoding"), NULL);
|
||||
GError *err = g_error_new (GST_TRANSCODER_ERROR,
|
||||
GST_TRANSCODER_ERROR_FAILED, "Could not start transcoding");
|
||||
api_bus_post_message (self, GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR, err, NULL);
|
||||
g_error_free (err);
|
||||
|
||||
return;
|
||||
} else if (state_ret == GST_STATE_CHANGE_NO_PREROLL) {
|
||||
self->is_live = TRUE;
|
||||
|
@ -1372,212 +1208,154 @@ gst_transcoder_error_get_name (GstTranscoderError error)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
G_DEFINE_INTERFACE (GstTranscoderSignalDispatcher,
|
||||
gst_transcoder_signal_dispatcher, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_dispatcher_default_init (G_GNUC_UNUSED
|
||||
GstTranscoderSignalDispatcherInterface * iface)
|
||||
/**
|
||||
* gst_transcoder_get_message_bus:
|
||||
* @transcoder: #GstTranscoder instance
|
||||
*
|
||||
* GstTranscoder API exposes a #GstBus instance which purpose is to provide data
|
||||
* structures representing transcoder-internal events in form of #GstMessage-s of
|
||||
* type GST_MESSAGE_APPLICATION.
|
||||
*
|
||||
* Each message carries a "transcoder-message" field of type #GstTranscoderMessage.
|
||||
* Further fields of the message data are specific to each possible value of
|
||||
* that enumeration.
|
||||
*
|
||||
* Applications can consume the messages asynchronously within their own
|
||||
* event-loop / UI-thread etc. Note that in case the application does not
|
||||
* consume the messages, the bus will accumulate these internally and eventually
|
||||
* fill memory. To avoid that, the bus has to be set "flushing".
|
||||
*
|
||||
* Returns: (transfer full): The transcoder message bus instance
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstBus *
|
||||
gst_transcoder_get_message_bus (GstTranscoder * self)
|
||||
{
|
||||
|
||||
return g_object_ref (self->api_bus);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_signal_dispatcher_dispatch (GstTranscoderSignalDispatcher * self,
|
||||
GstTranscoder * transcoder, void (*emitter) (gpointer data), gpointer data,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GstTranscoderSignalDispatcherInterface *iface;
|
||||
|
||||
if (!self) {
|
||||
emitter (data);
|
||||
if (destroy)
|
||||
destroy (data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_fail (GST_IS_TRANSCODER_SIGNAL_DISPATCHER (self));
|
||||
iface = GST_TRANSCODER_SIGNAL_DISPATCHER_GET_INTERFACE (self);
|
||||
g_return_if_fail (iface->dispatch != NULL);
|
||||
|
||||
iface->dispatch (self, transcoder, emitter, data, destroy);
|
||||
}
|
||||
|
||||
struct _GstTranscoderGMainContextSignalDispatcher
|
||||
{
|
||||
GObject parent;
|
||||
GMainContext *application_context;
|
||||
};
|
||||
|
||||
struct _GstTranscoderGMainContextSignalDispatcherClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_interface_init
|
||||
(GstTranscoderSignalDispatcherInterface * iface);
|
||||
|
||||
enum
|
||||
{
|
||||
G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_0,
|
||||
G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT,
|
||||
G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GstTranscoderGMainContextSignalDispatcher,
|
||||
gst_transcoder_g_main_context_signal_dispatcher, G_TYPE_OBJECT,
|
||||
G_IMPLEMENT_INTERFACE (GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER,
|
||||
gst_transcoder_g_main_context_signal_dispatcher_interface_init));
|
||||
|
||||
static GParamSpec
|
||||
* g_main_context_signal_dispatcher_param_specs
|
||||
[G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST] = { NULL, };
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_finalize (GObject * object)
|
||||
{
|
||||
GstTranscoderGMainContextSignalDispatcher *self =
|
||||
GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
|
||||
|
||||
if (self->application_context)
|
||||
g_main_context_unref (self->application_context);
|
||||
|
||||
G_OBJECT_CLASS
|
||||
(gst_transcoder_g_main_context_signal_dispatcher_parent_class)->finalize
|
||||
(object);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_set_property (GObject * object,
|
||||
guint prop_id, const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTranscoderGMainContextSignalDispatcher *self =
|
||||
GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT:
|
||||
self->application_context = g_value_dup_boxed (value);
|
||||
if (!self->application_context)
|
||||
self->application_context = g_main_context_ref_thread_default ();
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_get_property (GObject * object,
|
||||
guint prop_id, GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstTranscoderGMainContextSignalDispatcher *self =
|
||||
GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT:
|
||||
g_value_set_boxed (value, self->application_context);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_class_init
|
||||
(GstTranscoderGMainContextSignalDispatcherClass * klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->finalize =
|
||||
gst_transcoder_g_main_context_signal_dispatcher_finalize;
|
||||
gobject_class->set_property =
|
||||
gst_transcoder_g_main_context_signal_dispatcher_set_property;
|
||||
gobject_class->get_property =
|
||||
gst_transcoder_g_main_context_signal_dispatcher_get_property;
|
||||
|
||||
g_main_context_signal_dispatcher_param_specs
|
||||
[G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_APPLICATION_CONTEXT] =
|
||||
g_param_spec_boxed ("application-context", "Application Context",
|
||||
"Application GMainContext to dispatch signals to", G_TYPE_MAIN_CONTEXT,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
g_object_class_install_properties (gobject_class,
|
||||
G_MAIN_CONTEXT_SIGNAL_DISPATCHER_PROP_LAST,
|
||||
g_main_context_signal_dispatcher_param_specs);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_init
|
||||
(G_GNUC_UNUSED GstTranscoderGMainContextSignalDispatcher * self)
|
||||
{
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void (*emitter) (gpointer data);
|
||||
gpointer data;
|
||||
GDestroyNotify destroy;
|
||||
} GMainContextSignalDispatcherData;
|
||||
|
||||
static gboolean
|
||||
g_main_context_signal_dispatcher_dispatch_gsourcefunc (gpointer user_data)
|
||||
{
|
||||
GMainContextSignalDispatcherData *data = user_data;
|
||||
|
||||
data->emitter (data->data);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
g_main_context_signal_dispatcher_dispatch_destroy (gpointer user_data)
|
||||
{
|
||||
GMainContextSignalDispatcherData *data = user_data;
|
||||
|
||||
if (data->destroy)
|
||||
data->destroy (data->data);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_dispatch (GstTranscoderSignalDispatcher * iface,
|
||||
G_GNUC_UNUSED GstTranscoder * transcoder, void (*emitter) (gpointer data),
|
||||
gpointer data, GDestroyNotify destroy)
|
||||
{
|
||||
GstTranscoderGMainContextSignalDispatcher *self =
|
||||
GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (iface);
|
||||
GMainContextSignalDispatcherData *gsourcefunc_data =
|
||||
g_new0 (GMainContextSignalDispatcherData, 1);
|
||||
|
||||
gsourcefunc_data->emitter = emitter;
|
||||
gsourcefunc_data->data = data;
|
||||
gsourcefunc_data->destroy = destroy;
|
||||
|
||||
g_main_context_invoke_full (self->application_context,
|
||||
G_PRIORITY_DEFAULT, g_main_context_signal_dispatcher_dispatch_gsourcefunc,
|
||||
gsourcefunc_data, g_main_context_signal_dispatcher_dispatch_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_transcoder_g_main_context_signal_dispatcher_interface_init (GstTranscoderSignalDispatcherInterface * iface)
|
||||
{
|
||||
iface->dispatch = gst_transcoder_g_main_context_signal_dispatcher_dispatch;
|
||||
}
|
||||
/* *INDENT-ON* */
|
||||
|
||||
/**
|
||||
* gst_transcoder_g_main_context_signal_dispatcher_new:
|
||||
* @application_context: (allow-none): GMainContext to use or %NULL
|
||||
* gst_transcoder_message_get_name:
|
||||
* @message: a #GstTranscoderMessage
|
||||
*
|
||||
* Returns: (transfer full):
|
||||
* Returns (transfer none): The message name
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
GstTranscoderSignalDispatcher *
|
||||
gst_transcoder_g_main_context_signal_dispatcher_new (GMainContext *
|
||||
application_context)
|
||||
const gchar *
|
||||
gst_transcoder_message_get_name (GstTranscoderMessage message)
|
||||
{
|
||||
return g_object_new (GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER,
|
||||
"application-context", application_context, NULL);
|
||||
GEnumClass *enum_class;
|
||||
GEnumValue *enum_value;
|
||||
enum_class = g_type_class_ref (GST_TYPE_TRANSCODER_MESSAGE);
|
||||
enum_value = g_enum_get_value (enum_class, message);
|
||||
g_assert (enum_value != NULL);
|
||||
g_type_class_unref (enum_class);
|
||||
return enum_value->value_name;
|
||||
}
|
||||
|
||||
|
||||
#define PARSE_MESSAGE_FIELD(msg, field, value_type, value) G_STMT_START { \
|
||||
const GstStructure *data = NULL; \
|
||||
g_return_if_fail (gst_transcoder_is_transcoder_message (msg)); \
|
||||
data = gst_message_get_structure (msg); \
|
||||
if (!gst_structure_get (data, field, value_type, value, NULL)) { \
|
||||
g_error ("Could not parse field from structure: %s", field); \
|
||||
} \
|
||||
} G_STMT_END
|
||||
|
||||
/**
|
||||
* gst_transcoder_is_transcoder_message:
|
||||
* @msg: A #GstMessage
|
||||
*
|
||||
* Returns: A #gboolean indicating whether the passes message represents a #GstTranscoder message or not.
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
gboolean
|
||||
gst_transcoder_is_transcoder_message (GstMessage * msg)
|
||||
{
|
||||
const GstStructure *data = NULL;
|
||||
g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE);
|
||||
|
||||
data = gst_message_get_structure (msg);
|
||||
g_return_val_if_fail (data, FALSE);
|
||||
|
||||
return g_str_equal (gst_structure_get_name (data),
|
||||
GST_TRANSCODER_MESSAGE_DATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_message_parse_duration:
|
||||
* @msg: A #GstMessage
|
||||
* @duration: (out): the resulting duration
|
||||
*
|
||||
* Parse the given duration @msg and extract the corresponding #GstClockTime
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_transcoder_message_parse_duration (GstMessage * msg,
|
||||
GstClockTime * duration)
|
||||
{
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_DURATION,
|
||||
GST_TYPE_CLOCK_TIME, duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_message_parse_position:
|
||||
* @msg: A #GstMessage
|
||||
* @position: (out): the resulting position
|
||||
*
|
||||
* Parse the given position @msg and extract the corresponding #GstClockTime
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_transcoder_message_parse_position (GstMessage * msg,
|
||||
GstClockTime * position)
|
||||
{
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_POSITION,
|
||||
GST_TYPE_CLOCK_TIME, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_message_parse_error:
|
||||
* @msg: A #GstMessage
|
||||
* @error: (out): the resulting error
|
||||
* @details: (out): (transfer none): A GstStructure containing extra details about the error
|
||||
*
|
||||
* Parse the given error @msg and extract the corresponding #GError
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_transcoder_message_parse_error (GstMessage * msg, GError * error,
|
||||
GstStructure ** details)
|
||||
{
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ERROR, G_TYPE_ERROR,
|
||||
error);
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS,
|
||||
GST_TYPE_STRUCTURE, details);
|
||||
}
|
||||
|
||||
/**
|
||||
* gst_transcoder_message_parse_warning:
|
||||
* @msg: A #GstMessage
|
||||
* @error: (out): the resulting warning
|
||||
* @details: (out): (transfer none): A GstStructure containing extra details about the warning
|
||||
*
|
||||
* Parse the given error @msg and extract the corresponding #GError warning
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
void
|
||||
gst_transcoder_message_parse_warning (GstMessage * msg, GError * error,
|
||||
GstStructure ** details)
|
||||
{
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_WARNING, G_TYPE_ERROR,
|
||||
error);
|
||||
PARSE_MESSAGE_FIELD (msg, GST_TRANSCODER_MESSAGE_DATA_ISSUE_DETAILS,
|
||||
GST_TYPE_STRUCTURE, details);
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GstTranscoderSignalDispatcher GstTranscoderSignalDispatcher;
|
||||
typedef struct _GstTranscoderSignalDispatcherInterface GstTranscoderSignalDispatcherInterface;
|
||||
|
||||
/*********** Error definitions ************/
|
||||
#define GST_TRANSCODER_ERROR (gst_transcoder_error_quark ())
|
||||
|
||||
|
@ -31,6 +28,51 @@ GQuark gst_transcoder_error_quark (void);
|
|||
GST_TRANSCODER_API
|
||||
const gchar * gst_transcoder_error_get_name (GstTranscoderError error);
|
||||
|
||||
/*********** Messages types definitions ************/
|
||||
|
||||
/**
|
||||
* GstTranscoderMessage:
|
||||
* @GST_TRANSCODER_MESSAGE_POSITION_UPDATED: Sink position changed
|
||||
* @GST_TRANSCODER_MESSAGE_DURATION_CHANGED: Duration of stream changed
|
||||
* @GST_TRANSCODER_MESSAGE_DONE: Transcoding is done
|
||||
* @GST_TRANSCODER_MESSAGE_ERROR: Message contains an error
|
||||
* @GST_TRANSCODER_MESSAGE_WARNING: Message contains an error
|
||||
*
|
||||
* Types of messages that will be posted on the transcoder API bus.
|
||||
*
|
||||
* See also #gst_transcoder_get_message_bus()
|
||||
*
|
||||
* Since: 1.20
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GST_TRANSCODER_MESSAGE_POSITION_UPDATED,
|
||||
GST_TRANSCODER_MESSAGE_DURATION_CHANGED,
|
||||
GST_TRANSCODER_MESSAGE_DONE,
|
||||
GST_TRANSCODER_MESSAGE_ERROR,
|
||||
GST_TRANSCODER_MESSAGE_WARNING,
|
||||
} GstTranscoderMessage;
|
||||
|
||||
GST_TRANSCODER_API
|
||||
gboolean gst_transcoder_is_transcoder_message (GstMessage * msg);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
const gchar * gst_transcoder_message_get_name (GstTranscoderMessage message);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_message_parse_position (GstMessage * msg, GstClockTime * position);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_message_parse_duration (GstMessage * msg, GstClockTime * duration);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_message_parse_error (GstMessage * msg, GError * error, GstStructure ** details);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_message_parse_warning (GstMessage * msg, GError * error, GstStructure ** details);
|
||||
|
||||
|
||||
|
||||
/*********** GstTranscoder definition ************/
|
||||
#define GST_TYPE_TRANSCODER (gst_transcoder_get_type ())
|
||||
|
||||
|
@ -50,22 +92,24 @@ GstTranscoder * gst_transcoder_new (const gchar * source_
|
|||
GST_TRANSCODER_API
|
||||
GstTranscoder * gst_transcoder_new_full (const gchar * source_uri,
|
||||
const gchar * dest_uri,
|
||||
GstEncodingProfile *profile,
|
||||
GstTranscoderSignalDispatcher *signal_dispatcher);
|
||||
GstEncodingProfile * profile);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
gboolean gst_transcoder_run (GstTranscoder *self,
|
||||
gboolean gst_transcoder_run (GstTranscoder * self,
|
||||
GError ** error);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_set_cpu_usage (GstTranscoder *self,
|
||||
GstBus * gst_transcoder_get_message_bus (GstTranscoder * transcoder);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_set_cpu_usage (GstTranscoder * self,
|
||||
gint cpu_usage);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_run_async (GstTranscoder *self);
|
||||
void gst_transcoder_run_async (GstTranscoder * self);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
void gst_transcoder_set_position_update_interval (GstTranscoder *self,
|
||||
void gst_transcoder_set_position_update_interval (GstTranscoder * self,
|
||||
guint interval);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
|
@ -75,7 +119,7 @@ GST_TRANSCODER_API
|
|||
gchar * gst_transcoder_get_dest_uri (GstTranscoder * self);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
guint gst_transcoder_get_position_update_interval (GstTranscoder *self);
|
||||
guint gst_transcoder_get_position_update_interval (GstTranscoder * self);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GstClockTime gst_transcoder_get_position (GstTranscoder * self);
|
||||
|
@ -92,43 +136,7 @@ GST_TRANSCODER_API
|
|||
void gst_transcoder_set_avoid_reencoding (GstTranscoder * self,
|
||||
gboolean avoid_reencoding);
|
||||
|
||||
|
||||
/****************** Signal dispatcher *******************************/
|
||||
|
||||
#define GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER (gst_transcoder_signal_dispatcher_get_type ())
|
||||
#define GST_TRANSCODER_SIGNAL_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER, GstTranscoderSignalDispatcher))
|
||||
#define GST_IS_TRANSCODER_SIGNAL_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER))
|
||||
#define GST_TRANSCODER_SIGNAL_DISPATCHER_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TRANSCODER_SIGNAL_DISPATCHER, GstTranscoderSignalDispatcherInterface))
|
||||
|
||||
struct _GstTranscoderSignalDispatcherInterface {
|
||||
GTypeInterface parent_iface;
|
||||
|
||||
void (*dispatch) (GstTranscoderSignalDispatcher * self,
|
||||
GstTranscoder * transcoder,
|
||||
void (*emitter) (gpointer data),
|
||||
gpointer data,
|
||||
GDestroyNotify destroy);
|
||||
};
|
||||
|
||||
typedef struct _GstTranscoderGMainContextSignalDispatcher GstTranscoderGMainContextSignalDispatcher;
|
||||
typedef struct _GstTranscoderGMainContextSignalDispatcherClass GstTranscoderGMainContextSignalDispatcherClass;
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GType gst_transcoder_signal_dispatcher_get_type (void);
|
||||
|
||||
#define GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER (gst_transcoder_g_main_context_signal_dispatcher_get_type ())
|
||||
#define GST_IS_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER))
|
||||
#define GST_IS_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER))
|
||||
#define GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER, GstTranscoderGMainContextSignalDispatcherClass))
|
||||
#define GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER, GstTranscoderGMainContextSignalDispatcher))
|
||||
#define GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER, GstTranscoderGMainContextSignalDispatcherClass))
|
||||
#define GST_TRANSCODER_G_MAIN_CONTEXT_SIGNAL_DISPATCHER_CAST(obj) ((GstTranscoderGMainContextSignalDispatcher*)(obj))
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GType gst_transcoder_g_main_context_signal_dispatcher_get_type (void);
|
||||
|
||||
GST_TRANSCODER_API
|
||||
GstTranscoderSignalDispatcher * gst_transcoder_g_main_context_signal_dispatcher_new (GMainContext * application_context);
|
||||
#include "gsttranscoder-signal-adapter.h"
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
sources = files(['gsttranscoder.c'])
|
||||
headers = files(['gsttranscoder.h', 'transcoder-prelude.h'])
|
||||
sources = files(['gsttranscoder.c', 'gsttranscoder-signal-adapter.c'])
|
||||
headers = files(['gsttranscoder.h', 'transcoder-prelude.h', 'gsttranscoder-signal-adapter.h'])
|
||||
|
||||
install_headers(headers, subdir : 'gstreamer-' + api_version + '/gst/transcoder')
|
||||
|
||||
|
|
|
@ -282,6 +282,7 @@ main (int argc, char *argv[])
|
|||
GError *err = NULL;
|
||||
GstTranscoder *transcoder;
|
||||
GOptionContext *ctx;
|
||||
GstTranscoderSignalAdapter *signal_adapter;
|
||||
Settings settings = {
|
||||
.cpu_usage = 100,
|
||||
.rate = -1,
|
||||
|
@ -371,19 +372,22 @@ main (int argc, char *argv[])
|
|||
}
|
||||
|
||||
transcoder = gst_transcoder_new_full (settings.src_uri, settings.dest_uri,
|
||||
settings.profile, NULL);
|
||||
settings.profile);
|
||||
gst_transcoder_set_avoid_reencoding (transcoder, TRUE);
|
||||
|
||||
gst_transcoder_set_cpu_usage (transcoder, settings.cpu_usage);
|
||||
g_signal_connect (transcoder, "position-updated",
|
||||
G_CALLBACK (position_updated_cb), NULL);
|
||||
g_signal_connect (transcoder, "warning", G_CALLBACK (_warning_cb), NULL);
|
||||
g_signal_connect (transcoder, "error", G_CALLBACK (_error_cb), NULL);
|
||||
|
||||
g_assert (transcoder);
|
||||
signal_adapter = gst_transcoder_signal_adapter_new (transcoder, NULL);
|
||||
g_signal_connect_swapped (signal_adapter, "position-updated",
|
||||
G_CALLBACK (position_updated_cb), transcoder);
|
||||
g_signal_connect_swapped (signal_adapter, "warning", G_CALLBACK (_warning_cb),
|
||||
transcoder);
|
||||
g_signal_connect_swapped (signal_adapter, "error", G_CALLBACK (_error_cb),
|
||||
transcoder);
|
||||
|
||||
|
||||
ok ("Starting transcoding...");
|
||||
gst_transcoder_run (transcoder, &err);
|
||||
g_object_unref (signal_adapter);
|
||||
if (!err)
|
||||
ok ("\nDONE.");
|
||||
|
||||
|
|
Loading…
Reference in a new issue