Example #1
0
// GStreamer event filter that removes any image metadata.
static gboolean remove_image(GstPad* pad,
                            GstObject* parent,
                            GstEvent* event) {
    GstTagList* tags = NULL;
    GstPad* sink = NULL;
    gboolean ret = false;

    switch (GST_EVENT_TYPE(event)) {
        case GST_EVENT_TAG:
            gst_event_parse_tag(event, &tags);
            gst_tag_list_remove_tag(tags, "image");
            event = gst_event_new_tag(tags);
            break;
        case GST_EVENT_CAPS:
            sink = gst_element_get_static_pad(GST_ELEMENT(parent), "src");
            ret = gst_pad_push_event(sink, event);
            gst_object_unref(sink);
            return ret;
        default:
            break;
    }

    return gst_pad_event_default(pad, parent, event);
}
Example #2
0
GstTagList *
gst_droidcamsrc_exif_tags_from_jpeg_data (void *data, size_t size)
{
  GstTagList *tags = NULL;
  ExifMem *mem = exif_mem_new (g_malloc0, g_realloc, g_free);
  ExifData *exif = exif_data_new_mem (mem);
  unsigned char *exif_data = NULL;
  void *_exif_data = NULL;
  unsigned int exif_data_size = 0;
  GstBuffer *buffer;
  ExifEntry *iso;
  int x, i;

  exif_data_load_data (exif, data, size);
  exif_data_set_data_type (exif, EXIF_DATA_TYPE_COMPRESSED);

  exif_data_save_data (exif, &exif_data, &exif_data_size);
  if (!exif_data_size) {
    goto out;
  }

  if (exif_data_size <= 6) {
    goto out;
  }

  /* dump the data. based on libexif code */
  for (x = 0; x < EXIF_IFD_COUNT; x++) {
    if (exif->ifd[x] && exif->ifd[x]->count) {
      for (i = 0; i < exif->ifd[x]->count; i++) {
        char val[1024];
        ExifEntry *e = exif->ifd[x]->entries[i];
        GST_LOG ("Exif IFD: %s. Tag 0x%x (%s) = %s", exif_ifd_get_name (x),
            e->tag, exif_tag_get_name_in_ifd (e->tag, exif_entry_get_ifd (e)),
            exif_entry_get_value (e, val, sizeof (val)));
      }
    }
  }

  _exif_data = exif_data;

  exif_data += 6;
  exif_data_size -= 6;

  buffer = gst_buffer_new_wrapped_full (GST_MEMORY_FLAG_READONLY,
      exif_data, exif_data_size, 0, exif_data_size, NULL, NULL);
  tags = gst_tag_list_from_exif_buffer_with_tiff_header (buffer);
  gst_buffer_unref (buffer);

  /* We don't want these tags */
  gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MANUFACTURER);
  gst_tag_list_remove_tag (tags, GST_TAG_DEVICE_MODEL);
  gst_tag_list_remove_tag (tags, GST_TAG_APPLICATION_NAME);
  gst_tag_list_remove_tag (tags, GST_TAG_DATE_TIME);

  /* we have a mess with ISO so we will just behave as N9 */
  iso = exif_content_get_entry (exif->ifd[EXIF_IFD_EXIF],
      EXIF_TAG_ISO_SPEED_RATINGS);

  if (iso) {
#ifdef __arm__
    guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_MOTOROLA);
#else
    guint16 val = exif_get_short (iso->data, EXIF_BYTE_ORDER_INTEL);
#endif
    gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
        GST_TAG_CAPTURING_ISO_SPEED, val, NULL);
  }

  /* TODO: the following are being dropped
   *
   * 0x213  EXIF_TAG_YCBCR_POSITIONING
   * 0x9004 EXIF_TAG_DATE_TIME_DIGITIZED
   * 0x9101 EXIF_TAG_COMPONENTS_CONFIGURATION
   * 0xa001 EXIF_TAG_COLOR_SPACE
   * 0xa002 EXIF_TAG_PIXEL_X_DIMENSION
   * 0xa003 EXIF_TAG_PIXEL_Y_DIMENSION
   * 0xa005 EXIF_TAG_INTEROPERABILITY_IFD_POINTER
   * thumbnail.
   * 0x100 EXIF_TAG_IMAGE_WIDTH
   * 0x101 EXIF_TAG_IMAGE_LENGTH
   * 0x9203 EXIF_TAG_BRIGHTNESS_VALUE
   * 0x9205 EXIF_TAG_MAX_APERTURE_VALUE
   * 0x9206 EXIF_TAG_SUBJECT_DISTANCE
   * 0x9208 EXIF_TAG_LIGHT_SOURCE
   * 0x9286 EXIF_TAG_USER_COMMENT
   */
