template<> GstTagList* refGPtr<GstTagList>(GstTagList* ptr)
{
    if (ptr)
        gst_tag_list_ref(ptr);

    return ptr;
}
GstPlayerStreamInfo *
gst_player_stream_info_copy (GstPlayerStreamInfo * ref)
{
  GstPlayerStreamInfo *info = NULL;

  if (!ref)
    return NULL;

  if (GST_IS_PLAYER_VIDEO_INFO (ref))
    info = gst_player_video_info_copy ((GstPlayerVideoInfo *) ref);
  else if (GST_IS_PLAYER_AUDIO_INFO (ref))
    info = gst_player_audio_info_copy ((GstPlayerAudioInfo *) ref);
  else
    info = gst_player_subtitle_info_copy ((GstPlayerSubtitleInfo *) ref);

  info->stream_index = ref->stream_index;
  if (ref->tags)
    info->tags = gst_tag_list_ref (ref->tags);
  if (ref->caps)
    info->caps = gst_caps_copy (ref->caps);
  if (ref->codec)
    info->codec = g_strdup (ref->codec);

  return info;
}
GstEvent *
gst_kate_util_decoder_base_get_tag_event (GstKateDecoderBase * decoder)
{
  if (!decoder->tags)
    return NULL;
  decoder->tags_changed = FALSE;
  return gst_event_new_tag (gst_tag_list_ref (decoder->tags));
}
static GstFlowReturn
gst_tag_mux_render_start_tag (GstTagMux * mux)
{
  GstTagMuxClass *klass;
  GstBuffer *buffer;
  GstTagList *taglist;
  GstEvent *event;
  GstFlowReturn ret;
  GstSegment segment;

  taglist = gst_tag_mux_get_tags (mux);

  klass = GST_TAG_MUX_CLASS (G_OBJECT_GET_CLASS (mux));

  if (klass->render_start_tag == NULL)
    goto no_vfunc;

  buffer = klass->render_start_tag (mux, taglist);

  /* Null buffer is ok, just means we're not outputting anything */
  if (buffer == NULL) {
    GST_INFO_OBJECT (mux, "No start tag generated");
    mux->priv->start_tag_size = 0;
    return GST_FLOW_OK;
  }

  mux->priv->start_tag_size = gst_buffer_get_size (buffer);
  GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes",
      mux->priv->start_tag_size);

  /* Send newsegment event from byte position 0, so the tag really gets
   * written to the start of the file, independent of the upstream segment */
  gst_segment_init (&segment, GST_FORMAT_BYTES);
  gst_pad_push_event (mux->priv->srcpad, gst_event_new_segment (&segment));

  /* Send an event about the new tags to downstream elements */
  /* gst_event_new_tag takes ownership of the list, so use a copy */
  event = gst_event_new_tag (gst_tag_list_ref (taglist));
  gst_pad_push_event (mux->priv->srcpad, event);

  GST_BUFFER_OFFSET (buffer) = 0;
  ret = gst_pad_push (mux->priv->srcpad, buffer);

  mux->priv->current_offset = mux->priv->start_tag_size;
  mux->priv->max_offset =
      MAX (mux->priv->max_offset, mux->priv->current_offset);

  return ret;

no_vfunc:
  {
    GST_ERROR_OBJECT (mux, "Subclass does not implement "
        "render_start_tag vfunc!");
    return GST_FLOW_ERROR;
  }
}
/**
 * gst_stream_get_tags:
 * @stream: a #GstStream
 *
 * Retrieve the tags for @stream, if any
 *
 * Returns: (transfer full) (nullable): The #GstTagList for @stream
 *
 * Since: 1.10
 */
GstTagList *
gst_stream_get_tags (GstStream * stream)
{
  GstTagList *res = NULL;

  GST_OBJECT_LOCK (stream);
  if (stream->priv->tags)
    res = gst_tag_list_ref (stream->priv->tags);
  GST_OBJECT_UNLOCK (stream);

  return res;
}
static inline void
_push_mandatory_events (GstAggregator * self)
{
  GstAggregatorPrivate *priv = self->priv;

  if (g_atomic_int_get (&self->priv->send_stream_start)) {
    gchar s_id[32];

    GST_INFO_OBJECT (self, "pushing stream start");
    /* stream-start (FIXME: create id based on input ids) */
    g_snprintf (s_id, sizeof (s_id), "agg-%08x", g_random_int ());
    if (!gst_pad_push_event (self->srcpad, gst_event_new_stream_start (s_id))) {
      GST_WARNING_OBJECT (self->srcpad, "Sending stream start event failed");
    }
    g_atomic_int_set (&self->priv->send_stream_start, FALSE);
  }

  if (self->priv->srccaps) {

    GST_INFO_OBJECT (self, "pushing caps: %" GST_PTR_FORMAT,
        self->priv->srccaps);
    if (!gst_pad_push_event (self->srcpad,
            gst_event_new_caps (self->priv->srccaps))) {
      GST_WARNING_OBJECT (self->srcpad, "Sending caps event failed");
    }
    gst_caps_unref (self->priv->srccaps);
    self->priv->srccaps = NULL;
  }

  if (g_atomic_int_get (&self->priv->send_segment)) {
    if (!g_atomic_int_get (&self->priv->flush_seeking)) {
      GstEvent *segev = gst_event_new_segment (&self->segment);

      if (!self->priv->seqnum)
        self->priv->seqnum = gst_event_get_seqnum (segev);
      else
        gst_event_set_seqnum (segev, self->priv->seqnum);

      GST_DEBUG_OBJECT (self, "pushing segment %" GST_PTR_FORMAT, segev);
      gst_pad_push_event (self->srcpad, segev);
      g_atomic_int_set (&self->priv->send_segment, FALSE);
    }
  }

  if (priv->tags && priv->tags_changed) {
    gst_pad_push_event (self->srcpad,
        gst_event_new_tag (gst_tag_list_ref (priv->tags)));
    priv->tags_changed = FALSE;
  }
}
Exemple #7
0
/**
 * gst_toc_merge_tags:
 * @toc: A #GstToc instance
 * @tags: (allow-none): A #GstTagList or %NULL
 * @mode: A #GstTagMergeMode
 *
 * Merge @tags into the existing tags of @toc using @mode.
 */
void
gst_toc_merge_tags (GstToc * toc, GstTagList * tags, GstTagMergeMode mode)
{
  g_return_if_fail (toc != NULL);
  g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (toc)));

  if (!toc->tags) {
    toc->tags = gst_tag_list_ref (tags);
  } else {
    GstTagList *tmp = gst_tag_list_merge (toc->tags, tags, mode);
    gst_tag_list_unref (toc->tags);
    toc->tags = tmp;
  }
}
Exemple #8
0
/**
 * gst_toc_entry_merge_tags:
 * @entry: A #GstTocEntry instance
 * @tags: (allow-none): A #GstTagList or %NULL
 * @mode: A #GstTagMergeMode
 *
 * Merge @tags into the existing tags of @entry using @mode.
 */
void
gst_toc_entry_merge_tags (GstTocEntry * entry, GstTagList * tags,
    GstTagMergeMode mode)
{
  g_return_if_fail (entry != NULL);
  g_return_if_fail (gst_mini_object_is_writable (GST_MINI_OBJECT_CAST (entry)));

  if (!entry->tags) {
    entry->tags = gst_tag_list_ref (tags);
  } else {
    GstTagList *tmp = gst_tag_list_merge (entry->tags, tags, mode);
    gst_tag_list_unref (entry->tags);
    entry->tags = tmp;
  }
}
void
gst_kate_util_decoder_base_add_tags (GstKateDecoderBase * decoder,
    GstTagList * tags, gboolean take_ownership_of_tags)
{
  if (!decoder->tags) {
    if (!take_ownership_of_tags)
      tags = gst_tag_list_ref (tags);
    decoder->tags = tags;
  } else {
    GstTagList *old = decoder->tags;
    decoder->tags = gst_tag_list_merge (old, tags, GST_TAG_MERGE_REPLACE);
    gst_tag_list_unref (old);
    if (take_ownership_of_tags)
      gst_tag_list_unref (tags);
  }
  decoder->tags_changed = TRUE;
}
GstPlayerMediaInfo *
gst_player_media_info_copy (GstPlayerMediaInfo * ref)
{
  GList *l;
  GstPlayerMediaInfo *info;

  if (!ref)
    return NULL;

  info = gst_player_media_info_new (ref->uri);
  info->duration = ref->duration;
  info->seekable = ref->seekable;
  if (ref->tags)
    info->tags = gst_tag_list_ref (ref->tags);
  if (ref->title)
    info->title = g_strdup (ref->title);
  if (ref->container)
    info->container = g_strdup (ref->container);
  if (ref->image_sample)
    info->image_sample = gst_sample_ref (ref->image_sample);

  for (l = ref->stream_list; l != NULL; l = l->next) {
    GstPlayerStreamInfo *s;

    s = gst_player_stream_info_copy ((GstPlayerStreamInfo *) l->data);
    info->stream_list = g_list_append (info->stream_list, s);

    if (GST_IS_PLAYER_AUDIO_INFO (s))
      info->audio_stream_list = g_list_append (info->audio_stream_list, s);
    else if (GST_IS_PLAYER_VIDEO_INFO (s))
      info->video_stream_list = g_list_append (info->video_stream_list, s);
    else
      info->subtitle_stream_list =
          g_list_append (info->subtitle_stream_list, s);
  }

  return info;
}
static void
gst_rg_analysis_handle_eos (GstRgAnalysis * filter)
{
  gboolean album_processing = (filter->num_tracks > 0);
  gboolean album_finished = (filter->num_tracks == 1);
  gboolean album_skipping = album_processing && filter->skip;

  filter->has_track_gain = FALSE;
  filter->has_track_peak = FALSE;

  if (album_finished) {
    filter->ignore_tags = FALSE;
    filter->skip = FALSE;
    filter->has_album_gain = FALSE;
    filter->has_album_peak = FALSE;
  } else if (!album_skipping) {
    filter->skip = FALSE;
  }

  /* We might have just fully processed a track because it has
   * incomplete tags.  If we do album processing and allow skipping
   * (not forced), prevent switching to skipping if a later track with
   * full tags comes along: */
  if (!filter->forced && album_processing && !album_finished)
    filter->ignore_tags = TRUE;

  if (!filter->skip) {
    GstTagList *tag_list = NULL;
    gboolean track_success;
    gboolean album_success = FALSE;

    track_success = gst_rg_analysis_track_result (filter, &tag_list);

    if (album_finished)
      album_success = gst_rg_analysis_album_result (filter, &tag_list);
    else if (!album_processing)
      rg_analysis_reset_album (filter->ctx);

    if (track_success || album_success) {
      GST_LOG_OBJECT (filter, "posting tag list with results");
      gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND,
          GST_TAG_REFERENCE_LEVEL, filter->reference_level, NULL);
      /* This steals our reference to the list: */
      gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (GST_BASE_TRANSFORM
              (filter)), gst_event_new_tag (gst_tag_list_ref (tag_list)));
    }
  }

  if (album_processing) {
    filter->num_tracks--;

    if (!album_finished) {
      GST_DEBUG_OBJECT (filter, "album not finished yet (num-tracks is now %u)",
          filter->num_tracks);
    } else {
      GST_DEBUG_OBJECT (filter, "album finished (num-tracks is now 0)");
    }
  }

  if (album_processing)
    g_object_notify (G_OBJECT (filter), "num-tracks");
}
Exemple #12
0
static gboolean
gst_wavenc_event (GstPad * pad, GstObject * parent, GstEvent * event)
{
  gboolean res = TRUE;
  GstWavEnc *wavenc;
  GstTagList *tags;
  GstToc *toc;

  wavenc = GST_WAVENC (parent);

  switch (GST_EVENT_TYPE (event)) {
    case GST_EVENT_CAPS:
    {
      GstCaps *caps;

      gst_event_parse_caps (event, &caps);
      gst_wavenc_sink_setcaps (pad, caps);

      /* have our own src caps */
      gst_event_unref (event);
      break;
    }
    case GST_EVENT_EOS:
    {
      GstFlowReturn flow;
      GST_DEBUG_OBJECT (wavenc, "got EOS");

      flow = gst_wavenc_write_toc (wavenc);
      if (flow != GST_FLOW_OK) {
        GST_WARNING_OBJECT (wavenc, "error pushing toc: %s",
            gst_flow_get_name (flow));
      }
      flow = gst_wavenc_write_tags (wavenc);
      if (flow != GST_FLOW_OK) {
        GST_WARNING_OBJECT (wavenc, "error pushing tags: %s",
            gst_flow_get_name (flow));
      }

      /* write header with correct length values */
      gst_wavenc_push_header (wavenc);

      /* we're done with this file */
      wavenc->finished_properly = TRUE;

      /* and forward the EOS event */
      res = gst_pad_event_default (pad, parent, event);
      break;
    }
    case GST_EVENT_SEGMENT:
      /* Just drop it, it's probably in TIME format
       * anyway. We'll send our own newsegment event */
      gst_event_unref (event);
      break;
    case GST_EVENT_TOC:
      gst_event_parse_toc (event, &toc, NULL);
      if (toc) {
        if (wavenc->toc != toc) {
          if (wavenc->toc)
            gst_toc_unref (wavenc->toc);
          wavenc->toc = toc;
        } else {
          gst_toc_unref (toc);
        }
      }
      res = gst_pad_event_default (pad, parent, event);
      break;
    case GST_EVENT_TAG:
      gst_event_parse_tag (event, &tags);
      if (tags) {
        if (wavenc->tags != tags) {
          if (wavenc->tags)
            gst_tag_list_unref (wavenc->tags);
          wavenc->tags = gst_tag_list_ref (tags);
        }
      }
      res = gst_pad_event_default (pad, parent, event);
      break;
    default:
      res = gst_pad_event_default (pad, parent, event);
      break;
  }

  return res;
}
GstFlowReturn
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
    GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
    GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev)
{
  kate_packet kp;
  int ret;
  GstFlowReturn rflow = GST_FLOW_OK;
  gboolean is_header;
  GstMapInfo info;
  gsize header_size;
  guint8 header[1];

  header_size = gst_buffer_extract (buf, 0, header, 1);

  GST_DEBUG_OBJECT (element,
      "got kate packet, %" G_GSIZE_FORMAT " bytes, type %02x",
      gst_buffer_get_size (buf), header_size == 0 ? -1 : header[0]);

  is_header = header_size > 0 && (header[0] & 0x80);

  if (!is_header && decoder->tags_changed) {
    /* after we've processed headers, send any tags before processing the data packet */
    GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s",
        GST_DEBUG_PAD_NAME (tagpad));
    gst_pad_push_event (tagpad,
        gst_kate_util_decoder_base_get_tag_event (decoder));
  }

  if (gst_buffer_map (buf, &info, GST_MAP_READ)) {
    kate_packet_wrap (&kp, info.size, info.data);
    ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
    gst_buffer_unmap (buf, &info);
  } else {
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("Failed to map buffer"));
    return GST_FLOW_ERROR;
  }

  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("Failed to decode Kate packet: %s",
            gst_kate_util_get_error_message (ret)));
    return GST_FLOW_ERROR;
  }

  if (G_UNLIKELY (ret > 0)) {
    GST_DEBUG_OBJECT (element,
        "kate_high_decode_packetin has received EOS packet");
  }

  /* headers may be interesting to retrieve information from */
  if (G_UNLIKELY (is_header)) {
    switch (header[0]) {
      case 0x80:               /* ID header */
        GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
            decoder->k.ki->language, decoder->k.ki->category);
        if (src_caps) {
          if (*src_caps) {
            gst_caps_unref (*src_caps);
            *src_caps = NULL;
          }
          if (strcmp (decoder->k.ki->category, "K-SPU") == 0 ||
              strcmp (decoder->k.ki->category, "spu-subtitles") == 0) {
            *src_caps = gst_caps_new_empty_simple ("subpicture/x-dvd");
          } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
            *src_caps = gst_caps_new_simple ("text/x-raw", "format",
                G_TYPE_STRING, "utf8", NULL);
          } else {
            *src_caps = gst_caps_new_simple ("text/x-raw", "format",
                G_TYPE_STRING, "pango-markup", NULL);
          }
          GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps);
          if (!gst_pad_set_caps (srcpad, *src_caps)) {
            GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT,
                *src_caps);
          }
        }
        if (decoder->k.ki->language && *decoder->k.ki->language) {
          GstTagList *tags = gst_tag_list_new_empty ();
          gchar *lang_code;

          /* en_GB -> en */
          lang_code = g_ascii_strdown (decoder->k.ki->language, -1);
          g_strdelimit (lang_code, NULL, '\0');
          gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_LANGUAGE_CODE,
              lang_code, NULL);
          g_free (lang_code);
          /* TODO: category - where should it go ? */
          gst_kate_util_decoder_base_add_tags (decoder, tags, TRUE);
        }

        /* update properties */
        if (decoder->language)
          g_free (decoder->language);
        decoder->language = g_strdup (decoder->k.ki->language);
        if (decoder->category)
          g_free (decoder->category);
        decoder->category = g_strdup (decoder->k.ki->category);
        decoder->original_canvas_width = decoder->k.ki->original_canvas_width;
        decoder->original_canvas_height = decoder->k.ki->original_canvas_height;

        /* we can now send away any event we've delayed, as the src pad now has caps */
        gst_kate_util_decoder_base_drain_event_queue (decoder);

        break;

      case 0x81:               /* Vorbis comments header */
        GST_INFO_OBJECT (element, "Parsed comments header");
        {
          gchar *encoder = NULL;
          GstTagList *list = gst_tag_list_from_vorbiscomment_buffer (buf,
              (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
          if (!list) {
            GST_ERROR_OBJECT (element, "failed to decode comment header");
            list = gst_tag_list_new_empty ();
          }
          if (encoder) {
            gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
                GST_TAG_ENCODER, encoder, NULL);
            g_free (encoder);
          }
          gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
              GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
          gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
              GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
              NULL);

          gst_kate_util_decoder_base_add_tags (decoder, list, TRUE);

          if (decoder->initialized) {
            gst_pad_push_event (tagpad,
                gst_event_new_tag (gst_tag_list_ref (decoder->tags)));
          }
        }
        break;

      default:
        break;
    }
  }
