mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 13:41: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)
|
gst_pnmdec_chain_raw (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFlowReturn r = GST_FLOW_OK;
|
GstFlowReturn r = GST_FLOW_OK;
|
||||||
|
GstBuffer *out;
|
||||||
|
|
||||||
/* If we got the whole image, just push the buffer. */
|
/* If we got the whole image, just push the buffer. */
|
||||||
if (GST_BUFFER_SIZE (buf) == s->size) {
|
if (GST_BUFFER_SIZE (buf) == s->size) {
|
||||||
|
@ -108,10 +109,11 @@ gst_pnmdec_chain_raw (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||||
if (!s->buf) {
|
if (!s->buf) {
|
||||||
s->buf = buf;
|
s->buf = buf;
|
||||||
} else {
|
} 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_SIZE (s->buf) + GST_BUFFER_SIZE (buf));
|
||||||
|
gst_buffer_unref (buf);
|
||||||
gst_buffer_unref (s->buf);
|
gst_buffer_unref (s->buf);
|
||||||
s->buf = buf;
|
s->buf = out;
|
||||||
}
|
}
|
||||||
if (!s->buf)
|
if (!s->buf)
|
||||||
return GST_FLOW_ERROR;
|
return GST_FLOW_ERROR;
|
||||||
|
@ -132,16 +134,46 @@ static GstFlowReturn
|
||||||
gst_pnmdec_chain_ascii (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
gst_pnmdec_chain_ascii (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GScanner *scanner;
|
GScanner *scanner;
|
||||||
GstBuffer *out = gst_buffer_new_and_alloc (s->size);
|
GstBuffer *out;
|
||||||
guint i = 0;
|
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);
|
scanner = g_scanner_new (NULL);
|
||||||
g_scanner_input_text (scanner, (gchar *) GST_BUFFER_DATA (buf),
|
g_scanner_input_text (scanner, b, bs);
|
||||||
GST_BUFFER_SIZE (buf));
|
|
||||||
while (!g_scanner_eof (scanner)) {
|
while (!g_scanner_eof (scanner)) {
|
||||||
switch (g_scanner_get_next_token (scanner)) {
|
switch (g_scanner_get_next_token (scanner)) {
|
||||||
case G_TOKEN_INT:
|
case G_TOKEN_INT:
|
||||||
if (i == s->size) {
|
if (i == target) {
|
||||||
GST_DEBUG_OBJECT (s, "PNM file contains too much data.");
|
GST_DEBUG_OBJECT (s, "PNM file contains too much data.");
|
||||||
gst_buffer_unref (buf);
|
gst_buffer_unref (buf);
|
||||||
gst_buffer_unref (out);
|
gst_buffer_unref (out);
|
||||||
|
@ -154,15 +186,18 @@ gst_pnmdec_chain_ascii (GstPnmdec * s, GstPad * src, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
g_scanner_destroy (scanner);
|
g_scanner_destroy (scanner);
|
||||||
gst_buffer_unref (buf);
|
|
||||||
|
|
||||||
if (i < s->size) {
|
/* If we didn't get the whole image, handle the last byte with care. */
|
||||||
GST_DEBUG_OBJECT (s, "FIXME: Decoding of ASCII encoded files split "
|
if (i < target && b[bs - 1] > '0' && b[bs - 1] <= '9')
|
||||||
"over several buffers is not implemented!");
|
s->last_byte = GST_BUFFER_DATA (out)[--i];
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
if (!i) {
|
||||||
gst_buffer_unref (out);
|
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);
|
return gst_pnmdec_chain_raw (s, src, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,7 +210,7 @@ gst_pnmdec_chain (GstPad * pad, GstBuffer * data)
|
||||||
GstFlowReturn r = GST_FLOW_OK;
|
GstFlowReturn r = GST_FLOW_OK;
|
||||||
guint offset = 0;
|
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),
|
switch (gst_pnm_info_mngr_scan (&s->mngr, GST_BUFFER_DATA (data),
|
||||||
GST_BUFFER_SIZE (data))) {
|
GST_BUFFER_SIZE (data))) {
|
||||||
case GST_PNM_INFO_MNGR_RESULT_FAILED:
|
case GST_PNM_INFO_MNGR_RESULT_FAILED:
|
||||||
|
|
|
@ -39,7 +39,7 @@ struct _GstPnmdec
|
||||||
GstElement element;
|
GstElement element;
|
||||||
|
|
||||||
GstPnmInfoMngr mngr;
|
GstPnmInfoMngr mngr;
|
||||||
guint size;
|
guint size, last_byte;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -134,6 +134,7 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
|
mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
|
||||||
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
||||||
mngr->data_offset += i;
|
mngr->data_offset += i;
|
||||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - 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 *= 10;
|
||||||
mngr->info.width += buf[i++] - 0x030;
|
mngr->info.width += buf[i++] - 0x030;
|
||||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_WIDTH;
|
|
||||||
mngr->data_offset += i;
|
mngr->data_offset += i;
|
||||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||||
case GST_PNM_INFO_MNGR_STATE_DATA_HEIGHT:
|
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 '\n':
|
||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
|
mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
|
||||||
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
mngr->state = GST_PNM_INFO_MNGR_STATE_WHITE_SPACE;
|
||||||
mngr->data_offset += i;
|
mngr->data_offset += i;
|
||||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - 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 *= 10;
|
||||||
mngr->info.height += buf[i++] - 0x030;
|
mngr->info.height += buf[i++] - 0x030;
|
||||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_HEIGHT;
|
|
||||||
mngr->data_offset += i;
|
mngr->data_offset += i;
|
||||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||||
case GST_PNM_INFO_MNGR_STATE_DATA_MAX:
|
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 '\n':
|
||||||
case '\t':
|
case '\t':
|
||||||
case ' ':
|
case ' ':
|
||||||
|
mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
|
||||||
mngr->data_offset += i + 1;
|
mngr->data_offset += i + 1;
|
||||||
return GST_PNM_INFO_MNGR_RESULT_FINISHED;
|
return GST_PNM_INFO_MNGR_RESULT_FINISHED;
|
||||||
default:
|
default:
|
||||||
|
@ -178,7 +179,6 @@ gst_pnm_info_mngr_scan (GstPnmInfoMngr * mngr, const guint8 * buf,
|
||||||
}
|
}
|
||||||
mngr->info.max *= 10;
|
mngr->info.max *= 10;
|
||||||
mngr->info.max += buf[i++] - 0x030;
|
mngr->info.max += buf[i++] - 0x030;
|
||||||
mngr->info.fields |= GST_PNM_INFO_FIELDS_MAX;
|
|
||||||
mngr->data_offset += i;
|
mngr->data_offset += i;
|
||||||
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
return gst_pnm_info_mngr_scan (mngr, buf + i, buf_len - i);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue