Пример #1
0
static GstFlowReturn
gst_wavenc_write_tags (GstWavEnc * wavenc)
{
  const GstTagList *user_tags;
  GstTagList *tags;
  guint size;
  GstBuffer *buf;
  GstByteWriter bw;

  g_return_val_if_fail (wavenc != NULL, GST_FLOW_OK);

  user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (wavenc));
  if ((!wavenc->tags) && (!user_tags)) {
    GST_DEBUG_OBJECT (wavenc, "have no tags");
    return GST_FLOW_OK;
  }
  tags =
      gst_tag_list_merge (user_tags, wavenc->tags,
      gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (wavenc)));

  GST_DEBUG_OBJECT (wavenc, "writing tags");

  gst_byte_writer_init_with_size (&bw, 1024, FALSE);

  /* add LIST INFO chunk */
  gst_byte_writer_put_data (&bw, (const guint8 *) "LIST", 4);
  gst_byte_writer_put_uint32_le (&bw, 0);
  gst_byte_writer_put_data (&bw, (const guint8 *) "INFO", 4);

  /* add tags */
  gst_tag_list_foreach (tags, gst_wavparse_tags_foreach, &bw);

  /* sets real size of LIST INFO chunk */
  size = gst_byte_writer_get_pos (&bw);
  gst_byte_writer_set_pos (&bw, 4);
  gst_byte_writer_put_uint32_le (&bw, size - 8);

  gst_tag_list_unref (tags);

  buf = gst_byte_writer_reset_and_get_buffer (&bw);
  wavenc->meta_length += gst_buffer_get_size (buf);
  return gst_pad_push (wavenc->srcpad, buf);
}
Пример #2
0
static void
gst_exif_tag_rewrite_offsets (GstExifWriter * writer, guint32 base_offset)
{
  guint32 offset;

  GST_LOG ("Rewriting tag entries offsets");

  offset = gst_byte_writer_get_size (&writer->tagwriter);
  while (gst_byte_writer_get_pos (&writer->tagwriter) <
      gst_byte_writer_get_size (&writer->tagwriter)) {
    guint16 type = 0;
    guint32 cur_offset = 0;
    GstByteReader *reader;
    gint byte_size = 0;
    guint32 count = 0;
    guint16 tag_id = 0;

    reader = (GstByteReader *) & writer->tagwriter;

    /* read the type */
    if (writer->byte_order == G_LITTLE_ENDIAN) {
      if (!gst_byte_reader_get_uint16_le (reader, &tag_id))
        break;
      if (!gst_byte_reader_get_uint16_le (reader, &type))
        break;
      if (!gst_byte_reader_get_uint32_le (reader, &count))
        break;
    } else {
      if (!gst_byte_reader_get_uint16_be (reader, &tag_id))
        break;
      if (!gst_byte_reader_get_uint16_be (reader, &type))
        break;
      if (!gst_byte_reader_get_uint32_be (reader, &count))
        break;
    }

    switch (type) {
      case EXIF_TYPE_BYTE:
      case EXIF_TYPE_ASCII:
      case EXIF_TYPE_UNDEFINED:
        byte_size = count;
        break;
      case EXIF_TYPE_SHORT:
        byte_size = count * 2;  /* 2 bytes */
        break;
      case EXIF_TYPE_LONG:
      case EXIF_TYPE_SLONG:
        byte_size = count * 4;  /* 4 bytes */
        break;
      case EXIF_TYPE_RATIONAL:
      case EXIF_TYPE_SRATIONAL:
        byte_size = count * 8;  /* 8 bytes */
        break;
      default:
        g_assert_not_reached ();
        break;
    }

    /* adjust the offset if needed */
    if (byte_size > 4 || tag_id == EXIF_GPS_IFD_TAG) {
      if (writer->byte_order == G_LITTLE_ENDIAN) {
        if (gst_byte_reader_peek_uint32_le (reader, &cur_offset)) {
          gst_byte_writer_put_uint32_le (&writer->tagwriter,
              cur_offset + offset + base_offset);
        }
      } else {
        if (gst_byte_reader_peek_uint32_be (reader, &cur_offset)) {
          gst_byte_writer_put_uint32_be (&writer->tagwriter,
              cur_offset + offset + base_offset);
        }
      }
      GST_DEBUG ("Rewriting tag offset from %u to (%u + %u + %u) %u",
          cur_offset, cur_offset, offset, base_offset,
          cur_offset + offset + base_offset);
    } else {
      gst_byte_reader_skip (reader, 4);
      GST_DEBUG ("No need to rewrite tag offset");
    }
  }
}
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;
}