Exemplo n.º 1
0
/*
 * Writes the tag entry.
 *
 * The tag entry is the tag id, the tag type,
 * the count and the offset.
 *
 * The offset is the on the amount of data writen so far, as one
 * can't predict the total bytes that the tag entries will take.
 * This means those fields requires being updated later.
 */
static void
gst_exif_writer_write_tag_header (GstExifWriter * writer,
    guint16 exif_tag, guint16 exif_type, guint32 count, guint32 offset,
    gboolean is_data)
{
  GST_DEBUG ("Writing tag entry: id %x, type %u, count %u, offset %u",
      exif_tag, exif_type, count, offset);

  if (writer->byte_order == G_LITTLE_ENDIAN) {
    gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_tag);
    gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_type);
    gst_byte_writer_put_uint32_le (&writer->tagwriter, count);
    gst_byte_writer_put_uint32_le (&writer->tagwriter, offset);
  } else if (writer->byte_order == G_BIG_ENDIAN) {
    gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_tag);
    gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_type);
    gst_byte_writer_put_uint32_be (&writer->tagwriter, count);
    if (is_data) {
      gst_byte_writer_put_uint32_le (&writer->tagwriter, offset);
    } else {
      gst_byte_writer_put_uint32_be (&writer->tagwriter, offset);
    }
  } else {
    g_assert_not_reached ();
  }

  writer->tags_total++;
}
Exemplo n.º 2
0
/**
 * gst_tag_list_to_exif_buffer_with_tiff_header:
 * @taglist: The taglist
 *
 * Formats the tags in taglist into exif structure, a tiff header
 * is put in the beginning of the buffer.
 *
 * Returns: A GstBuffer containing the data
 *
 * Since: 0.10.30
 */
GstBuffer *
gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist)
{
  GstBuffer *ifd;
  GstByteWriter writer;
  guint size;

  ifd = gst_tag_list_to_exif_buffer (taglist, G_BYTE_ORDER, 8);
  if (ifd == NULL) {
    GST_WARNING ("Failed to create exif buffer");
    return NULL;
  }
  size = TIFF_HEADER_SIZE + GST_BUFFER_SIZE (ifd);

  /* TODO what is the correct endianness here? */
  gst_byte_writer_init_with_size (&writer, size, FALSE);
  /* TIFF header */
  if (G_BYTE_ORDER == G_LITTLE_ENDIAN) {
    gst_byte_writer_put_uint16_le (&writer, TIFF_LITTLE_ENDIAN);
    gst_byte_writer_put_uint16_le (&writer, 42);
    gst_byte_writer_put_uint32_le (&writer, 8);
  } else {
    gst_byte_writer_put_uint16_be (&writer, TIFF_BIG_ENDIAN);
    gst_byte_writer_put_uint16_be (&writer, 42);
    gst_byte_writer_put_uint32_be (&writer, 8);
  }
  if (!gst_byte_writer_put_data (&writer, GST_BUFFER_DATA (ifd),
          GST_BUFFER_SIZE (ifd))) {
    GST_WARNING ("Byte writer size mismatch");
    /* reaching here is a programming error because we should have a buffer
     * large enough */
    g_assert_not_reached ();
    gst_buffer_unref (ifd);
    gst_byte_writer_reset (&writer);
    return NULL;
  }
  gst_buffer_unref (ifd);
  return gst_byte_writer_reset_and_get_buffer (&writer);
}
Exemplo n.º 3
0
static GstBuffer *
write_exif_ifd (const GstTagList * taglist, gboolean byte_order,
    guint32 base_offset, const GstExifTagMatch * tag_map)
{
  GstExifWriter writer;
  gint i;

  GST_DEBUG ("Formatting taglist %p as exif buffer. Byte order: %d, "
      "base_offset: %u", taglist, byte_order, base_offset);

  g_assert (byte_order == G_LITTLE_ENDIAN || byte_order == G_BIG_ENDIAN);

  if (!gst_tag_list_has_ifd_tags (taglist, tag_map)) {
    GST_DEBUG ("No tags for this ifd");
    return NULL;
  }

  gst_exif_writer_init (&writer, byte_order);

  /* write tag number as 0 */
  gst_byte_writer_put_uint16_le (&writer.tagwriter, 0);

  /* write both tag headers and data
   * in ascending id order */

  for (i = 0; tag_map[i].exif_tag != 0; i++) {

    /* special cases have NULL gst tag */
    if (tag_map[i].gst_tag == NULL) {
      GstBuffer *inner_ifd = NULL;
      const GstExifTagMatch *inner_tag_map = NULL;

      GST_LOG ("Inner ifd tag: %x", tag_map[i].exif_tag);

      if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG) {
        inner_tag_map = tag_map_gps;
      }

      if (inner_tag_map) {
        /* The base offset for this inner ifd is the sum of:
         * - the current base offset
         * - the total tag data of current this ifd
         * - the total data of the current ifd
         * - its own tag entry length still to be writen (12)
         * - 4 bytes for the next ifd entry still to be writen
         */
        inner_ifd = write_exif_ifd (taglist, byte_order, base_offset +
            gst_byte_writer_get_size (&writer.tagwriter) +
            gst_byte_writer_get_size (&writer.datawriter) + 12 + 4,
            inner_tag_map);
      }

      if (inner_ifd) {
        GST_DEBUG ("Adding inner ifd: %x", tag_map[i].exif_tag);
        gst_exif_writer_write_tag_header (&writer, tag_map[i].exif_tag,
            EXIF_TYPE_LONG, 1,
            gst_byte_writer_get_size (&writer.datawriter), FALSE);
        gst_byte_writer_put_data (&writer.datawriter,
            GST_BUFFER_DATA (inner_ifd), GST_BUFFER_SIZE (inner_ifd));
        gst_buffer_unref (inner_ifd);
      }
      continue;
    }

    GST_LOG ("Checking tag %s", tag_map[i].gst_tag);
    if (gst_tag_list_get_value_index (taglist, tag_map[i].gst_tag, 0) == NULL)
      continue;

    write_exif_tag_from_taglist (&writer, taglist, &tag_map[i]);
  }

  /* Add the next IFD offset, we just set it to 0 because
   * there is no easy way to predict what it is going to be.
   * The user might rewrite the value if needed */
  gst_byte_writer_put_uint32_le (&writer.tagwriter, 0);

  /* write the number of tags */
  gst_byte_writer_set_pos (&writer.tagwriter, 0);
  if (writer.byte_order == G_LITTLE_ENDIAN)
    gst_byte_writer_put_uint16_le (&writer.tagwriter, writer.tags_total);
  else
    gst_byte_writer_put_uint16_be (&writer.tagwriter, writer.tags_total);

  /* now that we know the tag headers size, we can add the offsets */
  gst_exif_tag_rewrite_offsets (&writer, base_offset);

  return gst_exif_writer_reset_and_get_buffer (&writer);
}
Exemplo n.º 4
0
static GstFlowReturn
gst_jif_mux_recombine_image (GstJifMux * self, GstBuffer ** new_buf,
                             GstBuffer * old_buf)
{
    GstBuffer *buf;
    GstByteWriter *writer;
    GstFlowReturn fret;
    GstJifMuxMarker *m;
    GList *node;
    guint size = self->priv->scan_size;
    gboolean writer_status = TRUE;

    /* iterate list and collect size */
    for (node = self->priv->markers; node; node = g_list_next (node)) {
        m = (GstJifMuxMarker *) node->data;

        /* some markers like e.g. SOI are empty */
        if (m->size) {
            size += 2 + m->size;
        }
        /* 0xff <marker> */
        size += 2;
    }
    GST_INFO_OBJECT (self, "old size: %u, new size: %u",
                     GST_BUFFER_SIZE (old_buf), size);

    /* allocate new buffer */
    fret = gst_pad_alloc_buffer_and_set_caps (self->priv->srcpad,
            GST_BUFFER_OFFSET (old_buf), size, GST_PAD_CAPS (self->priv->srcpad),
            &buf);
    if (fret != GST_FLOW_OK)
        goto no_buffer;

    /* copy buffer metadata */
    gst_buffer_copy_metadata (buf, old_buf,
                              GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS);

    /* memcopy markers */
    writer = gst_byte_writer_new_with_buffer (buf, TRUE);
    for (node = self->priv->markers; node && writer_status;
            node = g_list_next (node)) {
        m = (GstJifMuxMarker *) node->data;

        writer_status &= gst_byte_writer_put_uint8 (writer, 0xff);
        writer_status &= gst_byte_writer_put_uint8 (writer, m->marker);

        GST_DEBUG_OBJECT (self, "marker = %2x, size = %u", m->marker, m->size + 2);

        if (m->size) {
            writer_status &= gst_byte_writer_put_uint16_be (writer, m->size + 2);
            writer_status &= gst_byte_writer_put_data (writer, m->data, m->size);
        }

        if (m->marker == SOS) {
            GST_DEBUG_OBJECT (self, "scan data, size = %u", self->priv->scan_size);
            writer_status &=
                gst_byte_writer_put_data (writer, self->priv->scan_data,
                                          self->priv->scan_size);
        }
    }
    gst_byte_writer_free (writer);

    if (!writer_status) {
        GST_WARNING_OBJECT (self, "Failed to write to buffer, calculated size "
                            "was probably too short");
        g_assert_not_reached ();
    }

    *new_buf = buf;
    return GST_FLOW_OK;

no_buffer:
    GST_WARNING_OBJECT (self, "failed to allocate output buffer, flow_ret = %s",
                        gst_flow_get_name (fret));
    return fret;
}