out:
  if (_exif_data) {
    exif_mem_free (mem, _exif_data);
  }

  if (exif) {
    exif_data_free (exif);
  }

  exif_mem_unref (mem);

  return tags;
}
Example #3
0
static void
bt_song_info_set_property (GObject * const object, const guint property_id,
    const GValue * const value, GParamSpec * const pspec)
{
  const BtSongInfo *const self = BT_SONG_INFO (object);
  return_if_disposed ();
  switch (property_id) {
    case SONG_INFO_SONG:
      self->priv->song = BT_SONG (g_value_get_object (value));
      g_object_try_weak_ref (self->priv->song);
      GST_DEBUG ("set the song for song-info: %p", self->priv->song);
      break;
    case SONG_INFO_FILE_NAME:
      g_free (self->priv->file_name);
      self->priv->file_name = g_value_dup_string (value);
      GST_DEBUG ("set the file-name for song_info: %s", self->priv->file_name);
      break;
    case SONG_INFO_INFO:{
      const gchar *str = g_value_get_string (value);
      if ((self->priv->info != str) && (!self->priv->info || !str
              || strcmp (self->priv->info, str))) {
        g_free (self->priv->info);
        if (str) {
          self->priv->info = g_value_dup_string (value);
          gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_DESCRIPTION, self->priv->info, NULL);
        } else {
          self->priv->info = NULL;
          gst_tag_list_remove_tag (self->priv->taglist, GST_TAG_DESCRIPTION);
        }
        GST_DEBUG ("set the info for song_info: %s", self->priv->info);
      }
      break;
    }
    case SONG_INFO_NAME:{
      const gchar *str = g_value_get_string (value);
      if ((self->priv->name != str) && (!self->priv->name || !str
              || strcmp (self->priv->name, str))) {
        g_free (self->priv->name);
        if (str) {
          self->priv->name = g_value_dup_string (value);
          gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_TITLE, self->priv->name, NULL);
        } else {
          self->priv->name = NULL;
          gst_tag_list_remove_tag (self->priv->taglist, GST_TAG_TITLE);
        }
        GST_DEBUG ("set the name for song_info: %s", self->priv->name);
      }
      break;
    }
    case SONG_INFO_GENRE:{
      const gchar *str = g_value_get_string (value);
      if ((self->priv->genre != str) && (!self->priv->genre || !str
              || strcmp (self->priv->genre, str))) {
        g_free (self->priv->genre);
        if (str) {
          self->priv->genre = g_value_dup_string (value);
          gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_GENRE, self->priv->genre, NULL);
        } else {
          self->priv->genre = NULL;
          gst_tag_list_remove_tag (self->priv->taglist, GST_TAG_GENRE);
        }
        GST_DEBUG ("set the genre for song_info: %s", self->priv->genre);
      }
      break;
    }
    case SONG_INFO_AUTHOR:{
      const gchar *str = g_value_get_string (value);
      if ((self->priv->author != str) && (!self->priv->author || !str
              || strcmp (self->priv->author, str))) {
        g_free (self->priv->author);
        if (str) {
          self->priv->author = g_value_dup_string (value);
          gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_ARTIST, self->priv->author, NULL);
        } else {
          self->priv->author = NULL;
          gst_tag_list_remove_tag (self->priv->taglist, GST_TAG_ARTIST);
        }
        GST_DEBUG ("set the author for song_info: %s", self->priv->author);
      }
      break;
    }
    case SONG_INFO_BPM:{
      gulong val = g_value_get_ulong (value);
      if (self->priv->beats_per_minute != val) {
        self->priv->beats_per_minute = val;
        gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_BEATS_PER_MINUTE, (gdouble) self->priv->beats_per_minute,
            NULL);
        bt_song_info_tempo_changed (self);
        GST_DEBUG ("set the bpm for song_info: %lu",
            self->priv->beats_per_minute);
      }
      break;
    }
    case SONG_INFO_TPB:{
      gulong val = g_value_get_ulong (value);
      if (self->priv->ticks_per_beat != val) {
        self->priv->ticks_per_beat = val;
        bt_song_info_tempo_changed (self);
        GST_DEBUG ("set the tpb for song_info: %lu",
            self->priv->ticks_per_beat);
      }
    }
      break;
    case SONG_INFO_BARS:{
      gulong val = g_value_get_ulong (value);
      if (self->priv->bars != val) {
        self->priv->bars = val;
        bt_song_info_tempo_changed (self);
        GST_DEBUG ("set the bars for song_info: %lu", self->priv->bars);
      }
      break;
    }
    case SONG_INFO_CREATE_DTS:{
      const gchar *const dts = g_value_get_string (value);

      if (dts) {
        if (strlen (dts) == DTS_LEN) {
          strcpy (self->priv->create_dts, dts);
        }
      } else {
        time_t now = time (NULL);
        /* this is ISO 8601 Date and Time Format
         * %F     Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99)
         * %T     The time in 24-hour notation (%H:%M:%S). (SU)
         */
        strftime (self->priv->create_dts, DTS_LEN + 1, "%FT%TZ", gmtime (&now));
      }
      break;
    }
    case SONG_INFO_CHANGE_DTS:{
      const gchar *const dts = g_value_get_string (value);

      if (dts) {
        if (strlen (dts) == DTS_LEN) {
          struct tm tm = { 0, };
          strcpy (self->priv->change_dts, dts);
          // parse date and update tag
          strptime (dts, "%FT%TZ", &tm);
          g_date_set_time_t (self->priv->tag_date, mktime (&tm));
          gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
              GST_TAG_DATE, self->priv->tag_date, NULL);
        }
      } else {
        time_t now = time (NULL);
        strftime (self->priv->change_dts, DTS_LEN + 1, "%FT%TZ", gmtime (&now));
        g_date_set_time_t (self->priv->tag_date, now);
        gst_tag_list_add (self->priv->taglist, GST_TAG_MERGE_REPLACE,
            GST_TAG_DATE, self->priv->tag_date, NULL);
      }
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
}
static GstEvent *
gst_rg_volume_tag_event (GstRgVolume * self, GstEvent * event)
{
  GstTagList *tag_list;
  gboolean has_track_gain, has_track_peak, has_album_gain, has_album_peak;
  gboolean has_ref_level;

  g_return_val_if_fail (event != NULL, NULL);
  g_return_val_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG, event);

  gst_event_parse_tag (event, &tag_list);

  if (gst_tag_list_is_empty (tag_list))
    return event;

  has_track_gain = gst_tag_list_get_double (tag_list, GST_TAG_TRACK_GAIN,
      &self->track_gain);
  has_track_peak = gst_tag_list_get_double (tag_list, GST_TAG_TRACK_PEAK,
      &self->track_peak);
  has_album_gain = gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_GAIN,
      &self->album_gain);
  has_album_peak = gst_tag_list_get_double (tag_list, GST_TAG_ALBUM_PEAK,
      &self->album_peak);
  has_ref_level = gst_tag_list_get_double (tag_list, GST_TAG_REFERENCE_LEVEL,
      &self->reference_level);

  if (!has_track_gain && !has_track_peak && !has_album_gain && !has_album_peak)
    return event;

  if (has_ref_level && (has_track_gain || has_album_gain)
      && (ABS (self->reference_level - RG_REFERENCE_LEVEL) > 1.e-6)) {
    /* Log a message stating the amount of adjustment that is applied below. */
    GST_DEBUG_OBJECT (self,
        "compensating for reference level difference by %" GAIN_FORMAT,
        RG_REFERENCE_LEVEL - self->reference_level);
  }
  if (has_track_gain) {
    self->track_gain += RG_REFERENCE_LEVEL - self->reference_level;
  }
  if (has_album_gain) {
    self->album_gain += RG_REFERENCE_LEVEL - self->reference_level;
  }

  /* Ignore values that are obviously invalid. */
  if (G_UNLIKELY (has_track_gain && !VALID_GAIN (self->track_gain))) {
    GST_DEBUG_OBJECT (self,
        "ignoring bogus track gain value %" GAIN_FORMAT, self->track_gain);
    has_track_gain = FALSE;
  }
  if (G_UNLIKELY (has_track_peak && !VALID_PEAK (self->track_peak))) {
    GST_DEBUG_OBJECT (self,
        "ignoring bogus track peak value %" PEAK_FORMAT, self->track_peak);
    has_track_peak = FALSE;
  }
  if (G_UNLIKELY (has_album_gain && !VALID_GAIN (self->album_gain))) {
    GST_DEBUG_OBJECT (self,
        "ignoring bogus album gain value %" GAIN_FORMAT, self->album_gain);
    has_album_gain = FALSE;
  }
  if (G_UNLIKELY (has_album_peak && !VALID_PEAK (self->album_peak))) {
    GST_DEBUG_OBJECT (self,
        "ignoring bogus album peak value %" PEAK_FORMAT, self->album_peak);
    has_album_peak = FALSE;
  }

  /* Clamp peaks >1.0.  Float based decoders can produce spurious samples >1.0,
   * cutting these files back to 1.0 should not cause any audible distortion.
   * This is most often seen with Vorbis files. */
  if (has_track_peak && self->track_peak > 1.) {
    GST_DEBUG_OBJECT (self,
        "clamping track peak %" PEAK_FORMAT " to 1.0", self->track_peak);
    self->track_peak = 1.0;
  }
  if (has_album_peak && self->album_peak > 1.) {
    GST_DEBUG_OBJECT (self,
        "clamping album peak %" PEAK_FORMAT " to 1.0", self->album_peak);
    self->album_peak = 1.0;
  }

  self->has_track_gain |= has_track_gain;
  self->has_track_peak |= has_track_peak;
  self->has_album_gain |= has_album_gain;
  self->has_album_peak |= has_album_peak;

  event = (GstEvent *) gst_mini_object_make_writable (GST_MINI_OBJECT (event));
  gst_event_parse_tag (event, &tag_list);

  gst_tag_list_remove_tag (tag_list, GST_TAG_TRACK_GAIN);
  gst_tag_list_remove_tag (tag_list, GST_TAG_TRACK_PEAK);
  gst_tag_list_remove_tag (tag_list, GST_TAG_ALBUM_GAIN);
  gst_tag_list_remove_tag (tag_list, GST_TAG_ALBUM_PEAK);
  gst_tag_list_remove_tag (tag_list, GST_TAG_REFERENCE_LEVEL);

  gst_rg_volume_update_gain (self);

  if (gst_tag_list_is_empty (tag_list)) {
    gst_event_unref (event);
    event = NULL;
  }

  return event;
}