From 1b7a2c9c72be2474e33aa9235b502d3b3fe38cc0 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 6 Feb 2006 12:38:48 +0000 Subject: [PATCH] Make theoraenc and the tests leak free. Like, really. Original commit message from CVS: * ext/theora/theoraenc.c: (gst_theora_enc_class_init), (theora_enc_finalize), (theora_enc_sink_setcaps), (theora_set_header_on_caps), (theora_enc_chain), (theora_enc_change_state): * tests/check/pipelines/theoraenc.c: (GST_START_TEST): Make theoraenc and the tests leak free. Like, really. --- ChangeLog | 9 +++++++ ext/theora/theoraenc.c | 39 +++++++++++++++++++++++++++---- tests/check/pipelines/theoraenc.c | 8 +++---- 3 files changed, 47 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index 58feb0c62f..a52b0873cc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2006-02-06 Jan Schmidt + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_finalize), (theora_enc_sink_setcaps), + (theora_set_header_on_caps), (theora_enc_chain), + (theora_enc_change_state): + * tests/check/pipelines/theoraenc.c: (GST_START_TEST): + Make theoraenc and the tests leak free. Like, really. + 2006-02-06 Jan Schmidt * ext/theora/theoraenc.c: (gst_theora_enc_class_init), diff --git a/ext/theora/theoraenc.c b/ext/theora/theoraenc.c index ee79e1c15d..cb22dde7d3 100644 --- a/ext/theora/theoraenc.c +++ b/ext/theora/theoraenc.c @@ -263,9 +263,12 @@ theora_enc_finalize (GObject * object) { GstTheoraEnc *enc = GST_THEORA_ENC (object); + GST_DEBUG_OBJECT (enc, "Finalizing"); theora_clear (&enc->state); theora_comment_clear (&enc->comment); theora_info_clear (&enc->info); + + G_OBJECT_CLASS (parent_class)->finalize (object); } static gboolean @@ -281,6 +284,7 @@ theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps) gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + theora_info_clear (&enc->info); theora_info_init (&enc->info); /* Theora has a divisible-by-sixteen restriction for the encoded video size but * we can define a visible area using the frame_width/frame_height */ @@ -431,28 +435,43 @@ theora_set_header_on_caps (GstCaps * caps, GstBuffer * buf1, caps = gst_caps_make_writable (caps); structure = gst_caps_get_structure (caps, 0); + /* Copy buffers, because we can't use the originals - + * it creates a circular refcount with the caps<->buffers */ + buf1 = gst_buffer_copy (buf1); + buf2 = gst_buffer_copy (buf2); + buf3 = gst_buffer_copy (buf3); + /* mark buffers */ GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS); GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS); GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS); - /* put buffers in a fixed list */ + /* put copies of the buffers in a fixed list */ g_value_init (&array, GST_TYPE_ARRAY); + g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, buf1); gst_value_array_append_value (&array, &value); g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, buf2); gst_value_array_append_value (&array, &value); g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); gst_value_set_buffer (&value, buf3); gst_value_array_append_value (&array, &value); - gst_structure_set_value (structure, "streamheader", &array); g_value_unset (&value); + + gst_structure_set_value (structure, "streamheader", &array); g_value_unset (&array); + /* Unref our copies */ + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); + gst_buffer_unref (buf3); + return caps; } @@ -520,13 +539,19 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer) } /* create the remaining theora headers */ + theora_comment_clear (&enc->comment); theora_comment_init (&enc->comment); - /* Currently leaks due to libtheora API brokenness, I don't think we can - * portably work around it. Leaks ~50 bytes per encoder instance, so not a - * huge problem. */ + theora_encode_comment (&enc->comment, &op); ret = theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf2); + /* Theora expects us to put this packet buffer into an ogg page, + * in which case it becomes the ogg library's responsibility to + * free it. Since we're copying and outputting a gst_buffer, + * we need to free it ourselves. */ + if (op.packet) + free (op.packet); + if (ret != GST_FLOW_OK) { gst_buffer_unref (buf1); goto header_buffer_alloc; @@ -551,6 +576,8 @@ theora_enc_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_set_caps (buf2, caps); gst_buffer_set_caps (buf3, caps); + gst_caps_unref (caps); + /* push out the header buffers */ if ((ret = theora_push_buffer (enc, buf1)) != GST_FLOW_OK) { gst_buffer_unref (buf2); @@ -775,6 +802,7 @@ theora_enc_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_NULL_TO_READY: break; case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state"); theora_info_init (&enc->info); theora_comment_init (&enc->comment); enc->packetno = 0; @@ -791,6 +819,7 @@ theora_enc_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PLAYING_TO_PAUSED: break; case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state"); theora_clear (&enc->state); theora_comment_clear (&enc->comment); theora_info_clear (&enc->info); diff --git a/tests/check/pipelines/theoraenc.c b/tests/check/pipelines/theoraenc.c index 27e3bd6709..7229191afc 100644 --- a/tests/check/pipelines/theoraenc.c +++ b/tests/check/pipelines/theoraenc.c @@ -188,7 +188,7 @@ GST_START_TEST (test_granulepos_offset) pipe_str = g_strdup_printf ("videotestsrc timestamp-offset=%" G_GUINT64_FORMAT " ! video/x-raw-yuv,format=(fourcc)I420,framerate=10/1" - " ! theoraenc ! fakesink", TIMESTAMP_OFFSET); + " ! theoraenc ! fakesink name=fs0", TIMESTAMP_OFFSET); bin = gst_parse_launch (pipe_str, &error); fail_unless (bin != NULL, "Error parsing pipeline: %s", @@ -197,7 +197,7 @@ GST_START_TEST (test_granulepos_offset) /* get the pad */ { - GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fakesink0"); + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fs0"); fail_unless (sink != NULL, "Could not get fakesink out of bin"); pad = gst_element_get_pad (sink, "sink"); @@ -276,7 +276,7 @@ GST_START_TEST (test_continuity) pipe_str = g_strdup_printf ("videotestsrc" " ! video/x-raw-yuv,format=(fourcc)I420,framerate=10/1" - " ! theoraenc ! fakesink"); + " ! theoraenc ! fakesink name=fs0"); bin = gst_parse_launch (pipe_str, &error); fail_unless (bin != NULL, "Error parsing pipeline: %s", @@ -285,7 +285,7 @@ GST_START_TEST (test_continuity) /* get the pad */ { - GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fakesink0"); + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fs0"); fail_unless (sink != NULL, "Could not get fakesink out of bin"); pad = gst_element_get_pad (sink, "sink");