summaryrefslogtreecommitdiffstats
path: root/gst/real/gstrealvideodec.c
diff options
context:
space:
mode:
Diffstat (limited to 'gst/real/gstrealvideodec.c')
-rw-r--r--gst/real/gstrealvideodec.c179
1 files changed, 135 insertions, 44 deletions
diff --git a/gst/real/gstrealvideodec.c b/gst/real/gstrealvideodec.c
index 3c471f5d..27558426 100644
--- a/gst/real/gstrealvideodec.c
+++ b/gst/real/gstrealvideodec.c
@@ -65,8 +65,8 @@ GST_BOILERPLATE (GstRealVideoDec, gst_real_video_dec, GstElement,
GST_TYPE_ELEMENT);
static gboolean open_library (GstRealVideoDec * dec,
- GstRealVideoDecHooks * hooks, GstRealVideoDecVersion version);
-static void close_library (GstRealVideoDecHooks hooks);
+ GstRealVideoDecVersion version, GstRVDecLibrary * lib);
+static void close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib);
typedef struct
{
@@ -103,7 +103,7 @@ gst_real_video_dec_chain (GstPad * pad, GstBuffer * in)
dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
- if (G_UNLIKELY (dec->hooks.transform == NULL || dec->hooks.module == NULL))
+ if (G_UNLIKELY (dec->lib.Transform == NULL || dec->lib.module == NULL))
goto not_negotiated;
data = GST_BUFFER_DATA (in);
@@ -162,9 +162,9 @@ gst_real_video_dec_chain (GstPad * pad, GstBuffer * in)
/* jump over the frag table to the fragments */
data += frag_size;
- result = dec->hooks.transform (
+ result = dec->lib.Transform (
(gchar *) data,
- (gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->hooks.context);
+ (gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->lib.context);
if (result)
goto could_not_transform;
@@ -243,10 +243,51 @@ could_not_push:
}
}
-static gboolean
-gst_real_video_dec_activate_push (GstPad * pad, gboolean active)
+static GstCaps *
+gst_real_video_dec_getcaps (GstPad * pad)
{
- return TRUE;
+ GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
+ GstCaps *res;
+
+ if (dec->checked_modules) {
+ GValue versions = { 0 };
+ GValue version = { 0 };
+
+ GST_LOG_OBJECT (dec, "constructing caps");
+ res = gst_caps_new_empty ();
+
+ g_value_init (&versions, GST_TYPE_LIST);
+ g_value_init (&version, G_TYPE_INT);
+
+ if (dec->valid_rv20) {
+ g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_2);
+ gst_value_list_append_value (&versions, &version);
+ }
+ if (dec->valid_rv30) {
+ g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_3);
+ gst_value_list_append_value (&versions, &version);
+ }
+ if (dec->valid_rv40) {
+ g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_4);
+ gst_value_list_append_value (&versions, &version);
+ }
+
+ if (gst_value_list_get_size (&versions) > 0) {
+ res = gst_caps_new_simple ("video/x-pn-realvideo", NULL);
+ gst_structure_set_value (gst_caps_get_structure (res, 0),
+ "rmversion", &versions);
+ } else {
+ res = gst_caps_new_empty ();
+ }
+ g_value_unset (&versions);
+ g_value_unset (&version);
+ } else {
+ GST_LOG_OBJECT (dec, "returning padtemplate caps");
+ res = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+ }
+ GST_LOG_OBJECT (dec, "returning caps %" GST_PTR_FORMAT, res);
+
+ return res;
}
static gboolean
@@ -259,7 +300,6 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
gchar data[36];
gboolean bres;
const GValue *v;
- GstRealVideoDecHooks hooks = { 0, 0, 0, 0, 0, 0 };
if (!gst_structure_get_int (s, "rmversion", &version) ||
!gst_structure_get_int (s, "width", (gint *) & width) ||
@@ -272,8 +312,10 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
GST_LOG_OBJECT (dec, "Setting version to %d", version);
- if (!open_library (dec, &hooks, version))
- return FALSE;
+ close_library (dec, &dec->lib);
+
+ if (!open_library (dec, version, &dec->lib))
+ goto open_failed;
/* Initialize REAL driver. */
GST_WRITE_UINT16_LE (data + 0, 11);
@@ -285,8 +327,7 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
GST_WRITE_UINT32_LE (data + 16, 1);
GST_WRITE_UINT32_LE (data + 20, format);
- res = hooks.init (&data, &hooks.context);
- if (res)
+ if ((res = dec->lib.Init (&data, &dec->lib.context)))
goto could_not_initialize;
if ((v = gst_structure_get_value (s, "codec_data"))) {
@@ -328,7 +369,7 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
for (i = 0; i < bufsize; i++)
msgdata[i + 2] = 4 * (guint32) bufdata[i];
- res = hooks.custom_message (&msg, hooks.context);
+ res = dec->lib.Message (&msg, dec->lib.context);
g_free (msgdata);
if (res)
@@ -344,8 +385,6 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
if (!bres)
goto could_not_set_caps;
- close_library (dec->hooks);
- dec->hooks = hooks;
dec->version = version;
dec->width = width;
dec->height = height;
@@ -361,34 +400,35 @@ missing_keys:
GST_ERROR_OBJECT (dec, "Could not find all necessary keys in structure.");
return FALSE;
}
-
+open_failed:
+ {
+ GST_ERROR_OBJECT (dec, "failed to open library");
+ return FALSE;
+ }
could_not_initialize:
{
- close_library (hooks);
GST_ERROR_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
+ close_library (dec, &dec->lib);
return FALSE;
}
-
could_not_allocate:
{
- close_library (hooks);
GST_ERROR_OBJECT (dec, "Could not allocate memory.");
+ close_library (dec, &dec->lib);
return FALSE;
}
-
could_not_send_message:
{
- close_library (hooks);
GST_ERROR_OBJECT (dec, "Failed to send custom message needed for "
"initialization (%i).", res);
+ close_library (dec, &dec->lib);
return FALSE;
}
-
could_not_set_caps:
{
- close_library (hooks);
GST_ERROR_OBJECT (dec, "Could not convince peer to accept dimensions "
"%i x %i.", dec->width, dec->height);
+ close_library (dec, &dec->lib);
return FALSE;
}
}
@@ -396,8 +436,8 @@ could_not_set_caps:
/* Attempts to open the correct library for the configured version */
static gboolean
-open_library (GstRealVideoDec * dec, GstRealVideoDecHooks * hooks,
- GstRealVideoDecVersion version)
+open_library (GstRealVideoDec * dec, GstRealVideoDecVersion version,
+ GstRVDecLibrary * lib)
{
gpointer rv_custom_msg, rv_free, rv_init, rv_transform;
GModule *module = NULL;
@@ -464,11 +504,11 @@ codec_search_done:
goto could_not_load;
}
- hooks->init = (GstRealVideoDecInitFunc) rv_init;
- hooks->free = (GstRealVideoDecFreeFunc) rv_free;
- hooks->transform = (GstRealVideoDecTransformFunc) rv_transform;
- hooks->custom_message = (GstRealVideoDecMessageFunc) rv_custom_msg;
- hooks->module = module;
+ lib->Init = rv_init;
+ lib->Free = rv_free;
+ lib->Transform = rv_transform;
+ lib->Message = rv_custom_msg;
+ lib->module = module;
dec->error_count = 0;
@@ -479,44 +519,93 @@ unknown_version:
GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version);
return FALSE;
}
-
could_not_open:
{
GST_ERROR_OBJECT (dec, "Could not open library '%s' in '%s': %s", names,
path, g_module_error ());
return FALSE;
}
-
could_not_load:
{
- close_library (*hooks);
+ close_library (dec, lib);
GST_ERROR_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
return FALSE;
}
}
static void
-close_library (GstRealVideoDecHooks hooks)
+close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib)
+{
+ if (lib->context) {
+ GST_LOG_OBJECT (dec, "closing library");
+ if (lib->Free)
+ lib->Free (lib->context);
+ }
+ if (lib->module) {
+ GST_LOG_OBJECT (dec, "closing library module");
+ g_module_close (lib->module);
+ lib->module = NULL;
+ }
+ memset (lib, 0, sizeof (*lib));
+}
+
+static void
+gst_real_video_dec_probe_modules (GstRealVideoDec * dec)
+{
+ GstRVDecLibrary dummy = { NULL };
+
+ if ((dec->valid_rv20 =
+ open_library (dec, GST_REAL_VIDEO_DEC_VERSION_2, &dummy)))
+ close_library (dec, &dummy);
+ if ((dec->valid_rv30 =
+ open_library (dec, GST_REAL_VIDEO_DEC_VERSION_3, &dummy)))
+ close_library (dec, &dummy);
+ if ((dec->valid_rv40 =
+ open_library (dec, GST_REAL_VIDEO_DEC_VERSION_4, &dummy)))
+ close_library (dec, &dummy);
+}
+
+static GstStateChangeReturn
+gst_real_video_dec_change_state (GstElement * element,
+ GstStateChange transition)
{
- if (hooks.context && hooks.free)
- hooks.free (hooks.context);
+ GstStateChangeReturn ret;
+ GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (element);
- if (hooks.module) {
- g_module_close (hooks.module);
- hooks.module = NULL;
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ gst_real_video_dec_probe_modules (dec);
+ dec->checked_modules = TRUE;
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ close_library (dec, &dec->lib);
+ break;
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ dec->checked_modules = FALSE;
+ break;
+ default:
+ break;
}
+ return ret;
}
static void
gst_real_video_dec_init (GstRealVideoDec * dec, GstRealVideoDecClass * klass)
{
dec->snk = gst_pad_new_from_static_template (&snk_t, "sink");
+ gst_pad_set_getcaps_function (dec->snk,
+ GST_DEBUG_FUNCPTR (gst_real_video_dec_getcaps));
gst_pad_set_setcaps_function (dec->snk,
GST_DEBUG_FUNCPTR (gst_real_video_dec_setcaps));
gst_pad_set_chain_function (dec->snk,
GST_DEBUG_FUNCPTR (gst_real_video_dec_chain));
- gst_pad_set_activatepush_function (dec->snk,
- GST_DEBUG_FUNCPTR (gst_real_video_dec_activate_push));
gst_element_add_pad (GST_ELEMENT (dec), dec->snk);
dec->src = gst_pad_new_from_static_template (&src_t, "src");
@@ -542,8 +631,7 @@ gst_real_video_dec_finalize (GObject * object)
{
GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (object);
- close_library (dec->hooks);
- memset (&dec->hooks, 0, sizeof (dec->hooks));
+ close_library (dec, &dec->lib);
if (dec->real_codecs_path) {
g_free (dec->real_codecs_path);
@@ -641,11 +729,14 @@ static void
gst_real_video_dec_class_init (GstRealVideoDecClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
object_class->set_property = gst_real_video_dec_set_property;
object_class->get_property = gst_real_video_dec_get_property;
object_class->finalize = gst_real_video_dec_finalize;
+ element_class->change_state = gst_real_video_dec_change_state;
+
g_object_class_install_property (object_class, PROP_REAL_CODECS_PATH,
g_param_spec_string ("real-codecs-path",
"Path where to search for RealPlayer codecs",