gst/real/gstrealvideodec.*: Implement error recovery on setcaps failure.
Original commit message from CVS: Patch by: Lutz Mueller <lutz@topfrose.de> * gst/real/gstrealvideodec.c: (gst_real_video_dec_decode), (gst_real_video_dec_setcaps), (open_library), (close_library), (gst_real_video_dec_finalize): * gst/real/gstrealvideodec.h: Implement error recovery on setcaps failure.
This commit is contained in:
parent
bda3b5839a
commit
30d26643a6
10
ChangeLog
10
ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2007-01-06 Edward Hervey <edward@fluendo.com>
|
||||||
|
|
||||||
|
Patch by: Lutz Mueller <lutz@topfrose.de>
|
||||||
|
|
||||||
|
* gst/real/gstrealvideodec.c: (gst_real_video_dec_decode),
|
||||||
|
(gst_real_video_dec_setcaps), (open_library), (close_library),
|
||||||
|
(gst_real_video_dec_finalize):
|
||||||
|
* gst/real/gstrealvideodec.h:
|
||||||
|
Implement error recovery on setcaps failure.
|
||||||
|
|
||||||
2007-01-06 Edward Hervey <edward@fluendo.com>
|
2007-01-06 Edward Hervey <edward@fluendo.com>
|
||||||
|
|
||||||
Patch by: Lutz Mueller <lutz@topfrose.de>
|
Patch by: Lutz Mueller <lutz@topfrose.de>
|
||||||
|
@ -69,8 +69,9 @@ enum
|
|||||||
GST_BOILERPLATE (GstRealVideoDec, gst_real_video_dec, GstElement,
|
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,
|
||||||
static void close_library (GstRealVideoDec * dec);
|
GstRealVideoDecHooks * hooks, GstRealVideoDecVersion version);
|
||||||
|
static void close_library (GstRealVideoDecHooks hooks);
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -352,9 +353,9 @@ gst_real_video_dec_decode (GstRealVideoDec * dec, GstBuffer * in, guint offset)
|
|||||||
tin.timestamp = GST_BUFFER_TIMESTAMP (out);
|
tin.timestamp = GST_BUFFER_TIMESTAMP (out);
|
||||||
data = gst_adapter_take (dec->adapter, dec->length);
|
data = gst_adapter_take (dec->adapter, dec->length);
|
||||||
|
|
||||||
result = dec->transform (
|
result = dec->hooks.transform (
|
||||||
(gchar *) data,
|
(gchar *) data,
|
||||||
(gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->context);
|
(gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->hooks.context);
|
||||||
|
|
||||||
g_free (data);
|
g_free (data);
|
||||||
if (result)
|
if (result)
|
||||||
@ -489,36 +490,37 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
|
|||||||
{
|
{
|
||||||
GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
|
GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
|
||||||
GstStructure *s = gst_caps_get_structure (caps, 0);
|
GstStructure *s = gst_caps_get_structure (caps, 0);
|
||||||
gint version, res;
|
gint version, res, width, height, format, subformat;
|
||||||
|
gint framerate_num, framerate_denom;
|
||||||
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 *) & dec->width) ||
|
!gst_structure_get_int (s, "width", (gint *) & width) ||
|
||||||
!gst_structure_get_int (s, "height", (gint *) & dec->height) ||
|
!gst_structure_get_int (s, "height", (gint *) & height) ||
|
||||||
!gst_structure_get_int (s, "format", &dec->format) ||
|
!gst_structure_get_int (s, "format", &format) ||
|
||||||
!gst_structure_get_int (s, "subformat", &dec->subformat) ||
|
!gst_structure_get_int (s, "subformat", &subformat) ||
|
||||||
!gst_structure_get_fraction (s, "framerate", &dec->framerate_num,
|
!gst_structure_get_fraction (s, "framerate", &framerate_num,
|
||||||
&dec->framerate_denom))
|
&framerate_denom))
|
||||||
goto missing_keys;
|
goto missing_keys;
|
||||||
dec->version = version;
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (dec, "Setting version to %d", version);
|
GST_LOG_OBJECT (dec, "Setting version to %d", version);
|
||||||
|
|
||||||
if (!open_library (dec))
|
if (!open_library (dec, &hooks, version))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* Initialize REAL driver. */
|
/* Initialize REAL driver. */
|
||||||
GST_WRITE_UINT16_LE (data + 0, 11);
|
GST_WRITE_UINT16_LE (data + 0, 11);
|
||||||
GST_WRITE_UINT16_LE (data + 2, dec->width);
|
GST_WRITE_UINT16_LE (data + 2, width);
|
||||||
GST_WRITE_UINT16_LE (data + 4, dec->height);
|
GST_WRITE_UINT16_LE (data + 4, height);
|
||||||
GST_WRITE_UINT16_LE (data + 6, 0);
|
GST_WRITE_UINT16_LE (data + 6, 0);
|
||||||
GST_WRITE_UINT32_LE (data + 8, 0);
|
GST_WRITE_UINT32_LE (data + 8, 0);
|
||||||
GST_WRITE_UINT32_LE (data + 12, dec->subformat);
|
GST_WRITE_UINT32_LE (data + 12, subformat);
|
||||||
GST_WRITE_UINT32_LE (data + 16, 0);
|
GST_WRITE_UINT32_LE (data + 16, 0);
|
||||||
GST_WRITE_UINT32_LE (data + 20, dec->format);
|
GST_WRITE_UINT32_LE (data + 20, format);
|
||||||
res = dec->init (&data, &dec->context);
|
res = hooks.init (&data, &hooks.context);
|
||||||
if (res)
|
if (res)
|
||||||
goto could_not_initialize;
|
goto could_not_initialize;
|
||||||
|
|
||||||
@ -544,16 +546,16 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
|
|||||||
goto could_not_allocate;
|
goto could_not_allocate;
|
||||||
|
|
||||||
msg.type = 0x24;
|
msg.type = 0x24;
|
||||||
msg.msg = 1 + ((dec->subformat >> 16) & 7);
|
msg.msg = 1 + ((subformat >> 16) & 7);
|
||||||
msg.data = msgdata;
|
msg.data = msgdata;
|
||||||
for (i = 0; i < 6; i++)
|
for (i = 0; i < 6; i++)
|
||||||
msg.extra[i] = 0;
|
msg.extra[i] = 0;
|
||||||
msgdata[0] = dec->width;
|
msgdata[0] = width;
|
||||||
msgdata[1] = dec->height;
|
msgdata[1] = height;
|
||||||
for (i = 0; i < GST_BUFFER_SIZE (buf); i++)
|
for (i = 0; i < GST_BUFFER_SIZE (buf); i++)
|
||||||
msgdata[i + 2] = 4 * GST_BUFFER_DATA (buf)[i];
|
msgdata[i + 2] = 4 * GST_BUFFER_DATA (buf)[i];
|
||||||
|
|
||||||
res = dec->custom_message (&msg, dec->context);
|
res = hooks.custom_message (&msg, hooks.context);
|
||||||
|
|
||||||
g_free (msgdata);
|
g_free (msgdata);
|
||||||
if (res)
|
if (res)
|
||||||
@ -562,13 +564,23 @@ gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
|
|||||||
|
|
||||||
caps = gst_caps_new_simple ("video/x-raw-yuv",
|
caps = gst_caps_new_simple ("video/x-raw-yuv",
|
||||||
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
|
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
|
||||||
"framerate", GST_TYPE_FRACTION, dec->framerate_num, dec->framerate_denom,
|
"framerate", GST_TYPE_FRACTION, framerate_num, framerate_denom,
|
||||||
"width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, NULL);
|
"width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
|
||||||
bres = gst_pad_set_caps (GST_PAD (dec->src), caps);
|
bres = gst_pad_set_caps (GST_PAD (dec->src), caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (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->width = width;
|
||||||
|
dec->height = height;
|
||||||
|
dec->format = format;
|
||||||
|
dec->subformat = subformat;
|
||||||
|
dec->framerate_num = framerate_num;
|
||||||
|
dec->framerate_denom = framerate_denom;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
missing_keys:
|
missing_keys:
|
||||||
@ -579,24 +591,21 @@ missing_keys:
|
|||||||
|
|
||||||
could_not_initialize:
|
could_not_initialize:
|
||||||
{
|
{
|
||||||
dlclose (dec->handle);
|
close_library (hooks);
|
||||||
dec->handle = NULL;
|
|
||||||
GST_DEBUG_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
GST_DEBUG_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_allocate:
|
could_not_allocate:
|
||||||
{
|
{
|
||||||
dlclose (dec->handle);
|
close_library (hooks);
|
||||||
dec->handle = NULL;
|
|
||||||
GST_DEBUG_OBJECT (dec, "Could not allocate memory.");
|
GST_DEBUG_OBJECT (dec, "Could not allocate memory.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
could_not_send_message:
|
could_not_send_message:
|
||||||
{
|
{
|
||||||
dlclose (dec->handle);
|
close_library (hooks);
|
||||||
dec->handle = NULL;
|
|
||||||
GST_DEBUG_OBJECT (dec, "Failed to send custom message needed for "
|
GST_DEBUG_OBJECT (dec, "Failed to send custom message needed for "
|
||||||
"initialization (%i).", res);
|
"initialization (%i).", res);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -604,8 +613,7 @@ could_not_send_message:
|
|||||||
|
|
||||||
could_not_set_caps:
|
could_not_set_caps:
|
||||||
{
|
{
|
||||||
dlclose (dec->handle);
|
close_library (hooks);
|
||||||
dec->handle = NULL;
|
|
||||||
GST_DEBUG_OBJECT (dec, "Could not convince peer to accept dimensions "
|
GST_DEBUG_OBJECT (dec, "Could not convince peer to accept dimensions "
|
||||||
"%i x %i.", dec->width, dec->height);
|
"%i x %i.", dec->width, dec->height);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -615,20 +623,20 @@ 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)
|
open_library (GstRealVideoDec * dec, GstRealVideoDecHooks * hooks,
|
||||||
|
GstRealVideoDecVersion version)
|
||||||
{
|
{
|
||||||
gchar *path = NULL;
|
gchar *path = NULL;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec,
|
GST_DEBUG_OBJECT (dec,
|
||||||
"Attempting to open shared library for real video version %d",
|
"Attempting to open shared library for real video version %d", version);
|
||||||
dec->version);
|
|
||||||
|
|
||||||
/* FIXME : Search for the correct library in various places if dec->path_rv20
|
/* FIXME : Search for the correct library in various places if dec->path_rv20
|
||||||
* isn't set explicitely !
|
* isn't set explicitely !
|
||||||
* Library names can also be different (ex : drv30.so vs drvc.so)
|
* Library names can also be different (ex : drv30.so vs drvc.so)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
switch (dec->version) {
|
switch (version) {
|
||||||
case GST_REAL_VIDEO_DEC_VERSION_2:
|
case GST_REAL_VIDEO_DEC_VERSION_2:
|
||||||
{
|
{
|
||||||
if (dec->path_rv20)
|
if (dec->path_rv20)
|
||||||
@ -669,27 +677,26 @@ open_library (GstRealVideoDec * dec)
|
|||||||
goto unknown_version;
|
goto unknown_version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* First close any open library */
|
hooks->handle = dlopen (path, RTLD_LAZY);
|
||||||
close_library (dec);
|
if (!hooks->handle)
|
||||||
|
|
||||||
dec->handle = dlopen (path, RTLD_LAZY);
|
|
||||||
if (!dec->handle)
|
|
||||||
goto could_not_open;
|
goto could_not_open;
|
||||||
|
|
||||||
/* First try opening legacy symbols */
|
/* First try opening legacy symbols */
|
||||||
dec->custom_message = dlsym (dec->handle, "RV20toYUV420CustomMessage");
|
hooks->custom_message = dlsym (hooks->handle, "RV20toYUV420CustomMessage");
|
||||||
dec->free = dlsym (dec->handle, "RV20toYUV420Free");
|
hooks->free = dlsym (hooks->handle, "RV20toYUV420Free");
|
||||||
dec->init = dlsym (dec->handle, "RV20toYUV420Init");
|
hooks->init = dlsym (hooks->handle, "RV20toYUV420Init");
|
||||||
dec->transform = dlsym (dec->handle, "RV20toYUV420Transform");
|
hooks->transform = dlsym (hooks->handle, "RV20toYUV420Transform");
|
||||||
|
|
||||||
if (!(dec->custom_message && dec->free && dec->init && dec->transform)) {
|
if (!(hooks->custom_message && hooks->free && hooks->init
|
||||||
|
&& hooks->transform)) {
|
||||||
/* Else try loading new symbols */
|
/* Else try loading new symbols */
|
||||||
dec->custom_message = dlsym (dec->handle, "RV40toYUV420CustomMessage");
|
hooks->custom_message = dlsym (hooks->handle, "RV40toYUV420CustomMessage");
|
||||||
dec->free = dlsym (dec->handle, "RV40toYUV420Free");
|
hooks->free = dlsym (hooks->handle, "RV40toYUV420Free");
|
||||||
dec->init = dlsym (dec->handle, "RV40toYUV420Init");
|
hooks->init = dlsym (hooks->handle, "RV40toYUV420Init");
|
||||||
dec->transform = dlsym (dec->handle, "RV40toYUV420Transform");
|
hooks->transform = dlsym (hooks->handle, "RV40toYUV420Transform");
|
||||||
|
|
||||||
if (!(dec->custom_message && dec->free && dec->init && dec->transform))
|
if (!(hooks->custom_message && hooks->free && hooks->init
|
||||||
|
&& hooks->transform))
|
||||||
goto could_not_load;
|
goto could_not_load;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -699,13 +706,13 @@ no_known_libraries:
|
|||||||
{
|
{
|
||||||
GST_ELEMENT_ERROR (dec, LIBRARY, INIT,
|
GST_ELEMENT_ERROR (dec, LIBRARY, INIT,
|
||||||
("Couldn't find a realvideo shared library for version %d",
|
("Couldn't find a realvideo shared library for version %d",
|
||||||
dec->version), (NULL));
|
version), (NULL));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
unknown_version:
|
unknown_version:
|
||||||
{
|
{
|
||||||
GST_ERROR_OBJECT (dec, "Cannot handle version %i.", dec->version);
|
GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -717,28 +724,20 @@ could_not_open:
|
|||||||
|
|
||||||
could_not_load:
|
could_not_load:
|
||||||
{
|
{
|
||||||
close_library (dec);
|
close_library (*hooks);
|
||||||
GST_ERROR_OBJECT (dec, "Could not load all symbols.");
|
GST_ERROR_OBJECT (dec, "Could not load all symbols.");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
close_library (GstRealVideoDec * dec)
|
close_library (GstRealVideoDecHooks hooks)
|
||||||
{
|
{
|
||||||
if (dec->context && dec->free) {
|
if (hooks.context && hooks.free)
|
||||||
dec->free (dec->context);
|
hooks.free (hooks.context);
|
||||||
dec->context = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
dec->custom_message = NULL;
|
if (hooks.handle)
|
||||||
dec->free = NULL;
|
dlclose (hooks.handle);
|
||||||
dec->init = NULL;
|
|
||||||
dec->transform = NULL;
|
|
||||||
|
|
||||||
if (dec->handle)
|
|
||||||
dlclose (dec->handle);
|
|
||||||
dec->handle = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -779,7 +778,8 @@ gst_real_video_dec_finalize (GObject * object)
|
|||||||
dec->adapter = NULL;
|
dec->adapter = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
close_library (dec);
|
close_library (dec->hooks);
|
||||||
|
memset (&dec->hooks, 0, sizeof (dec->hooks));
|
||||||
|
|
||||||
if (dec->path_rv20) {
|
if (dec->path_rv20) {
|
||||||
g_free (dec->path_rv20);
|
g_free (dec->path_rv20);
|
||||||
|
@ -42,6 +42,17 @@ enum _GstRealVideoDecVersion
|
|||||||
GST_REAL_VIDEO_DEC_VERSION_4 = 4
|
GST_REAL_VIDEO_DEC_VERSION_4 = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
gpointer handle;
|
||||||
|
|
||||||
|
guint32 (*custom_message) (gpointer, gpointer);
|
||||||
|
guint32 (*free) (gpointer);
|
||||||
|
guint32 (*init) (gpointer, gpointer);
|
||||||
|
guint32 (*transform) (gchar *, gchar *, gpointer, gpointer, gpointer);
|
||||||
|
|
||||||
|
gpointer context;
|
||||||
|
} GstRealVideoDecHooks;
|
||||||
|
|
||||||
struct _GstRealVideoDec
|
struct _GstRealVideoDec
|
||||||
{
|
{
|
||||||
GstElement parent;
|
GstElement parent;
|
||||||
@ -59,14 +70,7 @@ struct _GstRealVideoDec
|
|||||||
guint16 next_seq, last_seq;
|
guint16 next_seq, last_seq;
|
||||||
|
|
||||||
/* Hooks */
|
/* Hooks */
|
||||||
gpointer handle;
|
GstRealVideoDecHooks hooks;
|
||||||
guint32 (*custom_message) (gpointer, gpointer);
|
|
||||||
guint32 (*free) (gpointer);
|
|
||||||
guint32 (*init) (gpointer, gpointer);
|
|
||||||
guint32 (*transform) (gchar *, gchar *, gpointer, gpointer, gpointer);
|
|
||||||
|
|
||||||
/* Used by the REAL library. */
|
|
||||||
gpointer context;
|
|
||||||
|
|
||||||
/* State */
|
/* State */
|
||||||
GstAdapter *adapter;
|
GstAdapter *adapter;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user