mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 06:58:56 +00:00
gst/real/gstrealaudiodec.c: Add raversions we can support on the caps.
Original commit message from CVS: * gst/real/gstrealaudiodec.c: (gst_real_audio_dec_chain), (close_library), (open_library), (gst_real_audio_dec_probe_modules), (gst_real_audio_dec_getcaps), (gst_real_audio_dec_setcaps), (gst_real_audio_dec_init), (gst_real_audio_dec_change_state), (gst_real_audio_dec_finalize): Add raversions we can support on the caps. Refactor the loading of the real codecs like realvideo so that we can implement probing. Probe all supported formats by trying to load the .so files, only report the versions on the caps that we can actually load. * gst/real/gstrealvideodec.c: (gst_real_video_dec_chain), (gst_real_video_dec_getcaps), (gst_real_video_dec_setcaps), (open_library), (close_library), (gst_real_video_dec_probe_modules), (gst_real_video_dec_change_state), (gst_real_video_dec_init), (gst_real_video_dec_finalize), (gst_real_video_dec_class_init): * gst/real/gstrealvideodec.h: Change the loading of the library like the audio decoder. Probe the supported formats by trying to load the .so files and only report the versions on the caps that we can actually load.
This commit is contained in:
parent
7ce74ccd5d
commit
1a39f60d9f
4 changed files with 443 additions and 182 deletions
24
ChangeLog
24
ChangeLog
|
@ -1,3 +1,27 @@
|
||||||
|
2008-06-13 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
|
* gst/real/gstrealaudiodec.c: (gst_real_audio_dec_chain),
|
||||||
|
(close_library), (open_library),
|
||||||
|
(gst_real_audio_dec_probe_modules), (gst_real_audio_dec_getcaps),
|
||||||
|
(gst_real_audio_dec_setcaps), (gst_real_audio_dec_init),
|
||||||
|
(gst_real_audio_dec_change_state), (gst_real_audio_dec_finalize):
|
||||||
|
Add raversions we can support on the caps.
|
||||||
|
Refactor the loading of the real codecs like realvideo so that we can
|
||||||
|
implement probing.
|
||||||
|
Probe all supported formats by trying to load the .so files, only report
|
||||||
|
the versions on the caps that we can actually load.
|
||||||
|
|
||||||
|
* gst/real/gstrealvideodec.c: (gst_real_video_dec_chain),
|
||||||
|
(gst_real_video_dec_getcaps), (gst_real_video_dec_setcaps),
|
||||||
|
(open_library), (close_library),
|
||||||
|
(gst_real_video_dec_probe_modules),
|
||||||
|
(gst_real_video_dec_change_state), (gst_real_video_dec_init),
|
||||||
|
(gst_real_video_dec_finalize), (gst_real_video_dec_class_init):
|
||||||
|
* gst/real/gstrealvideodec.h:
|
||||||
|
Change the loading of the library like the audio decoder.
|
||||||
|
Probe the supported formats by trying to load the .so files and only
|
||||||
|
report the versions on the caps that we can actually load.
|
||||||
|
|
||||||
2008-06-13 Zaheer Abbas Merali <zaheerabbas at merali dot org>
|
2008-06-13 Zaheer Abbas Merali <zaheerabbas at merali dot org>
|
||||||
|
|
||||||
patch by: Sebastian Pölsterl
|
patch by: Sebastian Pölsterl
|
||||||
|
|
|
@ -38,7 +38,9 @@ GST_ELEMENT_DETAILS ("RealAudio decoder",
|
||||||
|
|
||||||
static GstStaticPadTemplate snk_t =
|
static GstStaticPadTemplate snk_t =
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS ("audio/x-pn-realaudio; " "audio/x-sipro "));
|
GST_STATIC_CAPS ("audio/x-pn-realaudio, "
|
||||||
|
"raversion = { 3, 4, 5, 6, 8 }; " "audio/x-sipro "));
|
||||||
|
|
||||||
static GstStaticPadTemplate src_t =
|
static GstStaticPadTemplate src_t =
|
||||||
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS ("audio/x-raw-int, "
|
GST_STATIC_CAPS ("audio/x-raw-int, "
|
||||||
|
@ -67,25 +69,31 @@ enum
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
GST_REAL_AUDIO_DEC_VERSION_COOK = 8,
|
|
||||||
GST_REAL_AUDIO_DEC_VERSION_ATRK = 3,
|
GST_REAL_AUDIO_DEC_VERSION_ATRK = 3,
|
||||||
GST_REAL_AUDIO_DEC_VERSION_14_4 = 4,
|
GST_REAL_AUDIO_DEC_VERSION_14_4 = 4,
|
||||||
GST_REAL_AUDIO_DEC_VERSION_28_8 = 5,
|
GST_REAL_AUDIO_DEC_VERSION_28_8 = 5,
|
||||||
GST_REAL_AUDIO_DEC_VERSION_SIPR = 6
|
GST_REAL_AUDIO_DEC_VERSION_SIPR = 6,
|
||||||
|
GST_REAL_AUDIO_DEC_VERSION_COOK = 8
|
||||||
} GstRealAudioDecVersion;
|
} GstRealAudioDecVersion;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
guint16 (*RADecode) (gpointer, guint8 *, guint32, guint8 *, guint32 *,
|
/* Hooks */
|
||||||
|
GModule *module;
|
||||||
|
|
||||||
|
/* Used by the REAL library. */
|
||||||
|
gpointer context;
|
||||||
|
|
||||||
|
guint16 (*RADecode) (gpointer, guint8 *, guint32, guint8 *, guint32 *,
|
||||||
guint32);
|
guint32);
|
||||||
guint16 (*RACloseCodec) (gpointer);
|
guint16 (*RACloseCodec) (gpointer);
|
||||||
guint16 (*RAFreeDecoder) (gpointer);
|
guint16 (*RAFreeDecoder) (gpointer);
|
||||||
guint16 (*RAInitDecoder) (gpointer, gpointer);
|
guint16 (*RAInitDecoder) (gpointer, gpointer);
|
||||||
guint16 (*RAOpenCodec2) (gpointer, const gchar *);
|
guint16 (*RAOpenCodec2) (gpointer, const gchar *);
|
||||||
guint16 (*RASetFlavor) (gpointer, guint16);
|
guint16 (*RASetFlavor) (gpointer, guint16);
|
||||||
void (*SetDLLAccessPath) (gchar *);
|
void (*SetDLLAccessPath) (gchar *);
|
||||||
void (*RASetPwd) (gpointer, gchar *);
|
void (*RASetPwd) (gpointer, gchar *);
|
||||||
} RealFunctions;
|
} GstRADecLibrary;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -108,16 +116,21 @@ struct _GstRealAudioDec
|
||||||
/* Caps */
|
/* Caps */
|
||||||
guint width, height, leaf_size;
|
guint width, height, leaf_size;
|
||||||
|
|
||||||
/* Hooks */
|
GstRADecLibrary lib;
|
||||||
GModule *module;
|
|
||||||
RealFunctions funcs;
|
|
||||||
|
|
||||||
/* Used by the REAL library. */
|
|
||||||
gpointer context;
|
|
||||||
|
|
||||||
/* Properties */
|
/* Properties */
|
||||||
gchar *real_codecs_path, *racook_names, *raatrk_names, *ra14_4_names,
|
gboolean checked_modules;
|
||||||
*ra28_8_names, *rasipr_names;
|
gchar *real_codecs_path;
|
||||||
|
gchar *raatrk_names;
|
||||||
|
gboolean valid_atrk;
|
||||||
|
gchar *ra14_4_names;
|
||||||
|
gboolean valid_ra14_4;
|
||||||
|
gchar *ra28_8_names;
|
||||||
|
gboolean valid_ra28_8;
|
||||||
|
gchar *rasipr_names;
|
||||||
|
gboolean valid_sipr;
|
||||||
|
gchar *racook_names;
|
||||||
|
gboolean valid_cook;
|
||||||
gchar *pwd;
|
gchar *pwd;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,7 +152,7 @@ gst_real_audio_dec_chain (GstPad * pad, GstBuffer * in)
|
||||||
guint16 res = 0;
|
guint16 res = 0;
|
||||||
guint len;
|
guint len;
|
||||||
|
|
||||||
if (G_UNLIKELY (dec->funcs.RADecode == NULL || dec->module == NULL))
|
if (G_UNLIKELY (dec->lib.RADecode == NULL || dec->lib.module == NULL))
|
||||||
goto not_negotiated;
|
goto not_negotiated;
|
||||||
|
|
||||||
timestamp = GST_BUFFER_TIMESTAMP (in);
|
timestamp = GST_BUFFER_TIMESTAMP (in);
|
||||||
|
@ -151,7 +164,7 @@ gst_real_audio_dec_chain (GstPad * pad, GstBuffer * in)
|
||||||
if (flow != GST_FLOW_OK)
|
if (flow != GST_FLOW_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
res = dec->funcs.RADecode (dec->context, GST_BUFFER_DATA (in),
|
res = dec->lib.RADecode (dec->lib.context, GST_BUFFER_DATA (in),
|
||||||
GST_BUFFER_SIZE (in), GST_BUFFER_DATA (out), &len, -1);
|
GST_BUFFER_SIZE (in), GST_BUFFER_DATA (out), &len, -1);
|
||||||
|
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
|
@ -184,47 +197,36 @@ not_negotiated:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
gst_real_audio_dec_setcaps (GstPad * pad, GstCaps * caps)
|
close_library (GstRealAudioDec * dec, GstRADecLibrary * lib)
|
||||||
{
|
{
|
||||||
GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (GST_PAD_PARENT (pad));
|
if (lib->context) {
|
||||||
GstStructure *s = gst_caps_get_structure (caps, 0);
|
GST_LOG_OBJECT (dec, "closing library");
|
||||||
|
if (lib->RACloseCodec)
|
||||||
|
lib->RACloseCodec (lib->context);
|
||||||
|
/* lib->RAFreeDecoder (lib->context); */
|
||||||
|
lib->context = NULL;
|
||||||
|
lib->module = NULL;
|
||||||
|
lib->RACloseCodec = NULL;
|
||||||
|
}
|
||||||
|
if (lib->module) {
|
||||||
|
GST_LOG_OBJECT (dec, "closing library module");
|
||||||
|
g_module_close (lib->module);
|
||||||
|
lib->module = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
open_library (GstRealAudioDec * dec, gint version, GstRADecLibrary * lib)
|
||||||
|
{
|
||||||
|
gchar *path, *names;
|
||||||
|
gchar **split_names, **split_path;
|
||||||
|
gint i, j;
|
||||||
gpointer ra_close_codec, ra_decode, ra_free_decoder;
|
gpointer ra_close_codec, ra_decode, ra_free_decoder;
|
||||||
gpointer ra_open_codec2, ra_init_decoder, ra_set_flavor;
|
gpointer ra_open_codec2, ra_init_decoder, ra_set_flavor;
|
||||||
gpointer set_dll_access_path = NULL, ra_set_pwd = NULL;
|
gpointer set_dll_access_path = NULL, ra_set_pwd = NULL;
|
||||||
gchar *path, *names;
|
|
||||||
gchar **split_names, **split_path;
|
|
||||||
gint version, flavor, channels, rate, leaf_size, packet_size, width, height;
|
|
||||||
guint16 res = 0;
|
|
||||||
RAInit data;
|
|
||||||
gboolean bres;
|
|
||||||
const GValue *v;
|
|
||||||
GstBuffer *buf = NULL;
|
|
||||||
const gchar *name = gst_structure_get_name (s);
|
|
||||||
GModule *module = NULL;
|
|
||||||
gpointer context = NULL;
|
|
||||||
RealFunctions funcs = { NULL, };
|
|
||||||
int i, j;
|
|
||||||
gchar *tmppath = NULL;
|
gchar *tmppath = NULL;
|
||||||
|
guint16 res = 0;
|
||||||
if (!strcmp (name, "audio/x-sipro"))
|
|
||||||
version = GST_REAL_AUDIO_DEC_VERSION_SIPR;
|
|
||||||
else {
|
|
||||||
if (!gst_structure_get_int (s, "raversion", &version))
|
|
||||||
goto missing_keys;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_structure_get_int (s, "flavor", &flavor) ||
|
|
||||||
!gst_structure_get_int (s, "channels", &channels) ||
|
|
||||||
!gst_structure_get_int (s, "width", &width) ||
|
|
||||||
!gst_structure_get_int (s, "rate", &rate) ||
|
|
||||||
!gst_structure_get_int (s, "height", &height) ||
|
|
||||||
!gst_structure_get_int (s, "leaf_size", &leaf_size) ||
|
|
||||||
!gst_structure_get_int (s, "packet_size", &packet_size))
|
|
||||||
goto missing_keys;
|
|
||||||
|
|
||||||
if ((v = gst_structure_get_value (s, "codec_data")))
|
|
||||||
buf = g_value_peek_pointer (v);
|
|
||||||
|
|
||||||
path = dec->real_codecs_path ? dec->real_codecs_path :
|
path = dec->real_codecs_path ? dec->real_codecs_path :
|
||||||
DEFAULT_REAL_CODECS_PATH;
|
DEFAULT_REAL_CODECS_PATH;
|
||||||
|
@ -249,6 +251,8 @@ gst_real_audio_dec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
goto unknown_version;
|
goto unknown_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (dec, "splitting paths %s, names %s", path, names);
|
||||||
|
|
||||||
split_path = g_strsplit (path, ":", 0);
|
split_path = g_strsplit (path, ":", 0);
|
||||||
split_names = g_strsplit (names, ":", 0);
|
split_names = g_strsplit (names, ":", 0);
|
||||||
|
|
||||||
|
@ -256,10 +260,14 @@ gst_real_audio_dec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
for (j = 0; split_names[j]; j++) {
|
for (j = 0; split_names[j]; j++) {
|
||||||
gchar *codec = g_strconcat (split_path[i], "/", split_names[j], NULL);
|
gchar *codec = g_strconcat (split_path[i], "/", split_names[j], NULL);
|
||||||
|
|
||||||
module = g_module_open (codec, G_MODULE_BIND_LAZY);
|
GST_LOG_OBJECT (dec, "opening module %s", codec);
|
||||||
|
|
||||||
|
lib->module = g_module_open (codec, G_MODULE_BIND_LAZY);
|
||||||
g_free (codec);
|
g_free (codec);
|
||||||
if (module)
|
if (lib->module)
|
||||||
goto codec_search_done;
|
goto codec_search_done;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (dec, "failure, try next one...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -267,37 +275,39 @@ codec_search_done:
|
||||||
/* we keep the path for a while to set the dll access path */
|
/* we keep the path for a while to set the dll access path */
|
||||||
g_strfreev (split_names);
|
g_strfreev (split_names);
|
||||||
|
|
||||||
if (module == NULL)
|
if (lib->module == NULL)
|
||||||
goto could_not_open;
|
goto could_not_open;
|
||||||
|
|
||||||
if (!g_module_symbol (module, "RACloseCodec", &ra_close_codec) ||
|
GST_LOG_OBJECT (dec, "finding symbols");
|
||||||
!g_module_symbol (module, "RADecode", &ra_decode) ||
|
|
||||||
!g_module_symbol (module, "RAFreeDecoder", &ra_free_decoder) ||
|
if (!g_module_symbol (lib->module, "RACloseCodec", &ra_close_codec) ||
|
||||||
!g_module_symbol (module, "RAOpenCodec2", &ra_open_codec2) ||
|
!g_module_symbol (lib->module, "RADecode", &ra_decode) ||
|
||||||
!g_module_symbol (module, "RAInitDecoder", &ra_init_decoder) ||
|
!g_module_symbol (lib->module, "RAFreeDecoder", &ra_free_decoder) ||
|
||||||
!g_module_symbol (module, "RASetFlavor", &ra_set_flavor)) {
|
!g_module_symbol (lib->module, "RAOpenCodec2", &ra_open_codec2) ||
|
||||||
|
!g_module_symbol (lib->module, "RAInitDecoder", &ra_init_decoder) ||
|
||||||
|
!g_module_symbol (lib->module, "RASetFlavor", &ra_set_flavor)) {
|
||||||
goto could_not_load;
|
goto could_not_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_module_symbol (module, "RASetPwd", &ra_set_pwd);
|
g_module_symbol (lib->module, "RASetPwd", &ra_set_pwd);
|
||||||
g_module_symbol (module, "SetDLLAccessPath", &set_dll_access_path);
|
g_module_symbol (lib->module, "SetDLLAccessPath", &set_dll_access_path);
|
||||||
|
|
||||||
funcs.RACloseCodec = (guint16 (*)(gpointer)) ra_close_codec;
|
lib->RACloseCodec = (guint16 (*)(gpointer)) ra_close_codec;
|
||||||
funcs.RADecode =
|
lib->RADecode =
|
||||||
(guint16 (*)(gpointer, guint8 *, guint32, guint8 *, guint32 *, guint32))
|
(guint16 (*)(gpointer, guint8 *, guint32, guint8 *, guint32 *, guint32))
|
||||||
ra_decode;
|
ra_decode;
|
||||||
funcs.RAFreeDecoder = (guint16 (*)(gpointer)) ra_free_decoder;
|
lib->RAFreeDecoder = (guint16 (*)(gpointer)) ra_free_decoder;
|
||||||
funcs.RAOpenCodec2 = (guint16 (*)(gpointer, const gchar *)) ra_open_codec2;
|
lib->RAOpenCodec2 = (guint16 (*)(gpointer, const gchar *)) ra_open_codec2;
|
||||||
funcs.RAInitDecoder = (guint16 (*)(gpointer, gpointer)) ra_init_decoder;
|
lib->RAInitDecoder = (guint16 (*)(gpointer, gpointer)) ra_init_decoder;
|
||||||
funcs.RASetFlavor = (guint16 (*)(gpointer, guint16)) ra_set_flavor;
|
lib->RASetFlavor = (guint16 (*)(gpointer, guint16)) ra_set_flavor;
|
||||||
funcs.RASetPwd = (void (*)(gpointer, gchar *)) ra_set_pwd;
|
lib->RASetPwd = (void (*)(gpointer, gchar *)) ra_set_pwd;
|
||||||
funcs.SetDLLAccessPath = (void (*)(gchar *)) set_dll_access_path;
|
lib->SetDLLAccessPath = (void (*)(gchar *)) set_dll_access_path;
|
||||||
|
|
||||||
if (funcs.SetDLLAccessPath)
|
if (lib->SetDLLAccessPath)
|
||||||
funcs.SetDLLAccessPath (split_path[i]);
|
lib->SetDLLAccessPath (split_path[i]);
|
||||||
|
|
||||||
tmppath = g_strdup_printf ("%s/", split_path[i]);
|
tmppath = g_strdup_printf ("%s/", split_path[i]);
|
||||||
if ((res = funcs.RAOpenCodec2 (&context, tmppath))) {
|
if ((res = lib->RAOpenCodec2 (&lib->context, tmppath))) {
|
||||||
g_free (tmppath);
|
g_free (tmppath);
|
||||||
goto could_not_initialize;
|
goto could_not_initialize;
|
||||||
}
|
}
|
||||||
|
@ -306,6 +316,157 @@ codec_search_done:
|
||||||
/* now we are done with the split paths, so free them */
|
/* now we are done with the split paths, so free them */
|
||||||
g_strfreev (split_path);
|
g_strfreev (split_path);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
/* ERRORS */
|
||||||
|
unknown_version:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (dec, "Cannot handle version %i.", version);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
could_not_open:
|
||||||
|
{
|
||||||
|
g_strfreev (split_path);
|
||||||
|
GST_DEBUG_OBJECT (dec, "Could not find library '%s' in '%s'", names, path);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
could_not_load:
|
||||||
|
{
|
||||||
|
g_strfreev (split_path);
|
||||||
|
close_library (dec, lib);
|
||||||
|
GST_DEBUG_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
could_not_initialize:
|
||||||
|
{
|
||||||
|
close_library (dec, lib);
|
||||||
|
GST_WARNING_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_real_audio_dec_probe_modules (GstRealAudioDec * dec)
|
||||||
|
{
|
||||||
|
GstRADecLibrary dummy = { NULL };
|
||||||
|
|
||||||
|
if ((dec->valid_atrk =
|
||||||
|
open_library (dec, GST_REAL_AUDIO_DEC_VERSION_ATRK, &dummy)))
|
||||||
|
close_library (dec, &dummy);
|
||||||
|
if ((dec->valid_ra14_4 =
|
||||||
|
open_library (dec, GST_REAL_AUDIO_DEC_VERSION_14_4, &dummy)))
|
||||||
|
close_library (dec, &dummy);
|
||||||
|
if ((dec->valid_ra28_8 =
|
||||||
|
open_library (dec, GST_REAL_AUDIO_DEC_VERSION_28_8, &dummy)))
|
||||||
|
close_library (dec, &dummy);
|
||||||
|
if ((dec->valid_sipr =
|
||||||
|
open_library (dec, GST_REAL_AUDIO_DEC_VERSION_SIPR, &dummy)))
|
||||||
|
close_library (dec, &dummy);
|
||||||
|
if ((dec->valid_cook =
|
||||||
|
open_library (dec, GST_REAL_AUDIO_DEC_VERSION_COOK, &dummy)))
|
||||||
|
close_library (dec, &dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_real_audio_dec_getcaps (GstPad * pad)
|
||||||
|
{
|
||||||
|
GstRealAudioDec *dec = GST_REAL_AUDIO_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_atrk) {
|
||||||
|
g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_ATRK);
|
||||||
|
gst_value_list_append_value (&versions, &version);
|
||||||
|
}
|
||||||
|
if (dec->valid_ra14_4) {
|
||||||
|
g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_14_4);
|
||||||
|
gst_value_list_append_value (&versions, &version);
|
||||||
|
}
|
||||||
|
if (dec->valid_ra28_8) {
|
||||||
|
g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_28_8);
|
||||||
|
gst_value_list_append_value (&versions, &version);
|
||||||
|
}
|
||||||
|
if (dec->valid_sipr) {
|
||||||
|
g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_SIPR);
|
||||||
|
gst_value_list_append_value (&versions, &version);
|
||||||
|
}
|
||||||
|
if (dec->valid_cook) {
|
||||||
|
g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_COOK);
|
||||||
|
gst_value_list_append_value (&versions, &version);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst_value_list_get_size (&versions) > 0) {
|
||||||
|
res = gst_caps_new_simple ("audio/x-pn-realaudio", NULL);
|
||||||
|
gst_structure_set_value (gst_caps_get_structure (res, 0),
|
||||||
|
"raversion", &versions);
|
||||||
|
} else {
|
||||||
|
res = gst_caps_new_empty ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dec->valid_sipr) {
|
||||||
|
gst_caps_append (res, gst_caps_new_simple ("audio/x-sipro", NULL));
|
||||||
|
}
|
||||||
|
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
|
||||||
|
gst_real_audio_dec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
|
{
|
||||||
|
GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (GST_PAD_PARENT (pad));
|
||||||
|
GstStructure *s = gst_caps_get_structure (caps, 0);
|
||||||
|
gint version, flavor, channels, rate, leaf_size, packet_size, width, height;
|
||||||
|
guint16 res = 0;
|
||||||
|
RAInit data;
|
||||||
|
gboolean bres;
|
||||||
|
const GValue *v;
|
||||||
|
GstBuffer *buf = NULL;
|
||||||
|
const gchar *name = gst_structure_get_name (s);
|
||||||
|
|
||||||
|
if (!strcmp (name, "audio/x-sipro")) {
|
||||||
|
version = GST_REAL_AUDIO_DEC_VERSION_SIPR;
|
||||||
|
} else {
|
||||||
|
if (!gst_structure_get_int (s, "raversion", &version))
|
||||||
|
goto missing_keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gst_structure_get_int (s, "flavor", &flavor) ||
|
||||||
|
!gst_structure_get_int (s, "channels", &channels) ||
|
||||||
|
!gst_structure_get_int (s, "width", &width) ||
|
||||||
|
!gst_structure_get_int (s, "rate", &rate) ||
|
||||||
|
!gst_structure_get_int (s, "height", &height) ||
|
||||||
|
!gst_structure_get_int (s, "leaf_size", &leaf_size) ||
|
||||||
|
!gst_structure_get_int (s, "packet_size", &packet_size))
|
||||||
|
goto missing_keys;
|
||||||
|
|
||||||
|
if ((v = gst_structure_get_value (s, "codec_data")))
|
||||||
|
buf = g_value_peek_pointer (v);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (dec, "opening code for version %d", version);
|
||||||
|
|
||||||
|
/* first close existing decoder */
|
||||||
|
close_library (dec, &dec->lib);
|
||||||
|
|
||||||
|
if (!open_library (dec, version, &dec->lib))
|
||||||
|
goto could_not_open;
|
||||||
|
|
||||||
|
/* we have the module, no initialize with the caps data */
|
||||||
data.samplerate = rate;
|
data.samplerate = rate;
|
||||||
data.width = width;
|
data.width = width;
|
||||||
data.channels = channels;
|
data.channels = channels;
|
||||||
|
@ -315,16 +476,16 @@ codec_search_done:
|
||||||
data.datalen = buf ? GST_BUFFER_SIZE (buf) : 0;
|
data.datalen = buf ? GST_BUFFER_SIZE (buf) : 0;
|
||||||
data.data = buf ? GST_BUFFER_DATA (buf) : NULL;
|
data.data = buf ? GST_BUFFER_DATA (buf) : NULL;
|
||||||
|
|
||||||
if ((res = funcs.RAInitDecoder (context, &data))) {
|
if ((res = dec->lib.RAInitDecoder (dec->lib.context, &data))) {
|
||||||
GST_WARNING_OBJECT (dec, "RAInitDecoder() failed");
|
GST_WARNING_OBJECT (dec, "RAInitDecoder() failed");
|
||||||
goto could_not_initialize;
|
goto could_not_initialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (funcs.RASetPwd) {
|
if (dec->lib.RASetPwd) {
|
||||||
funcs.RASetPwd (context, dec->pwd ? dec->pwd : DEFAULT_PWD);
|
dec->lib.RASetPwd (dec->lib.context, dec->pwd ? dec->pwd : DEFAULT_PWD);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = funcs.RASetFlavor (context, flavor))) {
|
if ((res = dec->lib.RASetFlavor (dec->lib.context, flavor))) {
|
||||||
GST_WARNING_OBJECT (dec, "RASetFlavor(%d) failed", flavor);
|
GST_WARNING_OBJECT (dec, "RASetFlavor(%d) failed", flavor);
|
||||||
goto could_not_initialize;
|
goto could_not_initialize;
|
||||||
}
|
}
|
||||||
|
@ -343,15 +504,8 @@ codec_search_done:
|
||||||
dec->width = width;
|
dec->width = width;
|
||||||
dec->height = height;
|
dec->height = height;
|
||||||
dec->leaf_size = leaf_size;
|
dec->leaf_size = leaf_size;
|
||||||
if (dec->context) {
|
|
||||||
dec->funcs.RACloseCodec (dec->context);
|
GST_LOG_OBJECT (dec, "opened module");
|
||||||
dec->funcs.RAFreeDecoder (dec->context);
|
|
||||||
}
|
|
||||||
dec->context = context;
|
|
||||||
if (dec->module)
|
|
||||||
g_module_close (dec->module);
|
|
||||||
dec->module = module;
|
|
||||||
dec->funcs = funcs;
|
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
|
@ -360,41 +514,21 @@ missing_keys:
|
||||||
GST_DEBUG_OBJECT (dec, "Could not find all necessary keys in structure.");
|
GST_DEBUG_OBJECT (dec, "Could not find all necessary keys in structure.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
unknown_version:
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (dec, "Cannot handle version %i.", version);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
could_not_open:
|
could_not_open:
|
||||||
{
|
{
|
||||||
g_strfreev (split_path);
|
GST_DEBUG_OBJECT (dec, "Could not find decoder");
|
||||||
GST_DEBUG_OBJECT (dec, "Could not find library '%s' in '%s'", names, path);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
could_not_load:
|
|
||||||
{
|
|
||||||
g_module_close (module);
|
|
||||||
g_strfreev (split_path);
|
|
||||||
GST_DEBUG_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
could_not_initialize:
|
could_not_initialize:
|
||||||
{
|
{
|
||||||
if (context) {
|
close_library (dec, &dec->lib);
|
||||||
funcs.RACloseCodec (context);
|
|
||||||
funcs.RAFreeDecoder (context);
|
|
||||||
}
|
|
||||||
g_module_close (module);
|
|
||||||
GST_WARNING_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
GST_WARNING_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
could_not_set_caps:
|
could_not_set_caps:
|
||||||
{
|
{
|
||||||
if (context) {
|
/* should normally not fail */
|
||||||
funcs.RACloseCodec (context);
|
close_library (dec, &dec->lib);
|
||||||
funcs.RAFreeDecoder (context);
|
|
||||||
}
|
|
||||||
g_module_close (module);
|
|
||||||
GST_DEBUG_OBJECT (dec, "Could not convince peer to accept caps.");
|
GST_DEBUG_OBJECT (dec, "Could not convince peer to accept caps.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -406,6 +540,8 @@ gst_real_audio_dec_init (GstRealAudioDec * dec, GstRealAudioDecClass * klass)
|
||||||
dec->snk = gst_pad_new_from_static_template (&snk_t, "sink");
|
dec->snk = gst_pad_new_from_static_template (&snk_t, "sink");
|
||||||
gst_pad_set_setcaps_function (dec->snk,
|
gst_pad_set_setcaps_function (dec->snk,
|
||||||
GST_DEBUG_FUNCPTR (gst_real_audio_dec_setcaps));
|
GST_DEBUG_FUNCPTR (gst_real_audio_dec_setcaps));
|
||||||
|
gst_pad_set_getcaps_function (dec->snk,
|
||||||
|
GST_DEBUG_FUNCPTR (gst_real_audio_dec_getcaps));
|
||||||
gst_pad_set_chain_function (dec->snk,
|
gst_pad_set_chain_function (dec->snk,
|
||||||
GST_DEBUG_FUNCPTR (gst_real_audio_dec_chain));
|
GST_DEBUG_FUNCPTR (gst_real_audio_dec_chain));
|
||||||
gst_element_add_pad (GST_ELEMENT (dec), dec->snk);
|
gst_element_add_pad (GST_ELEMENT (dec), dec->snk);
|
||||||
|
@ -430,10 +566,25 @@ gst_real_audio_dec_change_state (GstElement * element,
|
||||||
GstStateChange transition)
|
GstStateChange transition)
|
||||||
{
|
{
|
||||||
GstStateChangeReturn ret;
|
GstStateChangeReturn ret;
|
||||||
|
GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (element);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||||
|
gst_real_audio_dec_probe_modules (dec);
|
||||||
|
dec->checked_modules = TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
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;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -446,19 +597,7 @@ gst_real_audio_dec_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (object);
|
GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (object);
|
||||||
|
|
||||||
if (dec->context) {
|
close_library (dec, &dec->lib);
|
||||||
dec->funcs.RACloseCodec (dec->context);
|
|
||||||
/* Calling RAFreeDecoder seems to randomly cause SEGFAULTs.
|
|
||||||
* All other implementation (xine, mplayer) have also got this function call
|
|
||||||
* commented. So until we know more, we comment it too. */
|
|
||||||
|
|
||||||
/* dec->funcs.RAFreeDecoder (dec->context); */
|
|
||||||
dec->context = NULL;
|
|
||||||
}
|
|
||||||
if (dec->module) {
|
|
||||||
g_module_close (dec->module);
|
|
||||||
dec->module = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dec->real_codecs_path) {
|
if (dec->real_codecs_path) {
|
||||||
g_free (dec->real_codecs_path);
|
g_free (dec->real_codecs_path);
|
||||||
|
|
|
@ -65,8 +65,8 @@ GST_BOILERPLATE (GstRealVideoDec, gst_real_video_dec, GstElement,
|
||||||
GST_TYPE_ELEMENT);
|
GST_TYPE_ELEMENT);
|
||||||
|
|
||||||
static gboolean open_library (GstRealVideoDec * dec,
|
static gboolean open_library (GstRealVideoDec * dec,
|
||||||
GstRealVideoDecHooks * hooks, GstRealVideoDecVersion version);
|
GstRealVideoDecVersion version, GstRVDecLibrary * lib);
|
||||||
static void close_library (GstRealVideoDecHooks hooks);
|
static void close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
|
@ -103,7 +103,7 @@ gst_real_video_dec_chain (GstPad * pad, GstBuffer * in)
|
||||||
|
|
||||||
dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
|
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;
|
goto not_negotiated;
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (in);
|
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 */
|
/* jump over the frag table to the fragments */
|
||||||
data += frag_size;
|
data += frag_size;
|
||||||
|
|
||||||
result = dec->hooks.transform (
|
result = dec->lib.Transform (
|
||||||
(gchar *) data,
|
(gchar *) data,
|
||||||
(gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->hooks.context);
|
(gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->lib.context);
|
||||||
if (result)
|
if (result)
|
||||||
goto could_not_transform;
|
goto could_not_transform;
|
||||||
|
|
||||||
|
@ -243,10 +243,51 @@ could_not_push:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstCaps *
|
||||||
gst_real_video_dec_activate_push (GstPad * pad, gboolean active)
|
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
|
static gboolean
|
||||||
|
@ -259,7 +300,6 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
gchar data[36];
|
gchar data[36];
|
||||||
gboolean bres;
|
gboolean bres;
|
||||||
const GValue *v;
|
const GValue *v;
|
||||||
GstRealVideoDecHooks hooks = { 0, 0, 0, 0, 0, 0 };
|
|
||||||
|
|
||||||
if (!gst_structure_get_int (s, "rmversion", &version) ||
|
if (!gst_structure_get_int (s, "rmversion", &version) ||
|
||||||
!gst_structure_get_int (s, "width", (gint *) & width) ||
|
!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);
|
GST_LOG_OBJECT (dec, "Setting version to %d", version);
|
||||||
|
|
||||||
if (!open_library (dec, &hooks, version))
|
close_library (dec, &dec->lib);
|
||||||
return FALSE;
|
|
||||||
|
if (!open_library (dec, version, &dec->lib))
|
||||||
|
goto open_failed;
|
||||||
|
|
||||||
/* Initialize REAL driver. */
|
/* Initialize REAL driver. */
|
||||||
GST_WRITE_UINT16_LE (data + 0, 11);
|
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 + 16, 1);
|
||||||
GST_WRITE_UINT32_LE (data + 20, format);
|
GST_WRITE_UINT32_LE (data + 20, format);
|
||||||
|
|
||||||
res = hooks.init (&data, &hooks.context);
|
if ((res = dec->lib.Init (&data, &dec->lib.context)))
|
||||||
if (res)
|
|
||||||
goto could_not_initialize;
|
goto could_not_initialize;
|
||||||
|
|
||||||
if ((v = gst_structure_get_value (s, "codec_data"))) {
|
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++)
|
for (i = 0; i < bufsize; i++)
|
||||||
msgdata[i + 2] = 4 * (guint32) bufdata[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);
|
g_free (msgdata);
|
||||||
if (res)
|
if (res)
|
||||||
|
@ -344,8 +385,6 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
if (!bres)
|
if (!bres)
|
||||||
goto could_not_set_caps;
|
goto could_not_set_caps;
|
||||||
|
|
||||||
close_library (dec->hooks);
|
|
||||||
dec->hooks = hooks;
|
|
||||||
dec->version = version;
|
dec->version = version;
|
||||||
dec->width = width;
|
dec->width = width;
|
||||||
dec->height = height;
|
dec->height = height;
|
||||||
|
@ -361,34 +400,35 @@ missing_keys:
|
||||||
GST_ERROR_OBJECT (dec, "Could not find all necessary keys in structure.");
|
GST_ERROR_OBJECT (dec, "Could not find all necessary keys in structure.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
open_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR_OBJECT (dec, "failed to open library");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
could_not_initialize:
|
could_not_initialize:
|
||||||
{
|
{
|
||||||
close_library (hooks);
|
|
||||||
GST_ERROR_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
GST_ERROR_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
||||||
|
close_library (dec, &dec->lib);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_allocate:
|
could_not_allocate:
|
||||||
{
|
{
|
||||||
close_library (hooks);
|
|
||||||
GST_ERROR_OBJECT (dec, "Could not allocate memory.");
|
GST_ERROR_OBJECT (dec, "Could not allocate memory.");
|
||||||
|
close_library (dec, &dec->lib);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_send_message:
|
could_not_send_message:
|
||||||
{
|
{
|
||||||
close_library (hooks);
|
|
||||||
GST_ERROR_OBJECT (dec, "Failed to send custom message needed for "
|
GST_ERROR_OBJECT (dec, "Failed to send custom message needed for "
|
||||||
"initialization (%i).", res);
|
"initialization (%i).", res);
|
||||||
|
close_library (dec, &dec->lib);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_set_caps:
|
could_not_set_caps:
|
||||||
{
|
{
|
||||||
close_library (hooks);
|
|
||||||
GST_ERROR_OBJECT (dec, "Could not convince peer to accept dimensions "
|
GST_ERROR_OBJECT (dec, "Could not convince peer to accept dimensions "
|
||||||
"%i x %i.", dec->width, dec->height);
|
"%i x %i.", dec->width, dec->height);
|
||||||
|
close_library (dec, &dec->lib);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,8 +436,8 @@ could_not_set_caps:
|
||||||
/* Attempts to open the correct library for the configured version */
|
/* Attempts to open the correct library for the configured version */
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
open_library (GstRealVideoDec * dec, GstRealVideoDecHooks * hooks,
|
open_library (GstRealVideoDec * dec, GstRealVideoDecVersion version,
|
||||||
GstRealVideoDecVersion version)
|
GstRVDecLibrary * lib)
|
||||||
{
|
{
|
||||||
gpointer rv_custom_msg, rv_free, rv_init, rv_transform;
|
gpointer rv_custom_msg, rv_free, rv_init, rv_transform;
|
||||||
GModule *module = NULL;
|
GModule *module = NULL;
|
||||||
|
@ -464,11 +504,11 @@ codec_search_done:
|
||||||
goto could_not_load;
|
goto could_not_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks->init = (GstRealVideoDecInitFunc) rv_init;
|
lib->Init = rv_init;
|
||||||
hooks->free = (GstRealVideoDecFreeFunc) rv_free;
|
lib->Free = rv_free;
|
||||||
hooks->transform = (GstRealVideoDecTransformFunc) rv_transform;
|
lib->Transform = rv_transform;
|
||||||
hooks->custom_message = (GstRealVideoDecMessageFunc) rv_custom_msg;
|
lib->Message = rv_custom_msg;
|
||||||
hooks->module = module;
|
lib->module = module;
|
||||||
|
|
||||||
dec->error_count = 0;
|
dec->error_count = 0;
|
||||||
|
|
||||||
|
@ -479,44 +519,93 @@ unknown_version:
|
||||||
GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version);
|
GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_open:
|
could_not_open:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (dec, "Could not open library '%s' in '%s': %s", names,
|
GST_ERROR_OBJECT (dec, "Could not open library '%s' in '%s': %s", names,
|
||||||
path, g_module_error ());
|
path, g_module_error ());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_load:
|
could_not_load:
|
||||||
{
|
{
|
||||||
close_library (*hooks);
|
close_library (dec, lib);
|
||||||
GST_ERROR_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
|
GST_ERROR_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_library (GstRealVideoDecHooks hooks)
|
close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib)
|
||||||
{
|
{
|
||||||
if (hooks.context && hooks.free)
|
if (lib->context) {
|
||||||
hooks.free (hooks.context);
|
GST_LOG_OBJECT (dec, "closing library");
|
||||||
|
if (lib->Free)
|
||||||
if (hooks.module) {
|
lib->Free (lib->context);
|
||||||
g_module_close (hooks.module);
|
|
||||||
hooks.module = NULL;
|
|
||||||
}
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GstStateChangeReturn ret;
|
||||||
|
GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (element);
|
||||||
|
|
||||||
|
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
|
static void
|
||||||
gst_real_video_dec_init (GstRealVideoDec * dec, GstRealVideoDecClass * klass)
|
gst_real_video_dec_init (GstRealVideoDec * dec, GstRealVideoDecClass * klass)
|
||||||
{
|
{
|
||||||
dec->snk = gst_pad_new_from_static_template (&snk_t, "sink");
|
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_pad_set_setcaps_function (dec->snk,
|
||||||
GST_DEBUG_FUNCPTR (gst_real_video_dec_setcaps));
|
GST_DEBUG_FUNCPTR (gst_real_video_dec_setcaps));
|
||||||
gst_pad_set_chain_function (dec->snk,
|
gst_pad_set_chain_function (dec->snk,
|
||||||
GST_DEBUG_FUNCPTR (gst_real_video_dec_chain));
|
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);
|
gst_element_add_pad (GST_ELEMENT (dec), dec->snk);
|
||||||
|
|
||||||
dec->src = gst_pad_new_from_static_template (&src_t, "src");
|
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);
|
GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (object);
|
||||||
|
|
||||||
close_library (dec->hooks);
|
close_library (dec, &dec->lib);
|
||||||
memset (&dec->hooks, 0, sizeof (dec->hooks));
|
|
||||||
|
|
||||||
if (dec->real_codecs_path) {
|
if (dec->real_codecs_path) {
|
||||||
g_free (dec->real_codecs_path);
|
g_free (dec->real_codecs_path);
|
||||||
|
@ -641,11 +729,14 @@ static void
|
||||||
gst_real_video_dec_class_init (GstRealVideoDecClass * klass)
|
gst_real_video_dec_class_init (GstRealVideoDecClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (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->set_property = gst_real_video_dec_set_property;
|
||||||
object_class->get_property = gst_real_video_dec_get_property;
|
object_class->get_property = gst_real_video_dec_get_property;
|
||||||
object_class->finalize = gst_real_video_dec_finalize;
|
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_object_class_install_property (object_class, PROP_REAL_CODECS_PATH,
|
||||||
g_param_spec_string ("real-codecs-path",
|
g_param_spec_string ("real-codecs-path",
|
||||||
"Path where to search for RealPlayer codecs",
|
"Path where to search for RealPlayer codecs",
|
||||||
|
|
|
@ -35,11 +35,6 @@ typedef struct _GstRealVideoDec GstRealVideoDec;
|
||||||
typedef struct _GstRealVideoDecClass GstRealVideoDecClass;
|
typedef struct _GstRealVideoDecClass GstRealVideoDecClass;
|
||||||
typedef enum _GstRealVideoDecVersion GstRealVideoDecVersion;
|
typedef enum _GstRealVideoDecVersion GstRealVideoDecVersion;
|
||||||
|
|
||||||
typedef guint32 (*GstRealVideoDecMessageFunc) (gpointer, gpointer);
|
|
||||||
typedef guint32 (*GstRealVideoDecFreeFunc) (gpointer);
|
|
||||||
typedef guint32 (*GstRealVideoDecInitFunc) (gpointer, gpointer);
|
|
||||||
typedef guint32 (*GstRealVideoDecTransformFunc) (gchar *, gchar *, gpointer, gpointer, gpointer);
|
|
||||||
|
|
||||||
enum _GstRealVideoDecVersion
|
enum _GstRealVideoDecVersion
|
||||||
{
|
{
|
||||||
GST_REAL_VIDEO_DEC_VERSION_2 = 2,
|
GST_REAL_VIDEO_DEC_VERSION_2 = 2,
|
||||||
|
@ -50,13 +45,21 @@ enum _GstRealVideoDecVersion
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GModule *module;
|
GModule *module;
|
||||||
|
|
||||||
|
gpointer context;
|
||||||
|
|
||||||
|
guint32 (*Init) (gpointer, gpointer);
|
||||||
|
guint32 (*Free) (gpointer);
|
||||||
|
guint32 (*Transform) (gchar *, gchar *, gpointer, gpointer, gpointer);
|
||||||
|
guint32 (*Message) (gpointer, gpointer);
|
||||||
|
|
||||||
|
/*
|
||||||
GstRealVideoDecMessageFunc custom_message;
|
GstRealVideoDecMessageFunc custom_message;
|
||||||
GstRealVideoDecFreeFunc free;
|
GstRealVideoDecFreeFunc free;
|
||||||
GstRealVideoDecInitFunc init;
|
GstRealVideoDecInitFunc init;
|
||||||
GstRealVideoDecTransformFunc transform;
|
GstRealVideoDecTransformFunc transform;
|
||||||
|
*/
|
||||||
|
|
||||||
gpointer context;
|
} GstRVDecLibrary;
|
||||||
} GstRealVideoDecHooks;
|
|
||||||
|
|
||||||
struct _GstRealVideoDec
|
struct _GstRealVideoDec
|
||||||
{
|
{
|
||||||
|
@ -72,14 +75,18 @@ struct _GstRealVideoDec
|
||||||
|
|
||||||
gint error_count;
|
gint error_count;
|
||||||
|
|
||||||
/* Hooks */
|
/* Library functions */
|
||||||
GstRealVideoDecHooks hooks;
|
GstRVDecLibrary lib;
|
||||||
|
|
||||||
/* Properties */
|
/* Properties */
|
||||||
gchar *real_codecs_path;
|
gchar *real_codecs_path;
|
||||||
|
gboolean checked_modules;
|
||||||
gchar *rv20_names;
|
gchar *rv20_names;
|
||||||
|
gboolean valid_rv20;
|
||||||
gchar *rv30_names;
|
gchar *rv30_names;
|
||||||
|
gboolean valid_rv30;
|
||||||
gchar *rv40_names;
|
gchar *rv40_names;
|
||||||
|
gboolean valid_rv40;
|
||||||
gint max_errors;
|
gint max_errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue