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;
}
Exemple #2
0
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;
}
Exemple #3
0
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;
}