From 6ce8a5609f379fafd4feef6899f7f4e8012da0b4 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 19 May 2010 17:13:17 +0200 Subject: [PATCH] [MOVED FROM BAD 018/134] vp8: Improve error handling and debug output --- ext/vp8/Makefile.am | 2 + ext/vp8/gstvp8dec.c | 34 +++++++++------- ext/vp8/gstvp8enc.c | 105 ++++++++++++++++++++++---------------------------- ext/vp8/gstvp8utils.c | 57 +++++++++++++++++++++++++++ ext/vp8/gstvp8utils.h | 30 +++++++++++++++ 5 files changed, 156 insertions(+), 72 deletions(-) create mode 100644 ext/vp8/gstvp8utils.c create mode 100644 ext/vp8/gstvp8utils.h diff --git a/ext/vp8/Makefile.am b/ext/vp8/Makefile.am index 583f263..5487b35 100644 --- a/ext/vp8/Makefile.am +++ b/ext/vp8/Makefile.am @@ -4,6 +4,7 @@ plugin_LTLIBRARIES = \ libgstvp8_la_SOURCES = \ gstvp8dec.c \ gstvp8enc.c \ + gstvp8utils.c \ plugin.c \ gst/video/gstbasevideocodec.c \ gst/video/gstbasevideodecoder.c \ @@ -33,6 +34,7 @@ libgstvp8_la_LIBADD += $(GST_PLUGINS_BASE_LIBS) -lgsttag-@GST_MAJORMINOR@ -lgstv libgstvp8_la_LIBADD += $(VPX_LIBS) noinst_HEADERS = \ + gstvp8utils.h \ gst/video/gstbasevideocodec.h \ gst/video/gstbasevideodecoder.h \ gst/video/gstbasevideoencoder.h \ diff --git a/ext/vp8/gstvp8dec.c b/ext/vp8/gstvp8dec.c index 00eb7e2..f6d08f4 100644 --- a/ext/vp8/gstvp8dec.c +++ b/ext/vp8/gstvp8dec.c @@ -36,6 +36,7 @@ #include #include +#include "gstvp8utils.h" GST_DEBUG_CATEGORY (gst_vp8dec_debug); #define GST_CAT_DEFAULT gst_vp8dec_debug @@ -156,7 +157,7 @@ gst_vp8_dec_class_init (GstVP8DecClass * klass) static void gst_vp8_dec_init (GstVP8Dec * gst_vp8_dec, GstVP8DecClass * klass) { - GST_DEBUG ("gst_vp8_dec_init"); + GST_DEBUG_OBJECT (gst_vp8_dec, "gst_vp8_dec_init"); } static void @@ -164,7 +165,7 @@ gst_vp8_dec_finalize (GObject * object) { GstVP8Dec *gst_vp8_dec; - GST_DEBUG ("finalize"); + GST_DEBUG_OBJECT (object, "finalize"); g_return_if_fail (GST_IS_GST_VP8_DEC (object)); gst_vp8_dec = GST_VP8_DEC (object); @@ -181,7 +182,7 @@ gst_vp8_dec_set_property (GObject * object, guint prop_id, g_return_if_fail (GST_IS_GST_VP8_DEC (object)); src = GST_VP8_DEC (object); - GST_DEBUG ("gst_vp8_dec_set_property"); + GST_DEBUG_OBJECT (object, "gst_vp8_dec_set_property"); switch (prop_id) { default: break; @@ -210,6 +211,7 @@ gst_vp8_dec_start (GstBaseVideoDecoder * decoder) { GstVP8Dec *gst_vp8_dec = GST_VP8_DEC (decoder); + GST_DEBUG_OBJECT (gst_vp8_dec, "start"); decoder->packetized = TRUE; gst_vp8_dec->decoder_inited = FALSE; @@ -221,6 +223,7 @@ gst_vp8_dec_stop (GstBaseVideoDecoder * base_video_decoder) { GstVP8Dec *gst_vp8_dec = GST_VP8_DEC (base_video_decoder); + GST_DEBUG_OBJECT (gst_vp8_dec, "stop"); if (gst_vp8_dec->decoder_inited) vpx_codec_destroy (&gst_vp8_dec->decoder); gst_vp8_dec->decoder_inited = FALSE; @@ -232,7 +235,7 @@ gst_vp8_dec_reset (GstBaseVideoDecoder * base_video_decoder) { GstVP8Dec *decoder; - GST_DEBUG ("reset"); + GST_DEBUG_OBJECT (base_video_decoder, "reset"); decoder = GST_VP8_DEC (base_video_decoder); @@ -246,7 +249,6 @@ gst_vp8_dec_reset (GstBaseVideoDecoder * base_video_decoder) static GstFlowReturn gst_vp8_dec_parse_data (GstBaseVideoDecoder * decoder, gboolean at_eos) { - return GST_FLOW_OK; } @@ -315,12 +317,11 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) { GstVP8Dec *dec; GstFlowReturn ret; - long status; + vpx_codec_err_t status; vpx_codec_iter_t iter = NULL; vpx_image_t *img; - vpx_codec_err_t res; - GST_DEBUG ("handle_frame"); + GST_DEBUG_OBJECT (decoder, "handle_frame"); dec = GST_VP8_DEC (decoder); @@ -331,11 +332,12 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) memset (&stream_info, 0, sizeof (stream_info)); stream_info.sz = sizeof (stream_info); - res = vpx_codec_peek_stream_info (&vpx_codec_vp8_dx_algo, + status = vpx_codec_peek_stream_info (&vpx_codec_vp8_dx_algo, GST_BUFFER_DATA (frame->sink_buffer), GST_BUFFER_SIZE (frame->sink_buffer), &stream_info); - if (res != VPX_CODEC_OK || !stream_info.is_kf) { + if (status != VPX_CODEC_OK || !stream_info.is_kf) { + GST_WARNING_OBJECT (decoder, "No keyframe, skipping"); gst_base_video_decoder_skip_frame (decoder, frame); return GST_FLOW_OK; } @@ -346,11 +348,12 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) decoder->state.format = GST_VIDEO_FORMAT_I420; gst_vp8_dec_send_tags (dec); - res = + status = vpx_codec_dec_init (&dec->decoder, &vpx_codec_vp8_dx_algo, NULL, flags); - if (res != VPX_CODEC_OK) { + if (status != VPX_CODEC_OK) { GST_ELEMENT_ERROR (dec, LIBRARY, INIT, - ("Failed to initialize VP8 decoder"), (NULL)); + ("Failed to initialize VP8 decoder"), ("%s", + gst_vpx_error_name (status))); return GST_FLOW_ERROR; } dec->decoder_inited = TRUE; @@ -376,7 +379,8 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) ret = gst_base_video_decoder_alloc_src_frame (decoder, frame); if (ret != GST_FLOW_OK) { - GST_WARNING ("failed to get buffer"); + GST_WARNING_OBJECT (decoder, "failed to get buffer: %s", + gst_flow_get_name (ret)); goto out; } @@ -384,6 +388,8 @@ gst_vp8_dec_handle_frame (GstBaseVideoDecoder * decoder, GstVideoFrame * frame) GST_BUFFER_DATA (frame->sink_buffer), GST_BUFFER_SIZE (frame->sink_buffer), NULL, 0); if (status) { + GST_ELEMENT_ERROR (decoder, LIBRARY, ENCODE, + ("Failed to decode frame"), ("%s", gst_vpx_error_name (status))); return GST_FLOW_ERROR; } diff --git a/ext/vp8/gstvp8enc.c b/ext/vp8/gstvp8enc.c index bb22dfe..f4d9e27 100644 --- a/ext/vp8/gstvp8enc.c +++ b/ext/vp8/gstvp8enc.c @@ -38,6 +38,7 @@ #include #include +#include "gstvp8utils.h" GST_DEBUG_CATEGORY (gst_vp8enc_debug); #define GST_CAT_DEFAULT gst_vp8enc_debug @@ -138,9 +139,6 @@ static gboolean gst_vp8_enc_sink_event (GstPad * pad, GstEvent * event); GType gst_vp8_enc_get_type (void); -static const char *vpx_error_name (vpx_codec_err_t status); - - static GstStaticPadTemplate gst_vp8_enc_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -250,14 +248,13 @@ gst_vp8_enc_class_init (GstVP8EncClass * klass) "Speed", 0, 2, DEFAULT_SPEED, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); - } static void gst_vp8_enc_init (GstVP8Enc * gst_vp8_enc, GstVP8EncClass * klass) { - GST_DEBUG ("init"); + GST_DEBUG_OBJECT (gst_vp8_enc, "init"); gst_vp8_enc->bitrate = DEFAULT_BITRATE; gst_vp8_enc->quality = DEFAULT_QUALITY; @@ -277,7 +274,7 @@ gst_vp8_enc_finalize (GObject * object) { GstVP8Enc *gst_vp8_enc; - GST_DEBUG ("finalize"); + GST_DEBUG_OBJECT (object, "finalize"); g_return_if_fail (GST_IS_GST_VP8_ENC (object)); gst_vp8_enc = GST_VP8_ENC (object); @@ -295,7 +292,7 @@ gst_vp8_enc_set_property (GObject * object, guint prop_id, g_return_if_fail (GST_IS_GST_VP8_ENC (object)); gst_vp8_enc = GST_VP8_ENC (object); - GST_DEBUG ("gst_vp8_enc_set_property"); + GST_DEBUG_OBJECT (object, "gst_vp8_enc_set_property"); switch (prop_id) { case PROP_BITRATE: gst_vp8_enc->bitrate = g_value_get_int (value); @@ -359,7 +356,7 @@ gst_vp8_enc_start (GstBaseVideoEncoder * base_video_encoder) { GstVP8Enc *encoder; - GST_DEBUG ("start"); + GST_DEBUG_OBJECT (base_video_encoder, "start"); encoder = GST_VP8_ENC (base_video_encoder); @@ -371,6 +368,8 @@ gst_vp8_enc_stop (GstBaseVideoEncoder * base_video_encoder) { GstVP8Enc *encoder; + GST_DEBUG_OBJECT (base_video_encoder, "stop"); + encoder = GST_VP8_ENC (base_video_encoder); if (encoder->inited) { @@ -389,11 +388,10 @@ gst_vp8_enc_set_format (GstBaseVideoEncoder * base_video_encoder, { GstVP8Enc *encoder; - GST_DEBUG ("set_format"); + GST_DEBUG_OBJECT (base_video_encoder, "set_format"); encoder = GST_VP8_ENC (base_video_encoder); - return TRUE; } @@ -423,7 +421,6 @@ gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder) "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d, NULL); - /* Create Ogg stream-info */ stream_hdr = gst_buffer_new_and_alloc (24); data = GST_BUFFER_DATA (stream_hdr); @@ -479,11 +476,11 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder) GstVP8Enc *encoder; GstVideoFrame *frame; int flags = 0; - int status; + vpx_codec_err_t status; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; - GST_DEBUG ("finish"); + GST_DEBUG_OBJECT (base_video_encoder, "finish"); encoder = GST_VP8_ENC (base_video_encoder); @@ -491,7 +488,9 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder) vpx_codec_encode (&encoder->encoder, NULL, encoder->n_frames, 1, flags, 0); if (status != 0) { - GST_ERROR ("encode returned %d %s", status, vpx_error_name (status)); + GST_ERROR_OBJECT (encoder, "encode returned %d %s", status, + gst_vpx_error_name (status)); + return FALSE; } pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter); @@ -500,18 +499,19 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder) GstVP8EncCoderHook *hook; gboolean invisible, keyframe; - GST_DEBUG ("packet %d type %d", pkt->data.frame.sz, pkt->kind); + GST_DEBUG_OBJECT (encoder, "packet %d type %d", pkt->data.frame.sz, + pkt->kind); if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) { - GST_ERROR ("non frame pkt"); + GST_ERROR_OBJECT (encoder, "non frame pkt"); continue; } invisible = (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) != 0; keyframe = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; frame = gst_base_video_encoder_get_oldest_frame (base_video_encoder); + g_assert (frame != NULL); hook = frame->coder_hook; - /* FIXME: If frame is NULL something went really wrong! */ buffer = gst_buffer_new_and_alloc (pkt->data.frame.sz); @@ -536,33 +536,6 @@ gst_vp8_enc_finish (GstBaseVideoEncoder * base_video_encoder) return TRUE; } -static const char * -vpx_error_name (vpx_codec_err_t status) -{ - switch (status) { - case VPX_CODEC_OK: - return "OK"; - case VPX_CODEC_ERROR: - return "error"; - case VPX_CODEC_MEM_ERROR: - return "mem error"; - case VPX_CODEC_ABI_MISMATCH: - return "abi mismatch"; - case VPX_CODEC_INCAPABLE: - return "incapable"; - case VPX_CODEC_UNSUP_BITSTREAM: - return "unsupported bitstream"; - case VPX_CODEC_UNSUP_FEATURE: - return "unsupported feature"; - case VPX_CODEC_CORRUPT_FRAME: - return "corrupt frame"; - case VPX_CODEC_INVALID_PARAM: - return "invalid parameter"; - default: - return "unknown"; - } -} - static vpx_image_t * gst_vp8_enc_buffer_to_image (GstVP8Enc * enc, GstBuffer * buffer) { @@ -612,14 +585,14 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, GstVP8Enc *encoder; const GstVideoState *state; guint8 *src; - long status; + vpx_codec_err_t status; int flags = 0; vpx_codec_iter_t iter = NULL; const vpx_codec_cx_pkt_t *pkt; vpx_image_t *image; GstVP8EncCoderHook *hook; - GST_DEBUG ("handle_frame"); + GST_DEBUG_OBJECT (base_video_encoder, "handle_frame"); encoder = GST_VP8_ENC (base_video_encoder); src = GST_BUFFER_DATA (frame->sink_buffer); @@ -627,13 +600,19 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, state = gst_base_video_encoder_get_state (base_video_encoder); encoder->n_frames++; - GST_DEBUG ("res id %d size %d %d", encoder->resolution_id, - state->width, state->height); + GST_DEBUG_OBJECT (base_video_encoder, "res id %d size %d %d", + encoder->resolution_id, state->width, state->height); if (!encoder->inited) { vpx_codec_enc_cfg_t cfg; - vpx_codec_enc_config_default (&vpx_codec_vp8_cx_algo, &cfg, 0); + status = vpx_codec_enc_config_default (&vpx_codec_vp8_cx_algo, &cfg, 0); + if (status != VPX_CODEC_OK) { + GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, + ("Failed to get default encoder configuration"), ("%s", + gst_vpx_error_name (status))); + return FALSE; + } cfg.g_w = base_video_encoder->state.width; cfg.g_h = base_video_encoder->state.height; @@ -664,7 +643,8 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, &cfg, 0); if (status) { GST_ELEMENT_ERROR (encoder, LIBRARY, INIT, - ("Failed to initialize VP8 encoder"), (NULL)); + ("Failed to initialize encoder"), ("%s", + gst_vpx_error_name (status))); return GST_FLOW_ERROR; } @@ -688,7 +668,12 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, status = vpx_codec_encode (&encoder->encoder, image, encoder->n_frames, 1, flags, speed_table[encoder->speed]); if (status != 0) { - GST_ERROR ("encode returned %d %s", status, vpx_error_name (status)); + GST_ELEMENT_ERROR (encoder, LIBRARY, ENCODE, + ("Failed to encode frame"), ("%s", gst_vpx_error_name (status))); + g_slice_free (GstVP8EncCoderHook, hook); + frame->coder_hook = NULL; + g_slice_free (vpx_image_t, image); + return FALSE; } pkt = vpx_codec_get_cx_data (&encoder->encoder, &iter); @@ -696,18 +681,19 @@ gst_vp8_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder, GstBuffer *buffer; gboolean invisible; - GST_DEBUG ("packet %d type %d", pkt->data.frame.sz, pkt->kind); + GST_DEBUG_OBJECT (encoder, "packet %d type %d", pkt->data.frame.sz, + pkt->kind); if (pkt->kind != VPX_CODEC_CX_FRAME_PKT) { - GST_ERROR ("non frame pkt"); + GST_ERROR_OBJECT (encoder, "non frame pkt"); continue; } invisible = (pkt->data.frame.flags & VPX_FRAME_IS_INVISIBLE) != 0; frame = gst_base_video_encoder_get_oldest_frame (base_video_encoder); + g_assert (frame != NULL); frame->is_sync_point = (pkt->data.frame.flags & VPX_FRAME_IS_KEY) != 0; hook = frame->coder_hook; - /* FIXME: If frame is NULL something went really wrong! */ buffer = gst_buffer_new_and_alloc (pkt->data.frame.sz); @@ -754,7 +740,7 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, GList *l; gint inv_count; - GST_DEBUG ("shape_output"); + GST_DEBUG_OBJECT (base_video_encoder, "shape_output"); encoder = GST_VP8_ENC (base_video_encoder); @@ -784,8 +770,10 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_buffer_set_caps (buf, base_video_encoder->caps); ret = gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), buf); - if (ret != GST_FLOW_OK) + if (ret != GST_FLOW_OK) { + GST_WARNING_OBJECT (encoder, "flow error %d", ret); goto done; + } } buf = frame->src_buffer; @@ -814,8 +802,9 @@ gst_vp8_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_buffer_set_caps (buf, base_video_encoder->caps); ret = gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder), buf); - if (ret != GST_FLOW_OK) - GST_ERROR ("flow error %d", ret); + if (ret != GST_FLOW_OK) { + GST_WARNING_OBJECT (encoder, "flow error %d", ret); + } done: g_list_foreach (hook->invisible, (GFunc) gst_mini_object_unref, NULL); diff --git a/ext/vp8/gstvp8utils.c b/ext/vp8/gstvp8utils.c new file mode 100644 index 0000000..e206780 --- /dev/null +++ b/ext/vp8/gstvp8utils.c @@ -0,0 +1,57 @@ +/* VP8 + * Copyright (C) 2006 David Schleef + * Copyright (C) 2010 Entropy Wave Inc + * Copyright (C) 2010 Sebastian Dröge + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvp8utils.h" + +const char * +gst_vpx_error_name (vpx_codec_err_t status) +{ + switch (status) { + case VPX_CODEC_OK: + return "OK"; + case VPX_CODEC_ERROR: + return "error"; + case VPX_CODEC_MEM_ERROR: + return "mem error"; + case VPX_CODEC_ABI_MISMATCH: + return "abi mismatch"; + case VPX_CODEC_INCAPABLE: + return "incapable"; + case VPX_CODEC_UNSUP_BITSTREAM: + return "unsupported bitstream"; + case VPX_CODEC_UNSUP_FEATURE: + return "unsupported feature"; + case VPX_CODEC_CORRUPT_FRAME: + return "corrupt frame"; + case VPX_CODEC_INVALID_PARAM: + return "invalid parameter"; + default: + return "unknown"; + } +} diff --git a/ext/vp8/gstvp8utils.h b/ext/vp8/gstvp8utils.h new file mode 100644 index 0000000..4c07127 --- /dev/null +++ b/ext/vp8/gstvp8utils.h @@ -0,0 +1,30 @@ +/* VP8 + * Copyright (C) 2006 David Schleef + * Copyright (C) 2010 Entropy Wave Inc + * Copyright (C) 2010 Sebastian Dröge + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include +#include + +G_BEGIN_DECLS + +const char * gst_vpx_error_name (vpx_codec_err_t status); + +G_END_DECLS -- 2.7.4