mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 18:50:48 +00:00
pnm: Handle ASCII encoded PNM data that is split over multiple buffers
Also: - unref buffers after gst_buffer_span - fix scanning of header if header data is split over several buffers Fixes bug #595700.
This commit is contained in:
parent
960f418378
commit
a744f8136b
3 changed files with 51 additions and 16 deletions
|
@ -95,6 +95,7 @@ static GstFlowReturn
|
|||
gst_pnmdec_chain_raw (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||
{
|
||||
GstFlowReturn r = GST_FLOW_OK;
|
||||
GstBuffer *out;
|
||||
|
||||
/* If we got the whole image, just push the buffer. */
|
||||
if (GST_BUFFER_SIZE (buf) == s->size) {
|
||||
|
@ -108,10 +109,11 @@ gst_pnmdec_chain_raw (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
|||
if (!s->buf) {
|
||||
s->buf = buf;
|
||||
} else {
|
||||
buf = gst_buffer_span (s->buf, 0, buf,
|
||||
out = gst_buffer_span (s->buf, 0, buf,
|
||||
GST_BUFFER_SIZE (s->buf) + GST_BUFFER_SIZE (buf));
|
||||
gst_buffer_unref (buf);
|
||||
gst_buffer_unref (s->buf);
|
||||
s->buf = buf;
|
||||
s->buf = out;
|
||||
}
|
||||
if (!s->buf)
|
||||
return GST_FLOW_ERROR;
|
||||
|
@ -132,16 +134,46 @@ static GstFlowReturn
|
|||
gst_pnmdec_chain_ascii (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||
{
|
||||
GScanner *scanner;
|
||||
GstBuffer *out = gst_buffer_new_and_alloc (s->size);
|
||||
GstBuffer *out;
|
||||
guint i = 0;
|
||||
gchar *b = (gchar *) GST_BUFFER_DATA (buf);
|
||||
guint bs = GST_BUFFER_SIZE (buf);
|
||||
guint target = s->size - (s->buf ? GST_BUFFER_SIZE (s->buf) : 0);
|
||||
|
||||
if (!bs) {
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
if (s->last_byte) {
|
||||
while (*b >= '0' && *b <= '9') {
|
||||
s->last_byte = 10 * s->last_byte + *b - '0';
|
||||
b++;
|
||||
if (!--bs) {
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
if (s->last_byte > 255) {
|
||||
gst_buffer_unref (buf);
|
||||
GST_DEBUG_OBJECT (s, "Corrupt ASCII encoded PNM file.");
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
out = gst_buffer_new_and_alloc (target);
|
||||
|
||||
if (s->last_byte) {
|
||||
GST_BUFFER_DATA (out)[i++] = s->last_byte;
|
||||
s->last_byte = 0;
|
||||
}
|
||||
|
||||
scanner = g_scanner_new (NULL);
|
||||
g_scanner_input_text (scanner, (gchar *) GST_BUFFER_DATA (buf),
|
||||
GST_BUFFER_SIZE (buf));
|
||||
g_scanner_input_text (scanner, b, bs);
|
||||
while (!g_scanner_eof (scanner)) {
|
||||
switch (g_scanner_get_next_token (scanner)) {
|
||||
case G_TOKEN_INT:
|
||||
if (i == s->size) {
|
||||
if (i == target) {
|
||||
GST_DEBUG_OBJECT (s, "PNM file contains too much data.");
|
||||
gst_buffer_unref (buf);
|
||||
gst_buffer_unref (out);
|
||||
|
@ -154,15 +186,18 @@ gst_pnmdec_chain_ascii (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
|||
}
|
||||
}
|
||||
g_scanner_destroy (scanner);
|
||||
gst_buffer_unref (buf);
|
||||
|
||||
if (i < s->size) {
|
||||
GST_DEBUG_OBJECT (s, "FIXME: Decoding of ASCII encoded files split "
|
||||
"over several buffers is not implemented!");
|
||||
/* If we didn't get the whole image, handle the last byte with care. */
|
||||
if (i < target && b[bs - 1] > '0' && b[bs - 1] <= '9')
|
||||
s->last_byte = GST_BUFFER_DATA (out)[--i];
|
||||
|
||||
gst_buffer_unref (buf);
|
||||
if (!i) {
|
||||
gst_buffer_unref (out);
|
||||
return GST_FLOW_ERROR;
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
GST_BUFFER_SIZE (out) = i;
|
||||
return gst_pnmdec_chain_raw (s, src, out);
|
||||
}
|
||||
|
||||
|
@ -175,7 +210,7 @@ gst_pnmdec_chain (GstPad * pad, GstBuffer * data)
|
|||
GstFlowReturn r = GST_FLOW_OK;
|
||||
guint offset = 0;
|
||||
|
||||
if (!(s->mngr.info.fields & GST_PNM_INFO_FIELDS_ALL)) {
|
||||
if (s->mngr.info.fields != GST_PNM_INFO_FIELDS_ALL) {
|
||||
switch (gst_pnm_info_mngr_scan (&s->mngr, GST_BUFFER_DATA (data),
|
||||
GST_BUFFER_SIZE (data))) {
|
||||
case GST_PNM_INFO_MNGR_RESULT_FAILED:
|
||||
|
|
|
@ -39,7 +39,7 @@ struct _GstPnmdec
|
|||
GstElement element;
|
||||
|
||||
GstPnmInfoMngr mngr;
|
||||
guint size;
|
||||
guint size, last_byte;
|
||||
GstBuffer *buf;
|
||||
};
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
case '\n':
|
||||
case '\t':
|
||||
case ' ':
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
|
||||
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
||||
mngr->data_offset += i;
|
||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||
|
@ -143,7 +144,6 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
}
|
||||
mngr->info.width *= 10;
|
||||
mngr->info.width += buf[i++] - 0x030;
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
|
||||
mngr->data_offset += i;
|
||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||
case GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT:
|
||||
|
@ -152,6 +152,7 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
case '\n':
|
||||
case '\t':
|
||||
case ' ':
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
|
||||
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
||||
mngr->data_offset += i;
|
||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||
|
@ -161,7 +162,6 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
}
|
||||
mngr->info.height *= 10;
|
||||
mngr->info.height += buf[i++] - 0x030;
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
|
||||
mngr->data_offset += i;
|
||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||
case GST_PNM_INFO_MNGR_STATE_DATA_MAX:
|
||||
|
@ -170,6 +170,7 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
case '\n':
|
||||
case '\t':
|
||||
case ' ':
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
|
||||
mngr->data_offset += i + 1;
|
||||
return GST_PNM_INFO_MNGR_RESULT_FINISHED;
|
||||
default:
|
||||
|
@ -178,7 +179,6 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
|||
}
|
||||
mngr->info.max *= 10;
|
||||
mngr->info.max += buf[i++] - 0x030;
|
||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
|
||||
mngr->data_offset += i;
|
||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue