Commit 39d8d88a authored by Wim Taymans's avatar Wim Taymans
Browse files

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.
parent ccce64b2
2006-10-30 Wim Taymans <wim@fluendo.com>
* 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.
2006-10-30 Wim Taymans <wim@fluendo.com>
Patch by: Mark Nauwelaerts <manauw at skynet be>
......
......@@ -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);
......
......@@ -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;
}
......@@ -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;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment