summaryrefslogtreecommitdiffstats
path: root/ext/jpeg
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2006-10-30 09:24:53 +0000
committerWim Taymans <wim.taymans@gmail.com>2006-10-30 09:24:53 +0000
commit39d8d88afe8870ecf3449a02883e036e273770d6 (patch)
tree19ba1be78abad13934bfdae46b243ffc518d018f /ext/jpeg
parentccce64b2930a26d0e827846edde62386baceb9bf (diff)
ext/jpeg/: Various cleanups, capsnego and leak fixes.
Original commit message from CVS: * ext/jpeg/gstjpegenc.c: (gst_jpegenc_getcaps): * ext/jpeg/gstsmokedec.c: (gst_smokedec_class_init), (gst_smokedec_init), (gst_smokedec_finalize), (gst_smokedec_chain), (gst_smokedec_change_state): * ext/jpeg/gstsmokeenc.c: (gst_smokeenc_class_init), (gst_smokeenc_init), (gst_smokeenc_finalize), (gst_smokeenc_getcaps), (gst_smokeenc_setcaps), (gst_smokeenc_resync), (gst_smokeenc_chain), (gst_smokeenc_set_property), (gst_smokeenc_get_property), (gst_smokeenc_change_state): Various cleanups, capsnego and leak fixes.
Diffstat (limited to 'ext/jpeg')
-rw-r--r--ext/jpeg/gstjpegenc.c9
-rw-r--r--ext/jpeg/gstsmokedec.c91
-rw-r--r--ext/jpeg/gstsmokeenc.c177
3 files changed, 204 insertions, 73 deletions
diff --git a/ext/jpeg/gstjpegenc.c b/ext/jpeg/gstjpegenc.c
index 107b14db..5e85d8a0 100644
--- a/ext/jpeg/gstjpegenc.c
+++ b/ext/jpeg/gstjpegenc.c
@@ -264,12 +264,19 @@ gst_jpegenc_getcaps (GstPad * pad)
/* we want to proxy properties like width, height and framerate from the
other end of the element */
otherpad = (pad == jpegenc->srcpad) ? jpegenc->sinkpad : jpegenc->srcpad;
- caps = gst_pad_get_allowed_caps (otherpad);
+
+ caps = gst_pad_peer_get_caps (otherpad);
+ if (caps == NULL)
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+ else
+ caps = gst_caps_make_writable (caps);
+
if (pad == jpegenc->srcpad) {
name = "image/jpeg";
} else {
name = "video/x-raw-yuv";
}
+
for (i = 0; i < gst_caps_get_size (caps); i++) {
structure = gst_caps_get_structure (caps, i);
diff --git a/ext/jpeg/gstsmokedec.c b/ext/jpeg/gstsmokedec.c
index 56e43799..665de92d 100644
--- a/ext/jpeg/gstsmokedec.c
+++ b/ext/jpeg/gstsmokedec.c
@@ -51,6 +51,10 @@ enum
static void gst_smokedec_base_init (gpointer g_class);
static void gst_smokedec_class_init (GstSmokeDec * klass);
static void gst_smokedec_init (GstSmokeDec * smokedec);
+static void gst_smokedec_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_smokedec_change_state (GstElement * element, GstStateChange transition);
static GstFlowReturn gst_smokedec_chain (GstPad * pad, GstBuffer * buf);
@@ -114,12 +118,19 @@ gst_smokedec_base_init (gpointer g_class)
static void
gst_smokedec_class_init (GstSmokeDec * klass)
{
+ GObjectClass *gobject_class;
GstElementClass *gstelement_class;
+ gobject_class = (GObjectClass *) klass;
gstelement_class = (GstElementClass *) klass;
parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = gst_smokedec_finalize;
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_smokedec_change_state);
+
GST_DEBUG_CATEGORY_INIT (smokedec_debug, "smokedec", 0, "Smoke decoder");
}
@@ -140,17 +151,19 @@ gst_smokedec_init (GstSmokeDec * smokedec)
gst_pad_use_fixed_caps (smokedec->srcpad);
gst_element_add_pad (GST_ELEMENT (smokedec), smokedec->srcpad);
- /* reset the initial video state */
- smokedec->format = -1;
- smokedec->width = -1;
- smokedec->height = -1;
- smokedec->fps_num = -1;
- smokedec->fps_denom = -1;
- smokedec->next_time = 0;
-
smokecodec_decode_new (&smokedec->info);
}
+static void
+gst_smokedec_finalize (GObject * object)
+{
+ GstSmokeDec *dec = GST_SMOKEDEC (object);
+
+ smokecodec_info_free (dec->info);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
static GstFlowReturn
gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
{
@@ -171,6 +184,9 @@ gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
size = GST_BUFFER_SIZE (buf);
time = GST_BUFFER_TIMESTAMP (buf);
+ if (size < 1)
+ goto too_small;
+
GST_LOG_OBJECT (smokedec, "got buffer of %lu bytes", size);
/* have the ID packet. */
@@ -208,7 +224,6 @@ gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
gst_caps_unref (caps);
}
-
if (smokedec->need_keyframe) {
if (!(flags & SMOKECODEC_KEYFRAME))
goto keyframe_skip;
@@ -216,13 +231,12 @@ gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
smokedec->need_keyframe = FALSE;
}
- outbuf = gst_buffer_new ();
- outsize = GST_BUFFER_SIZE (outbuf) = width * height + width * height / 2;
- outdata = g_malloc (outsize);
- GST_BUFFER_DATA (outbuf) = outdata;
- GST_BUFFER_MALLOCDATA (outbuf) = outdata;
+ outsize = width * height + width * height / 2;
+ outbuf = gst_buffer_new_and_alloc (outsize);
+ outdata = GST_BUFFER_DATA (outbuf);
- GST_BUFFER_DURATION (outbuf) = GST_SECOND * fps_denom / fps_num;
+ GST_BUFFER_DURATION (outbuf) =
+ gst_util_uint64_scale_int (GST_SECOND, fps_denom, fps_num);
GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokedec->srcpad));
@@ -234,7 +248,10 @@ gst_smokedec_chain (GstPad * pad, GstBuffer * buf)
}
}
GST_BUFFER_TIMESTAMP (outbuf) = time;
- smokedec->next_time = time + GST_BUFFER_DURATION (outbuf);
+ if (time != -1)
+ smokedec->next_time = time + GST_BUFFER_DURATION (outbuf);
+ else
+ smokedec->next_time = -1;
smokeret = smokecodec_decode (smokedec->info, data, size, outdata);
if (smokeret != SMOKECODEC_OK)
@@ -250,6 +267,13 @@ done:
return ret;
/* ERRORS */
+too_small:
+ {
+ GST_ELEMENT_ERROR (smokedec, STREAM, DECODE,
+ (NULL), ("Input buffer too small"));
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
header_error:
{
GST_ELEMENT_ERROR (smokedec, STREAM, DECODE,
@@ -271,3 +295,38 @@ decode_error:
goto done;
}
}
+
+static GstStateChangeReturn
+gst_smokedec_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret;
+ GstSmokeDec *dec;
+
+ dec = GST_SMOKEDEC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ /* reset the initial video state */
+ dec->format = -1;
+ dec->width = -1;
+ dec->height = -1;
+ dec->fps_num = -1;
+ dec->fps_denom = -1;
+ dec->next_time = 0;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret != GST_STATE_CHANGE_SUCCESS)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
diff --git a/ext/jpeg/gstsmokeenc.c b/ext/jpeg/gstsmokeenc.c
index 7f0cbc64..eef8f8f4 100644
--- a/ext/jpeg/gstsmokeenc.c
+++ b/ext/jpeg/gstsmokeenc.c
@@ -36,10 +36,6 @@ GST_ELEMENT_DETAILS ("Smoke video encoder",
GST_DEBUG_CATEGORY_STATIC (smokeenc_debug);
#define GST_CAT_DEFAULT smokeenc_debug
-#define SMOKEENC_DEFAULT_MIN_QUALITY 10
-#define SMOKEENC_DEFAULT_MAX_QUALITY 85
-#define SMOKEENC_DEFAULT_THRESHOLD 3000
-#define SMOKEENC_DEFAULT_KEYFRAME 20
/* SmokeEnc signals and args */
enum
@@ -49,19 +45,28 @@ enum
LAST_SIGNAL
};
+#define DEFAULT_PROP_MIN_QUALITY 10
+#define DEFAULT_PROP_MAX_QUALITY 85
+#define DEFAULT_PROP_THRESHOLD 3000
+#define DEFAULT_PROP_KEYFRAME 20
+
enum
{
- ARG_0,
- ARG_MIN_QUALITY,
- ARG_MAX_QUALITY,
- ARG_THRESHOLD,
- ARG_KEYFRAME
+ PROP_0,
+ PROP_MIN_QUALITY,
+ PROP_MAX_QUALITY,
+ PROP_THRESHOLD,
+ PROP_KEYFRAME
/* FILL ME */
};
static void gst_smokeenc_base_init (gpointer g_class);
static void gst_smokeenc_class_init (GstSmokeEnc * klass);
static void gst_smokeenc_init (GstSmokeEnc * smokeenc);
+static void gst_smokeenc_finalize (GObject * object);
+
+static GstStateChangeReturn
+gst_smokeenc_change_state (GstElement * element, GstStateChange transition);
static GstFlowReturn gst_smokeenc_chain (GstPad * pad, GstBuffer * buf);
static gboolean gst_smokeenc_setcaps (GstPad * pad, GstCaps * caps);
@@ -141,22 +146,26 @@ gst_smokeenc_class_init (GstSmokeEnc * klass)
parent_class = g_type_class_peek_parent (klass);
+ gobject_class->finalize = gst_smokeenc_finalize;
gobject_class->set_property = gst_smokeenc_set_property;
gobject_class->get_property = gst_smokeenc_get_property;
- g_object_class_install_property (gobject_class, ARG_MIN_QUALITY,
+ g_object_class_install_property (gobject_class, PROP_MIN_QUALITY,
g_param_spec_int ("qmin", "Qmin", "Minimum quality",
- 0, 100, SMOKEENC_DEFAULT_MIN_QUALITY, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_MAX_QUALITY,
+ 0, 100, DEFAULT_PROP_MIN_QUALITY, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_MAX_QUALITY,
g_param_spec_int ("qmax", "Qmax", "Maximum quality",
- 0, 100, SMOKEENC_DEFAULT_MAX_QUALITY, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_THRESHOLD,
+ 0, 100, DEFAULT_PROP_MAX_QUALITY, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_THRESHOLD,
g_param_spec_int ("threshold", "Threshold", "Motion estimation threshold",
- 0, 100000000, SMOKEENC_DEFAULT_THRESHOLD, G_PARAM_READWRITE));
- g_object_class_install_property (gobject_class, ARG_KEYFRAME,
+ 0, 100000000, DEFAULT_PROP_THRESHOLD, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, PROP_KEYFRAME,
g_param_spec_int ("keyframe", "Keyframe",
"Insert keyframe every N frames", 1, 100000,
- SMOKEENC_DEFAULT_KEYFRAME, G_PARAM_READWRITE));
+ DEFAULT_PROP_KEYFRAME, G_PARAM_READWRITE));
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_smokeenc_change_state);
GST_DEBUG_CATEGORY_INIT (smokeenc_debug, "smokeenc", 0,
"Smoke encoding element");
@@ -177,22 +186,24 @@ gst_smokeenc_init (GstSmokeEnc * smokeenc)
smokeenc->srcpad =
gst_pad_new_from_static_template (&gst_smokeenc_src_pad_template, "src");
gst_pad_set_getcaps_function (smokeenc->sinkpad, gst_smokeenc_getcaps);
- gst_pad_use_fixed_caps (smokeenc->sinkpad);
- /*gst_pad_set_link_function (smokeenc->sinkpad, gst_smokeenc_link); */
+ gst_pad_use_fixed_caps (smokeenc->srcpad);
gst_element_add_pad (GST_ELEMENT (smokeenc), smokeenc->srcpad);
- /* reset the initial video state */
- smokeenc->width = 0;
- smokeenc->height = 0;
- smokeenc->frame = 0;
- smokeenc->need_header = TRUE;
+ smokeenc->min_quality = DEFAULT_PROP_MIN_QUALITY;
+ smokeenc->max_quality = DEFAULT_PROP_MAX_QUALITY;
+ smokeenc->threshold = DEFAULT_PROP_THRESHOLD;
+ smokeenc->keyframe = DEFAULT_PROP_KEYFRAME;
+}
+
+static void
+gst_smokeenc_finalize (GObject * object)
+{
+ GstSmokeEnc *enc = GST_SMOKEENC (object);
- gst_smokeenc_resync (smokeenc);
+ if (enc->info)
+ smokecodec_info_free (enc->info);
- smokeenc->min_quality = SMOKEENC_DEFAULT_MIN_QUALITY;
- smokeenc->max_quality = SMOKEENC_DEFAULT_MAX_QUALITY;
- smokeenc->threshold = SMOKEENC_DEFAULT_THRESHOLD;
- smokeenc->keyframe = SMOKEENC_DEFAULT_KEYFRAME;
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GstCaps *
@@ -208,12 +219,19 @@ gst_smokeenc_getcaps (GstPad * pad)
/* we want to proxy properties like width, height and framerate from the
other end of the element */
otherpad = (pad == smokeenc->srcpad) ? smokeenc->sinkpad : smokeenc->srcpad;
- caps = gst_pad_get_allowed_caps (otherpad);
+
+ caps = gst_pad_peer_get_caps (otherpad);
+ if (caps == NULL)
+ caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
+ else
+ caps = gst_caps_make_writable (caps);
+
if (pad == smokeenc->srcpad) {
name = "video/x-smoke";
} else {
name = "video/x-raw-yuv";
}
+
for (i = 0; i < gst_caps_get_size (caps); i++) {
structure = gst_caps_get_structure (caps, i);
@@ -234,14 +252,17 @@ gst_smokeenc_getcaps (GstPad * pad)
static gboolean
gst_smokeenc_setcaps (GstPad * pad, GstCaps * caps)
{
- GstSmokeEnc *smokeenc = GST_SMOKEENC (gst_pad_get_parent (pad));
+ GstSmokeEnc *smokeenc;
GstStructure *structure;
- gboolean ret = TRUE;
GstCaps *othercaps;
- GstPad *otherpad;
const GValue *framerate;
+ GstPad *otherpad;
+ gboolean ret;
+
+ smokeenc = GST_SMOKEENC (gst_pad_get_parent (pad));
otherpad = (pad == smokeenc->srcpad) ? smokeenc->sinkpad : smokeenc->srcpad;
+
structure = gst_caps_get_structure (caps, 0);
framerate = gst_structure_get_value (structure, "framerate");
if (framerate) {
@@ -267,12 +288,10 @@ gst_smokeenc_setcaps (GstPad * pad, GstCaps * caps)
NULL);
GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, othercaps);
- ret = gst_pad_set_caps (otherpad, othercaps);
+ gst_pad_set_caps (otherpad, othercaps);
gst_caps_unref (othercaps);
- if (ret) {
- ret = gst_smokeenc_resync (smokeenc);
- }
+ ret = gst_smokeenc_resync (smokeenc);
gst_object_unref (smokeenc);
@@ -294,18 +313,27 @@ gst_smokeenc_resync (GstSmokeEnc * smokeenc)
GST_DEBUG ("resync: %dx%d@%d/%dfps", smokeenc->width, smokeenc->height,
smokeenc->fps_num, smokeenc->fps_denom);
+ if (smokeenc->info)
+ smokecodec_info_free (smokeenc->info);
+
ret = smokecodec_encode_new (&smokeenc->info, smokeenc->width,
smokeenc->height, smokeenc->fps_num, smokeenc->fps_denom);
- if (ret != SMOKECODEC_OK) {
- GST_WARNING_OBJECT (smokeenc, "smokecodec_encode_new() failed: %d", ret);
- return FALSE;
- }
+
+ if (ret != SMOKECODEC_OK)
+ goto init_failed;
smokecodec_set_quality (smokeenc->info, smokeenc->min_quality,
smokeenc->max_quality);
GST_DEBUG ("resync done");
return TRUE;
+
+ /* ERRORS */
+init_failed:
+ {
+ GST_WARNING_OBJECT (smokeenc, "smokecodec_encode_new() failed: %d", ret);
+ return FALSE;
+ }
}
static GstFlowReturn
@@ -329,13 +357,15 @@ gst_smokeenc_chain (GstPad * pad, GstBuffer * buf)
if (smokeenc->need_header) {
outbuf = gst_buffer_new_and_alloc (256);
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokeenc->srcpad));
+ outdata = GST_BUFFER_DATA (outbuf);
+
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
- smokecodec_encode_id (smokeenc->info, GST_BUFFER_DATA (outbuf), &encsize);
+ smokecodec_encode_id (smokeenc->info, outdata, &encsize);
GST_BUFFER_SIZE (outbuf) = encsize;
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokeenc->srcpad));
ret = gst_pad_push (smokeenc->srcpad, outbuf);
if (ret != GST_FLOW_OK)
@@ -344,14 +374,14 @@ gst_smokeenc_chain (GstPad * pad, GstBuffer * buf)
smokeenc->need_header = FALSE;
}
- outbuf = gst_buffer_new ();
outsize = smokeenc->width * smokeenc->height * 3;
- outdata = g_malloc (outsize);
- GST_BUFFER_DATA (outbuf) = outdata;
- GST_BUFFER_MALLOCDATA (outbuf) = outdata;
+ outbuf = gst_buffer_new_and_alloc (outsize);
+ outdata = GST_BUFFER_DATA (outbuf);
+
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
GST_BUFFER_DURATION (outbuf) =
- smokeenc->fps_denom * GST_SECOND / smokeenc->fps_num;
+ gst_util_uint64_scale_int (GST_SECOND, smokeenc->fps_denom,
+ smokeenc->fps_num);
gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokeenc->srcpad));
flags = 0;
@@ -368,6 +398,8 @@ gst_smokeenc_chain (GstPad * pad, GstBuffer * buf)
GST_BUFFER_OFFSET (outbuf) = smokeenc->frame;
GST_BUFFER_OFFSET_END (outbuf) = smokeenc->frame + 1;
+ gst_buffer_set_caps (outbuf, GST_PAD_CAPS (smokeenc->srcpad));
+
ret = gst_pad_push (smokeenc->srcpad, outbuf);
smokeenc->frame++;
@@ -387,16 +419,16 @@ gst_smokeenc_set_property (GObject * object, guint prop_id,
smokeenc = GST_SMOKEENC (object);
switch (prop_id) {
- case ARG_MIN_QUALITY:
+ case PROP_MIN_QUALITY:
smokeenc->min_quality = g_value_get_int (value);
break;
- case ARG_MAX_QUALITY:
+ case PROP_MAX_QUALITY:
smokeenc->max_quality = g_value_get_int (value);
break;
- case ARG_THRESHOLD:
+ case PROP_THRESHOLD:
smokeenc->threshold = g_value_get_int (value);
break;
- case ARG_KEYFRAME:
+ case PROP_KEYFRAME:
smokeenc->keyframe = g_value_get_int (value);
break;
default:
@@ -414,16 +446,16 @@ gst_smokeenc_get_property (GObject * object, guint prop_id, GValue * value,
smokeenc = GST_SMOKEENC (object);
switch (prop_id) {
- case ARG_MIN_QUALITY:
+ case PROP_MIN_QUALITY:
g_value_set_int (value, smokeenc->min_quality);
break;
- case ARG_MAX_QUALITY:
+ case PROP_MAX_QUALITY:
g_value_set_int (value, smokeenc->max_quality);
break;
- case ARG_THRESHOLD:
+ case PROP_THRESHOLD:
g_value_set_int (value, smokeenc->threshold);
break;
- case ARG_KEYFRAME:
+ case PROP_KEYFRAME:
g_value_set_int (value, smokeenc->keyframe);
break;
default:
@@ -431,3 +463,36 @@ gst_smokeenc_get_property (GObject * object, guint prop_id, GValue * value,
break;
}
}
+
+static GstStateChangeReturn
+gst_smokeenc_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret;
+ GstSmokeEnc *enc;
+
+ enc = GST_SMOKEENC (element);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_PAUSED:
+ /* reset the initial video state */
+ enc->width = 0;
+ enc->height = 0;
+ enc->frame = 0;
+ enc->need_header = TRUE;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+ if (ret != GST_STATE_CHANGE_SUCCESS)
+ return ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_PAUSED_TO_READY:
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}