mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 04:01:08 +00:00
jpegdec: add "max-errors" property to ignore decoding errors
Add property to ignore decoding errors. Default is to ignore a few decoding errors if the input is packetized, but error out immediately if the input is not packetized. Ignoring errors for packetized input most likely doesn't work properly yet, so don't do that for now. https://bugzilla.gnome.org/show_bug.cgi?id=623063
This commit is contained in:
parent
100673bf14
commit
addbc3c4ca
2 changed files with 140 additions and 19 deletions
|
@ -52,11 +52,13 @@
|
|||
(((struct GstJpegDecSourceMgr*)((cinfo_ptr)->src))->dec)
|
||||
|
||||
#define JPEG_DEFAULT_IDCT_METHOD JDCT_FASTEST
|
||||
#define JPEG_DEFAULT_MAX_ERRORS 0
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_IDCT_METHOD
|
||||
PROP_IDCT_METHOD,
|
||||
PROP_MAX_ERRORS
|
||||
};
|
||||
|
||||
/* *INDENT-OFF* */
|
||||
|
@ -192,6 +194,21 @@ gst_jpeg_dec_class_init (GstJpegDecClass * klass)
|
|||
JPEG_DEFAULT_IDCT_METHOD,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstJpegDec:max-errors
|
||||
*
|
||||
* Error out after receiving N consecutive decoding errors
|
||||
* (-1 = never error out, 0 = automatic, 1 = fail on first error, etc.)
|
||||
*
|
||||
* Since: 0.10.27
|
||||
**/
|
||||
g_object_class_install_property (gobject_class, PROP_MAX_ERRORS,
|
||||
g_param_spec_int ("max-errors", "Maximum Consecutive Decoding Errors",
|
||||
"Error out after receiving N consecutive decoding errors "
|
||||
"(-1 = never fail, 0 = automatic, 1 = fail on first error)",
|
||||
-1, G_MAXINT, JPEG_DEFAULT_MAX_ERRORS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
gstelement_class->change_state =
|
||||
GST_DEBUG_FUNCPTR (gst_jpeg_dec_change_state);
|
||||
|
||||
|
@ -199,6 +216,81 @@ gst_jpeg_dec_class_init (GstJpegDecClass * klass)
|
|||
GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_jpeg_dec_clear_error (GstJpegDec * dec)
|
||||
{
|
||||
g_free (dec->error_msg);
|
||||
dec->error_msg = NULL;
|
||||
dec->error_line = 0;
|
||||
dec->error_func = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_jpeg_dec_set_error_va (GstJpegDec * dec, const gchar * func, gint line,
|
||||
const gchar * debug_msg_format, va_list args)
|
||||
{
|
||||
#ifndef GST_DISABLE_GST_DEBUG
|
||||
gst_debug_log_valist (GST_CAT_DEFAULT, GST_LEVEL_WARNING, __FILE__, func,
|
||||
line, (GObject *) dec, debug_msg_format, args);
|
||||
#endif
|
||||
|
||||
g_free (dec->error_msg);
|
||||
if (debug_msg_format)
|
||||
dec->error_msg = g_strdup_vprintf (debug_msg_format, args);
|
||||
else
|
||||
dec->error_msg = NULL;
|
||||
|
||||
dec->error_line = line;
|
||||
dec->error_func = func;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_jpeg_dec_set_error (GstJpegDec * dec, const gchar * func, gint line,
|
||||
const gchar * debug_msg_format, ...)
|
||||
{
|
||||
va_list va;
|
||||
|
||||
va_start (va, debug_msg_format);
|
||||
gst_jpeg_dec_set_error_va (dec, func, line, debug_msg_format, va);
|
||||
va_end (va);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_jpeg_dec_post_error_or_warning (GstJpegDec * dec)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
int max_errors;
|
||||
|
||||
++dec->error_count;
|
||||
max_errors = g_atomic_int_get (&dec->max_errors);
|
||||
|
||||
if (max_errors < 0) {
|
||||
ret = GST_FLOW_OK;
|
||||
} else if (max_errors == 0) {
|
||||
/* FIXME: do something more clever in "automatic mode" */
|
||||
if (dec->packetized) {
|
||||
ret = (dec->error_count < 3) ? GST_FLOW_OK : GST_FLOW_ERROR;
|
||||
} else {
|
||||
ret = GST_FLOW_ERROR;
|
||||
}
|
||||
} else {
|
||||
ret = (dec->error_count < max_errors) ? GST_FLOW_OK : GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (dec, "decoding error %d/%d (%s)", dec->error_count,
|
||||
max_errors, (ret == GST_FLOW_OK) ? "ignoring error" : "erroring out");
|
||||
|
||||
gst_element_message_full (GST_ELEMENT (dec),
|
||||
(ret == GST_FLOW_OK) ? GST_MESSAGE_WARNING : GST_MESSAGE_ERROR,
|
||||
GST_STREAM_ERROR, GST_STREAM_ERROR_DECODE,
|
||||
g_strdup (_("Failed to decode JPEG image")), dec->error_msg,
|
||||
__FILE__, dec->error_func, dec->error_line);
|
||||
|
||||
dec->error_msg = NULL;
|
||||
gst_jpeg_dec_clear_error (dec);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static boolean
|
||||
gst_jpeg_dec_fill_input_buffer (j_decompress_ptr cinfo)
|
||||
{
|
||||
|
@ -346,6 +438,7 @@ gst_jpeg_dec_init (GstJpegDec * dec)
|
|||
|
||||
/* init properties */
|
||||
dec->idct_method = JPEG_DEFAULT_IDCT_METHOD;
|
||||
dec->max_errors = JPEG_DEFAULT_MAX_ERRORS;
|
||||
|
||||
dec->adapter = gst_adapter_new ();
|
||||
}
|
||||
|
@ -954,10 +1047,9 @@ gst_jpeg_dec_decode_direct (GstJpegDec * dec, guchar * base[3],
|
|||
|
||||
format_not_supported:
|
||||
{
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||
(_("Failed to decode JPEG image")),
|
||||
("Unsupported subsampling schema: v_samp factors: %u %u %u",
|
||||
v_samp[0], v_samp[1], v_samp[2]));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Unsupported subsampling schema: v_samp factors: %u %u %u",
|
||||
v_samp[0], v_samp[1], v_samp[2]);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
@ -1440,6 +1532,11 @@ again:
|
|||
goto drop_buffer;
|
||||
}
|
||||
|
||||
/* reset error count on successful decode */
|
||||
dec->error_count = 0;
|
||||
|
||||
++dec->good_count;
|
||||
|
||||
GST_LOG_OBJECT (dec, "pushing buffer (ts=%" GST_TIME_FORMAT ", dur=%"
|
||||
GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
|
||||
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
|
||||
|
@ -1452,6 +1549,11 @@ done:
|
|||
|
||||
exit:
|
||||
|
||||
if (G_UNLIKELY (ret == GST_FLOW_ERROR)) {
|
||||
jpeg_abort_decompress (&dec->cinfo);
|
||||
ret = gst_jpeg_dec_post_error_or_warning (dec);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
/* special cases */
|
||||
|
@ -1468,9 +1570,8 @@ need_more_data:
|
|||
/* ERRORS */
|
||||
wrong_size:
|
||||
{
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||
("Picture is too small or too big (%ux%u)", width, height),
|
||||
("Picture is too small or too big (%ux%u)", width, height));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Picture is too small or too big (%ux%u)", width, height);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1480,8 +1581,9 @@ decode_error:
|
|||
|
||||
dec->jerr.pub.format_message ((j_common_ptr) (&dec->cinfo), err_msg);
|
||||
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||
(_("Failed to decode JPEG image")), ("Error #%u: %s", code, err_msg));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Decode error #%u: %s", code, err_msg);
|
||||
|
||||
if (outbuf) {
|
||||
gst_buffer_unref (outbuf);
|
||||
outbuf = NULL;
|
||||
|
@ -1507,9 +1609,8 @@ alloc_failed:
|
|||
jpeg_abort_decompress (&dec->cinfo);
|
||||
if (ret != GST_FLOW_UNEXPECTED && ret != GST_FLOW_WRONG_STATE &&
|
||||
ret != GST_FLOW_NOT_LINKED) {
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||
("Buffer allocation failed, reason: %s", reason),
|
||||
("Buffer allocation failed, reason: %s", reason));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Buffer allocation failed, reason: %s", reason);
|
||||
}
|
||||
goto exit;
|
||||
}
|
||||
|
@ -1522,22 +1623,22 @@ drop_buffer:
|
|||
}
|
||||
components_not_supported:
|
||||
{
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
|
||||
("more components than supported: %d > 3", dec->cinfo.num_components));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"more components than supported: %d > 3", dec->cinfo.num_components);
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
unsupported_colorspace:
|
||||
{
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
|
||||
("Picture has unknown or unsupported colourspace"));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Picture has unknown or unsupported colourspace");
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
invalid_yuvrgbgrayscale:
|
||||
{
|
||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
|
||||
("Picture is corrupt or unhandled YUV/RGB/grayscale layout"));
|
||||
gst_jpeg_dec_set_error (dec, GST_FUNCTION, __LINE__,
|
||||
"Picture is corrupt or unhandled YUV/RGB/grayscale layout");
|
||||
ret = GST_FLOW_ERROR;
|
||||
goto done;
|
||||
}
|
||||
|
@ -1632,6 +1733,9 @@ gst_jpeg_dec_set_property (GObject * object, guint prop_id,
|
|||
case PROP_IDCT_METHOD:
|
||||
dec->idct_method = g_value_get_enum (value);
|
||||
break;
|
||||
case PROP_MAX_ERRORS:
|
||||
g_atomic_int_set (&dec->max_errors, g_value_get_int (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -1651,6 +1755,9 @@ gst_jpeg_dec_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
case PROP_IDCT_METHOD:
|
||||
g_value_set_enum (value, dec->idct_method);
|
||||
break;
|
||||
case PROP_MAX_ERRORS:
|
||||
g_value_set_int (value, g_atomic_int_get (&dec->max_errors));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
|
@ -1668,6 +1775,8 @@ gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
|
|||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||
dec->error_count = 0;
|
||||
dec->good_count = 0;
|
||||
dec->framerate_numerator = 0;
|
||||
dec->framerate_denominator = 1;
|
||||
dec->caps_framerate_numerator = dec->caps_framerate_denominator = 0;
|
||||
|
|
|
@ -113,6 +113,18 @@ struct _GstJpegDec {
|
|||
|
||||
/* properties */
|
||||
gint idct_method;
|
||||
gint max_errors; /* ATOMIC */
|
||||
|
||||
/* current error (the message is the debug message) */
|
||||
gchar *error_msg;
|
||||
int error_line;
|
||||
const gchar *error_func;
|
||||
|
||||
/* number of errors since start or last successfully decoded image */
|
||||
guint error_count;
|
||||
|
||||
/* number of successfully decoded images since start */
|
||||
guint good_count;
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct GstJpegDecErrorMgr jerr;
|
||||
|
|
Loading…
Reference in a new issue