#include <stdio.h>
static gboolean gst_pnmdec_start (GstVideoDecoder * decoder);
+static GstFlowReturn gst_pnmdec_finish (GstVideoDecoder * decoder);
static gboolean gst_pnmdec_set_format (GstVideoDecoder * decoder,
GstVideoCodecState * state);
static gboolean gst_pnmdec_stop (GstVideoDecoder * decoder);
"Lutz Mueller <lutz@users.sourceforge.net>");
vdec_class->start = gst_pnmdec_start;
+ vdec_class->finish = gst_pnmdec_finish;
vdec_class->stop = gst_pnmdec_stop;
vdec_class->parse = gst_pnmdec_parse;
vdec_class->handle_frame = gst_pnmdec_handle_frame;
{
GScanner *scanner;
guint i = 0;
- guint target;
+ guint target, last_val = 0;
GstMapInfo map;
guint8 *outdata;
gst_buffer_map (s->buf, &map, GST_MAP_WRITE);
+ if (bs) {
+ GST_MEMDUMP_OBJECT (s, "Starting parse:", b, MIN (16, bs));
+ }
+
/* leave the number of bytes already parsed */
outdata = map.data + s->current_size;
- if (!bs) {
- goto drop_ok;
- }
- if (s->last_byte) {
- while (*b >= '0' && *b <= '9') {
- s->last_byte = 10 * s->last_byte + *b - '0';
+ if (s->have_last_val) {
+ while (bs && *b >= '0' && *b <= '9') {
+ s->last_val = 10 * s->last_val + *b - '0';
b++;
if (!--bs) {
goto drop_error;
}
}
- if (s->last_byte > s->mngr.info.max) {
+ if (s->last_val > s->mngr.info.max) {
GST_DEBUG_OBJECT (s, "Corrupt ASCII encoded PNM file.");
goto drop_error;
}
- }
- if (s->last_byte) {
- outdata[i++] = s->last_byte;
- s->last_byte = 0;
+ GST_LOG_OBJECT (s, "Collected partial value from previous parse - %u",
+ s->last_val);
+ if (s->mngr.info.max > 255) {
+ if (i + 1 >= target) {
+ GST_DEBUG_OBJECT (s, "PNM file contains too much data.");
+ goto drop_error;
+ }
+ if (s->out_format == GST_VIDEO_FORMAT_GRAY16_BE)
+ GST_WRITE_UINT16_BE (outdata + i, s->last_val);
+ else
+ GST_WRITE_UINT16_LE (outdata + i, s->last_val);
+ i += 2;
+ } else {
+ outdata[i++] = s->last_val;
+ }
+ last_val = s->last_val;
+ s->have_last_val = FALSE;
}
+ /* Might be no data if we're at EOS */
+ if (!bs)
+ goto done;
+
scanner = g_scanner_new (NULL);
g_scanner_input_text (scanner, (gchar *) b, bs);
while (!g_scanner_eof (scanner)) {
switch (g_scanner_get_next_token (scanner)) {
case G_TOKEN_INT:
- if (i == target) {
- GST_DEBUG_OBJECT (s, "PNM file contains too much data.");
- g_scanner_destroy (scanner);
- goto drop_error;
+ if (s->mngr.info.max > 255) {
+ if (i + 1 >= target) {
+ GST_DEBUG_OBJECT (s,
+ "PNM file contains too much data after line %u col %u.",
+ scanner->line, scanner->position);
+ g_scanner_destroy (scanner);
+ goto done; // drop_error;
+ }
+ if (s->out_format == GST_VIDEO_FORMAT_GRAY16_BE)
+ GST_WRITE_UINT16_BE (outdata + i, scanner->value.v_int);
+ else
+ GST_WRITE_UINT16_LE (outdata + i, scanner->value.v_int);
+ i += 2;
+ } else {
+ if (i == target) {
+ GST_DEBUG_OBJECT (s,
+ "PNM file contains too much data after line %u col %u.",
+ scanner->line, scanner->position);
+ g_scanner_destroy (scanner);
+ goto drop_error;
+ }
+ outdata[i++] = scanner->value.v_int;
}
- outdata[i++] = scanner->value.v_int;
+ last_val = scanner->value.v_int;
break;
default:
/* Should we care? */ ;
g_scanner_destroy (scanner);
/* If we didn't get the whole image, handle the last byte with care. */
- if (i && i < target && b[bs - 1] > '0' && b[bs - 1] <= '9') {
- s->last_byte = outdata[--i];
+ if (i && i < target && b[bs - 1] >= '0' && b[bs - 1] <= '9') {
+ s->last_val = last_val;
+ s->have_last_val = TRUE;
+ if (s->mngr.info.max > 255)
+ i -= 2;
+ else
+ i--;
+ GST_LOG_OBJECT (s, "Stored last value %u for next parse cycle",
+ s->last_val);
}
- /* Update the number of bytes parsed in this scan */
+done:
+ /* Update the number of output bytes parsed in this scan */
s->current_size += i;
+ GST_LOG_OBJECT (s, "Parsed %u bytes, now have %u bytes of %u output",
+ i, s->current_size, s->size);
gst_buffer_unmap (s->buf, &map);
return GST_FLOW_OK;
-drop_ok:
- gst_buffer_unmap (s->buf, &map);
- return GST_FLOW_OK;
drop_error:
gst_buffer_unmap (s->buf, &map);
}
gst_buffer_unmap (frame->output_buffer, &omap);
+ s->current_size = 0;
+
r = gst_video_decoder_finish_frame (GST_VIDEO_DECODER (s), frame);
out:
GstPnmdec *s = GST_PNMDEC (decoder);
GstFlowReturn r = GST_FLOW_OK;
guint offset = 0;
- const guint8 *raw_data;
+ const guint8 *raw_data = NULL;
GST_VIDEO_CODEC_FRAME_SET_SYNC_POINT (frame);
size = gst_adapter_available (adapter);
- if (size < 8) {
- goto need_more_data;
- }
- raw_data = gst_adapter_map (adapter, size);
+ if (size > 0)
+ raw_data = gst_adapter_map (adapter, size);
+
+ GST_LOG_OBJECT (s, "Entering parse with %" G_GSIZE_FORMAT " bytes. at_eos %d",
+ size, at_eos);
if (s->mngr.info.fields != GST_PNM_INFO_FIELDS_ALL) {
GstPnmInfoMngrResult res;
+ if (size < 8)
+ goto need_more_data;
+
res = gst_pnm_info_mngr_scan (&s->mngr, raw_data, size);
switch (res) {
goto out;
if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
- s->mngr.data_offset++;
/* It is not possible to know the size of input ascii data to parse.
So we have to parse and know the number of pixels parsed and
then finally decide when we have full frame */
+ GST_DEBUG_OBJECT (s, "Allocating output frame of size %u", s->size);
s->buf = gst_buffer_new_and_alloc (s->size);
}
offset = s->mngr.data_offset;
}
if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
- /* Parse ASCII data dn populate s->current_size with the number of
+ /* Parse ASCII data and populate s->current_size with the number of
bytes actually parsed from the input data */
+ GST_DEBUG_OBJECT (s, "Parsing %u bytes at offset %u", (guint) size, offset);
r = gst_pnmdec_parse_ascii (s, raw_data + offset, size);
} else {
/* Bitmap Contains 8 pixels in a byte */
{
GstPnmdec *pnmdec = (GstPnmdec *) decoder;
gst_video_decoder_set_packetized (GST_VIDEO_DECODER (pnmdec), FALSE);
+ gst_pnmdec_flush (pnmdec);
return TRUE;
}
+
+static GstFlowReturn
+gst_pnmdec_finish (GstVideoDecoder * decoder)
+{
+ GstPnmdec *s = (GstPnmdec *) decoder;
+
+ GST_LOG_OBJECT (s, "finishing");
+
+ if (s->mngr.info.encoding == GST_PNM_ENCODING_ASCII) {
+ /* One last go at outputting any final value */
+ gst_pnmdec_parse_ascii (s, 0, 0);
+ if (s->size <= s->current_size) {
+ return gst_video_decoder_have_frame (decoder);
+ }
+ }
+
+ return GST_FLOW_OK;
+}