#if ((KATE_VERSION_MAJOR<<16)|(KATE_VERSION_MINOR<<8)|KATE_VERSION_PATCH) >= 0x000400
  else if (*ev && (*ev)->meta) {
    int count = kate_meta_query_count ((*ev)->meta);
    if (count > 0) {
      GstTagList *evtags = gst_tag_list_new_empty ();
      int idx;
      GST_DEBUG_OBJECT (decoder, "Kate event has %d attached metadata", count);
      for (idx = 0; idx < count; ++idx) {
        const char *tag, *value;
        size_t len;
        if (kate_meta_query ((*ev)->meta, idx, &tag, &value, &len) < 0) {
          GST_WARNING_OBJECT (decoder, "Failed to retrieve metadata %d", idx);
        } else {
          if (gst_kate_util_is_utf8_string (value, len)) {
            gchar *compound = g_strdup_printf ("%s=%s", tag, value);
            GST_DEBUG_OBJECT (decoder,
                "Metadata %d: %s=%s (%" G_GSIZE_FORMAT " bytes)", idx, tag,
                value, len);
            gst_tag_list_add (evtags, GST_TAG_MERGE_APPEND,
                GST_TAG_EXTENDED_COMMENT, compound, NULL);
            g_free (compound);
          } else {
            GST_INFO_OBJECT (decoder,
                "Metadata %d, (%s, %" G_GSIZE_FORMAT
                " bytes) is binary, ignored", idx, tag, len);
          }
        }
      }
      gst_kate_util_decoder_base_add_tags (decoder, evtags, TRUE);
      gst_pad_push_event (tagpad,
          gst_kate_util_decoder_base_get_tag_event (decoder));
    }
  }
#endif

  return rflow;
}