mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 05:06:17 +00:00
ext/jpeg/gstjpegdec.*: Cleanups. Don't create caps for every chain.
Original commit message from CVS: * ext/jpeg/gstjpegdec.c: (gst_jpeg_dec_init), (gst_jpeg_dec_chain), (gst_jpeg_dec_change_state): * ext/jpeg/gstjpegdec.h: Cleanups. Don't create caps for every chain.
This commit is contained in:
parent
3a08bb8732
commit
a6562db286
3 changed files with 103 additions and 59 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
2005-10-28 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
* ext/jpeg/gstjpegdec.c: (gst_jpeg_dec_init), (gst_jpeg_dec_chain),
|
||||||
|
(gst_jpeg_dec_change_state):
|
||||||
|
* ext/jpeg/gstjpegdec.h:
|
||||||
|
Cleanups. Don't create caps for every chain.
|
||||||
|
|
||||||
2005-10-27 Edgard Lima Edgard Lima <edgard.lima@indt.org.br>
|
2005-10-27 Edgard Lima Edgard Lima <edgard.lima@indt.org.br>
|
||||||
|
|
||||||
* gst/law/alaw-encode.c: (gst_alawenc_init),
|
* gst/law/alaw-encode.c: (gst_alawenc_init),
|
||||||
|
|
|
@ -54,7 +54,7 @@ GST_STATIC_PAD_TEMPLATE ("sink",
|
||||||
GST_STATIC_CAPS ("image/jpeg, "
|
GST_STATIC_CAPS ("image/jpeg, "
|
||||||
"width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
|
"width = (int) [ " G_STRINGIFY (MIN_WIDTH) ", " G_STRINGIFY (MAX_WIDTH)
|
||||||
" ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
|
" ], " "height = (int) [ " G_STRINGIFY (MIN_HEIGHT) ", "
|
||||||
G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (double) [ 1, MAX ]")
|
G_STRINGIFY (MAX_HEIGHT) " ], " "framerate = (double) [ 0, MAX ]")
|
||||||
);
|
);
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY (jpeg_dec_debug);
|
GST_DEBUG_CATEGORY (jpeg_dec_debug);
|
||||||
|
@ -243,10 +243,6 @@ gst_jpeg_dec_init (GstJpegDec * dec)
|
||||||
(&gst_jpeg_dec_src_pad_template), "src");
|
(&gst_jpeg_dec_src_pad_template), "src");
|
||||||
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
|
gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
|
||||||
|
|
||||||
dec->packetized = FALSE;
|
|
||||||
dec->next_ts = 0;
|
|
||||||
dec->fps = 1.0;
|
|
||||||
|
|
||||||
/* setup jpeglib */
|
/* setup jpeglib */
|
||||||
memset (&dec->cinfo, 0, sizeof (dec->cinfo));
|
memset (&dec->cinfo, 0, sizeof (dec->cinfo));
|
||||||
memset (&dec->jerr, 0, sizeof (dec->jerr));
|
memset (&dec->jerr, 0, sizeof (dec->jerr));
|
||||||
|
@ -696,7 +692,6 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
GstJpegDec *dec;
|
GstJpegDec *dec;
|
||||||
GstBuffer *outbuf;
|
GstBuffer *outbuf;
|
||||||
GstCaps *caps;
|
|
||||||
gulong size;
|
gulong size;
|
||||||
guchar *data, *outdata;
|
guchar *data, *outdata;
|
||||||
guchar *base[3], *last[3];
|
guchar *base[3], *last[3];
|
||||||
|
@ -704,11 +699,15 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
gint width, height;
|
gint width, height;
|
||||||
gint r_h, r_v;
|
gint r_h, r_v;
|
||||||
gint i;
|
gint i;
|
||||||
|
guint code;
|
||||||
|
GstClockTime timestamp, duration;
|
||||||
|
|
||||||
dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
|
dec = GST_JPEG_DEC (GST_OBJECT_PARENT (pad));
|
||||||
|
|
||||||
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) {
|
timestamp = GST_BUFFER_TIMESTAMP (buf);
|
||||||
dec->next_ts = GST_BUFFER_TIMESTAMP (buf);
|
|
||||||
|
if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
|
||||||
|
dec->next_ts = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dec->tempbuf) {
|
if (dec->tempbuf) {
|
||||||
|
@ -719,7 +718,7 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
|
|
||||||
if (!gst_jpeg_dec_ensure_header (dec))
|
if (!gst_jpeg_dec_ensure_header (dec))
|
||||||
return GST_FLOW_OK; /* need more data */
|
goto need_more_data;
|
||||||
|
|
||||||
/* If we know that each input buffer contains data
|
/* If we know that each input buffer contains data
|
||||||
* for a whole jpeg image (e.g. MJPEG streams), just
|
* for a whole jpeg image (e.g. MJPEG streams), just
|
||||||
|
@ -727,25 +726,13 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
* the jpeg data */
|
* the jpeg data */
|
||||||
if (dec->packetized) {
|
if (dec->packetized) {
|
||||||
img_len = GST_BUFFER_SIZE (dec->tempbuf);
|
img_len = GST_BUFFER_SIZE (dec->tempbuf);
|
||||||
#if 0
|
|
||||||
/* This does not work, e.g. avidemux adds an
|
|
||||||
* extra 0 at the end of the buffer */
|
|
||||||
if (!gst_jpeg_dec_have_end_marker (dec)) {
|
|
||||||
gst_util_dump_mem (GST_BUFFER_DATA (dec->tempbuf),
|
|
||||||
GST_BUFFER_SIZE (dec->tempbuf));
|
|
||||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE, ("JPEG input without EOI marker"),
|
|
||||||
(NULL));
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* Parse jpeg image to handle jpeg input that
|
/* Parse jpeg image to handle jpeg input that
|
||||||
* is not aligned to buffer boundaries */
|
* is not aligned to buffer boundaries */
|
||||||
img_len = gst_jpeg_dec_parse_image_data (dec);
|
img_len = gst_jpeg_dec_parse_image_data (dec);
|
||||||
|
|
||||||
if (img_len == 0)
|
if (img_len == 0)
|
||||||
return GST_FLOW_OK; /* need more data */
|
goto need_more_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (guchar *) GST_BUFFER_DATA (dec->tempbuf);
|
data = (guchar *) GST_BUFFER_DATA (dec->tempbuf);
|
||||||
|
@ -756,17 +743,13 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
dec->jsrc.pub.bytes_in_buffer = size;
|
dec->jsrc.pub.bytes_in_buffer = size;
|
||||||
|
|
||||||
if (setjmp (dec->jerr.setjmp_buffer)) {
|
if (setjmp (dec->jerr.setjmp_buffer)) {
|
||||||
guint code = dec->jerr.pub.msg_code;
|
code = dec->jerr.pub.msg_code;
|
||||||
|
|
||||||
if (code == JERR_INPUT_EOF) {
|
if (code == JERR_INPUT_EOF) {
|
||||||
GST_DEBUG ("jpeg input EOF error, we probably need more data");
|
GST_DEBUG ("jpeg input EOF error, we probably need more data");
|
||||||
return GST_FLOW_OK;
|
goto need_more_data;
|
||||||
}
|
}
|
||||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
goto decode_error;
|
||||||
(_("Failed to decode JPEG image")),
|
|
||||||
("Error #%u: %s", code, dec->jerr.pub.jpeg_message_table[code]));
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto done;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
|
GST_LOG_OBJECT (dec, "reading header %02x %02x %02x %02x", data[0], data[1],
|
||||||
|
@ -796,41 +779,52 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
height = dec->cinfo.output_height;
|
height = dec->cinfo.output_height;
|
||||||
|
|
||||||
if (width < MIN_WIDTH || width > MAX_WIDTH ||
|
if (width < MIN_WIDTH || width > MAX_WIDTH ||
|
||||||
height < MIN_HEIGHT || height > MAX_HEIGHT) {
|
height < MIN_HEIGHT || height > MAX_HEIGHT)
|
||||||
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
goto wrong_size;
|
||||||
("Picture is too small or too big (%ux%u)", width, height),
|
|
||||||
("Picture is too small or too big (%ux%u)", width, height));
|
|
||||||
ret = GST_FLOW_ERROR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
caps = gst_caps_new_simple ("video/x-raw-yuv",
|
if (width != dec->caps_width || height != dec->caps_height ||
|
||||||
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
|
dec->fps != dec->caps_fps) {
|
||||||
"width", G_TYPE_INT, width,
|
GstCaps *caps;
|
||||||
"height", G_TYPE_INT, height,
|
|
||||||
"framerate", G_TYPE_DOUBLE, (double) dec->fps, NULL);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
|
/* framerate == 0.0 is a still frame */
|
||||||
GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d", dec->cinfo.max_v_samp_factor);
|
caps = gst_caps_new_simple ("video/x-raw-yuv",
|
||||||
|
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
|
||||||
|
"width", G_TYPE_INT, width,
|
||||||
|
"height", G_TYPE_INT, height,
|
||||||
|
"framerate", G_TYPE_DOUBLE, (double) dec->fps, NULL);
|
||||||
|
|
||||||
if (gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE,
|
GST_DEBUG_OBJECT (dec, "setting caps %" GST_PTR_FORMAT, caps);
|
||||||
I420_SIZE (width, height), caps, &outbuf) != GST_FLOW_OK) {
|
GST_DEBUG_OBJECT (dec, "max_v_samp_factor=%d",
|
||||||
GST_DEBUG_OBJECT (dec, "failed to alloc buffer");
|
dec->cinfo.max_v_samp_factor);
|
||||||
|
|
||||||
|
gst_pad_set_caps (dec->srcpad, caps);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
|
dec->caps_width = width;
|
||||||
|
dec->caps_height = height;
|
||||||
|
dec->caps_fps = dec->fps;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
ret = gst_pad_alloc_buffer (dec->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||||
caps = NULL;
|
I420_SIZE (width, height), GST_PAD_CAPS (dec->srcpad), &outbuf);
|
||||||
|
if (ret != GST_FLOW_OK)
|
||||||
|
goto alloc_failed;
|
||||||
|
|
||||||
outdata = GST_BUFFER_DATA (outbuf);
|
outdata = GST_BUFFER_DATA (outbuf);
|
||||||
GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
|
GST_BUFFER_TIMESTAMP (outbuf) = dec->next_ts;
|
||||||
GST_BUFFER_DURATION (outbuf) = GST_SECOND / dec->fps;
|
|
||||||
|
if (dec->packetized) {
|
||||||
|
duration = GST_SECOND / dec->fps;
|
||||||
|
dec->next_ts += duration;
|
||||||
|
} else {
|
||||||
|
duration = GST_CLOCK_TIME_NONE;
|
||||||
|
dec->next_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
}
|
||||||
|
GST_BUFFER_DURATION (outbuf) = duration;
|
||||||
|
|
||||||
GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
|
GST_LOG_OBJECT (dec, "width %d, height %d, buffer size %d, required size %d",
|
||||||
width, height, GST_BUFFER_SIZE (outbuf), I420_SIZE (width, height));
|
width, height, GST_BUFFER_SIZE (outbuf), I420_SIZE (width, height));
|
||||||
|
|
||||||
dec->next_ts += GST_BUFFER_DURATION (outbuf);
|
|
||||||
|
|
||||||
/* mind the swap, jpeglib outputs blue chroma first */
|
/* mind the swap, jpeglib outputs blue chroma first */
|
||||||
base[0] = outdata + I420_Y_OFFSET (width, height);
|
base[0] = outdata + I420_Y_OFFSET (width, height);
|
||||||
base[1] = outdata + I420_U_OFFSET (width, height);
|
base[1] = outdata + I420_U_OFFSET (width, height);
|
||||||
|
@ -864,9 +858,7 @@ gst_jpeg_dec_chain (GstPad * pad, GstBuffer * buf)
|
||||||
jpeg_finish_decompress (&dec->cinfo);
|
jpeg_finish_decompress (&dec->cinfo);
|
||||||
|
|
||||||
GST_LOG_OBJECT (dec, "pushing buffer");
|
GST_LOG_OBJECT (dec, "pushing buffer");
|
||||||
gst_pad_push (dec->srcpad, outbuf);
|
ret = gst_pad_push (dec->srcpad, outbuf);
|
||||||
|
|
||||||
ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) {
|
if (GST_BUFFER_SIZE (dec->tempbuf) == img_len) {
|
||||||
|
@ -879,8 +871,45 @@ done:
|
||||||
gst_buffer_unref (dec->tempbuf);
|
gst_buffer_unref (dec->tempbuf);
|
||||||
dec->tempbuf = buf;
|
dec->tempbuf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* special cases */
|
||||||
|
need_more_data:
|
||||||
|
{
|
||||||
|
GST_LOG_OBJECT (dec, "we need more data");
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
/* ERRORS */
|
||||||
|
wrong_size:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||||
|
("Picture is too small or too big (%ux%u)", width, height),
|
||||||
|
("Picture is too small or too big (%ux%u)", width, height));
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
decode_error:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||||
|
(_("Failed to decode JPEG image")),
|
||||||
|
("Error #%u: %s", code, dec->jerr.pub.jpeg_message_table[code]));
|
||||||
|
ret = GST_FLOW_ERROR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
alloc_failed:
|
||||||
|
{
|
||||||
|
const gchar *reason;
|
||||||
|
|
||||||
|
reason = gst_flow_get_name (ret);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (dec, "failed to alloc buffer, reason %s", reason);
|
||||||
|
if (GST_FLOW_IS_FATAL (ret)) {
|
||||||
|
GST_ELEMENT_ERROR (dec, STREAM, DECODE,
|
||||||
|
("Buffer allocation failed, reason: %s", reason),
|
||||||
|
("Buffer allocation failed, reason: %s", reason));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
|
@ -892,10 +921,13 @@ gst_jpeg_dec_change_state (GstElement * element, GstStateChange transition)
|
||||||
dec = GST_JPEG_DEC (element);
|
dec = GST_JPEG_DEC (element);
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_NULL_TO_READY:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
dec->next_ts = 0;
|
dec->fps = 0.0;
|
||||||
|
dec->caps_fps = 0.0;
|
||||||
|
dec->caps_width = -1;
|
||||||
|
dec->caps_height = -1;
|
||||||
dec->packetized = FALSE;
|
dec->packetized = FALSE;
|
||||||
break;
|
dec->next_ts = 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,6 +78,11 @@ struct _GstJpegDec {
|
||||||
/* video state */
|
/* video state */
|
||||||
gdouble fps;
|
gdouble fps;
|
||||||
|
|
||||||
|
/* negotiated state */
|
||||||
|
gdouble caps_fps;
|
||||||
|
gint caps_width;
|
||||||
|
gint caps_height;
|
||||||
|
|
||||||
struct jpeg_decompress_struct cinfo;
|
struct jpeg_decompress_struct cinfo;
|
||||||
struct GstJpegDecErrorMgr jerr;
|
struct GstJpegDecErrorMgr jerr;
|
||||||
struct GstJpegDecSourceMgr jsrc;
|
struct GstJpegDecSourceMgr jsrc;
|
||||||
|
|
Loading…
Reference in a new issue