mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
ext/jpeg/gstjpegenc.c: Don't leak input buffer in chain function (fixes #322667); make state change function thread-s...
Original commit message from CVS: * ext/jpeg/gstjpegenc.c: (gst_jpegenc_resync), (gst_jpegenc_chain), (gst_jpegenc_set_property), (gst_jpegenc_get_property), (gst_jpegenc_change_state): Don't leak input buffer in chain function (fixes #322667); make state change function thread-safe; don't repeat the current function name in GST_DEBUG statements; use GST_ROUND_UP_* macros; use gst_pad_alloc_buffer(); misc. minor cleanups.
This commit is contained in:
parent
2a46b7cf76
commit
804aff8689
2 changed files with 63 additions and 47 deletions
10
ChangeLog
10
ChangeLog
|
@ -1,3 +1,13 @@
|
|||
2005-11-28 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* ext/jpeg/gstjpegenc.c: (gst_jpegenc_resync), (gst_jpegenc_chain),
|
||||
(gst_jpegenc_set_property), (gst_jpegenc_get_property),
|
||||
(gst_jpegenc_change_state):
|
||||
Don't leak input buffer in chain function (fixes #322667); make
|
||||
state change function thread-safe; don't repeat the current function
|
||||
name in GST_DEBUG statements; use GST_ROUND_UP_* macros; use
|
||||
gst_pad_alloc_buffer(); misc. minor cleanups.
|
||||
|
||||
2005-11-28 Jan Schmidt <thaytan@mad.scientist.com>
|
||||
|
||||
* gst/matroska/matroska-mux.c:
|
||||
|
|
|
@ -41,20 +41,17 @@ GST_DEBUG_CATEGORY (jpegenc_debug);
|
|||
|
||||
/* These macros are adapted from videotestsrc.c
|
||||
* and/or gst-plugins/gst/games/gstvideoimage.c */
|
||||
#define ROUND_UP_2(x) (((x)+1)&~1)
|
||||
#define ROUND_UP_4(x) (((x)+3)&~3)
|
||||
#define ROUND_UP_8(x) (((x)+7)&~7)
|
||||
|
||||
/* I420 */
|
||||
#define I420_Y_ROWSTRIDE(width) (ROUND_UP_4(width))
|
||||
#define I420_U_ROWSTRIDE(width) (ROUND_UP_8(width)/2)
|
||||
#define I420_V_ROWSTRIDE(width) ((ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
|
||||
#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width))
|
||||
#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2)
|
||||
#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2)
|
||||
|
||||
#define I420_Y_OFFSET(w,h) (0)
|
||||
#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*ROUND_UP_2(h)))
|
||||
#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
|
||||
#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h)))
|
||||
#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
|
||||
|
||||
#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*ROUND_UP_2(h)/2))
|
||||
#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2))
|
||||
|
||||
/* JpegEnc signals and args */
|
||||
enum
|
||||
|
@ -333,13 +330,13 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc)
|
|||
{
|
||||
gint width, height;
|
||||
|
||||
GST_DEBUG ("gst_jpegenc_resync: resync");
|
||||
GST_DEBUG_OBJECT (jpegenc, "resync");
|
||||
|
||||
jpegenc->cinfo.image_width = width = jpegenc->width;
|
||||
jpegenc->cinfo.image_height = height = jpegenc->height;
|
||||
jpegenc->cinfo.input_components = 3;
|
||||
|
||||
GST_DEBUG ("gst_jpegenc_resync: wdith %d, height %d", width, height);
|
||||
GST_DEBUG_OBJECT (jpegenc, "width %d, height %d", width, height);
|
||||
|
||||
jpeg_set_defaults (&jpegenc->cinfo);
|
||||
jpegenc->cinfo.dct_method = JDCT_FASTEST;
|
||||
|
@ -360,7 +357,7 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc)
|
|||
jpegenc->bufsize = I420_SIZE (jpegenc->width, jpegenc->height);
|
||||
jpegenc->cinfo.raw_data_in = TRUE;
|
||||
jpegenc->cinfo.in_color_space = JCS_YCbCr;
|
||||
GST_DEBUG ("gst_jpegenc_resync: setting format to YUV420P");
|
||||
GST_DEBUG_OBJECT (jpegenc, "setting format to YUV420P");
|
||||
jpegenc->cinfo.comp_info[0].h_samp_factor = 2;
|
||||
jpegenc->cinfo.comp_info[0].v_samp_factor = 2;
|
||||
jpegenc->cinfo.comp_info[1].h_samp_factor = 1;
|
||||
|
@ -377,7 +374,7 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc)
|
|||
g_realloc (jpegenc->line[2], height * sizeof (char *) / 2);
|
||||
}
|
||||
|
||||
GST_DEBUG ("gst_jpegenc_resync: setting format done");
|
||||
GST_DEBUG_OBJECT (jpegenc, "setting format done");
|
||||
#if 0
|
||||
break;
|
||||
default:
|
||||
|
@ -392,36 +389,35 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc)
|
|||
//jpeg_suppress_tables(&jpegenc->cinfo, FALSE);
|
||||
|
||||
jpegenc->buffer = NULL;
|
||||
GST_DEBUG ("gst_jpegenc_resync: resync done");
|
||||
GST_DEBUG_OBJECT (jpegenc, "resync done");
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
GstJpegEnc *jpegenc;
|
||||
guchar *data, *outdata;
|
||||
gulong size, outsize;
|
||||
guchar *data;
|
||||
gulong size;
|
||||
GstBuffer *outbuf;
|
||||
|
||||
/* GstMeta *meta; */
|
||||
guint height, width;
|
||||
guchar *base[3];
|
||||
gint i, j, k;
|
||||
|
||||
/*usleep(10000); */
|
||||
jpegenc = GST_JPEGENC (GST_OBJECT_PARENT (pad));
|
||||
|
||||
data = GST_BUFFER_DATA (buf);
|
||||
size = GST_BUFFER_SIZE (buf);
|
||||
|
||||
GST_DEBUG ("gst_jpegenc_chain: got buffer of %ld bytes in '%s'", size,
|
||||
GST_OBJECT_NAME (jpegenc));
|
||||
GST_DEBUG_OBJECT (jpegenc, "got buffer of %u bytes", size);
|
||||
|
||||
outbuf = gst_buffer_new ();
|
||||
outsize = GST_BUFFER_SIZE (outbuf) = jpegenc->bufsize;
|
||||
outdata = GST_BUFFER_DATA (outbuf) = g_malloc (outsize);
|
||||
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf);
|
||||
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf);
|
||||
ret = gst_pad_alloc_buffer (jpegenc->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||
jpegenc->bufsize, GST_PAD_CAPS (jpegenc->srcpad), &outbuf);
|
||||
|
||||
if (ret != GST_FLOW_OK)
|
||||
goto done;
|
||||
|
||||
gst_buffer_stamp (outbuf, buf);
|
||||
|
||||
width = jpegenc->width;
|
||||
height = jpegenc->height;
|
||||
|
@ -430,14 +426,14 @@ gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
|
|||
base[1] = data + I420_U_OFFSET (width, height);
|
||||
base[2] = data + I420_V_OFFSET (width, height);
|
||||
|
||||
jpegenc->jdest.next_output_byte = outdata;
|
||||
jpegenc->jdest.free_in_buffer = outsize;
|
||||
jpegenc->jdest.next_output_byte = GST_BUFFER_DATA (outbuf);
|
||||
jpegenc->jdest.free_in_buffer = GST_BUFFER_SIZE (outbuf);
|
||||
|
||||
jpegenc->cinfo.smoothing_factor = jpegenc->smoothing;
|
||||
jpeg_set_quality (&jpegenc->cinfo, jpegenc->quality, TRUE);
|
||||
jpeg_start_compress (&jpegenc->cinfo, TRUE);
|
||||
|
||||
GST_DEBUG ("gst_jpegdec_chain: compressing");
|
||||
GST_DEBUG_OBJECT (jpegenc, "compressing");
|
||||
|
||||
for (i = 0; i < height; i += 2 * DCTSIZE) {
|
||||
/*g_print ("next scanline: %d\n", jpegenc->cinfo.next_scanline); */
|
||||
|
@ -455,28 +451,28 @@ gst_jpegenc_chain (GstPad * pad, GstBuffer * buf)
|
|||
}
|
||||
|
||||
jpeg_finish_compress (&jpegenc->cinfo);
|
||||
GST_DEBUG ("gst_jpegdec_chain: compressing done");
|
||||
GST_DEBUG_OBJECT (jpegenc, "compressing done");
|
||||
|
||||
GST_BUFFER_SIZE (outbuf) =
|
||||
(((outsize - jpegenc->jdest.free_in_buffer) + 3) & ~3);
|
||||
|
||||
gst_pad_push (jpegenc->srcpad, outbuf);
|
||||
GST_ROUND_UP_4 (jpegenc->bufsize - jpegenc->jdest.free_in_buffer);
|
||||
|
||||
g_signal_emit (G_OBJECT (jpegenc), gst_jpegenc_signals[FRAME_ENCODED], 0);
|
||||
|
||||
/*gst_buffer_unref (buf); */
|
||||
ret = gst_pad_push (jpegenc->srcpad, outbuf);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
done:
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_jpegenc_set_property (GObject * object, guint prop_id,
|
||||
const GValue * value, GParamSpec * pspec)
|
||||
{
|
||||
GstJpegEnc *jpegenc;
|
||||
GstJpegEnc *jpegenc = GST_JPEGENC (object);
|
||||
|
||||
g_return_if_fail (GST_IS_JPEGENC (object));
|
||||
jpegenc = GST_JPEGENC (object);
|
||||
GST_OBJECT_LOCK (jpegenc);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_QUALITY:
|
||||
|
@ -486,18 +482,20 @@ gst_jpegenc_set_property (GObject * object, guint prop_id,
|
|||
jpegenc->smoothing = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (jpegenc);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_jpegenc_get_property (GObject * object, guint prop_id, GValue * value,
|
||||
GParamSpec * pspec)
|
||||
{
|
||||
GstJpegEnc *jpegenc;
|
||||
GstJpegEnc *jpegenc = GST_JPEGENC (object);
|
||||
|
||||
g_return_if_fail (GST_IS_JPEGENC (object));
|
||||
jpegenc = GST_JPEGENC (object);
|
||||
GST_OBJECT_LOCK (jpegenc);
|
||||
|
||||
switch (prop_id) {
|
||||
case ARG_QUALITY:
|
||||
|
@ -510,22 +508,33 @@ gst_jpegenc_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
|
||||
GST_OBJECT_UNLOCK (jpegenc);
|
||||
}
|
||||
|
||||
static GstStateChangeReturn
|
||||
gst_jpegenc_change_state (GstElement * element, GstStateChange transition)
|
||||
{
|
||||
|
||||
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
||||
GstJpegEnc *filter = GST_JPEGENC (element);
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
||||
GST_DEBUG ("gst_jpegenc_change_state: setting line buffers");
|
||||
GST_DEBUG_OBJECT (element, "setting line buffers");
|
||||
filter->line[0] = NULL;
|
||||
filter->line[1] = NULL;
|
||||
filter->line[2] = NULL;
|
||||
gst_jpegenc_resync (filter);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
if (ret == GST_STATE_CHANGE_FAILURE)
|
||||
return ret;
|
||||
|
||||
switch (transition) {
|
||||
case GST_STATE_CHANGE_READY_TO_NULL:
|
||||
g_free (filter->line[0]);
|
||||
g_free (filter->line[1]);
|
||||
|
@ -538,8 +547,5 @@ gst_jpegenc_change_state (GstElement * element, GstStateChange transition)
|
|||
break;
|
||||
}
|
||||
|
||||
if (GST_ELEMENT_CLASS (parent_class)->change_state)
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
||||
|
||||
return GST_STATE_CHANGE_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue