コード例 #1
0
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;
  guint8 *data;
  gsize size;
  guint8 header[1];

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

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

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

  if (!is_header && decoder->tags) {
    /* 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_element_found_tags_for_pad (element, tagpad, decoder->tags);
    decoder->tags = NULL;
  }

  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
  kate_packet_wrap (&kp, size, data);
  ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
  gst_buffer_unmap (buf, data, size);

  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 ("video/x-dvd-subpicture");
          } else if (decoder->k.ki->text_markup_type == kate_markup_none) {
            *src_caps = gst_caps_new_empty_simple ("text/plain");
          } else {
            *src_caps = gst_caps_new_empty_simple ("text/x-pango-markup");
          }
          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 *old = decoder->tags, *tags = gst_tag_list_new_empty ();
          if (tags) {
            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 ? */
            decoder->tags =
                gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (tags);
            if (old)
              gst_tag_list_free (old);
          }
        }

        /* 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 *old = decoder->tags, *list =
              gst_tag_list_from_vorbiscomment_buffer (buf,
              (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
          if (list) {
            decoder->tags =
                gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (list);
          }

          if (!decoder->tags) {
            GST_ERROR_OBJECT (element, "failed to decode comment header");
            decoder->tags = gst_tag_list_new_empty ();
          }
          if (encoder) {
            gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
                GST_TAG_ENCODER, encoder, NULL);
            g_free (encoder);
          }
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
              NULL);

          if (old)
            gst_tag_list_free (old);

          if (decoder->initialized) {
            gst_element_found_tags_for_pad (element, tagpad, decoder->tags);
            decoder->tags = NULL;
          } else {
            /* Only push them as messages for the time being. *
             * They will be pushed on the pad once the decoder is initialized */
            gst_element_post_message (element,
                gst_message_new_tag (GST_OBJECT (element),
                    gst_tag_list_copy (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 (%zu 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, %zu bytes) is binary, ignored", idx, tag,
                len);
          }
        }
      }
      if (gst_tag_list_is_empty (evtags))
        gst_tag_list_free (evtags);
      else
        gst_element_found_tags_for_pad (element, tagpad, evtags);
    }
  }
#endif

  return rflow;
}
コード例 #2
0
ファイル: gstkateutil.c プロジェクト: JJCG/gst-plugins-bad
GstFlowReturn
gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder,
    GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad,
    const kate_event ** ev)
{
  kate_packet kp;
  int ret;
  GstFlowReturn rflow = GST_FLOW_OK;

  GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x",
      GST_BUFFER_SIZE (buf),
      GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]);
  kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf));
  ret = kate_high_decode_packetin (&decoder->k, &kp, ev);
  if (G_UNLIKELY (ret < 0)) {
    GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL),
        ("Failed to decode Kate packet: %d", ret));
    return GST_FLOW_ERROR;
  } else if (G_UNLIKELY (ret > 0)) {
    GST_DEBUG_OBJECT (element,
        "kate_high_decode_packetin has received EOS packet");
    return GST_FLOW_OK;
  }

  /* headers may be interesting to retrieve information from */
  if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0))
    switch (GST_BUFFER_DATA (buf)[0]) {
        GstCaps *caps;

      case 0x80:               /* ID header */
        GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s",
            decoder->k.ki->language, decoder->k.ki->category);
        caps = gst_caps_new_simple ("text/x-pango-markup", NULL);
        gst_pad_set_caps (srcpad, caps);
        gst_caps_unref (caps);
        if (decoder->k.ki->language && *decoder->k.ki->language) {
          GstTagList *old = decoder->tags, *tags = gst_tag_list_new ();
          if (tags) {
            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 ? */
            decoder->tags =
                gst_tag_list_merge (decoder->tags, tags, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (tags);
            if (old)
              gst_tag_list_free (old);
          }
        }

        /* 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;

        break;

      case 0x81:               /* Vorbis comments header */
        GST_INFO_OBJECT (element, "Parsed comments header");
        {
          gchar *encoder = NULL;
          GstTagList *old = decoder->tags, *list =
              gst_tag_list_from_vorbiscomment_buffer (buf,
              (const guint8 *) "\201kate\0\0\0\0", 9, &encoder);
          if (list) {
            decoder->tags =
                gst_tag_list_merge (decoder->tags, list, GST_TAG_MERGE_REPLACE);
            gst_tag_list_free (list);
          }

          if (!decoder->tags) {
            GST_ERROR_OBJECT (element, "failed to decode comment header");
            decoder->tags = gst_tag_list_new ();
          }
          if (encoder) {
            gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
                GST_TAG_ENCODER, encoder, NULL);
            g_free (encoder);
          }
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_SUBTITLE_CODEC, "Kate", NULL);
          gst_tag_list_add (decoder->tags, GST_TAG_MERGE_REPLACE,
              GST_TAG_ENCODER_VERSION, decoder->k.ki->bitstream_version_major,
              NULL);

          if (old)
            gst_tag_list_free (old);

          if (decoder->initialized) {
            gst_element_found_tags_for_pad (element, srcpad, decoder->tags);
            decoder->tags = NULL;
          } else {
            /* Only push them as messages for the time being. *
             * They will be pushed on the pad once the decoder is initialized */
            gst_element_post_message (element,
                gst_message_new_tag (GST_OBJECT (element),
                    gst_tag_list_copy (decoder->tags)));
          }
        }
        break;

      default:
        break;
    }

  return rflow;
}