static gboolean flx_decode_color (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer, gint scale) { guint8 count, indx; guint16 packs; if (!gst_byte_reader_get_uint16_le (reader, &packs)) goto error; indx = 0; GST_LOG ("GstFlxDec: cmap packs: %d", (guint) packs); while (packs--) { const guint8 *data; guint16 actual_count; /* color map index + skip count */ if (!gst_byte_reader_get_uint8 (reader, &indx)) goto error; /* number of rgb triplets */ if (!gst_byte_reader_get_uint8 (reader, &count)) goto error; actual_count = count == 0 ? 256 : count; if (!gst_byte_reader_get_data (reader, count * 3, &data)) goto error; GST_LOG_OBJECT (flxdec, "cmap count: %d (indx: %d)", actual_count, indx); flx_set_palette_vector (flxdec->converter, indx, actual_count, (guchar *) data, scale); } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Error decoding color palette"); return FALSE; }
static gboolean gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) { GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buffer); guint8 marker = 0; gboolean foundSOF = FALSE; if (!gst_byte_reader_peek_uint8 (&reader, &marker)) goto error; while (marker == 0xff) { if (!gst_byte_reader_skip (&reader, 1)) goto error; if (!gst_byte_reader_get_uint8 (&reader, &marker)) goto error; GST_DEBUG_OBJECT (parse, "marker = %x", marker); switch (marker) { case SOS: /* start of scan (begins compressed data) */ return foundSOF; case SOI: break; case DRI: if (!gst_byte_reader_skip (&reader, 4)) /* fixed size */ goto error; break; case COM: if (!gst_jpeg_parse_com (parse, &reader)) goto error; break; case APP1: if (!gst_jpeg_parse_app1 (parse, &reader)) goto error; break; case DHT: case DQT: /* Ignore these codes */ if (!gst_jpeg_parse_skip_marker (parse, &reader, marker)) goto error; break; case SOF2: parse->priv->interlaced = TRUE; /* fall through */ case SOF0: foundSOF = TRUE; /* parse Start Of Frame */ if (!gst_jpeg_parse_sof (parse, &reader)) goto error; return TRUE; default: if (marker == JPG || (marker >= JPG0 && marker <= JPG13)) { /* we'd like to remove them from the buffer */ if (!gst_jpeg_parse_remove_marker (parse, &reader, marker, buffer)) goto error; } else if (marker >= APP0 && marker <= APP15) { if (!gst_jpeg_parse_skip_marker (parse, &reader, marker)) goto error; } else { GST_WARNING_OBJECT (parse, "unhandled marker %x, leaving", marker); /* Not SOF or SOI. Must not be a JPEG file (or file pointer * is placed wrong). In either case, it's an error. */ return FALSE; } } if (!gst_byte_reader_peek_uint8 (&reader, &marker)) goto error; } return foundSOF; error: GST_WARNING_OBJECT (parse, "Error parsing image header (need more than %u bytes available)", gst_byte_reader_get_remaining (&reader)); return FALSE; }
static inline gboolean gst_jpeg_parse_sof (GstJpegParse * parse, GstByteReader * reader) { guint8 numcomps = 0; /* Number of components in image (1 for gray, 3 for YUV, etc.) */ guint8 precision; /* precision (in bits) for the samples */ guint8 compId[3]; /* unique value identifying each component */ guint8 qtId[3]; /* quantization table ID to use for this comp */ guint8 blockWidth[3]; /* Array[numComponents] giving the number of blocks (horiz) in this component */ guint8 blockHeight[3]; /* Same for the vertical part of this component */ guint8 i, value = 0; gint temp; /* flush length field */ if (!gst_byte_reader_skip (reader, 2)) return FALSE; /* Get sample precision */ if (!gst_byte_reader_get_uint8 (reader, &precision)) return FALSE; /* Get w and h */ if (!gst_byte_reader_get_uint16_be (reader, &parse->priv->height)) return FALSE; if (!gst_byte_reader_get_uint16_be (reader, &parse->priv->width)) return FALSE; /* Get number of components */ if (!gst_byte_reader_get_uint8 (reader, &numcomps)) return FALSE; if (numcomps > 3) return FALSE; /* Get decimation and quantization table id for each component */ for (i = 0; i < numcomps; i++) { /* Get component ID number */ if (!gst_byte_reader_get_uint8 (reader, &value)) return FALSE; compId[i] = value; /* Get decimation */ if (!gst_byte_reader_get_uint8 (reader, &value)) return FALSE; blockWidth[i] = (value & 0xf0) >> 4; blockHeight[i] = (value & 0x0f); /* Get quantization table id */ if (!gst_byte_reader_get_uint8 (reader, &value)) return FALSE; qtId[i] = value; } if (numcomps == 1) { /* gray image - no fourcc */ parse->priv->fourcc = 0; } else if (numcomps == 3) { temp = (blockWidth[0] * blockHeight[0]) / (blockWidth[1] * blockHeight[1]); if (temp == 4 && blockHeight[0] == 2) parse->priv->fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0'); else if (temp == 4 && blockHeight[0] == 4) parse->priv->fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B'); else if (temp == 2) parse->priv->fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); else if (temp == 1) parse->priv->fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2'); else parse->priv->fourcc = 0; } else { return FALSE; } GST_DEBUG_OBJECT (parse, "Header parsed"); return TRUE; }
static gboolean gst_jif_mux_parse_image (GstJifMux * self, GstBuffer * buf) { GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstJifMuxMarker *m; guint8 marker = 0; guint16 size = 0; const guint8 *data = NULL; GST_LOG_OBJECT (self, "Received buffer of size: %u", GST_BUFFER_SIZE (buf)); if (!gst_byte_reader_peek_uint8 (&reader, &marker)) goto error; while (marker == 0xff) { if (!gst_byte_reader_skip (&reader, 1)) goto error; if (!gst_byte_reader_get_uint8 (&reader, &marker)) goto error; switch (marker) { case RST0: case RST1: case RST2: case RST3: case RST4: case RST5: case RST6: case RST7: case SOI: GST_DEBUG_OBJECT (self, "marker = %x", marker); m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE); self->priv->markers = g_list_prepend (self->priv->markers, m); break; case EOI: GST_DEBUG_OBJECT (self, "marker = %x", marker); m = gst_jif_mux_new_marker (marker, 0, NULL, FALSE); self->priv->markers = g_list_prepend (self->priv->markers, m); goto done; break; default: if (!gst_byte_reader_get_uint16_be (&reader, &size)) goto error; if (!gst_byte_reader_get_data (&reader, size - 2, &data)) goto error; m = gst_jif_mux_new_marker (marker, size - 2, data, FALSE); self->priv->markers = g_list_prepend (self->priv->markers, m); GST_DEBUG_OBJECT (self, "marker = %2x, size = %u", marker, size); break; } if (marker == SOS) { gint eoi_pos = -1; gint i; /* search the last 5 bytes for the EOI marker */ g_assert (GST_BUFFER_SIZE (buf) >= 5); for (i = 5; i >= 2; i--) { if (GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf) - i] == 0xFF && GST_BUFFER_DATA (buf)[GST_BUFFER_SIZE (buf) - i + 1] == EOI) { eoi_pos = GST_BUFFER_SIZE (buf) - i; break; } } if (eoi_pos == -1) { GST_WARNING_OBJECT (self, "Couldn't find an EOI marker"); eoi_pos = GST_BUFFER_SIZE (buf); } /* remaining size except EOI is scan data */ self->priv->scan_size = eoi_pos - gst_byte_reader_get_pos (&reader); if (!gst_byte_reader_get_data (&reader, self->priv->scan_size, &self->priv->scan_data)) goto error; GST_DEBUG_OBJECT (self, "scan data, size = %u", self->priv->scan_size); } if (!gst_byte_reader_peek_uint8 (&reader, &marker)) goto error; } GST_INFO_OBJECT (self, "done parsing at 0x%x / 0x%x", gst_byte_reader_get_pos (&reader), GST_BUFFER_SIZE (buf)); done: self->priv->markers = g_list_reverse (self->priv->markers); return TRUE; error: GST_WARNING_OBJECT (self, "Error parsing image header (need more that %u bytes available)", gst_byte_reader_get_remaining (&reader)); return FALSE; }
static gboolean flx_decode_delta_flc (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer) { guint16 lines, start_l; g_return_val_if_fail (flxdec != NULL, FALSE); g_return_val_if_fail (flxdec->delta_data != NULL, FALSE); /* use last frame for delta */ if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &lines)) goto error; if (lines > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. too many lines."); return FALSE; } start_l = lines; while (lines) { guint16 opcode; if (!gst_byte_writer_set_pos (writer, flxdec->hdr.width * (start_l - lines))) goto error; /* process opcode(s) */ while (TRUE) { if (!gst_byte_reader_get_uint16_le (reader, &opcode)) goto error; if ((opcode & 0xc000) == 0) break; if ((opcode & 0xc000) == 0xc000) { /* line skip count */ gulong skip = (0x10000 - opcode); if (skip > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "skip line count too big."); return FALSE; } start_l += skip; if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + flxdec->hdr.width * skip)) goto error; } else { /* last pixel */ if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + flxdec->hdr.width)) goto error; if (!gst_byte_writer_put_uint8 (writer, opcode & 0xff)) goto error; } } /* last opcode is the packet count */ GST_LOG_OBJECT (flxdec, "have %d packets", opcode); while (opcode--) { /* skip count */ guint8 skip; gint8 count; if (!gst_byte_reader_get_uint8 (reader, &skip)) goto error; if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + skip)) goto error; /* RLE count */ if (!gst_byte_reader_get_int8 (reader, &count)) goto error; if (count < 0) { guint16 x; /* replicate word run */ count = ABS (count); GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "line too long."); return FALSE; } if (!gst_byte_reader_get_uint16_le (reader, &x)) goto error; while (count--) { if (!gst_byte_writer_put_uint16_le (writer, x)) { goto error; } } } else { GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLC packet detected. " "line too long."); return FALSE; } while (count--) { guint16 x; if (!gst_byte_reader_get_uint16_le (reader, &x)) goto error; if (!gst_byte_writer_put_uint16_le (writer, x)) goto error; } } } lines--; } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet"); return FALSE; }
static gboolean flx_decode_delta_fli (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer) { guint16 start_line, lines; guint line_start_i; g_return_val_if_fail (flxdec != NULL, FALSE); g_return_val_if_fail (flxdec->delta_data != NULL, FALSE); /* use last frame for delta */ if (!gst_byte_writer_put_data (writer, flxdec->delta_data, flxdec->size)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &start_line)) goto error; if (!gst_byte_reader_get_uint16_le (reader, &lines)) goto error; GST_LOG_OBJECT (flxdec, "height %d start line %d line count %d", flxdec->hdr.height, start_line, lines); if (start_line + lines > flxdec->hdr.height) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. too many lines."); return FALSE; } line_start_i = flxdec->hdr.width * start_line; if (!gst_byte_writer_set_pos (writer, line_start_i)) goto error; while (lines--) { guint8 packets; /* packet count */ if (!gst_byte_reader_get_uint8 (reader, &packets)) goto error; GST_LOG_OBJECT (flxdec, "have %d packets", packets); while (packets--) { /* skip count */ guint8 skip; gint8 count; if (!gst_byte_reader_get_uint8 (reader, &skip)) goto error; /* skip bytes */ if (!gst_byte_writer_set_pos (writer, gst_byte_writer_get_pos (writer) + skip)) goto error; /* RLE count */ if (!gst_byte_reader_get_int8 (reader, &count)) goto error; if (count < 0) { guint8 x; /* literal run */ count = ABS (count); GST_LOG_OBJECT (flxdec, "have literal run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. " "line too long."); return FALSE; } if (!gst_byte_reader_get_uint8 (reader, &x)) goto error; if (!gst_byte_writer_fill (writer, x, count)) goto error; } else { const guint8 *data; GST_LOG_OBJECT (flxdec, "have replicate run of size %d at offset %d", count, skip); if (skip + count > flxdec->hdr.width) { GST_ERROR_OBJECT (flxdec, "Invalid FLI packet detected. " "line too long."); return FALSE; } /* replicate run */ if (!gst_byte_reader_get_data (reader, count, &data)) goto error; if (!gst_byte_writer_put_data (writer, data, count)) goto error; } } line_start_i += flxdec->hdr.width; if (!gst_byte_writer_set_pos (writer, line_start_i)) goto error; } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Failed to decode FLI packet"); return FALSE; }
static gboolean flx_decode_brun (GstFlxDec * flxdec, GstByteReader * reader, GstByteWriter * writer) { gulong lines, row; g_return_val_if_fail (flxdec != NULL, FALSE); lines = flxdec->hdr.height; while (lines--) { /* packet count. * should not be used anymore, since the flc format can * contain more then 255 RLE packets. we use the frame * width instead. */ if (!gst_byte_reader_skip (reader, 1)) goto error; row = flxdec->hdr.width; while (row) { gint8 count; if (!gst_byte_reader_get_int8 (reader, &count)) goto error; if (count <= 0) { const guint8 *data; /* literal run */ count = ABS (count); GST_LOG_OBJECT (flxdec, "have literal run of size %d", count); if (count > row) { GST_ERROR_OBJECT (flxdec, "Invalid BRUN line detected. " "bytes to write exceeds the end of the row"); return FALSE; } row -= count; if (!gst_byte_reader_get_data (reader, count, &data)) goto error; if (!gst_byte_writer_put_data (writer, data, count)) goto error; } else { guint8 x; GST_LOG_OBJECT (flxdec, "have replicate run of size %d", count); if (count > row) { GST_ERROR_OBJECT (flxdec, "Invalid BRUN packet detected." "bytes to write exceeds the end of the row"); return FALSE; } /* replicate run */ row -= count; if (!gst_byte_reader_get_uint8 (reader, &x)) goto error; if (!gst_byte_writer_fill (writer, x, count)) goto error; } } } return TRUE; error: GST_ERROR_OBJECT (flxdec, "Failed to decode BRUN packet"); return FALSE; }